Wednesday, 25 November 2015

Unlocking the Authorization Asset

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.





Friday, 13 November 2015

Authorization for Everything


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.


Tuesday, 6 October 2015

Device Fingerprints for Mobile Applications

Browser fingerprints play a useful role to make security more convenient (refer to
"Smarter Security with Device Fingerprints"). The concept can be extended to any device, especially non-browser clients.

The client (mobile application for example) itself collects and includes fingerprint information in the authentication request. The authentication server (OpenAM) matches and eventually saves the device fingerprint as it would do with the browser fingerprint.

Device Fingerprints in the Authentication Process

A custom device fingerprint can be as simple as the following :
{
  "telephoneNumber": "+33123456789"
}
Based on the authentication process in the aforementioned article, the DeviceId (Match) authentication module gets adapted to include a function for telephone number match. See the openam-telephonenumber-deviceprint-serverscript.js file for inspiration. OpenAM supports the full authentication process via REST. Refer to "REST on every side" for the detailed steps.
Note that the out-of-the-box DeviceId (Save) authentication module can be used "as-is" for for privacy and consent.

Based on that, the device fingerprint can take any form, be signed or encrypted, as long as the corresponding DeviceId (Match) module can appropriately compare with stored fingerprints.[1]


In case you want to build this example or something similar, I published scripts for the purpose of inspiration within the openam-high5 GitHub project, in particular 630-custom-deviceprint-base-config, 631-deviceid-rest-telephonenumber.

References

[1] Die drei Fragezeichen, Fingerabdrücke, Kosmos, 2010





Friday, 25 September 2015

REST on every side

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=/deviceidrealm callback-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