Using OpenAM as a Trusted File Authorization Engine

A common theme in the DevOps world, or any containerization style infrastructure, may be the need to verify which executables (or files in general) can be installed, run, updated or deleted within a particular environment, image or container.  There are numerous ways this could be done.  Consider a use case where exe’s, Android APK’s or other 3rd party compiled files […]

SiteMinder Policy conversion to OpenAM XACML

In this article I discuss migrating SiteMinder policies to OpenAM. I have laid out an approach and framework to make the conversion possible using XML parsing, XML codifying and custom metadata that is necessary to resolve embedded repository externalities in the SiteMinder policy definition. I have also written a Java-based program that uses the methodology discussed in this article to parse through the SiteMinder policy and resolve each policy construct to an OpenAM equivalent policy object. The program codifies the XACML output step-by-step and on completion, one is able to import the XACML policy set into OpenAM via the policy editor.

There are going to be some complications in your situation such as when converting whitelisted resource URI – that SiteMinder does not ‘trap’ in the policy definition- you will need to know which URI are not in your SM policy extract and allowed by default, and then go about creating or adding the same URI in a new or ‘converted’ OpenAM policy. You would then need to whitelist those URI by explicitly allowing access in OpenAM.

I begin by describing the general layout of an XPS domain export at a high level, and how different policy constructs in a SiteMinder policy map over to OpenAM.

Survey of SiteMinder Policy Objects

While there is not a one-to-one mapping for every policy construct, there is a logical mapping that is useful to achieve a first pass on the conversion. Some of the complications are elaborated on below.

CA.SM::Domain -> OpenAM Policy Set Definition

The CA.SM::Domain object is the parent object to several domain-specific properties such as Mode, Name and UserDirectoriesLink references. Nested directly under the Domain object are CA.SM::Realm,  CA.SM::Policy and CA.SM::Response objects.

CA.SM::Realm -> OpenAM Policy Resources

The Realm object includes properties that describe the AgentGroupLink and AuthScheme settings, session properties such as IdleTimeout, and among other things, the ResourceFilter that is the protected resource URI. Realm also contains a nested object, called the CA.SM::Rule with an associated XID that describes the Actions available for the ResourceFilter- such as GET, PUT and POST- and properties that describe regular expression matching, time restrictions, resource pattern and IsEnabled among other things.

CA.SM::Response -> OpenAM Response Attributes

Response object is a container for one or more name-value pairs, or ‘response attributes’ expected by the agent. These can be of type Web agent responses or RADIUS responses. This conversion article and the Java program are limited to handling only the Web agent responses currently.

The Response object has an associated XID, and includes properties that describe the authorization conditions when the response is applicable- such as AccessAccept and AccessChallenge- and properties for AgentTypeLink and Name.

CA.SM::ResponseAttr

Response also nests CA.SM::ResponseAttr objects, each with a unique XID, that each have properties for AgentTypeAttrLink- pointing to ReferenceObjects such as “WebAgent-HTTP-Header-Variable” indicating the means of transport for the response attributs- and also the Value of the response codified in the form of display-name=<%userattr=”profile-attribute-name”%>. Here it is assumed that the value is sourced from a user attribute, which is mostly the case, although several types of ResponseAttrs are possible, including user attribute as already mentioned, DN Attribute, Static values, Session Variable, etc.

CA.SM::Policy -> OpenAM Policy Definition

Nested under the Domain object, and at peer level to the Realm and Response objects is the CA.SM::Policy object that serves to tie together protected resource URI to the corresponding user audience, rules including actions, response objects and optionally, IP address restrictions and time restrictions for those URI.

CA.SM::PolicyLink

The Policy object container has one or more CA.SM::PolicyLink objects that can be thought of as associations between the protected resources and the responses configured for each of them. The PolicyLink objects each have CA.SM::ResponseLink and CA.SM::RuleLink properties.

CA.SM::ResponseLink and CA.SM::RuleLink

The ResponseLink is a pointer to the Response object definition, and the RuleLink is a pointer to the Rule definition stored inside a CA.SM::Realm object. When invoked for a specific Realm, the policy enforces the Rule Actions as well as the Response attributes in case the policy evaluation is successful.

CA.SM::UserPolicy

The Policy object also contains one or more CA.SM::UserPolicy objects that can be thought of as audience restriction conditions. The UserPolicy object has properties defining the FilterPath, which is a SQL query but one that could be used to locate a set of users this policy applies to. Another property is the UserDirectoryLink that is a pointer to the external repository that contains the user profile data, and specifically stores the XID of the ReferenceObject by the name CA.SM::UserDirectory.

References

Besides Domain objects, there are also reference objects at a peer level to Domain. The Reference object tree encapsulates all external information that the policy references.

CA.SM::UserDirectory

The user repository information is stored under the CA.SM::UserDirectory ReferenceObject that includes a NameSpace attribute- such as “ODBC:”- and Server name. As mentioned previously the UserPolicy object stores a reference to the UserDirectory object using a UserDirectoryLink.

The program relies on these user directory references to be resolved using a metadata container in OpenDJ.

CA.SM::AgentGroup

The AgentGroup object refers to the SiteMinder agent configurations that all protect the same resources. The attribute AgentTypeLink contains a value that is referenced from CA.SM::Response objects using the AgentTypeLink property tying the web agent to that particular response object. There could be one or more Agent Groups.

CA.SM::AgentTypeAttr

One or more of these Reference objects define in what form the agent expects the response objects to be returned. Two currently supported, and commonly used, values include “WebAgent-HTTP-Header-Variable” and “WebAgent-HTTP-Cookie-Variable”. These are available for use in accept or reject responses only in SiteMinder.

Some other Reference objects include CA.SM::AgentType, which describes the SM agent- basically a Web Agent. Another is the CA.SM::AuthScheme which includes details about the form of authentication such as Forms-based, Basic auth or API.

Conversion to OpenAM

Converting CA.SM::Domain and CA.SM::Realm objects

Simply parse out these objects from the SiteMinder policy extract and create OpenAM policy set XACML definitions.

A code sample to establish the proper order and parity between the XACML elements is shown here:

        Element target = doc.createElementNS("ns2", "ns2:Target");
 	Element anyOf_subject = getAnyOfSubjectTree(doc, xmlMap);
 	target.appendChild(anyOf_subject);

 	Element anyOf_resource = getAnyOfResourceTree(doc, xmlMap, resourceUri);
 	target.appendChild(anyOf_resource);
 		
  	Element anyOf_application = getAnyOfApplicationTree(doc, xmlMap);
       	target.appendChild(anyOf_application);
       	
       	Element anyOf_action = getAnyOfActionTree(doc, xmlMap, actions);
       	target.appendChild(anyOf_action);

A code sample for creating the Resource URI in XACML format is shown below:

private static Element getAnyOfResourceTree(Document doc, Map<String, String> xmlMap, List resourceUri) {
// many AnyOf elements to define subject, resources, actions, etc
  	Element anyOf = doc.createElementNS("ns2", "ns2:AnyOf");
  	for(String url : resourceUri) {
		Element allOf = doc.createElementNS("ns2", "ns2:AllOf");
		Element Match = doc.createElementNS("ns2", "ns2:Match");
		Match.setAttribute("MatchId", "urn:sun:opensso:entitlement:resource-match:application:"+xmlMap.get("PolicyId"));
	       	Element AttributeValue = doc.createElementNS("ns2", "ns2:AttributeValue");
                AttributeValue.setAttribute("DataType", "http://www.w3.org/2001/XMLSchema#string");
                AttributeValue.setTextContent("*://*:*" + url);
   	        Match.appendChild(AttributeValue);
	       	Element AttributeDesignator = doc.createElementNS("ns2", "ns2:AttributeDesignator");
	       	AttributeDesignator.setAttribute("Category", "urn:oasis:names:tc:xacml:3.0:attribute-category:resource");
	       	AttributeDesignator.setAttribute("AttributeId", "urn:oasis:names:tc:xacml:1.0:resource:resource-id");
	       	AttributeDesignator.setAttribute("MustBePresent", "true");
	       	AttributeDesignator.setAttribute("DataType", "http://www.w3.org/2001/XMLSchema#string");
	       	Match.appendChild(AttributeDesignator);
	       	allOf.appendChild(Match);
	       	anyOf.appendChild(allOf);
  	}
	return anyOf;
}

Converting the CA.SM::Rule.Actions objects

Here the challenge is to convert the ResourceFilters into ResourceURI objects in the XACML definition, and then add the relevant actions to those resource URI as defined in the CA.SM::Realm object definition. A sample method that adds basic actions to a policy is shown here:

private static Element getAnyOfActionTree(Document doc, Map<String, String> xmlMap, List actions) {
	// many AnyOf elements to define subject, resources, actions, etc
  		Element anyOf = doc.createElementNS("ns2", "ns2:AnyOf");
  		for(String action : actions) {
      		Element allOf = doc.createElementNS("ns2", "ns2:AllOf");
  		Element Match = doc.createElementNS("ns2", "ns2:Match");
  		Match.setAttribute("MatchId", "urn:sun:opensso:entitlement:action-match:application:"+xmlMap.get("PolicyId"));
	       	Element AttributeValue = doc.createElementNS("ns2", "ns2:AttributeValue");
	       	AttributeValue.setAttribute("DataType", "http://www.w3.org/2001/XMLSchema#string");
	       	AttributeValue.setTextContent(action);
		   Match.appendChild(AttributeValue);
	       	Element AttributeDesignator = doc.createElementNS("ns2", "ns2:AttributeDesignator");
	       	AttributeDesignator.setAttribute("Category", "urn:oasis:names:tc:xacml:3.0:attribute-category:action");
	       	AttributeDesignator.setAttribute("AttributeId", "urn:oasis:names:tc:xacml:1.0:action:action-id");
	       	AttributeDesignator.setAttribute("MustBePresent", "true");
	       	AttributeDesignator.setAttribute("DataType", "http://www.w3.org/2001/XMLSchema#string");
	       	Match.appendChild(AttributeDesignator);
	       	allOf.appendChild(Match);       	
	       	anyOf.appendChild(allOf);
  	}
  	return anyOf;
   }

Converting Policy bindings for CA.SM::Real,  CA.SM::Response and CA.SM::UserPolicy objects

This portion is the most complex in the conversion because linkages have to be parsed out of the SiteMinder policy extract and rendered as separate OpenAM policies in XACML format. In order to convert a CA.SM::Policy object the program needs to follow the following algorithm at the very at least and in order:

  1. Establish the linkages between the CA.SM::Realm objects and the CA.SM::Response objects using the PolicyLink binder object
  2. Resolve the Response object, dynamic key-value pairs, by either directly reading the data from an external repository, or converting the references attributes to LDAP specific attributes
  3. Resolve the Subject Restrictions manifest in the PolicyLink.UserPolicy by converting the SQL Query to an LDAP search filter
  4. Create one OpenAM policy under the previously established Policy Set per Realm-Response-UserPolicy linkage

These steps are necessary in order to preserve the linkage of specific resource URI being accessible over the policy decision and returning specific response attributes.

Parsing out the bindings between CA.SM::Realm and CA.SM::Response objects

Since not all CA.SM::Realm objects in the SiteMinder policy extract refer to all the CA.SM::Response objects it becomes necessary to collect those objects that are bound together and dispatch them into one OpenAM policy. This is because OpenAM ties together a group of protected resource URI to a group of subject conditions, environment conditions and response attributes.

Resolving the Response object into static or dynamic OpenAM Response Attributes

A design decision here could be that the response attributes will be pulled from a user repository such as OpenDJ, making the CA.SM::ResponseAttr.Value definitions very easy to resolve. After parsing the definitions that usually are of the form:

CL_Header=<%userattr="<%userattr="CL_Cookie_Value"%>|UID=<%userattr="DEF_PROFILE_ID"%>|State=<%userattr="ST"%>|City=<%userattr="ADDR_CITY"%>|AddressLine1=<%userattr="ADDR1"%>|AddressLine2=<%userattr="ADDR2"%>|CompanyName=<%userattr="COMPANY"%>

One could construct the response objects one by one, with the display attribute (left of the “=” sign) as key and user profile attribute within quotes above, as the value. Simplistic string split and parsing techniques could be used to achieve this. The mapping of user profile attributes shown here could also be stored as key-value pairs in a metadata container in OpenDJ:

 

meta

Here, the connection information is stored as an LDAP url in description, admin username in sn and password (hidden) in givenName. The mapping of the user attributes is stored in cn. Using this information the program resolves the key-value pairs from the source repository to that of the target repository schema and the resulting key-value pairs are codified as OpenAM Response objects into XACML, as shown:

urn:sun:opensso:entitlement:json-resource-attribute:com.sun.identity.entitlement.UserAttributes:<attr-name>

Resolve the Subject Restrictions manifest in the PolicyLink.UserPolicy

Converting subject conditions derived from CA.SM::UserPolicy objects such as this one:

userpolicy

..would involve the same framework presented above, except this time we will create an LDAP search filter from the SQL Query- again assuming we are seeking data from an LDAP repository- to ensure the policy is only fired when the subject condition is satisfied.

The program can also provide support for directly retrieving user profile attributes – either for Subject Restrictions presented above in the form of LDAP filters, or for dynamically creating the Response key-value pairs in XACML. The metadata can have connection information stored as shown above that could be used to achieve this external lookup.

 

OpenIG on Docker: The Perfect Couple

This blog post was first published @ http://identityrocks.blogspot.fr/, included here with permission.

“Docker containers wrap a piece of software in a complete filesystem that contains everything needed to run […]” [1]


OpenIG (Open Identity Gateway) provides an elegant yet flexible way to integrate your applications, devices, APIs with modern identity standards such as token types, authentication and authorization. The gateway as your integration component can be deployed and scaled along the applications and services it secures.

Whilst organizations adopt containerization as part of a “well-oiled” delivery pipeline, which includes the gateway, OpenIG in a container is also very beneficial for evaluation purposes. Here’s how you can evaluate in just a couple of minutes.

As prerequisites, you need docker and git on your system.

  1. Checkout the ForgeRock docker project to retrieve the Dockerfile and sample OpenIG configuration files
  • git clone https://stash.forgerock.org/scm/docker/docker.git
  • cd docker/openig
  • Build the docker image
  • docker build -t forgerock/openig:latest .
  • Run the docker image and mount the sample-config directory from your local git copy in the container
  • docker run –detach -p 8080:8080 –volume <LOCAL_PATH_TO_GIT>/docker/openig/sample-config:/var/openig –name openig -it forgerock/openig
To test the sample configuration, point your client (e.g. web browser, curl) to http://localhost:8080/simplethrottle for instance. The response is determined by the StaticResponseHandler setting in the 20-simplethrottle.json file.
A simplified version of this procedure however without the sample configuration but not necessitating usage of git and clone the full repo goes as follows. This is well suited to evaluate the upcoming user interface.
  1. Download the Dockerfile from https://stash.forgerock.org/projects/DOCKER/repos/docker/browse/openig/Dockerfile
  2. Build the docker image (as above)
  • docker build -t forgerock/openig:latest .
  • Run the docker image
  • docker run -d -p 8080:8080 –name openig -it forgerock/openig
Other useful commands:
  • Start container: docker stop openig
  • Stop container: docker start openig
  • Get shell prompt: docker exec -i -t openig /bin/bash
  • Remove container: docker rm openig

References

[1]Package your application into a standardized unit for software development”. Retrieved from https://www.docker.com/what-docker on Sep 6th, 2016.

 

In flight Authorization Management

This blog post was first published @ identityrelationshipmanagement.blogspot.co.uk, included here with permission.

Access request, or authorization management is far from new.  The classic use case is the use of a workflow process that, via approval, updates a profile or account with a persisted attribute/group/permission in a target system.  At run time, when a user attempts to perform an action on the target system, the system locally checks the profile of the user and looks for particular attributes that have been persisted.

A slight variation on this theme, is to provide a mechanism to alter (or at least request to alter) the persisted permissions at near run time.  An example of this, is to leverage OAuth2 and use of a tokeninfo endpoint that can convert access_token scope data into scope values, that are used by resource server to handle local authorization.  Dependent on the content of the scope values, the resource server could provide a route for those persisted entries to be updated – aka an access request.

In the above example, we have a standard OAuth2 client-server relationship on the right hand side – it just so happens we’re also using the device flow pin and pair paradigm that is described here. Ultimately the TV application retrieves user data using OAuth2 – one of the attributes we send back to the TV, is an attribute called waterShedContent – this is a boolean value that governs whether the user can access post 9pm TV shows or not.  If the value is false, the TV player does not allow access – but does then provide a link into OpenIDM – which can trigger a workflow to request access.

Above flow goes something like this:

  1. User performs OAuth2 consent to allow the TV player access to certain profile attributes (0 is just the onboarding process for the TV via pin/pair for example)
  2. OpenAM retrieves static profile data such as the waterShedContent attribute and makes available via the ../tokeninfo end point accessible using the OAuth2 access_token
  3. Client interprets the data received from the ../tokeninfo endpoint to perform local authorization (if waterShedContent == true || false for example) providing a link into OpenIDM that can trigger an access request
  4. The BPMN workflow in IDM searches for an approver and assigns them a basic boolean gateway workflow – either allow or deny.  An allow triggers an openidm.patch that updates the necessary attribute that is then stored in OpenDJ
  5. The updated attribute is then made available via the ../tokeninfo endpoint again – perhaps via a refresh_token flow and the updated attribute is available in the client
Triggering a remote workflow (step 3) is pretty trivial – simply call /openidm/workflow/processinstance?_action=create with the necessary workflow you want to trigger.  To work out who to assign the workflow to, I leveraged the new relationship management feature of IDM and used the execution.setVariable(‘approver’, approver) function within the workflow.  The approver was simply an attribute within my initial user object that I set when I created my managed/object.

The code for the PoC-level TV-player with the necessary OAuth2 and workflow request code is available here.

Unlocking the Authorization Asset

This blog post was first published @ http://identityrocks.blogspot.fr/, included here with permission.

Consumer identity is a core asset to your business. Unlocking authorization and leveraging it into your business processes and (micro) services helps you in this endeavor as it drives a yet higher level of personalization and how users interact with resources and objects.

In a recent post titled “Authorization for Everything” I outlined how any resource or object can be described in ForgeRock’s identity platform authorization framework by the example of a home cinema.

But who’s going to setup the authorization objects and controls ?
(Question by an attendee of the ForgeRock Identity Summit in Düsseldorf)

User facing applications that operate or control devices or resources, like mobile applications or smart remote controls, are now enabled to call directly in the authorization framework to manage or evaluate permissions. This is also possible go via a hub to which an appliance like the home cinema would register when it is plugged in.

Smart authorization is now unlocked to any of these procedures, services and applications regardless of the platform. And the key is the REST API provided by the ForgeRock identity platform.

The key to drive authorization in the user experience or device management is the API !
Implement it where it creates most value for the consumer.
(My answer)

In full detail now how to manage and evaluate authorization elements via REST by the example of a home cinema.

Authorization Management via REST in detail
Step 1: Creating a resource type TV

First we create a resource type TV and specify the format of how to address the resource (e.g. tv://myhouse/homecinema) and possible actions for the resource.

Request:
curl -s –request POST –header “Content-Type: application/json” –data @request.json https://sso.redstone.com:443/sso/json/authzrealm/resourcetypes?_action=create&_prettyPrint=true
Request (JSON):
{
“patterns”: [
“tv://*/*”
],
“name”: “tv”,
“actions”: {
“ENABLE”: true,
“DISABLE”: true,
“BROADCAST SCREEN”: true,
“BROADCAST CAMERA”: true
}
}
Response (JSON):
{
“uuid” : “9fefc18f-5731-4963-a8d6-fa8aba7923d4”,
“name” : “tv”,
“description” : null,
“patterns” : [ “tv://*/*” ],
“actions” : {
“DISABLE” : true,
“ENABLE” : true,
“BROADCAST CAMERA” : true,
“BROADCAST SCREEN” : true
},
“createdBy” : “id=amadmin,ou=user,dc=sso-config,dc=com”,
“creationDate” : 1447989190178,
“lastModifiedBy” : “id=amadmin,ou=user,dc=sso-config,dc=com”,
“lastModifiedDate” : 1447989190178
}
Note the resource type’s UUID in the response. This value is needed later to assign a resource type to a policy.


Step 2: Creating the policy set (or application)

Next the resource set (or application) needs to be created with the resourceTypeUUID containing the one of resource type TV.

Request:
curl -s –request POST –header “Content-Type: application/json” –data @request.json https://sso.redstone.com:443/sso/json/authzrealm/applications?_action=create&_prettyPrint=true
Request (JSON):
{    “name” : “SmartHome”,
“applicationType” : “iPlanetAMWebAgentService”,
“description” : “Controlling objects in a smart home.”,
“resourceTypeUuids” : [ “9fefc18f-5731-4963-a8d6-fa8aba7923d4”],
“subjects” : [ “Policy”, “NOT”, “OR”, “JwtClaim”, “AuthenticatedUsers”, “AND”, “Identity”, “NONE” ],
“entitlementCombiner” : “DenyOverride”,
“saveIndex” : null,
“searchIndex” : null,
“resourceComparator” : null,
“attributeNames” : [ ],
“editable” : true,
“conditions” : [ “LEAuthLevel”, “Policy”, “Script”, “AuthenticateToService”, “SimpleTime”, “AMIdentityMembership”, “OR”, “IPv6”, “IPv4”, “SessionProperty”, “AuthScheme”, “AuthLevel”, “NOT”, “AuthenticateToRealm”, “AND”, “ResourceEnvIP”, “LDAPFilter”, “OAuth2Scope”, “Session” ]
}
Response (JSON):
{
“lastModifiedBy” : “id=amadmin,ou=user,dc=sso-config,dc=com” ],
“lastModifiedDate” : 1447989192860,
“creationDate” : 1447989192860,
“createdBy” : “id=amadmin,ou=user,dc=sso-config,dc=com”,
“applicationType” : “iPlanetAMWebAgentService”,
“subjects” : [ “Policy”, “NOT”, “OR”, “JwtClaim”, “AuthenticatedUsers”, “AND”, “Identity”, “NONE” ],
“entitlementCombiner” : “DenyOverride”,
“saveIndex” : null,
“searchIndex” : null,
“resourceComparator” : null,
“attributeNames” : [ ],
“editable” : true,
“conditions” : [ “LEAuthLevel”, “Policy”, “Script”, “AuthenticateToService”, “SimpleTime”, “AMIdentityMembership”, “OR”, “IPv6”, “IPv4”, “SessionProperty”, “AuthScheme”, “AuthLevel”, “NOT”, “AuthenticateToRealm”, “AND”, “ResourceEnvIP”, “LDAPFilter”, “OAuth2Scope”, “Session” ],
“description” : “Controlling objects in a smart home.”,
“name” : “SmartHome”
}
Step 3: Creating the policy giving permissions to Bob

Next the resource set (or application) needs to be created with the resourceTypeUUID containing the one of resource type TV.

Request:
curl -s –request POST –header “Content-Type: application/json” –data @request.json https://sso.redstone.com:443/sso/json/authzrealm/policies?_action=create&_prettyPrint=true
Request (JSON):
{
“name” : “HomeCinema”,
“active” : true,
“description” : “”,
“applicationName” : “SmartHome”,
“actionValues” : {
“ENABLE” : true,
“DISABLE” : true,
“BROADCAST SCREEN” : true,
“BROADCAST CAMERA” : true
},
“resources” : [ “tv://myhouse/homecinema” ],
“subject” : {
“type” : “Identity”,
“subjectValues” : [ “id=bob,ou=user,o=authzrealm,ou=services,dc=sso-config,dc=com” ]
},
“resourceTypeUuid” : “9fefc18f-5731-4963-a8d6-fa8aba7923d4”
}
Response (JSON):
{
“name” : “HomeCinema”,
“active” : true,
“description” : “”,
“applicationName” : “SmartHome”,
“actionValues” : {
“DISABLE” : true,
“ENABLE” : true,
“BROADCAST CAMERA” : true,
“BROADCAST SCREEN” : true
},
“resources” : [ “tv://myhouse/homecinema” ],
“subject” : {
“type” : “Identity”,
“subjectValues” : [ “id=bob,ou=user,o=authzrealm,ou=services,dc=sso-config,dc=com” ]
},
“resourceTypeUuid” : “9fefc18f-5731-4963-a8d6-fa8aba7923d4”,
“lastModifiedBy” : “id=amadmin,ou=user,dc=sso-config,dc=com”,
“lastModifiedDate” : “2015-11-20T03:13:14.274Z”,
“createdBy” : “id=amadmin,ou=user,dc=sso-config,dc=com”,
“creationDate” : “2015-11-20T03:13:14.274Z”
}
Step 4: Evaluating the policy for user Bob

Next the resource set (or application) needs to be created with the resourceTypeUUID containing the one of resource type TV. For completeness – the procedure is already outlined in “Authorization for Everything” – here’s how an upstream application would evaluate if Bob can broadcast the screen (or any other action). 

Request URL:

https://sso.redstone.com:443/sso/json/authzrealm/policies?_action=evaluateTree&_prettyPrint=true

Request (JSON):
{
“application”: “SmartHome”,
“resource”: “tv://myhouse/homecinema”,
“subject”: {
“ssoToken”: “AQIC5wM2LY4SfcxbXJgKBtBsbzH0OtxslnEQDHK2RJ5UJho.*AAJTSQACMDIAAlNLABQtOTIwMDUyMDgxMTA2Mzk1NjIzMgACUzEAAjAx*”
}
}
Response (JSON):
[ {
“advices” : { },
“ttl” : 9223372036854775807,
“resource” : “tv://myhouse/homecinema”,
“actions” : {
“DISABLE” : true,
“ENABLE” : true,
“BROADCAST CAMERA” : true,
“BROADCAST SCREEN” : true
},
“attributes” : { }
} ]

If you want to go further, look at the details of policy creation via REST, policy evaluation or maybe even reproduce my demo at the Identity Summit in Düsseldorf, check the openam-high5 GitHub project. In particular the 652-authz-create-policy and 654-authz-evaluate-policy-tv.

 

Authorization for Everything

This blog post was first published @ http://identityrocks.blogspot.fr/, included here with permission.

Smart contextual & conditional authorization lowers barriers enabling friction-less user on-boarding, more intuitive user journeys and ultimately increases your return on identity, right at the heart of your digital transformation strategy.
Moving beyond web and mobile application security, for any object, any action, any context, authorization shall be described. It’s ForgeRock’s identity platform that does provide you the framework. It provides you Authorization for Everything.

The model, principals and functionality can be applied to any business, so as an example, I describe authorization for an “ordinary” object, a family household. It is composed of the family members and family members and household appliances. Bob stores wine in his wine cabinet, not only for consumption, but also for investments. Inventory is thus a crucial as Bob wants to know the current value of his investments. Other “critical” resources are the screens. For the home cinema, we can image specific actions like turn on and off as well as broadcasting screen or camera. Not all family member should have the same permissions to these resources.

  

Authorization Management

The HomeCinema policy contains resources, actions, subjects and conditions. The whole Smith family is allowed to turn on and off the home cinema between 16h00 and 19h00. Bob should add a policy that allows him to operate the home cinema after 19h00 and broadcast the camera with his remote friends when football is on. Here’s how it looks in the OpenAM administration interface :

Any kind of resource with any kind of action can be described in the authorization framework, be it real estate, contracts, online media, etc. It a later post I shall describe how this can be done via API (REST), so that policy creation could be part of the resource or device registration process handled by application above the identity platform.

 

Policy Evaluation

Policy evaluation for a given resource and subject can be done via API. The policy enforcement point (which could be the home cinema itself but also a mobile app) requests a policy decision via REST. The user must be authenticated in some form prior to this request. The user’s SSO token is then added to the policy evaluation request.
Request URL:
https://sso.redstone.com:443/sso/json/authzrealm/policies?_action=evaluateTree&_prettyPrint=true
Request:

{
“application”: “SmartHome”,
“resource”: “tv://myhouse/homecinema”,
“subject”: {
“ssoToken”: “AQIC5wM2LY4Sfcw5j9MI_A6GO7s58XGwY7yTAuEeP4RJcvM.*AAJTSQACMDIAAlNLABQtOTAyNzM0MDcxNzQ3NDU3MTE4MAACUzEAAjAx*”
}
}

Response:

[ {
“advices” : { },
“ttl” : 9223372036854775807,
“resource” : “tv://myhouse/homecinema”,
“actions” : {
“DISABLE” : true,
“ENABLE” : true,
“BROADCAST CAMERA” : false,
“BROADCAST SCREEN” : false
},
“attributes” : { }
} ]
The user is only allow to turn the home cinema on and off, not to broadcast screen or camera. Any objects, actions, subjects, context and conditions can be described in the identity platform. Unlocking the authorization asset on top of your customer view enables an even more personalized experience.

If you want to look at the details of the policy evaluation request and how it fits in the authorization framework, check the openam-high5 GitHub project. In particular the 654-authz-evaluate-policy-tv or 655-authz-evaluate-policy-door  scripts.

REST on every side

This blog post was first published @ http://identityrocks.blogspot.fr/, included here with permission.

Regardless if web application, mobile application, device application or thing application development – identity management is there for you. Be it internal or external. The fast way in is REST. ForgeRock’s identity management platform delivers through REST. I’ll illustrate by example authentication via REST against a complex authentication chain.

“Representational State Transfer (REST) is a software architecture style for building scalable web services.” [1] [2]

The Authentication Chain
OpenAM’s authentication service can be composed of multiple authentication modules. The authentication chain consists 4 authentication modules including LDAP and device fingerprint. The relevance of such a chain was discussed in a previous article titled “Smarter Security with Device Fingerprints”.
For the purpose of simplicity, the OneTimePassword is replaced with a DataStore authentication module. Rather than providing a one time password (e.g. SMS passcode), the user has to provide username and password (same or different than before depending on the OpenAM configuration).
As there is no browser involved, any json structure can be sent back as the fingerprint.
The authentication process consists of 6 steps if no corresponding and valid device fingerprint was previously registered. In case it was, the authentication finishes after step 3.

The Tools: CURL, JQ and the Scripts
As client in this example serves the straightforward curl tool. This allows easy investigation of requests and responses.
Note that the JWT (JSON Web Token) needs to be passed on between all callbacks. For extracting specific elements of json, like the JWT, the jq tool can be of great use (for instance JWT_TOKEN=`echo ${CURL_RESPONSE} | jq –raw-output ‘.authId’`).
In case you want to build this example or something similar, I published in a GitHub project  scripts which could be of inspiration (see in particular 620-deviceid-base-config, 621-deviceid-rest-base, 622-deviceid-rest-ootb).

The Authentication Steps in Detail [3]
Step 1: Get the authentication token
An “empty” request is sent to obtain the JWT (JSON Web Token) and the first set of callbacks.

Request
curl -s –request POST –header “Content-Type: application/json” https://sso.yellowstone.com:443/sso/json/authenticate?realm=/deviceidrealm
Response

{
  "authId": "eyAidHlwIjogIkpXVCIsICJhbGciOiAiSFMyNTYiIH0.eyAib3RrIjogImdvbGhwOHFrNDVtbTI5cm91YWpyOHI2b2dkIiwgInJlYWxtIjogIm89ZGV2aWNlaWRyZWFsbSxvdT1zZXJ2aWNlcyxkYz1zc28tY29uZmlnLGRjPWNvbSIsICJzZXNzaW9uSWQiOiAiQVFJQzV3TTJMWTRTZmN5dDJ5VTFoc3J1OHZNZkhzVW1hMjd1QjA0S3YtQk5iZEUuKkFBSlRTUUFDTURJQUFsTkxBQk10TlRrek9UQXlOek0yTURJME1EZ3lNakkyQUFKVE1RQUNNREUuKiIgfQ.ZQGuCe3qDUEchsxcDCLdRU73g1i-isUAZDdp5ZOvVdM",
  "template": "",
  "stage": "LDAP1",
  "header": "Sign in to OpenAM",
  "callbacks": [
    {
      "type": "NameCallback",
      "output": [
        {
          "name": "prompt",
          "value": "User Name:"
        }
      ],
      "input": [
        {
          "name": "IDToken1",
          "value": ""
        }
      ]
    },
    {
      "type": "PasswordCallback",
      "output": [
        {
          "name": "prompt",
          "value": "Password:"
        }
      ],
      "input": [
        {
          "name": "IDToken2",
          "value": ""
        }
      ]
    }
  ]
}

Step 2: Provide callbacks for LDAP module
The JWT is passed with any subsequent request in this authentication process. Username and password are passed as required by the LDAP authentication module’s callback.

Request
curl -s –request POST –header “Content-Type: application/json” –data @callback-step2.json https://sso.yellowstone.com:443/sso/json/authenticate?realm=/deviceidrealm
callback-step2.json :

{
  "authId": "eyAidHlwIjogIkpXVCIsICJhbGciOiAiSFMyNTYiIH0.eyAib3RrIjogImdvbGhwOHFrNDVtbTI5cm91YWpyOHI2b2dkIiwgInJlYWxtIjogIm89ZGV2aWNlaWRyZWFsbSxvdT1zZXJ2aWNlcyxkYz1zc28tY29uZmlnLGRjPWNvbSIsICJzZXNzaW9uSWQiOiAiQVFJQzV3TTJMWTRTZmN5dDJ5VTFoc3J1OHZNZkhzVW1hMjd1QjA0S3YtQk5iZEUuKkFBSlRTUUFDTURJQUFsTkxBQk10TlRrek9UQXlOek0yTURJME1EZ3lNakkyQUFKVE1RQUNNREUuKiIgfQ.ZQGuCe3qDUEchsxcDCLdRU73g1i-isUAZDdp5ZOvVdM",
  "template": "",
  "stage": "LDAP1",
  "callbacks": [
    {
      "type": "NameCallback",
      "output": [
        {
          "name": "prompt",
          "value": " User Name: "
        }
      ],
      "input": [
        {
          "name": "IDToken1",
          "value": "demo"
        }
      ]
    },
    {
      "type": "PasswordCallback",
      "output": [
        {
          "name": "prompt",
          "value": " Password: "
        }
      ],
      "input": [
        {
          "name": "IDToken2",
          "value": "changeit"
        }
      ]
    }
  ]
}

Response
After successful LDAP authentication, the JavaScript which computes the fingerprint is sent in the TextOutputCallback.

{
  "authId": "eyAidHlwIjogIkpXVCIsICJhbGciOiAiSFMyNTYiIH0.eyAib3RrIjogImdvbGhwOHFrNDVtbTI5cm91YWpyOHI2b2dkIiwgInJlYWxtIjogIm89ZGV2aWNlaWRyZWFsbSxvdT1zZXJ2aWNlcyxkYz1zc28tY29uZmlnLGRjPWNvbSIsICJzZXNzaW9uSWQiOiAiQVFJQzV3TTJMWTRTZmN5dDJ5VTFoc3J1OHZNZkhzVW1hMjd1QjA0S3YtQk5iZEUuKkFBSlRTUUFDTURJQUFsTkxBQk10TlRrek9UQXlOek0yTURJME1EZ3lNakkyQUFKVE1RQUNNREUuKiIgfQ.ZQGuCe3qDUEchsxcDCLdRU73g1i-isUAZDdp5ZOvVdM",
  "template": "",
  "stage": "DeviceIdMatch2",
  "header": "Sign in to OpenAM",
  "callbacks": [
    {
      "type": "HiddenValueCallback",
      "output": [
        {
          "name": "value",
          "value": ""
        }
      ],
      "input": [
        {
          "name": "IDToken1",
          "value": "clientScriptOutputData"
        }
      ]
    },
    {
      "type": "TextOutputCallback",
      "output": [
        {
          "name": "message",
          "value": "JAVASCRIPT TO BE EXECUTED IN THE CLIENT BROWSER. OMITTED FOR READABILITY"
        },
        {
          "name": "messageType",
          "value": "4"
        }
      ]
    }
  ]
}

Step 3: Provide callbacks for DeviceId (Match) module
The fingerprint is sent back to the authentication process through the HiddenValueCallback. As there is no browser involved, any json element can be sent in. Note that the value element is of type String and the String contains the json. So properly encode the json (i.e. escape double quotes).

Request
curl -s –request POST –header “Content-Type: application/json” –data @callback-step3.json https://sso.yellowstone.com:443/sso/json/authenticate?realm=/deviceidrealmcallback-step3.json :

{
  "authId": "eyAidHlwIjogIkpXVCIsICJhbGciOiAiSFMyNTYiIH0.eyAib3RrIjogImdvbGhwOHFrNDVtbTI5cm91YWpyOHI2b2dkIiwgInJlYWxtIjogIm89ZGV2aWNlaWRyZWFsbSxvdT1zZXJ2aWNlcyxkYz1zc28tY29uZmlnLGRjPWNvbSIsICJzZXNzaW9uSWQiOiAiQVFJQzV3TTJMWTRTZmN5dDJ5VTFoc3J1OHZNZkhzVW1hMjd1QjA0S3YtQk5iZEUuKkFBSlRTUUFDTURJQUFsTkxBQk10TlRrek9UQXlOek0yTURJME1EZ3lNakkyQUFKVE1RQUNNREUuKiIgfQ.ZQGuCe3qDUEchsxcDCLdRU73g1i-isUAZDdp5ZOvVdM",
  "template": "",
  "stage": "DeviceIdMatch2",
  "callbacks": [
    {
      "type": "HiddenValueCallback",
      "input": [
        {
          "name": "IDToken1",
          "value": "THE FINGERPRINT GATHERED "
        }
      ]
    },
    {
      "type": "TextOutputCallback",
      "output": [
        {
          "name": "messageType",
          "value": "4"
        }
      ]
    }
  ]
}
Response

If the fingerprint corresponds to a registered fingerprint, then the authentication process would return successfully at this point. Otherwise (in this case), a second factor is required (DataStore module).

{
  "authId": "eyAidHlwIjogIkpXVCIsICJhbGciOiAiSFMyNTYiIH0.eyAib3RrIjogImdvbGhwOHFrNDVtbTI5cm91YWpyOHI2b2dkIiwgInJlYWxtIjogIm89ZGV2aWNlaWRyZWFsbSxvdT1zZXJ2aWNlcyxkYz1zc28tY29uZmlnLGRjPWNvbSIsICJzZXNzaW9uSWQiOiAiQVFJQzV3TTJMWTRTZmN5dDJ5VTFoc3J1OHZNZkhzVW1hMjd1QjA0S3YtQk5iZEUuKkFBSlRTUUFDTURJQUFsTkxBQk10TlRrek9UQXlOek0yTURJME1EZ3lNakkyQUFKVE1RQUNNREUuKiIgfQ.ZQGuCe3qDUEchsxcDCLdRU73g1i-isUAZDdp5ZOvVdM",
  "template": "",
  "stage": "DataStore1",
  "header": "Sign in to OpenAM",
  "callbacks": [
    {
      "type": "NameCallback",
      "output": [
        {
          "name": "prompt",
          "value": "User Name:"
        }
      ],
      "input": [
        {
          "name": "IDToken1",
          "value": ""
        }
      ]
    },
    {
      "type": "PasswordCallback",
      "output": [
        {
          "name": "prompt",
          "value": "Password:"
        }
      ],
      "input": [
        {
          "name": "IDToken2",
          "value": ""
        }
      ]
    }
  ]
}

Step 4: Provide callbacks for DataStore module
Request
curl -s –request POST –header “Content-Type: application/json” –data @callback-step4.json https://sso.yellowstone.com:443/sso/json/authenticate?realm=/deviceidrealm

callback-step4.json :

{
  "authId": "eyAidHlwIjogIkpXVCIsICJhbGciOiAiSFMyNTYiIH0.eyAib3RrIjogImdvbGhwOHFrNDVtbTI5cm91YWpyOHI2b2dkIiwgInJlYWxtIjogIm89ZGV2aWNlaWRyZWFsbSxvdT1zZXJ2aWNlcyxkYz1zc28tY29uZmlnLGRjPWNvbSIsICJzZXNzaW9uSWQiOiAiQVFJQzV3TTJMWTRTZmN5dDJ5VTFoc3J1OHZNZkhzVW1hMjd1QjA0S3YtQk5iZEUuKkFBSlRTUUFDTURJQUFsTkxBQk10TlRrek9UQXlOek0yTURJME1EZ3lNakkyQUFKVE1RQUNNREUuKiIgfQ.ZQGuCe3qDUEchsxcDCLdRU73g1i-isUAZDdp5ZOvVdM",
  "template": "",
  "stage": "DataStore1",
  "callbacks": [
    {
      "type": "NameCallback",
      "output": [
        {
          "name": "prompt",
          "value": " User Name: "
        }
      ],
      "input": [
        {
          "name": "IDToken1",
          "value": "demo"
        }
      ]
    },
    {
      "type": "PasswordCallback",
      "output": [
        {
          "name": "prompt",
          "value": " Password: "
        }
      ],
      "input": [
        {
          "name": "IDToken2",
          "value": "changeit"
        }
      ]
    }
  ]
}
Response 

Now that both factors succeeded, the user is asked whether to store the device fingerprint or not.

{
  "authId": "eyAidHlwIjogIkpXVCIsICJhbGciOiAiSFMyNTYiIH0.eyAib3RrIjogImdvbGhwOHFrNDVtbTI5cm91YWpyOHI2b2dkIiwgInJlYWxtIjogIm89ZGV2aWNlaWRyZWFsbSxvdT1zZXJ2aWNlcyxkYz1zc28tY29uZmlnLGRjPWNvbSIsICJzZXNzaW9uSWQiOiAiQVFJQzV3TTJMWTRTZmN5dDJ5VTFoc3J1OHZNZkhzVW1hMjd1QjA0S3YtQk5iZEUuKkFBSlRTUUFDTURJQUFsTkxBQk10TlRrek9UQXlOek0yTURJME1EZ3lNakkyQUFKVE1RQUNNREUuKiIgfQ.ZQGuCe3qDUEchsxcDCLdRU73g1i-isUAZDdp5ZOvVdM",
  "template": "",
  "stage": "DeviceIdSave2",
  "header": "Add to Trusted Devices",
  "callbacks": [
    {
      "type": "ChoiceCallback",
      "output": [
        {
          "name": "prompt",
          "value": "Add to Trusted Devices?"
        },
        {
          "name": "choices",
          "value": [
            "Yes",
            "No"
          ]
        },
        {
          "name": "defaultChoice",
          "value": 1
        }
      ],
      "input": [
        {
          "name": "IDToken1",
          "value": 1
        }
      ]
    }
  ]
} 

Step 5: Provide callbacks for DeviceId (Save) module – Consent to store device profile
The value 0 in the ChoiceCallback indicates that the user want to store the device fingerprint with his profile.

Request
curl -s –request POST –header “Content-Type: application/json” –data @callback-step5.json https://sso.yellowstone.com:443/sso/json/authenticate?realm=/deviceidrealm 
callback-step5.json :

{
  "authId": "eyAidHlwIjogIkpXVCIsICJhbGciOiAiSFMyNTYiIH0.eyAib3RrIjogImdvbGhwOHFrNDVtbTI5cm91YWpyOHI2b2dkIiwgInJlYWxtIjogIm89ZGV2aWNlaWRyZWFsbSxvdT1zZXJ2aWNlcyxkYz1zc28tY29uZmlnLGRjPWNvbSIsICJzZXNzaW9uSWQiOiAiQVFJQzV3TTJMWTRTZmN5dDJ5VTFoc3J1OHZNZkhzVW1hMjd1QjA0S3YtQk5iZEUuKkFBSlRTUUFDTURJQUFsTkxBQk10TlRrek9UQXlOek0yTURJME1EZ3lNakkyQUFKVE1RQUNNREUuKiIgfQ.ZQGuCe3qDUEchsxcDCLdRU73g1i-isUAZDdp5ZOvVdM",
  "template": "",
  "stage": "DeviceSave2",
  "callbacks": [
    {
      "type": "ChoiceCallback",
      "input": [
        {
          "name": "IDToken1",
          "value": "0"
        }
      ]
    }
  ]
}
Response

Then the user is prompted to provide a name under which the new profile shall be stored.

{
  "authId": "eyAidHlwIjogIkpXVCIsICJhbGciOiAiSFMyNTYiIH0.eyAib3RrIjogImdvbGhwOHFrNDVtbTI5cm91YWpyOHI2b2dkIiwgInJlYWxtIjogIm89ZGV2aWNlaWRyZWFsbSxvdT1zZXJ2aWNlcyxkYz1zc28tY29uZmlnLGRjPWNvbSIsICJzZXNzaW9uSWQiOiAiQVFJQzV3TTJMWTRTZmN5dDJ5VTFoc3J1OHZNZkhzVW1hMjd1QjA0S3YtQk5iZEUuKkFBSlRTUUFDTURJQUFsTkxBQk10TlRrek9UQXlOek0yTURJME1EZ3lNakkyQUFKVE1RQUNNREUuKiIgfQ.ZQGuCe3qDUEchsxcDCLdRU73g1i-isUAZDdp5ZOvVdM",
  "template": "",
  "stage": "DeviceIdSave3",
  "header": "Trusted Device Name",
  "callbacks": [
    {
      "type": "NameCallback",
      "output": [
        {
          "name": "prompt",
          "value": "Trusted Device Name?"
        }
      ],
      "input": [
        {
          "name": "IDToken1",
          "value": ""
        }
      ]
    }
  ]
}

Step 6: Provide callbacks for DeviceId (Save) module – Device profile name
Then If an empty Then If an empty v is provided as the device name, the authentication module will compute one which looks like “Profile: 21/08/2015 15:51”.
Request
curl -s –request POST –header “Content-Type: application/json” –data @callback-step6.json https://sso.yellowstone.com:443/sso/json/authenticate?realm=/deviceidrealm 
callback-step6.json :

{
  "authId": "eyAidHlwIjogIkpXVCIsICJhbGciOiAiSFMyNTYiIH0.eyAib3RrIjogImdvbGhwOHFrNDVtbTI5cm91YWpyOHI2b2dkIiwgInJlYWxtIjogIm89ZGV2aWNlaWRyZWFsbSxvdT1zZXJ2aWNlcyxkYz1zc28tY29uZmlnLGRjPWNvbSIsICJzZXNzaW9uSWQiOiAiQVFJQzV3TTJMWTRTZmN5dDJ5VTFoc3J1OHZNZkhzVW1hMjd1QjA0S3YtQk5iZEUuKkFBSlRTUUFDTURJQUFsTkxBQk10TlRrek9UQXlOek0yTURJME1EZ3lNakkyQUFKVE1RQUNNREUuKiIgfQ.ZQGuCe3qDUEchsxcDCLdRU73g1i-isUAZDdp5ZOvVdM",
  "template": "",
  "stage": "DeviceIdSave3",
  "callbacks": [
    {
      "type": "NameCallback",
      "input": [
        {
          "name": "IDToken1",
          "value": ""
        }
      ]
    }
  ]
} 
Response
Now the response contains an SSOToken. This means the authentication was successful.
{
  "tokenId": "AQIC5wM2LY4SfczOURj5zOskLzpSNfuSU9GYnW5XTu8Tudg.*AAJTSQACMDIAAlNLABM2OTIyMTc1MTIwOTUxMTA2NTcxAAJTMQACMDE.*",
  "successUrl": "/sso/console"
}

“And the LORD gave them rest on every side”. Joshua 21:44 [4]

 

References

[1] Pautasso, Cesare; Wilde, Erik; Alarcon, Rosa (2014), REST: Advanced Research Topics and Practical Applications
[2] Wikipedia contributors. “Representational state transfer.” Wikipedia, The Free Encyclopedia. Wikipedia, The Free Encyclopedia, 1 Sep. 2015. Web. 1 Sep. 2015.
[3] Craig, Mark; Goldsmith, David; Hirayama, Gene: Lee, Chris, et al. OpenAM Developer’s Guide Version 13.0.0-SNAPSHOT. ForgeRock, AS., 2015. <http://openam.forgerock.org/openam-documentation/openam-doc-source/doc/webhelp/dev-guide/rest-api-auth-json.html>
[4] The Holy Bible, New International Version, NIV Copyright 1973, 1978, 1984, 2011 by Biblica