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:
sub
– this 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 user info 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.
#ISAM