Identity Gateway 2023.11

Pass runtime data downstream in a JWT

This example sets up Identity Cloud as an identity provider, to pass identity or other runtime information downstream, in a JWT signed with a PEM.

For more information about using runtime data, refer to Passing data along the chain. To help with development, the sample application includes a /jwt endpoint to display the JWT, verify its signature, and decrypt it.

Before you start, prepare Identity Cloud, IG, and the sample application as described in Example installation for this guide.

  1. Set up secrets:

    1. Locate a directory for secrets, and go to it:

      $ cd /path/to/secrets
    2. Create the following secret key and certificate pair as PEM files:

      $ openssl req \
      -newkey rsa:2048 \
      -new \
      -nodes \
      -x509 \
      -days 3650 \
      -subj "/CN=ig.example.com/OU=example/O=com/L=fr/ST=fr/C=fr" \
      -keyout ig.example.com-key.pem \
      -out ig.example.com-certificate.pem

      Two PEM files are created, one for the secret key, and another for the associated certificate.

    3. Map the key and certificate to the same secret ID in IG:

      $ cat ig.example.com-key.pem ig.example.com-certificate.pem > key.manager.secret.id.pem
    4. Generate PEM files to sign and verify the JWT:

      $ openssl req \
      -newkey rsa:2048 \
      -new \
      -nodes \
      -x509 \
      -days 3650 \
      -subj "/CN=ig.example.com/OU=example/O=com/L=fr/ST=fr/C=fr" \
      -keyout id.key.for.signing.jwt.pem \
      -out id.key.for.verifying.jwt.pem
    5. Make sure the following files have been added to your secrets directory:

      • id.key.for.signing.jwt.pem

      • id.key.for.verifying.jwt.pem

      • key.manager.secret.id.pem

      • ig.example.com-certificate.pem

      • ig.example.com-key.pem

  2. Set up Identity Cloud:

    1. Log in to the Identity Cloud admin UI as an administrator.

    2. Go to group Identities > Manage > settings_system_daydream Alpha realm - Users, and add a user with the following values:

      • Username: demo

      • First name: demo

      • Last name: user

      • Email Address: demo@example.com

      • Password: Ch4ng3!t

    3. Register an IG agent with the following values, as described in Register an IG agent in Identity Cloud:

      • ID: ig_agent_jwt

      • Password: password

      • Redirect URLs: https://ig.example.com:8443/jwt/redirect

    4. (Optional) Authenticate the agent to Identity Cloud as described in Authenticate an IG agent to Identity Cloud.

      IG agents are automatically authenticated to Identity Cloud by a deprecated authentication module in Identity Cloud. This step is currently optional, but will be required when authentication chains and modules are removed in a future release of Identity Cloud.
    5. Add a Validation Service:

      1. In Identity Cloud, select open_in_new Native Consoles > Access Management. The AM admin UI is displayed.

      2. Select Services, and add a validation service with the following Valid goto URL Resources:

        • https://ig.example.com:8443/*

        • https://ig.example.com:8443/*?*

  3. Set up IG:

    1. Set up TLS by adding the following file to IG, replacing the value for the property secretsDir:

      • Linux

      • Windows

      $HOME/.openig/config/admin.json
      %appdata%\OpenIG\config\admin.json
      {
        "mode": "DEVELOPMENT",
        "properties": {
          "secretsDir": "/path/to/secrets"
        },
        "connectors": [
          {
            "port": 8080
          },
          {
            "port": 8443,
            "tls": "ServerTlsOptions-1"
          }
        ],
        "session": {
          "cookie": {
            "sameSite": "none",
            "secure": true
          }
        },
        "heap": [
          {
            "name": "ServerTlsOptions-1",
            "type": "ServerTlsOptions",
            "config": {
              "keyManager": {
                "type": "SecretsKeyManager",
                "config": {
                  "signingSecretId": "key.manager.secret.id",
                  "secretsProvider": "ServerIdentityStore"
                }
              }
            }
          },
          {
            "name": "ServerIdentityStore",
            "type": "FileSystemSecretStore",
            "config": {
              "format": "PLAIN",
              "directory": "&{secretsDir}",
              "suffix": ".pem",
              "mappings": [{
                "secretId": "key.manager.secret.id",
                "format": {
                  "type": "PemPropertyFormat"
                }
              }]
            }
          }
        ]
      }
    2. Set an environment variable for the IG agent password, and then restart IG:

      $ export AGENT_SECRET_ID='cGFzc3dvcmQ='

      The password is retrieved by a SystemAndEnvSecretStore, and must be base64-encoded.

    3. Add the following route to IG to serve the sample application .css and other static resources:

      • Linux

      • Windows

      $HOME/.openig/config/routes/00-static-resources.json
      %appdata%\OpenIG\config\routes\00-static-resources.json
      {
        "name" : "00-static-resources",
        "baseURI" : "http://app.example.com:8081",
        "condition": "${find(request.uri.path,'^/css') or matchesWithRegex(request.uri.path, '^/.*\\\\.ico$') or matchesWithRegex(request.uri.path, '^/.*\\\\.gif$')}",
        "handler": "ReverseProxyHandler"
      }
    4. Add the following route to IG, replacing the value for the properties secretsDir and amInstanceUrl:

      • Linux

      • Windows

      $HOME/.openig/config/routes/jwt-idc.json
      %appdata%\OpenIG\config\routes\jwt-idc.json
      {
        "name": "jwt-idc",
        "condition": "${find(request.uri.path, '/jwt')}",
        "baseURI": "http://app.example.com:8081",
        "properties": {
          "secretsDir": "/path/to/secrets",
          "amInstanceUrl": "https://myTenant.forgeblocks.com/am"
        },
        "heap": [
          {
            "name": "SystemAndEnvSecretStore-1",
            "type": "SystemAndEnvSecretStore"
          },
          {
            "name": "AmService-1",
            "type": "AmService",
            "config": {
              "url": "&{amInstanceUrl}",
              "realm": "/alpha",
              "agent": {
                "username": "ig_agent_jwt",
                "passwordSecretId": "agent.secret.id"
              },
              "secretsProvider": "SystemAndEnvSecretStore-1",
              "sessionCache": {
                "enabled": false
              }
            }
          },
          {
            "name": "pemPropertyFormat",
            "type": "PemPropertyFormat"
          },
          {
            "name": "FileSystemSecretStore-1",
            "type": "FileSystemSecretStore",
            "config": {
              "format": "PLAIN",
              "directory": "&{secretsDir}",
              "suffix": ".pem",
              "mappings": [{
                "secretId": "id.key.for.signing.jwt",
                "format": "pemPropertyFormat"
              }]
            }
          }
        ],
        "handler": {
          "type": "Chain",
          "config": {
            "filters": [
              {
                "name": "CrossDomainSingleSignOnFilter-1",
                "type": "CrossDomainSingleSignOnFilter",
                "config": {
                  "redirectEndpoint": "/jwt/redirect",
                  "authCookie": {
                    "path": "/jwt",
                    "name": "ig-token-cookie"
                  },
                  "amService": "AmService-1"
                }
              },
              {
                "name": "UserProfileFilter",
                "type": "UserProfileFilter",
                "config": {
                  "username": "${contexts.ssoToken.info.uid}",
                  "userProfileService": {
                    "type": "UserProfileService",
                    "config": {
                      "amService": "AmService-1"
                    }
                  }
                }
              },
              {
                "name": "JwtBuilderFilter-1",
                "type": "JwtBuilderFilter",
                "config": {
                  "template": {
                    "name": "${contexts.userProfile.commonName}",
                    "email": "${contexts.userProfile.rawInfo.mail[0]}"
                  },
                  "secretsProvider": "FileSystemSecretStore-1",
                  "signature": {
                    "secretId": "id.key.for.signing.jwt",
                    "algorithm": "RS512"
                  }
                }
              },
              {
                "name": "HeaderFilter-1",
                "type": "HeaderFilter",
                "config": {
                  "messageType": "REQUEST",
                  "add": {
                    "x-openig-user": ["${contexts.jwtBuilder.value}"]
                  }
                }
              }
            ],
            "handler": "ReverseProxyHandler"
          }
        }
      }
When verificationSecretId is not configured, IG discovers and uses the AM JWK set to verify the signature of AM session tokens. If the JWK set isn’t available, IG does not verify the tokens.
  1. Test the setup:

    1. Go to https://ig.example.com:8443/jwt.

      If you receive warnings that the site is not secure, respond to the warnings to access the site. The Identity Cloud login page is displayed.

    2. Log in to Identity Cloud as user demo, password Ch4ng3!t. The sample app displays the signed JWT along with its header and payload.

    3. In USE PEM FILE, enter the absolute path to id.key.for.verifying.jwt.pem to verify the JWT signature.