How-tos

7 mins read

Enriching Token Claims Using Cloudentity Extensions

Learn how to enrich claims for security tokens before the token is minted by the Cloudentity platform.

About Enriching Token Claims

With Extensions, Cloudentity enables developers to enrich claims for ID and access tokens issued by the platform. Developers can prepare JavaScript Extensions to modify the token claims before it is minted. Token claims can be enriched, for example, to:

  • Include data (such as user permissions) from an external system

  • Overwrite static attributes

  • Populate the token with risk information from external services

  • Populate token with fine-grained permissions for the user that resides in an external service

  • Populate token with business-related information about the user from external services.

Learn more

You can learn more about Cloudentity Extensions and enriching token claims by reading the Extending Cloudentity Capabilities.

Available Inputs

When creating Extension scripts that enrich claims for security tokens minted by the Cloudentity platform, developers have access to the following input objects within the script execution context:

  • client - to have access to client application data

    Client schema:

                    
                        
      {
        "application_type": "web",
        "application_types": [
          "single_page",
          "server_web",
          "mobile_desktop",
          "service",
          "legacy",
          "dcr"
        ],
        "audience": [
          "client_id"
        ],
        "authorization_server_id": "default",
        "backchannel_authentication_request_signing_alg": "string",
        "backchannel_client_notification_endpoint": "string",
        "backchannel_token_delivery_mode": "string",
        "backchannel_user_code_parameter": true,
        "client_id": "string",
        "client_id_issued_at": 0,
        "client_name": "My app",
        "client_secret": "stringstringstringstringstringst",
        "client_secret_expires_at": 0,
        "client_uri": "string",
        "description": "string",
        "developer_id": "string",
        "developer_metadata": {
          "property1": {},
          "property2": {}
        },
        "dynamically_registered": true,
        "grant_types": [
          "password",
          "refresh_token",
          "client_credentials",
          "implicit",
          "authorization_code"
        ],
        "hashed_rotated_secrets": [
          "string"
        ],
        "hashed_secret": "string",
        "id_token_encrypted_response_alg": "RSA-OAEP",
        "id_token_encrypted_response_enc": "A256GCM",
        "id_token_signed_response_alg": "ES256",
        "jwks": {
          "keys": []
        },
        "jwks_uri": "string",
        "logo_uri": "string",
        "metadata": {
          "property1": {},
          "property2": {}
        },
        "organisation_id": "5647fe90-f6bc-11eb-9a03-0242ac130003",
        "policy_uri": "string",
        "privacy": {
          "scopes": {
            "property1": {
              "pii_categories": [
                {
                  "name": "HIPAA"
                }
              ],
              "purpose": "string"
            },
            "property2": {
              "pii_categories": [
                {
                  "name": "HIPAA"
                }
              ],
              "purpose": "string"
            }
          }
        },
        "redirect_uris": [
          "https://example.com/callback"
        ],
        "request_object_signing_alg": "none",
        "request_uris": [
          "string"
        ],
        "require_pushed_authorization_requests": true,
        "response_types": [
          "token",
          "id_token",
          "code"
        ],
        "rotated_secrets": [
          "string"
        ],
        "scope": "email offline_access openid",
        "scopes": [
          "email",
          "offline_access",
          "openid"
        ],
        "sector_identifier_uri": "https://api.jsonbin.io/b/5db6ef08688fed59d2841f1e",
        "software_id": "string",
        "software_statement": "string",
        "software_version": "string",
        "subject_type": "public",
        "system": true,
        "tenant_id": "string",
        "tls_client_auth_san_dns": "string",
        "tls_client_auth_san_email": "string",
        "tls_client_auth_san_ip": "string",
        "tls_client_auth_san_uri": "string",
        "tls_client_auth_subject_dn": "string",
        "tls_client_certificate_bound_access_tokens": true,
        "token_endpoint_auth_method": "client_secret_basic",
        "token_endpoint_auth_signing_alg": "none",
        "tos_uri": "string",
        "trusted": true,
        "userinfo_signed_response_alg": "none"
      }
      
  • grant_type - to get the information about the authorization grant type that was requested by the client application

    Example values: client_credentials, token-exchange, urn:openid:params:grant-type:ciba

    For more information on available grant types, see Cloudentity Grant Types articles

  • granted_scopes - to have data about the scopes that are already granted to the client application

    Sample input:

                    
                        
      {
        "granted_scopes": ["email", "openid"]
      }
      
  • authorize_request - to have session data about the authorization request that concluded the call to the token endpoint. The developers have access to the original URL of the call to the authorize endpoint, and to the query parameters of this call.

    Sample input:

                    
                        
      {
        "authorize_request": {
          "url": "https://{tid}.eu.authz.cloudentity.io/{tid}/{aid}/oauth2/authorize",
          "query_params": {
            "prompt": ["login"]
          }
        }
      }
      
  • authn_ctx - to have information about the authentication context

    Sample input:

                    
                        
      {
      "access_token": {
          "acr": "1",
          "aid": "default",
          "amr": [
            "pwd"
          ],
          "aud": [
            "default-demo",
            "spiffe://default.acp.local/default-profile",
            "spiffe://default.acp.local/default-oauth2",
            "spiffe://default.acp.local/default-user-privacy-consent"
          ],
          "exp": 1651057535,
          "iat": 1651053934,
          "idp": "default",
          "iss": "https://default.acp.local:8443",
          "jti": "6e3b9808-f0f5-4d2c-80c9-1f54cf7cbf6f",
          "nbf": 1651053934,
          "scp": [
            "email",
            "introspect_tokens",
            "list_clients_with_access",
            "manage_consents",
            "offline_access",
            "openid",
            "profile",
            "revoke_client_access",
            "revoke_tokens",
            "view_consents"
          ],
          "st": "public",
          "sub": "9a663bf966861677ca77004a6b4c1fc87d11d78afeb245fb3549ab32783af3ab",
          "tid": "default"
        }
      }
      

    You can also find an example usage of the access_token input object in the Sample Script section.

  • id_token - to be able to enrich claims within the minted identity token

    Sample input:

                    
                        
      {
        "id_token": {
          "acr": "1",
          "amr": [
            "pwd"
          ],
          "aud": "default-demo",
          "auth_time": 1651053934,
          "email": "jdoe@example.com",
          "email_verified": true,
          "exp": 1651057534,
          "family_name": "Doe",
          "given_name": "John",
          "iat": 1651053934,
          "idp": "default",
          "idpm": "static",
          "iss": "https://default.acp.local:8443",
          "jti": "dbb369b4-cc83-4302-81fb-122e05c92334",
          "name": "John Doe",
          "nonce": "c9khaqmk66ml1d1ibki0",
          "rat": 1651053934,
          "refresh_token_expires_at": 1653645935,
          "sub": "9a663bf966861677ca77004a6b4c1fc87d11d78afeb245fb3549ab32783af3ab"
        }
      }
      

    You can also find an example usage of the access_token input object in the Sample Script section.

Tip

You can see the available inputs examples in the Extensions editor:

Available input example

Available Output

Extensions modifying claims within different security tokens can produce the following output:

  • access_token - to show the result of enriching claims within an access token

  • id_token - to show the result of enriching claims within an ID token

Example output

{
"id_token": {
   "role": "manager"
  }
}
{
"access_token": {
   "permissions": [
      "delete_user",
      "block_user",
      "accept_payrise_request"
   ]
  }
}

Tip

Extensions scripts do not override the entire content of an access token/ID token. The scripts update only those parts of a token that are explicitly defined in the Extension.

With Extensions that enrich token claims, you do not need to add any new attributes to your authentication context as the Extension is able to inject them dynamically.

Enrich Token Claims

  1. Create your Extension.

    When creating the Extension, use available inputs, outputs, and dependencies.

    Creating Extensions

    For instructions on how to create Cloudentity Extensions, test using test mode, and to learn what are recommended best practices when working with Extensions, see the Creating and Testing Extensions How-to article.

    To check how Extensions enriching claims work and look, see the Sample Script section.

  2. Assign the Extension:

    • At the authorization server level in OAuth » Tokens & Claims » Claims » Claims list » Pre-token minting extension.

      When the extension is attached at the authorization server level all client applications registered within the workspace are affected – the token claims are enriched for all of them using the assigned extension.

      Assigning Extension

    • At the client application level in Applications » Clients » OAuth » Custom claims and token enrichment » Pre-token minting extension.

      Extensions attached at the client level affect only the client they are assigned to and are executed after Extensions at the server level (if there are any).

      Assigning Extension at Client Level

  3. Verify enriched claims using Sandbox IDP and Demo Application/API

Sample Script

module.exports = async function(context) {
      const request = require('request-promise-native');

      try {
        const response = await request({
          method: 'GET',
          json: true,
          uri: 'https://raw.githubusercontent.com/LearnWebCode/json-example/master/pet-of-the-day.json'
        });

        const pet_name = response.name;
        const pet_species = response.species;

        return {
          id_token: {
            pet: {
              name: pet_name,
              species: pet_species
            }
          }
        };
      }catch(e) {
        console.error(e);
        return {  pet: null };
      }
}

In the Extension above, a request is made to fetch the pet of the day and enrich an ID token with the pet claim. If you wish, you can replace the id_token input parameter to access_token to enrich an access token. You can also enrich both tokens at the same time as shown below:

return {
   id_token: {
   pet: {
      name: pet_name,
      species: pet_species
   }
   }
   access_token: {
   pet: {
      name: pet_name,
      species: pet_species
   }
   }
};

Verify Enriched Claims Using Sandbox IDP and Demo Application/API

If you wish to confirm enriched claims for your security tokens, you can use Cloudentity Sandbox IDP and Demo Application if it is enabled for the workspace you are working on. If it is not, you can use Cloudentity APIs and a token decoder like jwt.io.

  1. Set up Sandbox IDP if is not available within the workspace you are working within.

  2. If the workspace has the Demo Application available, authenticate as the user you have set up within the Sandbox IDP.

    Accessing Demo Application

    You can access the Demo Application in three ways:

    • In the WORKSPACE MANAGER by clicking the dropdown for the workspace and selecting Demo application.

    • Within the workspace overview (Dashboards > Overview) Connected portals right-hand panel.

    • By visiting the https://{tid}.authz.cloudentity.io/{tid}/{wid}/demo URL with your tenant identifier set for the {tid} variable and the workspace identifier set for the {wid} variable.

  3. Depending on whether you enriched claims for an access token or id token (or both), investigate the claims for the token.

    Your enriched claims should be visible as the part of the Claims tab as shown below:

    Enriched claims

  4. If your workspace does not have a Demo Application available, you can get your token using any other client application and calling the Cloudentity OAuth 2.0 Token endpoint. Once you have the token, decode it using the jwt.io service to view the claims.

    Response Type

    Remember that if you wish to get a particular token (for example, only an ID token), you need to configure the Response Types setting in your client application OAuth configuration (Applications » Clients » OAuth).

Updated: Nov 2, 2023