Articles

Open ID Connect: Sharing identity information with Applications

Share this post:

Open ID Connect: Sharing identity information with Applications

When developing modern web applications, information about the user is essential for providing a rich user experience. There are many ways in which this identity information is gathered. Applications may source user data many different ways. They may simply request the user supply user profile information on signup, but more commonly social providers and pre-existing identities can bootstrap the process. From a technical perspective, this is authenticating to a service via federated single sign on(SSO).

The identity provider supplies information in an assertion to the application. These pieces of information provided by the identity provider(IDP) are called claims and are usually presented in a verifiable form. In SAML this is a signed XML Assertion, and in OpenID Connect this is an id_token, a signed JSON Web Token(JWT).

This article focuses on OpenID Connect, and the different ways with which ISAM can provide id_token claims as an OP.

At this point I’ll take a moment to mention that OpenID Connect has another way of retrieving identity claims, through the userinfo endpoint but it is not the focus of this article.

 

Taking a look at an id_token

Before we go too far into ISAM, let us take a look at an id_token.

Unlike an access token, an id_token has a well defined format, its a JWT with some specific claim and signing requirements.

An example JWT(which by definition is base64URL encoded):

eyJraWQiOiJyTlBWOWM0U0RVVlp6bVhkSVE3Nk5qckprSGtmZ0Z2ajBHN2RadTBEN3VJIiwiYWxnIjoiUlMyNTYifQ.
eyJub25jZSI6IjI5OTgwIiwiZW1haWwiOiJ0ZXN0dXNlckBteWlkcC5pYm0uY29tIiwiaWF0IjoxNTQxMTM4MjcwLCJpc3M
iOiJodHRwczovL3d3dy5teWlkcC5pYm0uY29tIiwic3ViIjoidGVzdHVzZXIiLCJleHAiOjE1NDExNDE4NzAsImF1ZCI6Im
15dGVzdENsaWVudCJ9.mEBrNXtdHMHGx1yO8fWJfCSnG_wmXuCLZ1djD2LNdfJR34dsHuYn4lhRmYZQUwpaqFP6IRzGmouZ
HHU27__jR0rtAOXKmidAgnNV7aNWLxArtqHaOul2Dkjm0JPYGdTyXiqDK-G-bylUQSaMn4UyQ335b6z3480Y90w4l0y0JLu
GZkmWAZTh06vkfwGnXnrC34kORO0A35FxQd8_4gBfil12Z_TNwcVQu5aP6-muJb29nzVX0Q8H5HcjSN-G1nPMQd2Z1jAzG2
lwTJnx7CC8kvVTU8-P7iFjXOpqGimARihrY7E6gGb93xJ_0_WEDEBixrBDp8-oTRRNjJJ0bWdVEw

This JWT is made up of 3 components:

  • A header
  • A body
  • A signature.

The JWT header contains details about how the JWT was signed. The JWT body contains the claims which the relying party is interested in and the signature is binary. All 3 portions are base64URL encoded, and the decoded format of the first two parts are JSON. id_tokens can also be encrypted, but that is outside the scope of this piece.

The portion of the JWT which we’re most interested in is the body, which has been decoded and formatted below:

{
  "nonce": "29980",
  "email": "testuser@myidp.ibm.com",
  "iat": 1541138270,
  "iss": "https://www.myidp.ibm.com",
  "sub": "testuser",
  "exp": 1541141870,
  "aud": "mytestClient"
}

Most of these claims are part of the OpenID Connect protocol. There are two which we will focus on:

subthis is the subject claim, this is a unique to the OP value representing the user identity which has been received. On ISAM the sub claim will be the username which was used to authenticate at the OP. If a relying party is consuming identities from multiple OPs, the sub and iss claim can be combined for a globally unique identifier.

email – this is identity information which has been provided by the OP, which in this instance is the email address of the user.

OpenID Connect defines a set of default claims, however it is up the the OP to decided which claims it will include, as well as any additional claims which it wishes to provide.

Requesting claims

The OpenID Connect protocol provides to methods by which a relying party can request claims from the OP. These methods are the scope and claims parameters.

Scope – The usage of the scope parameter is not exclusive to requesting claims. Scope can be used for other purposes but in the context of OpenID Connect the scopes profile, address, phone, and email are well defined. When the email scope is included it indicates to an OP that the relying party is requesting the users email address. The profile scope is used to request basic profile information, such as first name, last name, birth date and gender and the address and phone scopes are for requesting the claims of the same name. These scopes function the same as any other scope when requested, a user must consent to them.

The claims parameter allows the relying party to request individual claims, and to indicate if the claim MUST be returned. The claims parameter is a JSON body. For example(Some formatting has been added for readability):

claims = 
{
  "id_token": {
    "email": {
      "essential": true
    }
  }
}

Claims can also be used to request information be returned from the userinfo endpoint.

 

Claims on ISAM

Out of the box, ISAM supports mapping claims using attribute sources. An attribute source provides a single attribute value sourced from one of three backend stores, a static value, an LDAP, or a users credential as created when their user session was established. The source for credential attributes is varied, there is the reverse proxies – TAM attribute service  or the values can be populated by an EAI login. All attribute sources are treated the same if the attribute provided by the attribute source is required then the source is evaluated for a value. The request processing on ISAM takes the claim and scope parameters, builds a list of claim values which are needed and calls any available attribute source to get a value for the required claim. The attributes retrieved from attribute sources are added to the STSUU, prior to the pre-token mapping rule being ran, as well as prior to the id_token being produced.

The pre-token mapping rule is responsible for tagging all attributes as values to go into id_token claims. This means the pre-token rule has ultimate control over the claims of the id_token, as well as allowing alternatives to attribute sources for populating id_token claims. Things like a HTTP callout, STS chain, or the UserLookupHelper can be used to retrieve values to populate id_token claims. When using these methods all the configuration resides in JavaScript, and no attribute sources must be configured.

To manipulate claims in the pre-token mapping rule you can use the following:

Get a list of claim names which have been requested with these calls:

stsuu.getContextAttributes().getAttributesByType("urn:ibm:names:ITFIM:oidc:claim:voluntary");
stsuu.getContextAttributes().getAttributesByType("urn:ibm:names:ITFIM:oidc:claim:essential");

Note: The type is what identifies these attributes.

Claim names which have been explicitly requested using the claims parameter with essential set to true will be in the 2nd call. All other claims which have been requested via scope, or the claims parameter where essential was not set to true will be in the voluntary list. The return value of these calls is an array of attributes, where the name of the attribute is the claim name.

When using attribute sources, the claim values will be present in the stsuu attribute list. The names will have already been modified to alight the attribute source name with the claim name for example mapping the LDAP attribute mail to email as per the openid connect specification.

The pre-token mapping rule comes with an example which already manages iterating over the requested claims, and the attribute values present. To enable this example ensure that the variable customize_id_token near the beginning of the mapping rule is set to true.

In order to add any value to the id_token as a claim, ensure it is in the stsuu as an attribute, with the type urn:ibm:jwt:claim. All values with this type will be added to the JWT.

Adding custom claims can be done with the following snippet.

stsuu.addAttribute(new com.tivoli.am.fim.trustserver.sts.uuser.Attribute("claim_name" ,"urn:ibm:jwt:claim", "claim_value"));

You can also pre-populate the id_token claims with a JSON payload. This is done through the special value claim_json. This is essential for adding id_token claims of integer, boolean or complex type.

Setting claim_json can be done with the following snippet.

var claim_json = {};
claim_json["complex"] = {"a":"complex claim"}
claim_json["integer"] = 5;

stsuu.addContextAttribute(new com.tivoli.am.fim.trustserver.sts.uuser.Attribute("claim_json" ,"urn:ibm:oidc10:jwt:create", JSON.stringify(claim_json)));

Note: claim_json pre-populates the id_token claims, if another attribute is added to the claims via a regular stsuu urn:ibm:jwt:claim attribute method then the claim_json value will be overwritten. 

Note: Header claims can also be added, use the type urn:ibm:JWT:header:claim to add a header claim. This is useful for values like x5t

Authorization code flow and credential attributes.

When performing the authorization code flow, the request for authorization does not return an id_token which is instead returned from /token. The key difference here is that the request for authorization is the only one which has the users session, which contains the attributes which is used to populate the id_token claims. In order to over come this there is logic in the pre and post token mapping rule to save credential attributes during the request to /authorize, which are then retrieved during the request to /token when the id_token is created.

Configuring attribute sources

In order to add an attribute source to an id_token, first the attribute source must be configured. Attribute sources can be configured via the steps on the Knowledge Centre.

The JSON payload is(See the REST web service documentation):

[
  {
    "name": "email",
    "id": "1",
    "type": "credential",
    "value": "emailAddress",
    "properties": []
  },
  {
    "name": "mobile",
    "id": "2",
    "type": "credential",
    "value": "mobileNumber",
    "properties": []
  }
]

Note: The name of an attribute sources does not impact the claim name.

Adding attribute sources to an API protection definition

Adding the attribute source to the definition maps the attribute to the id_token claim. Use the API protection definition panel for OpenID Connect to add attribute sources.

The JSON payload for the definition(some portions omitted for brevity):

{
 ...
  "oidc": {
    "issueSecret": false,
    "poc": "https://www.myidp.ibm.com/mga",
    "dynamicClients": true,
    "iss": "https://www.myidp.ibm.com",
    "lifetime": 3600,
    "cert": "server",
    "enc": {
      "enc": null,
      "alg": null,
      "enabled": false
    },
    "alg": "RS256",
    "attributeSources": [
      {
        "attributeSourceId": "1",
        "attributeName": "email"
      },
      {
        "attributeSourceId": "2",
        "attributeName": "phone_number"
      }
    ],
    "enabled": true,
    "db": "rt_profile_keys"
  },
...
}

Note: The attribute name value here dictates the claim name.

Note: The attributeSourceId correlates to the ID returned by the attribute sources API payload shown earlier.

Trying it out

With the above attribute sources configured, and the two examples of custom claim manipulation included, an authorization request was performed with the scope openid email and a claims parameter with the value:

 {"id_token":{"phone_number":{"essential": true}}}"

Note: Claims parameter was URI decoded for readability.

A complete authorize request via GET:

https://www.myidp.ibm.com/mga/sps/oauth/oauth20/authorize?
scope=openid+email&
response_type=code&
client_id=mytestClient&
redirect_uri=https://application.ibm.com&
state=a1b2c3d4e5&
claims=%7B%22id_token%22%3A%20%7B%22phone_number%22%3A%20%7B%22essential%22%3A%20false%7D%7D%7D

Note: Line breaks added for readability


Decoded its claims are:

{
  "complex": {
    "a": "complex claim"
  },
  "integer": 5,
  "rt_hash": "7WH_WrTDShKB0WpeBWCXMQ",
  "phone_number": "61755512345",
  "email": "testuser@myidp.ibm.com",
  "iat": 1541460186,
  "iss": "https://www.myidp.ibm.com",
  "at_hash": "I59Nt3QKS3_TDey36GZZ_g",
  "sub": "testuser",
  "claim_name": "claim_value",
  "exp": 1541463786,
  "aud": "mytestClient"
}

 

Here we can see the requested claims email and phone_number were returned, as well as additional claims which the authorization server decided to include too.


Building identity aware web applications is essential to a good user experience and the  id_token is a modern and efficient way of combining the ease of federated single sign on with a personalised web application. This article has shown you how ISAM gives control to the administrator to configure and expose claims from traditional ISAM data stores, as well as how the pre-token rule can be used to integrate with other more bespoke sources of attributes. One of the key takeaways is that the pre-token rule can be used to control the format of the id_token, even when attribute sources are not configured.

 

 

Click here to rate this article

Rate this article :

Software Engineer - IBM Security Access Manager

More Articles stories
By Jeroen Tiggelman on August 4, 2019

IBM Security zSecure Suite 2.4 announced

IBM Security zSecure suite V2.4 was announced on July 23, 2019 with a planned availability date of September 30, 2019. You can read the US announcement letter here. RACF has made new JSON Web Token functionality in support of Multi-Factor Authentication also available for z/OS V2.2 and V2.3. Details about zSecure compatibility fixes can be […]

Continue reading

By Martin Schmidt on July 11, 2019

Modernizing your B2C Portal Security – LDAP Proxy Deep Dive

In this part of our series we are taking a deeper look on how the LDAP reverse proxy works and what is needed to be done to make it work. Enable CI In this part we look at what needs to be done on the CI side and what information needs to be collected. We […]

Continue reading

By Martin Schmidt on May 4, 2019

Modernizing your B2C Portal Security – Desired End State

Proposition: As we have seen in part one of this series, managing customer identities for a portal can be a challenge and distraction for the business.  In this part of the series we will outline how a modernized solution for a portal security can simplify operations and free your team up to focus on the […]

Continue reading