How To

How do I add custom claims to the OIDC Claims Script in AM (All versions) and OpenAM 13.x?

Last updated Oct 19, 2018

The purpose of this article is to provide information on adding custom claims to the OIDC Claims Script in AM/OpenAM and then obtaining the JWT ID token with the claims included.


Overview

AM 5.1 introduced improved OIDC claims support as detailed in AM 5.1 Release Notes › Major Improvements, which allows the use of the claims query parameter.

This article includes the following sections:

Adding custom claims to the script

The following process describes how to add custom claims to the OIDC Claims Script:

  1. Create a custom OIDC Claims Script by navigating to Realms > [Realm Name] > Scripts and clicking New Script. Enter a name for your script and select OIDC Claims as the script type.
  2. Specify the script details ensuring you make the following changes as needed:
    1. Declare any required classes in the import section at the top of the script.
    2. Add mapping details for the custom claim to the claimAttributes section. For example, a new customattr claim:
      // [ {claim}: {attribute retriever}, ... ]
      claimAttributes = [
              "email": userProfileClaimResolver.curry("mail"),
              "address": { claim, identity -> [ "formatted" : userProfileClaimResolver("postaladdress", claim, identity) ] },
              "phone_number": userProfileClaimResolver.curry("telephonenumber"),
              "given_name": userProfileClaimResolver.curry("givenname"),
              "zoneinfo": userProfileClaimResolver.curry("preferredtimezone"),
              "family_name": userProfileClaimResolver.curry("sn"),
              "locale": userProfileClaimResolver.curry("preferredlocale"),
              "name": userProfileClaimResolver.curry("cn"),
              "customattr": userProfileClaimResolver.curry("customattribute")
      ]
      
    3. Add the custom claim to the scope in the scopeClaimsMap section. For example, with the new customattr claim added to a new custom scope (you could add your custom claim to the profile scope instead if you want to include it in the "Your personal information" section on the consent page):
      // {scope}: [ {claim}, ... ]
      scopeClaimsMap = [
              "email": [ "email" ],
              "address": [ "address" ],
              "phone": [ "phone_number" ],
              "profile": [ "given_name", "zoneinfo", "family_name", "locale", "name"],
              "custom": [ "customattr" ] 
      ]
      
  3. Ensure the custom attribute used for mapping in the claimAttributes section exists as a user attribute in your identity repository. See the Adding user attribute to the data store configuration section in How do I update LDAP user attributes using the REST API in AM/OpenAM (All versions)? for further information.
  4. Add any classes you declared in the import section to the Java class whitelist:
    • AM / OpenAM 13.5 console: navigate to: Configure > Global Services > Scripting > Secondary Configurations > [Script Type] > Secondary Configurations > EngineConfiguration and add the Java class(es) to the Java class whitelist field.
    • OpenAM 13 console: navigate to: Configuration > Global > Scripting > Secondary Configuration Instance > [Script Type] > Secondary Configuration Instance > Engine Configuration and add the Java class(es) to the Java class whitelist field. 
  5. Update the OAuth2Provider to process claims correctly by navigating to Realms > [Realm Name] > Services > OAuth2 Provider (OpenAM 13.x does not have separate tabs, the following fields are on the same page):
    • Advanced tab - update the Supported Scopes field to include the scope you added in step 2c to display it on the consent page. For example, custom|en|Custom information will display the new custom scope in a Custom information section on the consent page.
    • OpenID Connect tab - select the OIDC claims script you created in step 1 in the OIDC Claims Script field.
    • OpenID Connect tab - update the Supported Claims field to include the custom claim (needed if you want to include claims when requesting an access token). For example, customattr|en|My custom attribute will display the new custom attribute on the consent page as My custom attribute.
    • Advanced OpenID Connect tab - enable the following options:
      • Enable "claims_parameter_supported" (needed if you want to include claims when requesting an access token)
      • Always Return Claims in ID Tokens
  6. Restart the web application container in which AM/OpenAM runs to complete this configuration.

Obtaining the JWT ID token using the authorize flow

The following example demonstrates obtaining the JWT ID token using the authorize flow, which includes the consent page:

  1. Initiate the flow by navigating to a URL such as the following:
    http://host1.example.com:8080/openam/oauth2/authorize?client_id=myClientID&redirect_uri=http://redirect.example.org&response_mode=form_post&response_type=code id_token&scope=openid profile custom&nonce=agreed
    
  2. Authenticate as normal; you will then be presented with the consent screen where you can observe the custom claim you added, for example:

  1. Provide consent; you will then be returned to redirect_uri with the code and id_token:
    http://redirect.example.org/#code=b9f41a4e-ffc7-4f50-838d-e26e7ed28e26&scope=openid%20profile%20custom&id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdF9oYXNoIjoiR1pvZkhxYWV3QkoyaFJqa0tpVDhFdyIsInN1YiI6ImRlbW8iLCJhdWRpdFRyYWNraW5nSWQiOiIwZDgzNmE4ZC1hZjRjLTRiMzMtYTNhMi1iZjA2Y2Q1OTBiOTEtMzkzNyIsImlzcyI6Imh0dHA6Ly9ob3N0MS5leGFtcGxlLmNvbTo4MDgwL29wZW5hbS9vYXV0aDIiLCJ0b2tlbk5hbWUiOiJpZF90b2tlbiIsImF1ZCI6Im15Q2xpZW50SUQiLCJhenAiOiJteUNsaWVudElEIiwiYXV0aF90aW1lIjoxNTM4Njc1MjI2LCJuYW1lIjoiZGVtbyIsInJlYWxtIjoiLyIsImV4cCI6MTUzODczMzE1MiwidG9rZW5UeXBlIjoiSldUVG9rZW4iLCJmYW1pbHlfbmFtZSI6ImRlbW8iLCJjdXN0b21hdHRyIjoiY3VzdG9tIHZhbHVlIiwiaWF0IjoxNTM4Njc1MjI2LCJqdGkiOiJiYjE4YTQwNC1mMDhjLTQ0NmUtOGUwMS04YjcwYzhkNDgxOTIifQ.XFl_UfiGIar319V2GlYASkxsJCXiO_DE59cAryLq3d4
    
  2. Decode the id_token returned (for example, using https://jwt.davetonge.co.uk/) to verify that the JWT includes the custom claim (customattr in this example):
    {
     "at_hash":"GZofHqaewBJ2hRjkKiT8Ew"
     "sub":"demo"
     "auditTrackingId":"0d836a8d-af4c-4b33-a3a2-bf06cd590b91-3937"
     "iss":"http://host1.example.com:8080/openam/oauth2"
     "tokenName":"id_token"
     "aud":"myClientID"
     "azp":"myClientID"
     "auth_time":1538675226
     "name":"demo"
     "realm":"/"
     "exp":1538733152
     "tokenType":"JWTToken"
     "family_name":"demo"
     "customattr":"custom value"
     "iat":1538675226
     "jti":"bb18a404-f08c-446e-8e01-8b70c8d48192"
    }
    
Note

You can also use the idtokeninfo endpoint to validate the returned id_token as described in OpenID Connect 1.0 Guide › Validating OpenID Connect 1.0 ID Tokens.

Obtaining the JWT ID token using the claims query parameter (AM 5.1 and later)

The following example demonstrates the use of the claims query parameter in obtaining the JWT ID token:

  1. Generate an OIDC token, including the custom claim in JSON format with URL encoding (see Requesting Claims using the "claims" Request Parameter for further information):
    $ curl -s -X POST --user "myClientID:password" -d 'grant_type=password&username=demo&password=changeit&scope=profile%20openid&claims={"userinfo":{"customattr":{"essential":true}}%2C"id_token":{"customattr":{"essential":true}}}' "http://host1.example.com:8080/openam/oauth2/access_token"
    
    Example response:
    {"access_token": "1a58a25b-a2ac-4258-9708-905c449b8a6b","refresh_token": "e91bf8ee-1987-4daa-a7a5-26c35c78ea34","scope": "openid profile","id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdF9oYXNoIjoiR1pvZkhxYWV3QkoyaFJqa0tpVDhFdyIsInN1YiI6ImRlbW8iLCJhdWRpdFRyYWNraW5nSWQiOiIwZDgzNmE4ZC1hZjRjLTRiMzMtYTNhMi1iZjA2Y2Q1OTBiOTEtMzkzNyIsImlzcyI6Imh0dHA6Ly9ob3N0MS5leGFtcGxlLmNvbTo4MDgwL29wZW5hbS9vYXV0aDIiLCJ0b2tlbk5hbWUiOiJpZF90b2tlbiIsImF1ZCI6Im15Q2xpZW50SUQiLCJhenAiOiJteUNsaWVudElEIiwiYXV0aF90aW1lIjoxNTM4Njc1MjI2LCJuYW1lIjoiZGVtbyIsInJlYWxtIjoiLyIsImV4cCI6MTUzODczMzE1MiwidG9rZW5UeXBlIjoiSldUVG9rZW4iLCJmYW1pbHlfbmFtZSI6ImRlbW8iLCJjdXN0b21hdHRyIjoiY3VzdG9tIHZhbHVlIiwiaWF0IjoxNTM4Njc1MjI2LCJqdGkiOiJiYjE4YTQwNC1mMDhjLTQ0NmUtOGUwMS04YjcwYzhkNDgxOTIifQ.XFl_UfiGIar319V2GlYASkxsJCXiO_DE59cAryLq3d4","token_type": "Bearer","expires_in": 3599}
    
  2. Decode the id_token (for example, using https://jwt.davetonge.co.uk/) to verify that the JWT includes the custom claim (customattr in this example):
    {
     "at_hash":"GZofHqaewBJ2hRjkKiT8Ew"
     "sub":"demo"
     "auditTrackingId":"0d836a8d-af4c-4b33-a3a2-bf06cd590b91-3937"
     "iss":"http://host1.example.com:8080/openam/oauth2"
     "tokenName":"id_token"
     "aud":"myClientID"
     "azp":"myClientID"
     "auth_time":1538675226
     "name":"demo"
     "realm":"/"
     "exp":1538733152
     "tokenType":"JWTToken"
     "family_name":"demo"
     "customattr":"custom value"
     "iat":1538675226
     "jti":"bb18a404-f08c-446e-8e01-8b70c8d48192"
    }
    

Troubleshooting

This section details some common errors and how to remedy them:

Error message Resolution
Caused by: java.util.concurrent.ExecutionException: javax.script.ScriptException: javax.script.ScriptException: java.lang.SecurityException: Access to Java class \”className\” is prohibited.

The class must be added to the whitelist as shown in step 4 in Adding custom claims to the script.

See Access to Java class is prohibited error with scripts running in AM (All versions) and OpenAM 13.x for further information.

 "error_description": "Requested claims must be allowed by the client's configuration.",
 "error": "invalid_request"  )
The custom claim must be added to the Supported Claims field as shown in step 5 in Adding custom claims to the script.
"error_description": "Invalid%20JSON%20in%20supplied%20claims%20parameter in the return callback"
The claim needs to be passed in JSON format in the curl command as shown in Obtaining the JWT ID token using the claims query parameter (AM 5.1 and later).

See Also

How do I automate the creation of scripts in AM (All versions) and OpenAM 13.x?

How do I add logging to server-side scripts in AM (All versions) and OpenAM 13.x?

How do I understand the JWTs used in OIDC that are generated or accepted by AM/OpenAM (All versions)?

Creating OAuth2 Provider in AM 5.5.x and 6 fails with a Could not initialise script configurations for realm error when using ssoadm

How do I modify the OIDC issuer ID or audience in a multi-server AM (All versions) environment?

FAQ: OAuth 2.0 in AM/OpenAM

OAuth 2.0 in AM/OpenAM

OpenID Connect 1.0 Guide

Development Guide › Developing with Scripts

Related Training

N/A

Related Issue Tracker IDs

OPENAM-11445 (Request to Customize OAuth2 Access Token Content)

OPENAM-10585 (The "claims" Request Parameter from the openid standard isn't functional)

OPENAM-10584 (Supported claims and scopes in OAuth2|OpenID provider are not hot swappable )

OPENAM-8440 (Pluggable OAuth2 Access Token Format)

OPENAM-7878 (Add functionality to modify the sub at the module level to override the clientID setting)



Copyright and TrademarksCopyright © 2018 ForgeRock, all rights reserved.
Loading...