OIDC Claims customization

You can customize the OIDC claims that contain information about the user and about the authentication event.

The OIDC specification describes standards for creating and processing claims. OpenID defines a standard set of basic profile Claims. You can use specific scope values to access pre-defined sets of Claims. You can also request individual Claims by using the claims request parameter.

The specification outlines the following structure for defining and handling claims:

  • There are about twenty standard claims, such as name, picture, gender, and so on.
  • You can use the scope parameter to request Claims. There are well defined scopes, each of which translates to a collection of standard claims such as profile, email, phone, and address.
  • You can also request claims individually by using the claims request parameter.
  • When an access token exists, claims are returned in UserInfo. When there is no access token, claims are returned in ID Tokens.
  • UserInfo is returned at the /userinfo endpoint. ID Tokens are returned at either the /authorize or /token endpoints, depending on which OIDC flow is executed.
  • There are additional request parameters that can affect the claims. Examples of these include max_age, acr_values, and claims_locales.

OIDC does not perform authentication itself, but relies on an authentication module to authenticate the user. This means that the OIDC protocol cannot provide claims values, because it has no knowledge of what user information is available, and how to the data is stored. For example, perhaps only the user name information is available, but is stored in LDAP as the attribute cn.

As a result, Security Access Manager supports the customization of claims values. For ID Tokens, you can customize claims values through a pre-token mapping rule. For UserInfo, you can customize claims in a post-mapping rule.

In Security Access Manager, when you create a new OIDC Definition, default pre-token and post-token mapping rules are created. These mapping rules contain examples of how the claims can be resolved.

Note: To review the OIDC specification, see http://openid.net/specs/openid-connect-core-1_0.html#Claims

UserInfo endpoint

The OIDC specification recommends the use of the UserInfo endpoint. The UserInfo endpoint is useful, for example, when a Relying Party cannot parse a JWT Token to obtain information about the authenticated user.

Without the use of customization, the /userinfo endpoint contains only the field sub. This is the subject identifier for the end-user at the issuer.

The specification mandates to output the claims as much as possible at the /userinfo endpoint, except when an access token is not generated. Also, in some cases the ID Token is generated at both /authorize and /token endpoint. The Security Access Manager will not impose any restriction of which claims must be output to ID Token or User Info. Likewise, there are no restrictions that the same claims must be returned at /authorize and /token. Based on the needs of your deployment, you can choose not to output some claims in certain flows even though the claims are requested.

The /userinfo endpoint is protected by an access token. You can access it by an HTTP GET or POST. See the following links:

An unauth ACL is attached for this endpoint.

Claims List

Many parameters can contribute to a claims list. For example, parameters specified by a scope are often used to build a list. By parsing the claims parameter, you can also retrieve individual claims and determine which claims are for UserInfo and which claims are for ID Tokens.

Security Access Manager builds a claims list and makes it available in the Security Token Service Universal User (STSUU) as a list of voluntary and essential claims. This list is produced only for OIDC requests that have scope openid against an OIDC-enabled provider.

The processing sequence is:

  1. The scope parameter is processed first, since all claims requested through it are voluntary claims. The specification defines only profile, address, email, and phone scopes as well-defined scopes. These translate into a list of standard claims. However, if the scope contains other scopes that are not well-defined, it is treated as an individual claim.
  2. Next the claims parameter is processed. Either UserInfo or ID Token is processed, depending on the endpoint.
Table 1. Claims types
Claim Type
Voluntary claims urn:ibm:names:ITFIM:oidc:claim:voluntary
Essential claims urn:ibm:names:ITFIM:oidc:claim:essential

For example, given a request with scope=“openid phone organization” and a claims parameter that is the described in the following JavaScript Object Notation (JSON):

{
   "userinfo":  {
    	"given_name": {"essential": true},
    	"email": {"essential": true},
    	"email_verified": {"essential": true},
    	"http://example.info/claims/groups": null
    },
   "id_token": {
    	"nickname": null,
    	"auth_time": {"essential": true},
    	"acr": {"values": ["urn:mace:silver"] }
    }
}

At the /authorize or /token endpoint where the ID Token can be generated, the following is available in the STSUU context:

<stsuuser:ContextAttributes>
        // from scope: phone and organization
<stsuuser:Attribute name=“organization" type="urn:ibm:names:ITFIM:oidc:claim:voluntary"/>
        <stsuuser:Attribute name="phone_number" type="urn:ibm:names:ITFIM:oidc:claim:voluntary"/>
        <stsuuser:Attribute name="phone_number_verified" 
                type="urn:ibm:names:ITFIM:oidc:claim:voluntary"/>
        // from id_token claims parameter
        <stsuuser:Attribute name="nickname" type="urn:ibm:names:ITFIM:oidc:claim:voluntary"/>
        <stsuuser:Attribute name="auth_time" type="urn:ibm:names:ITFIM:oidc:claim:essential"/>
        <stsuuser:Attribute name="acr" type="urn:ibm:names:ITFIM:oidc:claim:voluntary">
            <stsuuser:Value>urn:mace:silver</stsuuser:Value>
        </stsuuser:Attribute>
</stsuuser:ContextAttributes>

At the /userinfo endpoint, the following is available in the STSUU context:

<stsuuser:ContextAttributes>
        // from scope: phone and organization
        <stsuuser:Attribute name=“organization" type="urn:ibm:names:ITFIM:oidc:claim:voluntary"/>
        <stsuuser:Attribute name="phone_number" type="urn:ibm:names:ITFIM:oidc:claim:voluntary"/>
        <stsuuser:Attribute name="phone_number_verified" 
             type="urn:ibm:names:ITFIM:oidc:claim:voluntary"/>
        // from userinfo claims parameter
        <stsuuser:Attribute name="given_name" type="urn:ibm:names:ITFIM:oidc:claim:essential"/>
        <stsuuser:Attribute name="email" type="urn:ibm:names:ITFIM:oidc:claim:essential"/>
        <stsuuser:Attribute name="email_verified" 
              type="urn:ibm:names:ITFIM:oidc:claim:essential"/>
        <stsuuser:Attribute name="http://example.info/claims/groups" 
              type="urn:ibm:names:ITFIM:oidc:claim:voluntary"/>
</stsuuser:ContextAttributes>

Retrieving Claim Values

You can use the function associate() and UserLookupHelp to retrieve claim values. Security Access Manager allows you to also retrieve claim values by using attribute sources. The Federation support in Security Access Manager includes management of attribute sources, in the LMI under Advanced Access Control.

You can provide mappings between a specific attribute name and an attribute source, as part of configuring an OIDC Definition. During runtime, this mapping is resolved and made available in the STSUU.

For example, assume the attribute sources in the following table are configured.

Table 2. Example configuration of Attribute Sources
Attribute Name Value Type
CredentialNickName AZN_CRED_PRINCIPAL_NAME Credential
FixedOrganization www.ibm.com Fixed
LDAPMail mail LDAP

Assume also that you have created the following attribute mapping in the OIDC Definition configuration.

Table 3. Attribute Mapping
Attribute Name Attribute Source
email LDAPMail
nickname CredentialNickName
organization FixedOrganization

Then, during runtime, in the STSUU the following attributes can be found:

<stsuuser:AttributeList>
        <stsuuser:Attribute name=“nickname" type="urn:ibm:names:ITFIM:5.1:accessmanager">
            <stsuuser:Value>test1</stsuuser:Value>
        </stsuuser:Attribute>
        <stsuuser:Attribute name=“organization" type="urn:ibm:names:ITFIM:5.1:accessmanager">
            <stsuuser:Value>www.ibm.com</stsuuser:Value>
        </stsuuser:Attribute>
        <stsuuser:Attribute name="email" type="urn:ibm:names:ITFIM:5.1:accessmanager">
            <stsuuser:Value>test1@iswga.com</stsuuser:Value>
        </stsuuser:Attribute>
</stsuuser:AttributeList>

The resolution of attribute sources during runtime is dependent on the context. The context is the list of attributes that are available in the STSUU at that moment. The following conditions apply:

  • For fixed attribute source, there is no restriction on attribute source resolution.

  • For a credential type attribute source, resolution occurs best at the /authorize endpoint. This is because since the entire authentication information (and credential) is available at that time.

  • For LDAP type attribute source, if you are using a macro for the search filter or baseDN, resolution also depends on the context. The information might be available in STSUU, but in a different context it might be available under a different name. This means it can be difficult to create one LDAP attribute source that fits all contexts.

    The common use of a macro is to retrieve information based on the username that is being authenticated. Security Access Manager includes an attribute oidc_username which contains the authenticated username in all contexts: whether at /authorize, /token or /userinfo endpoints. For example, you can create a common LDAP Attribute Source, as shown in the following table.

    Table 4. LDAP Attribute Source example
    Type LDAP
    Attribute Name LDAPMail
    LDAP Attribute mail
    Server Connection TestLDAP
    Scope Subtree
    Selector uid
    Search filter: (uid={oidc_username})
    Base DN: dc=iswga

Saving Values or Parameters

Security Access Manager enables you to save values or parameters that are related to the claims at the /authorize endpoint.

For example, some request parameters can be specified at the /authorize endpoint, but the claims might be produced at the /token or /userinfo endpoint. The claims need to be saved so that they can be available at the /token or /userinfo endpoint. An example of this is the claims_locales request parameter.

Another example is the existence of values, such as credential information, that are available at the /authorize endpoint, but need to be output at the /token or /userinfo endpoint. An example of this is the values that are used in the credential type attribute sources. You can save these values. This overcomes the limitation of the attribute source such that for the credential-type attribute source, the context exists only at the /authorize endpoint, and if the values are not saved, the context is not available at any other endpoint.

You can do this by creating a context attribute in the STSUU of the type urn:ibm:names:ITFIM:oidc:claim:parameter for parameter or urn:ibm:names:ITFIM:oidc:claim:value for value.

The difference between these two types is that, during runtime, the claim value is put back into STSUU Attribute List under type urn:ibm:names:ITFIM:5.1:accessmanager, but the claim parameter is put in the STSUU context under type urn:ibm:names:ITFIM:oidc:claim:parameter.

Note that these saved values or parameters exist as long as the grant exists. When the grant is removed or expires, the saved values and parameters are removed.

For example, we man modify the pre-token mapping rule and add the following code to save the AZN_CRED_PRINCIPAL_NAME attribute.

var saveValue = stsuu.getAttributeContainer()
         .getAttributeValueByNameAndType("AZN_CRED_PRINCIPAL_NAME", 
         "urn:ibm:names:ITFIM:5.1:accessmanager");
if (saveValue != null) {
	var attro = new com.tivoli.am.fim.trustserver.sts.uuser.Attribute("AZN_CRED_PRINCIPAL_NAME",
		"urn:ibm:names:ITFIM:oidc:claim:value", saveValue);
	stsuu.getContextAttributes().setAttribute(attro);
}

By doing this, the CredentialNickName attribute source (as shown in the example earlier in this article) can be resolved in the /token or /userinfo endpoint.

Customizing claims

Security Access Manager provides, in pre-token and post-token mapping rule, examples of how to customize the claims.

For ID Tokens, customization is done in a pre-token mapping rule. You must enable the sample by setting the customize_id_token variable to true. For UserInfo, customization is done in a post-token mapping rule.

For the example, the algorithm used is the same. The first step is to retrieve the claim list. You might want to process essential claims and voluntary claims separately.

To resolve claims, the produceClaim() method is called. If an expected value, as specified by the claim, is found, use it. Next, try to find an attribute that has been resolved using Attribute Source mapping, and has the same name as the claim. Next, if still there is no value, for essential claims, you can set some value or optionally throw an STS exception. Note, however, that the OIDC specification does not recommend throwing an error even if an essential claim cannot be fulfilled.

For the final step, if the claim value exists, it is put into the STSUU. The type must be set correctly, in order to included as part of ID Token or UserInfo. For ID Token, the type must be urn:ibm:jwt:claim. For UserInfo, the type must be urn:ibm:names:ITFIM:oauth:response:attribute.

Special parameter for UserInfo

You can customize UserInfo by using a special attribute. You can create an attribute in the STSUU Context, with name userinfo and type urn:ibm:names:ITFIM:oauth:rule:userinfo, with the value as a JSON string.

The purpose of this special parameter is to allow you to provide a complex value for UserInfo, in situations where the limitations of the STSUU structure prevent support for the value. For example, the following JSON defines an address that consists of two parts:


{"firstname":"John",
  "lastname":"Doe",
  "address":{
     "zipcode":34234
     "city":"Newark"
  }
}

The JSON string provided in this parameter serves as the base JSON structure, and is added with other customization attributes, if they exist, to the output of the /userinfo endpoint.

Another use of the special parameter is when you want to generate UserInfo in JWT format. By default, the Security Access Manager implementation produces UserInfo in JSON format. If you need to produce UserInfo in JWT format, there is an example in the post-mapping rule.

To use the example in the post-mapping rule, complete the following steps:

  1. Create an STS chain that includes the modules in the table below.
    Table 5. Chain modules for JWT format
    Module Mode
    Default STSUU Module Instance Validate
    Default Jwt Module Issue
    Default STSUU Module Instance Issue

    For more information on creating STS templates and chains, see Managing trust chains.

  2. In the post mapping-rule, set produce_jwt_userinfo to true:
    var produce_jwt_userinfo = true;