Pass Identity and Other Runtime Data Downstream

The following sections describe how to pass identity or other runtime information downstream to a protected application:

The examples in this section use the following objects:

  • JwtBuilderFilter to collect runtime information and pack it into a JWT

  • HeaderFilter to add the information to the forwarded request

For more information about these objects, see JwtBuilderFilter, HeaderFilter, and JwkSetHandler.

To help with development, the sample application includes a /jwt endpoint to display the JWT, verify its signature, and decrypt the JWT.

Pass Runtime Data in an Unsigned JWT

In this example, a JwtBuilderFilter takes the username and email from the UserProfileContext, and stores them in an unsigned, unencrypted JWT.

  1. Set up AM:

    1. (For AM 6.5.x and earlier versions) Select Identities > demo, and set the demo user password to Ch4ng31t.

    2. (For AM 6.5.3 and later versions) Select Services > Add a Service, and add a Validation Service with the following Valid goto URL Resources :

      • http://openig.example.com:8080/*

      • http://openig.example.com:8080/*?*

    3. Select Applications > Agents > Identity Gateway, add an agent with the following values:

  2. Set up IG:

    1. 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.

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

      • Linux

      • Windows

      $HOME/.openig/routes/static-resources.json
      appdata\OpenIG\config\routes\static-resources.json
      {
        "name" : "sampleapp-resources",
        "baseURI" : "http://app.example.com:8081",
        "condition": "${matches(request.uri.path,'^/css')}",
        "handler": "ReverseProxyHandler"
      }
    3. Add the following route to IG:

      • Linux

      • Windows

      $HOME/.openig/routes/jwt-builder.json
      appdata\OpenIG\config\routes\jwt-builder.json
      {
        "name": "jwt",
        "heap": [
          {
            "name": "SystemAndEnvSecretStore-1",
            "type": "SystemAndEnvSecretStore"
          },
          {
            "name": "AmService-1",
            "type": "AmService",
            "config": {
              "agent": {
                "username": "ig_agent",
                "passwordSecretId": "agent.secret.id"
              },
              "secretsProvider": "SystemAndEnvSecretStore-1",
              "url": "http://openam.example.com:8088/openam",
              "version": "7.1"
            }
          }
        ],
        "handler": {
          "type": "Chain",
          "config": {
            "filters": [{
              "name": "SingleSignOnFilter",
              "type": "SingleSignOnFilter",
              "config": {
                "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]}"
                }
              }
            }, {
              "name": "HeaderFilter-1",
              "type": "HeaderFilter",
              "config": {
                "messageType": "REQUEST",
                "add": {
                  "x-openig-user": ["${contexts.jwtBuilder.value}"]
                }
              }
            }],
            "handler": "ReverseProxyHandler"
          }
        },
        "condition": "${matches(request.uri.path, '/jwt$')}",
        "baseURI": "http://app.example.com:8081"
      }

      Notice the following features of the route:

      • The route matches requests to /jwt.

      • The agent password for AmService is provided by a SystemAndEnvSecretStore in the heap.

      • If the request does not have a valid AM session cookie, the SingleSignOnFilter redirects the request to authenticate with the AM server declared in the route or in the heap.

        If the request already has a valid AM session cookie, or after the user authenticates with AM, the SingleSignOnFilter passes the request to the next filter, and stores the cookie value in an SsoTokenContext.

      • The UserProfileFilter reads the username from the SsoTokenContext, uses it to retrieve the user’s profile info from AM, and places the data into the UserProfileContext.

      • The JwtBuilderFilter takes the username and email from the UserProfileContext, and stores them in a JWT in the JwtBuilderContext.

      • The HeaderFilter retrieves the JWT from the JwtBuilderContext, and adds it to the header field x-openig-user in the request.

      • The ClientHandler passes the request to the sample app, which displays the JWT.

  3. Test the setup:

    1. Log out of AM, and then go to http://openig.example.com:8080/jwt.

    2. Log in to AM as user demo, password Ch4ng31t, or as another user. The sample app displays the JWT along with its header and payload, and labels it as unsigned.

Pass Runtime Data in a JWT Signed With a Symmetric Key

This example builds on Pass Runtime Data in an Unsigned JWT, to sign the JWT with a symmetric key, and store the key in a SystemAndEnvSecretStore.

Before you start, run the example Pass Runtime Data in an Unsigned JWT.

  1. Set an environment variable for the base64-encoded secret to sign the JWT:

    $ export SIGNING_KEY_SECRET_ID='cGFzc3dvcmQ='
  2. Add the following route to IG:

    • Linux

    • Windows

    $HOME/.openig/routes/jwt-builder-signature-symmetric.json
    appdata\OpenIG\config\routes\jwt-builder-signature-symmetric.json
    {
      "name": "jwt-signature-symmetric",
      "condition": "${matches(request.uri.path, '/jwt-signature-symmetric')}",
      "baseURI": "http://app.example.com:8081",
      "heap": [
        {
          "name": "AmService-1",
          "type": "AmService",
          "config": {
            "agent": {
              "username": "ig_agent",
              "passwordSecretId": "agent.secret.id"
            },
            "secretsProvider": "SystemAndEnvSecretStore-1",
            "url": "http://openam.example.com:8088/openam",
            "version": "7.1"
          }
        },
        {
          "name": "SecretKeyPropertyFormat-1",
          "type": "SecretKeyPropertyFormat",
          "config": {
            "format": "BASE64",
            "algorithm": "AES"
          }
        },
        {
          "name": "SystemAndEnvSecretStore-1",
          "type": "SystemAndEnvSecretStore",
          "config": {
            "mappings": [{
              "secretId": "signing.key.secret.id",
              "format": "SecretKeyPropertyFormat-1"
            }]
          }
        }
      ],
      "handler": {
        "type": "Chain",
        "config": {
          "filters": [{
            "name": "SingleSignOnFilter-1",
            "type": "SingleSignOnFilter",
            "config": {
              "amService": "AmService-1"
            }
          }, {
            "name": "UserProfileFilter-1",
            "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": "SystemAndEnvSecretStore-1",
              "signature": {
                "secretId": "signing.key.secret.id",
                "algorithm": "HS256"
              }
            }
          }, {
            "name": "HeaderFilter-1",
            "type": "HeaderFilter",
            "config": {
              "messageType": "REQUEST",
              "add": {
                "x-openig-user": ["${contexts.jwtBuilder.value}"]
              }
            }
          }],
          "handler": "ReverseProxyHandler"
        }
      }
    }

    Notice the following features of the route compared to jwt-builder.json:

    • The route matches requests to /jwt-signature-symmetric.

    • The JWT signing key is managed by the SysEnvStoreSecretStore in the heap, which refers to the SecretKeyPropertyFormat for the secret’s format.

    • The JwtBuilderFilter signature property refers to the JWT signing key in the SysEnvStoreSecretStore.

  3. Log out of AM, and go to http://openig.example.com:8080/jwt-signature-symmetric.

  4. Log in to AM as user demo, password Ch4ng31t, or as another user. The sample app displays the signed JWT along with its header and payload.

  5. Enter information about the secret used to sign the JWT, and verify the signature.

Pass Runtime Data in a JWT Signed With an Asymmetric Key

This example builds on Pass Runtime Data in an Unsigned JWT, and signs the JWT with an asymmetric RSA key.

Before you start, run the example Pass Runtime Data in an Unsigned JWT.

  1. Generate a PKCS12 KeyStore that contains an RSA key:

    $ keytool \
    -genkeypair \
    -keyalg RSA \
    -keysize 2048 \
    -alias signature-key \
    -keystore /path/to/secrets/jwtbuilderkeystore.pkcs12 \
    -storepass password \
    -storetype pkcs12 \
    -dname "CN=openig.example.com,O=Example Corp,C=FR"
  2. Set an environment variable for the KeyStore storepass:

    $ export KEYSTORE_SECRET_ID='cGFzc3dvcmQ='
  3. Add the following route to IG:

    • Linux

    • Windows

    $HOME/.openig/routes/jwt-builder-signature-asymmetric.json
    appdata\OpenIG\config\routes\jwt-builder-signature-asymmetric.json
    {
      "name": "jwt-signature-asymmetric",
      "condition": "${matches(request.uri.path, '/jwt-signature-asymmetric')}",
      "baseURI": "http://app.example.com:8081",
      "heap": [
        {
          "name": "AmService-1",
          "type": "AmService",
          "config": {
            "agent": {
              "username": "ig_agent",
              "passwordSecretId": "agent.secret.id"
            },
            "secretsProvider": "SystemAndEnvSecretStore-1",
            "url": "http://openam.example.com:8088/openam",
            "version": "7.1"
          }
        },
        {
          "name": "SystemAndEnvSecretStore-1",
          "type": "SystemAndEnvSecretStore"
        },
        {
          "name":"KeyStoreSecretStore-1",
          "type": "KeyStoreSecretStore",
          "config": {
            "file": "/path/to/secrets/jwtbuilderkeystore.pkcs12",
            "storeType": "PKCS12",
            "storePassword": "keystore.secret.id",
            "keyEntryPassword": "keystore.secret.id",
            "secretsProvider": "SystemAndEnvSecretStore-1",
            "mappings": [{
              "secretId": "id.key.for.signing.jwt",
              "aliases": [ "signature-key" ]
            }]
          }
        }
      ],
      "handler": {
        "type": "Chain",
        "config": {
          "filters": [{
            "name": "SingleSignOnFilter-1",
            "type": "SingleSignOnFilter",
            "config": {
              "amService": "AmService-1"
            }
          }, {
            "name": "UserProfileFilter-1",
            "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": "KeyStoreSecretStore-1",
              "signature": {
                "secretId": "id.key.for.signing.jwt"
              }
            }
          }, {
            "name": "HeaderFilter-1",
            "type": "HeaderFilter",
            "config": {
              "messageType": "REQUEST",
              "add": {
                "x-openig-user": ["${contexts.jwtBuilder.value}"]
              }
            }
          }],
          "handler": "ReverseProxyHandler"
        }
      }
    }

    Notice the following features of the route compared to jwt-builder.json:

    • The route matches requests to /jwt-signature-asymmetric.

    • The JWT signing key is managed by the KeyStoreSecretStore in the heap, which maps the alias of the JWT signing key to its secret ID.

    • The password for the KeyStoreSecretStore is managed by the SystemAndEnvSecretStore in the heap.

    • The JwtBuilderFilter property signature refers to the mapping for the signing key in KeyStoreSecretStore.

  4. Log out of AM, and then go to http://openig.example.com:8080/jwt-signature-asymmetric.

  5. Log in to AM as user demo, password Ch4ng31t, or as another user. The sample app displays the signed JWT along with its header and payload.

  6. Enter information about the KeyStore, and verify the signature.

Pass Runtime Data in a Signed and Encrypted JWT

This example builds on Pass Runtime Data in a JWT Signed With an Asymmetric Key to encrypt the signed JWT by using a new key in the pkcs12 KeyStore.

  1. Generate another key in the KeyStore:

    $ keytool \
    -genkeypair \
    -keyalg RSA \
    -keysize 2048 \
    -alias encryption-key \
    -keystore /path/to/secrets/jwtbuilderkeystore.pkcs12 \
    -storepass password \
    -storetype pkcs12 \
    -dname "CN=openig.example.com,O=Example Corp,C=FR"
  2. Add the following route to IG:

    • Linux

    • Windows

    $HOME/.openig/routes/jwt-builder-encrypt.json
    appdata\OpenIG\config\routes\jwt-builder-encrypt.json
    {
      "name": "jwt-encryption",
      "condition": "${matches(request.uri.path, '/jwt-encryption$')}",
      "baseURI": "http://app.example.com:8081",
      "heap": [
        {
          "name": "SystemAndEnvSecretStore-1",
          "type": "SystemAndEnvSecretStore"
        },
        {
          "name": "AmService-1",
          "type": "AmService",
          "config": {
            "agent": {
              "username": "ig_agent",
              "passwordSecretId": "agent.secret.id"
            },
            "secretsProvider": "SystemAndEnvSecretStore-1",
            "url": "http://openam.example.com:8088/openam",
            "version": "7.1"
          }
        },
        {
          "name":"myKeyStoreSecretStore",
          "type": "KeyStoreSecretStore",
          "config": {
            "file": "/path/to/secrets/jwtbuilderkeystore.pkcs12",
            "storeType": "PKCS12",
            "storePassword": "keystore.secret.id",
            "keyEntryPassword": "keystore.secret.id",
            "secretsProvider": "SystemAndEnvSecretStore-1",
            "mappings": [
              {
                "secretId": "id.key.for.signing.jwt",
                "aliases": [ "signature-key" ]
              },
              {
                "secretId": "id.key.for.encrypting.jwt",
                "aliases": [ "encryption-key" ]
              }
            ]
          }
        }
      ],
      "handler": {
        "type": "Chain",
        "config": {
          "filters": [{
            "name": "SingleSignOnFilter-1",
            "type": "SingleSignOnFilter",
            "config": {
              "amService": "AmService-1"
            }
          }, {
            "name": "UserProfileFilter-1",
            "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": "myKeyStoreSecretStore",
              "signature": {
                "secretId": "id.key.for.signing.jwt",
                "encryption": {
                  "secretId": "id.key.for.encrypting.jwt",
                  "algorithm": "RSA-OAEP-256",
                  "method": "A128CBC-HS256"
                }
              }
            }
          }, {
            "name": "HeaderFilter-1",
            "type": "HeaderFilter",
            "config": {
              "messageType": "REQUEST",
              "add": {
                "x-openig-user": ["${contexts.jwtBuilder.value}"]
              }
            }
          }],
          "handler": "ReverseProxyHandler"
        }
      }
    }

    Notice the following features of the route compared to jwt-builder-signature-asymmetric.json:

    • The route matches requests to /jwt-encryption.

    • The KeyStoreSecretStore includes a secret ID mapping to the alias of the encryption key.

    • The JwtBuilderFilter adds a signature/encryption property to refer to the mapping for the encryption key in KeyStoreSecretStore.

  3. Go to http://openig.example.com:8080/jwt-encryption.

  4. Log in to AM as user demo, password Ch4ng31t, or as another user. The sample app displays the signed JWT along with its header and encryption info. Because the JWT is encrypted, the sample app doesn’t display the payload.

  5. Enter information about the KeyStore, and select Decrypt JWT to display the payload.

Pass Runtime Data in a JWT Signed With a PEM

This example builds on Pass Runtime Data in an Unsigned JWT, to sign the JWT with a PEM file format.

Before you start, run the example Pass Runtime Data in an Unsigned JWT.

  1. Locate the a directory for the PEM file, and in a terminal create a variable for it:

    $ export SECRETS_DIR=/path/to/secrets
  2. Generate a self-signed certificate and private key as PEM file:

    $ openssl req \
    -newkey rsa:2048 \
    -new \
    -nodes \
    -x509 \
    -days 3650 \
    -subj "/CN=openig.example.com/OU=example/O=com/L=fr/ST=fr/C=fr" \
    -keyout $SECRETS_DIR/id.key.for.signing.jwt.pem \
    -out certificate.pem
  3. Add the following route to IG, replacing value of the property secretsDir with the directory for the PEM file:

    • Linux

    • Windows

    $HOME/.openig/routes/jwt-builder-signature-pem.json
    appdata\OpenIG\config\routes\jwt-builder-signature-pem.json
    {
      "name": "jwt-builder-signature-pem",
      "condition": "${matches(request.uri.path, '/jwt-builder-signature-pem')}",
      "baseURI": "http://app.example.com:8081",
      "properties": {
        "secretsDir": "/path/to/secrets"
      },
      "capture": "all",
      "heap": [
        {
          "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"
            }]
          }
        },
        {
          "name": "SystemAndEnvSecretStore-1",
          "type": "SystemAndEnvSecretStore"
        },
        {
          "name": "AmService-1",
          "type": "AmService",
          "config": {
            "agent": {
              "username": "ig_agent",
              "passwordSecretId": "agent.secret.id"
            },
            "secretsProvider": "SystemAndEnvSecretStore-1",
            "url": "http://openam.example.com:8088/openam",
            "version": "7.1"
          }
        }
      ],
      "handler": {
        "type": "Chain",
        "config": {
          "filters": [{
            "name": "SingleSignOnFilter",
            "type": "SingleSignOnFilter",
            "config": {
              "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"
        }
      }
    }

    Notice the following features of the route compared to jwt-builder.json:

    • The route matches requests to /jwt-builder-signature-pem.

    • The JwtBuilderFilter refers to the secret ID of the PEM, and uses the FileSystemSecretStore to manage the secret.

    • The FileSystemSecretStore mapping refers to the secret ID of the PEM, and uses the PemPropertyFormat to define the format.

  4. In a clear browser, go to http://openig.example.com:8080/jwt-builder-signature-pem.

  5. Log in to AM as user demo, password Ch4ng31t, or as another user. The sample app displays the signed JWT along with its header and payload.

Pass Runtime Data in a JWT Signed and Encrypted With a PEM

This example builds on Pass Runtime Data in a JWT Signed With a PEM, to encrypt the JWT with a PEM.

Before you start, run the example Pass Runtime Data in a JWT Signed With a PEM.

  1. Encode the previously created PEM with a simple password encryptedpassword:

    $ openssl pkcs8 \
    -topk8 \
    -inform PEM \
    -outform PEM \
    -in $SECRETS_DIR/id.key.for.signing.jwt.pem \
    -out $SECRETS_DIR/id.encrypted.key.for.signing.jwt.pem \
    -passout pass:encryptedpassword \
    -v1 PBE-SHA1-3DES

    The encoded PEM is stored in id.encrypted.key.for.signing.jwt.pem. The password to decode the PEM is encryptedpassword.

    If encryption fails, make sure that your encryption methods and ciphers are supported by the Java Cryptography Extension.
  2. In IG, create an environment variable for the base64-encoded password to decode the PEM, and then restart IG:

    $ export ID_KEY_FOR_DECRYPT_PEM='ZW5jcnlwdGVkcGFzc3dvcmQ='
  3. Add the following route to IG, replacing value of the property secretsDir with the directory for the PEM file:

    • Linux

    • Windows

    $HOME/.openig/routes/jwt-builder-encrypt-pem.json
    appdata\OpenIG\config\routes\jwt-builder-encrypt-pem.json
    {
      "name": "jwt-builder-encrypt-pem",
      "condition": "${matches(request.uri.path, '/jwt-builder-encrypt-pem')}",
      "baseURI": "http://app.example.com:8081",
      "properties": {
        "secretsDir": "/path/to/secrets"
      },
      "capture": "all",
      "heap": [
        {
          "name": "SystemAndEnvSecretStore-1",
          "type": "SystemAndEnvSecretStore"
        },
        {
          "name": "AmService-1",
          "type": "AmService",
          "config": {
            "agent": {
              "username": "ig_agent",
              "passwordSecretId": "agent.secret.id"
            },
            "secretsProvider": "SystemAndEnvSecretStore-1",
            "url": "http://openam.example.com:8088/openam",
            "version": "7.1"
          }
        },
        {
          "name": "SystemAndEnvSecretStore-2",
          "type": "SystemAndEnvSecretStore",
          "config": {
            "mappings": [{
              "secretId": "id.key.for.decrypt.pem",
              "format": "BASE64"
            }]
          }
        },
        {
          "name": "pemPropertyFormat",
          "type": "PemPropertyFormat",
          "config": {
            "decryptionSecretId": "id.key.for.decrypt.pem",
            "secretsProvider": "SystemAndEnvSecretStore-2"
          }
        },
        {
          "name": "FileSystemSecretStore-1",
          "type": "FileSystemSecretStore",
          "config": {
            "format": "PLAIN",
            "directory": "&{secretsDir}",
            "suffix": ".pem",
            "mappings": [{
              "secretId": "id.encrypted.key.for.signing.jwt",
              "format": "pemPropertyFormat"
            }]
          }
        }
      ],
      "handler": {
        "type": "Chain",
        "config": {
          "filters": [{
            "name": "SingleSignOnFilter",
            "type": "SingleSignOnFilter",
            "config": {
              "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.encrypted.key.for.signing.jwt",
                "algorithm": "RS512"
              }
            }
          }, {
            "name": "HeaderFilter-1",
            "type": "HeaderFilter",
            "config": {
              "messageType": "REQUEST",
              "add": {
                "x-openig-user": ["${contexts.jwtBuilder.value}"]
              }
            }
          }],
          "handler": "ReverseProxyHandler"
        }
      }
    }

    Notice the following features of the route compared to jwt-builder.json:

    • The route matches requests to /jwt-builder-encrypt-pem.

    • The JwtBuilderFilter refers to the secret ID of the encoded PEM, and uses the FileSystemSecretStore to manage the secret.

    • The FileSystemSecretStore mapping refers to the secret ID of the encoded PEM, and uses the PemPropertyFormat to define the PEM format.

    • The PemPropertyFormat is an encrypted key that refers to the secret ID of the base64-encoded password to decode the PEM.

  4. In a clear browser, go to http://openig.example.com:8080/jwt-builder-encrypt-pem.

  5. Log in to AM as user demo, password Ch4ng31t. The sample app displays the encrypted JWT.