Digipass S3 is now DigipassONE. This section is currently being updated to reflect our new name.

Configuring JWT generation and validation

Prev Next

The architecture of the API Server uses plugins to separate functionality into configurable and customizable components. Many of these plugins use JSON Web Tokens (JWTs) to transmit and/or receive the following:

  • Session information — returned from Nok Nok FIDO and non-FIDO authentication

  • Transaction information — returned after transaction confirmation

  • Credentials for an externally authenticated user — sent by an RP server after verifying a user with an External Authentication Method

A JSON object, called jwt_config, controls and configures JWT validation and generation. jwt_config specifies what algorithm and key to use, where to find the key, how long the JWT is valid, and which servers can issue a JWT to the API Server. JWT configuration is tenant-specific and that tenant is assigned in jwt_config.

You need to understand and modify this configuration object, if you do any of the following:

  • Generate or validate a JSON Web Token (JWT) that uses a different key or an algorithm other than HS256

  • Add or remove a server as an issuer of a JWT

  • Change the JWT's lifetime

  • Update the audience, this is usually the tenant

  • Enable the API Server to accept JWTs created by your backend server(s)

  • Add more keys to a JSON Web Key Set (JWKS) object

  • Add a Java KeyStore as a source of JSON Web Keys (JWKs)

  • Add a URL as a source of JWKs

  • Change how long a user session can be valid

For each of these plugins, the table below lists the name of the JWT configuration object, the purpose of the JWT, if the plugin generates a JWT, and if the plugin validates an issued JWT.

API Server Component

Configuration Object

Purpose of the JWT

Generates JWT?

Validates JWT?

JWT Processor plugin

jwt_config

Session token

yes

yes

Transaction plugin

jwt_config

Transaction token

yes

no

External Authentication plugin

jwt_config

Credentials for the authenticated user when using an External Authentication Method

no

yes

Table JWT Information Summary for API Server plugins

Using a JWT as a session token is a key concept in the S3 Suite. To understand how the session token is used, see Understanding the Session Token. To understand how the S3 Suite uses JWTs for external authentication, see Configuring an External Authentication Method.

You can optionally create a Default JWT Config, a tenant-wide jwt_config that controls JWT generation and validation for all of that tenant's API Server plugins. If you create a locally-defined JWT configuration object for an API Server plugin, like the JWT Processor plugin, then the settings in that locally-defined configuration override those in the Default JWT Config.

JSON Web Token Format describes the token format and claim set used by Nok Nok JWTs. The claims in a transaction confirmation JWT are slightly different from the claims in a standard JWT used by most plugins. To understand how a transaction confirmation token is used, see Transactions in the Developer Guide for Android, iOS or Web.

Overview of the JWT Configuration Object and JWT Configuration Object Fields start off by describing the structure and fields found in jwt_config. This provides the context to understand how to update this object to accomplish various tasks. Supported Algorithms list all the supported cryptographic and content encryption algorithms that you can use.

When you first install the S3 Suite, it automatically installs the default tenant. Only the JWT Processor plugin is installed with a predefined JWT configuration object. You can easily generate JWT configuration objects with default settings for the Default JWT Config or the remaining API Server plugins, see Generating JWT Configuration Objects.

Most organizations need to modify the JWT Processor plugin's jwt_config, often replacing the encryption algorithm, changing keys, or adding their own servers as issuers. When to Modify a JWT Configuration Object provides detailed instructions on how to perform common updates for any API Server plugin.

Finally, you want a frictionless approach to manage public keys for your RP backend servers that validate JWTs issued by the API Server. Instead of manually updating the JWKS (JSON Web Key Set) in the RP Server's configuration, have your RP server use key rotation and access the JWKS stored at an endpoint. The API Server provides predefined URL endpoints where it stores its JWKS. See Rotating Keys for Your RP Servers.

Overview of the JWT Configuration Object

jwt_config contains two main objects: generate and validate. generate contains the information needed to generate a JWT while validate contains the information needed to verify a received JWT. Because each issuer could use a different algorithm, key source, as well as other settings, the information required to verify a JWT is segregated by issuer. Consequently, validate contains an array of issuer objects.

The following is an example jwt_config with default settings for the JWT Processor plugin. This configuration generates and validates a session token using the symmetric HS256 algorithm with one secret key. The generated session token has a lifespan of 1 hour.

{
    "generate":{
        "issuer":"https://myApiServer.com",
        "audiences":[
            "default"
        ],
        "nbf_delta":0,
        "encryption":"",
        "token_lifetime":3600,
        "kid":"hs256_key",
        "algorithm":"HS256",
        "jwks_object":{
            "keys":[
                {
                    "kty":"oct",
                    "use":"sig",
                    "kid":"hs256_key",
                    "k":"-MooF_CY4pElMmcNZu93BJQUeQg_E9HwBu1LONc_WXA"
                }
            ]
        },
        "jwks_keystore":{
            "file":"/usr/share/tomcat/cert/keystore.jks",
            "storepass":"changeit",
            "keypass":{
                "alias":"hs256_key",
                "pass":"MyPrivateKeyPassword"
            }
        }
    },
    "validate":{
        "issuers":[
            {
                "issuer":"https://myApiServer.com",
                "audiences":[
                    "default"
                ],
                "encryption":"",
                "token_lifetime":3600,
                "max_clock_skew":180,
                "algorithm":"HS256",
                "jwks_object":{
                    "keys":[
                        {
                            "kty":"oct",
                            "use":"sig",
                            "kid":"hs256_key",
                            "k":"-MooF_CY4pElMmcNZu93BJQUeQg_E9HwBu1LONc_WXA"
                        }
                    ]
                },
                "jwks_keystore":{
                    "file":"/usr/share/tomcat/cert/keystore.jks",
                    "storepass":"changeit",
                    "keypass":{
                        "alias":"hs256_key",
                        "pass":"MyPrivateKeyPassword"
                    }
                },
                "jwks_uri":"https://evaluation93.noknoktest.com:8443/gwtutorial/jwks.json"
            }
        ]
    }
}

JWT Configuration Object Fields

This section starts by covering the 3 types of key sources that can be used in a JWT configuration object because key sources are specified in both the generate and validate objects. You can also use a certificate chain as an alternate way to provide a key and validate a JWT. Finally, the section describes the fields that are present in the generate and validate objects.

Key Sources

JWT generation and validation require that you specify a key source where the key required to sign or decrypt the JWT can be found. jwt_config enables you to specify up to 3 sources for your JWT keys.

Key Source

Corresponding Field

Note

JSON Web Key Set (JWKS)

jwks_object

Embedded in the JWT configuration object and stored in the Server database. Easy to read because it's in text format.

Tutorial Web App includes a sample JSON Web Key (JWK) Set file located at gwtutorial/jwks.json.

Java KeyStore

jwks_keystore

Stored outside of the Server databases. Protected by a password.

URL

jwks_uri

Only used to verify JWTs. Intended for storing public asymmetric keys at a single URL.

List of URLs

jwks_uris

Only used to verify JWTs. Intended for storing public asymmetric keys at multiple URLs.

In the generate object, only one of jwks_object or jwks_keystore is required, although you can use both.

In the validate object, only one of jwks_object, jwks_keystore, jwks_uri, or jwks_uris is required. You can use either jwks_uri or jwks_uris. You can choose to use all 3 types of key stores (JWKS, Java KeyStore, and URL(s)) or any combination.

All keys from all specified sources are fetched and cached by the Server. In the case of multiple key sources, which key to use for validation is based on the algorithm and kid from the JWT header. Which key to use for generation is determined by the algorithm and kid found in the generate section of the jwt_config. Make sure that the kid for each keys is unique.

For instructions on how to automatically rotate asymmetric public keys, see Rotating Public Keys for JWT Validation.

Using a Certificate Chain

A certificate chain is an additional mechanism for providing a key and validating a JWT. The API Server can assign a certificate chain to a JWT's x5c header parameter when it generates a JWT. It can also validate JWTs that contain a certificate chain.

To generate a JWT that contains a certificate chain, the JWK that the API Server uses from its generate object must have a certificate chain assigned to its x5c parameter. That key is stored in a Java Keystore or JWKS.

To validate a JWT that contains a certificate chain, you specify your Public Key Infrastructure (PKI) in jwt_config for the appropriate issuer. The API Server checks the pki object in jwt_config's validate object to determine if it should validate the certificate chain. The pki object includes the trust store and options for checking for revoked certificates. The fields of the pki object are described in validate fields.

generate Fields

The values contained in these fields specify the values that are assigned to the claim set when the API Server creates a JWT.

Field Name

Description

algorithm

Mandatory. String. The cryptographic algorithm for a JWT.

For valid values, refer to Cryptographic Algorithms.

audiences

Mandatory. An array containing one string: a Nok Nok tenant name. This jwt_config was created for this tenant. Used as the value for the aud claim.

encryption

Mandatory for a JWE. String. The content encryption algorithm for a JWE. When encryption has a value, algorithm must contain one of the JWE algorithms listed in Encrypted JWT (JWE).

For valid values, refer to Content Encryption Algorithms.

issuer

Mandatory. String. Your API Server's URL. For example, "https://example.com:8443". When the API Server generates a JWT, it inserts this as the value for the JWT's iss claim.

jti_claim

Optional. Boolean. Whether to include the jti claim in the JWT.

  • true: Generate a unique identifier and assign it to the jti claim.

  • false (default): Don't include the jti claim.

jwks_cache_refresh_interval

Optional. Integer. The amount of time, in seconds, to wait before updating the key cache (JWK set). For details, see Rotating Private Keys for JWT Generation. You can control cache refresh by using one of the values below.

  • -1 (default): The key cache is not refreshed.

  • 0: The key cache is always updated.

jwks_keystore

Optional if you use jwks_object.

An object containing information about a Java KeyStore. Contains the subfields listed in the rows below.

If you use a file for your Java Keystore, you must provide the following fields:

  • jwks_keystore.file

  • jwks_keystore.storepass

  • jwks_keystore.keypass.alias

You can optionally provide jwks_keystore.keypass.pass.

jwks_keystore.file

Optional. String. The full path of the Java KeyStore file.

jwks_keystore.keypass.alias

Optional. String. The key's alias name in the KeyStore.

The alias's name must be the same as the key id, in other words, kid = jwks_keystore.keypass.alias.

jwks_keystore.keypass.pass

Optional. String. The password for the key. If a key password is not specified, then the value of jwks_keystore.storepass is used. An empty password (i.e. password length is 0) assumes that the key is not protected in the KeyStore.

jwks_keystore.keys

Optional. A stringified JSON array with key references used when jwks_keystore.provider (below) contains the value "NokNokCryptoProvider".

jwks_keystore.provider

Optional. String. Name of the security provider to use.

This must be set to "NokNokCryptoProvider" if you are creating a Crypto Plugin. Nok Nok assumes that you have configured this provider in your Java platform, see Oracle's How to Implement a Provider in the Java Cryptography Architecture, Step 8.1 Configure the Provider.

jwks_keystore.storepass

Optional. String. The password for the KeyStore.

jwks_keystore.type

Optional. String. Type of the KeyStore to use. Defaults to JKS. Can be a standard keystore type, e.g. PKCS12, or a custom one.

jwks_object

Optional if you use jwks_keystore. JWK set object.

kid

Optional. String. The key identifier. Must match one of the keys contained in jwks_object or one of the aliases in jwks_keystore. The API Server uses this to identify the key to use with the algorithm. If omitted, the first key in the set that matches the specified algorithm is used.

The API Server inserts this into the header of the generated JWT.

nbf_delta

Optional. Integer, 0 or greater. Additional time from the JWT issue time that is specified by the iat claim in seconds to generate an nbf claim. Default is 0.

token_lifetime

Mandatory. Integer, 0 or greater. Token lifetime in seconds. Used to calculate the generated JWT's expiration time exp claim.

The token expiration time is calculated as

max(iat, nbf) + token_lifetime

type

Optional. String. The media type. The API Server assigns type's value to the generated JWT's typ header parameter. The default is an empty string. If your backend servers don't use media type, use the default value.

For more about typ and media types see typ in RFC 7519.

validate Fields

The validate object has one top-level field, an array called issuers. Each item in the issuers array is an object that corresponds to an issuer. The API Server uses the issuer object to validate JWTs it receives from that issuer. The field descriptions for the issuer object are listed in the table below.

Your backend servers that generate and send JWTs to the API Server are candidates whose information could be added to issuers. If you have backend servers that use the same cryptographic algorithm and sources for keys, then they are logically the same issuer and need only one issuer object to represent them. The JWTs that they send to the API Server must match the information contained in their issuer object.

Field Name

Description

absolute_timeout

Optional. Integer. Absolute timeout of the user session in seconds. Prevents JWTs from being renewed indefinitely. If the amount of time in absolute_timout has elapsed since the user last authenticated, this forces them to reauthenticate.

The API Server first checks if the JWT has expired. If the JWT is valid and has values for the auth_time claim and absolute_timeout field, the API Server verifies that the time passed since auth_time is less than absolute_timeout.

algorithm

Optional. String. The cryptographic algorithm for a JWT. If specified, the algorithm in the JWT header is checked against this field for matching. If it doesn't match, then the validation fails.

For valid values, refer to Cryptographic Algorithms.

audiences

Mandatory. An array containing one string: a Nok Nok tenant name. If the API Server is the issuer, then audiences must match generate.audiences.

encryption

Mandatory for a JWE. String. The content encryption algorithm for a JWE. When encryption has a value, algorithm must contain one of the JWE algorithms listed in Encrypted JWT (JWE).

For valid values, refer to Content Encryption Algorithms.

issuer

Mandatory. String. The issuer's URL. Must match the JWT's iss claim.

Two or more of your backend servers can share the issuer object, as long as they use the same field values, as described above, to generate their JWTs. The API Server ignores the backend server's web origin.

jwks_cache_refresh_interval

Optional. Integer. The amount of time, in seconds, to wait before updating the key cache (JWK set). See Rotating Private Keys for JWT Generation for details. You can control cache refresh by using one of the values below.

  • -1 (default): The key cache is not refreshed.

  • 0: The key cache is always updated.

jwks_keystore

Optional if you use one of jwks_object, jwks_uri or jwks_uris. An object containing information about a Java KeyStore. Contains the 6 fields listed in the rows below.

If you use a file for your Java Keystore, you must provide the following fields:

  • jwks_keystore.file

  • jwks_keystore.storepass

  • jwks_keystore.keypass.alias

You can optionally provide jwks_keystore.keypass.pass.

jwks_keystore.file

Optional. String. The full path of the Java KeyStore file.

jwks_keystore.keypass.alias

Optional. String. The key’s alias name in the KeyStore.

The alias's name must be the same as the key id from the JWT's header in order to match the KeyStore's key.

jwks_keystore.keypass.pass

Optional. Specifies the key password in the keyStore. If a key password is not specified, then the KeyStore password is used. An empty password, or password length of 0, assumes that the key is not protected in the KeyStore.

jwks_keystore.provider

Optional. String. Name of the security provider to use.

Nok Nok assumes that you have configured this provider in your Java platform, see Oracle's How to Implement a Provider in the Java Cryptography Architecture, Step 8.1 Configure the Provider.

jwks_keystore.storepass

Optional. The password for KeyStore.

jwks_keystore.type

Optional. String. Type of the KeyStore to use. Defaults to JKS. Can be a standard keystore type or a custom one.

jwks_object

Optional if you use one of jwks_keystore, jwks_uri or jwks_uris. JWKS object.

jwks_uri

Optional if you use one of jwks_object, jwks_keystore, or jwks_uris. String. URL where a JWK set is located. The URL should only contain public asymmetric keys. Can be used to implement key rotation.

jwks_uris

Optional if you use one of jwks_object, jwks_keystore, or jwks_uri. An array of strings. Each element is a URL where a JWK set is located. The URL should only contain public asymmetric keys. Can be used to implement key rotation.

max_clock_skew

Optional. Integer. The maximum clock skew in seconds. Accounts for clock skew when processing exp, nbf, or iat claims. Default: 60 seconds.

pki

Optional. An object containing information about a Public Key Infrastructure (PKI). Specifies options for certificate chain validation. Used when the JWT header includes the x5c attribute containing a certificate chain. Contains the fields listed below.

pki.enabled

Mandatory if you use pki. Boolean.

  • true: The API Server validates the certificate chain in the JWT's x5c header attribute, then uses the key from an end entity (EE) certificate in the chain to validate the signature.

  • false (default): The API Server does not validate the certificate chain and does not use the key in the chain to validate the signature.

pki.truststore

Optional. An object containing information about a trust store. The trust store contains the trusted root certificates used to validate the certificate chain. Contains the 5 fields listed below.

If not specified, the system default trust store is used.

Specify the default trust store using Java system properties.

pki.truststore.type

Optional. String. Type of the KeyStore to use as a trust store. Defaults to JKS. Can be a standard keystore type or a custom one.

pki.truststore.provider

Optional. String. Name of the security provider to use.

If not specified, the default provider is used. Nok Nok assumes that you have configured this provider in your Java platform, see Oracle's How to Implement a Provider in the Java Cryptography Architecture, Step 8.1 Configure the Provider.

pki.truststore.file

Optional. String. The full path of the Java trust store file.

pki.truststore.storepass

Optional. String. The password for the trust store.

pki.truststore.update_check_interval

Optional. Integer. Amount of time, in seconds, to wait before reloading the trust store. Defaults to -1 which means the trust store is loaded once and never reloaded.

pki.revocation

Optional. An object that specifies certificate revocation checking options. If not specified, revocation check is not performed. Contains the 2 fields below.

pki.revocation.enabled

Optional. Boolean.

  • true: Check for revoked certificates.

  • false (default): Do not check for revoked certificates.

pki.revocation.options

Optional. Array of strings. Specifies options to use to check for revoked certificates. See Oracle’s PKIXRevocationChecker.Option for valid values and defaults. Strings are not case sensitive.

token_lifetime

Optional. Integer. Must be 0 or greater. Defaults to 0. JWT lifetime in seconds. Verifies the age of the JWT if the iat or nbf claim is available.

The API Server verifies that the JWT is still valid by comparing its age to its exp claim. If the JWT is valid and token_lifetime has a value, the API Server next compares the JWT's age to token_lifetime.

Token age is calculated as
max(iat, nbf) + token_lifetime

type

Optional. String. The media type of the JWT. The API Server checks the typ parameter in the incoming JWT's header against type's value.

Supported Algorithms

Cryptographic Algorithms

JWTs can use the cryptographic algorithms listed in the tables below. Assign the strings in the Value column to jwt_config's algorithm parameter.

Signed JWT (JWS)

JWT with HMAC protection (symmetric)

Value

Description

HS256

HMAC with SHA-256, requires 256+ bit secret

HS384

HMAC with SHA-384, requires 384+ bit secret

HS512

HMAC with SHA-512, requires 512+ bit secret

JWT with RSA Signature (asymmetric)

Value

Description

RS256

RSA PKCS#1 signature with SHA-256

RS384

RSA PKCS#1 signature with SHA-384

RS512

RSA PKCS#1 signature with SHA-512

JWT with ECDSA Signature (asymmetric)

Value

Description

ES256

ECDSA with SHA-256

ES384

ECDSA with SHA-384

ES512

ECDSA with SHA-512

Encrypted JWT (JWE)

All encryption algorithms listed below work with any of the six standard available content encryption algorithms listed in Content Encryption Algorithms.

JWE with shared key

Value

Description

dir

Direct use of a shared symmetric key as the Content Encryption Key (CEK) for the block encryption step (rather than using the symmetric key to wrap the CEK).

JWT with AES encryption

AES and AES GCM key wrap encryptor of JWE objects

Value

Description

A128KW

AES Key Wrap Algorithm (RFC 3394) using 128-bit keys

A192KW

AES Key Wrap Algorithm (RFC 3394) using 192-bit keys

A256KW

AES Key Wrap Algorithm (RFC 3394) using 256-bit keys

A128GCMKW

AES in Galois/Counter Mode (GCM) (NIST.800-38D) 128-bit keys

A192GCMKW

AES in Galois/Counter Mode (GCM) (NIST.800-38D) 192-bit keys

A256GCMKW

AES in Galois/Counter Mode (GCM) (NIST.800-38D) 256-bit keys

JWT with RSA encryption

Value

Description

RSA1_5

RSAES PKCS1 V1.5

RSA-OAEP

RSAES using Optimal Asymmetric Encryption Padding (OAEP) (RFC 3447)

RSA-OAEP-256

RSAES using Optimal Asymmetric Encryption Padding (OAEP) (RFC 3447), with the SHA-256 hash function and the MGF1 with SHA-256 mask generation function.

JWT with ECDH encryption

Elliptic Curve Diffie-Hellman encryptor of JWE objects

Value

Description

ECDH-ES

Elliptic Curve Diffie-Hellman Ephemeral Static (RFC 6090) key agreement using the Concat KDF, as defined in section 5.8.1 of NIST.800-56A, with the agreed-upon key being used directly as the Content Encryption Key (CEK) (rather than being used to wrap the CEK)

ECDH-ES+A128KW

Elliptic Curve Diffie-Hellman Ephemeral Static key agreement per ECDH-ES, but where the agreed-upon key is used to wrap the Content Encryption Key (CEK) with the A128KW function (rather than being used directly as the CEK)

ECDH-ES+A192KW

Elliptic Curve Diffie-Hellman Ephemeral Static key agreement per ECDH-ES, but where the agreed-upon key is used to wrap the Content Encryption Key (CEK) with the A192KW function (rather than being used directly as the CEK)

ECDH-ES+A256KW

Elliptic Curve Diffie-Hellman Ephemeral Static key agreement per ECDH-ES, but where the agreed-upon key is used to wrap the Content Encryption Key (CEK) with the A256KW function (rather than being used directly as the CEK)

Content Encryption Algorithms

A JWE can use the content encryption algorithms listed in the table below. Assign the strings in the Value column to jwt_config's encryption parameter.

Value

Description

A128CBC-HS256

AES 128 CBC HMAC SHA 256 authenticated encryption using a 256-bit key

A192CBC-HS384

AES 192 CBC HMAC SHA 384 authenticated encryption using a 384-bit key

A256CBC-HS512

AES 256 CBC HMAC SHA 512 authenticated encryption using a 512-bit key

A128GCM

AES in GCM mode using a 128-bit key

A192GCM

AES in GCM mode using a 192-bit key

A256GCM

AES in GCM mode using a 256-bit key

Generating JWT configuration objects

After you install the S3 Suite or create a new tenant, many of the API Server plugins do not have a JWT configuration object defined for them, and the default JWT configuration object is also not defined yet. Prepare your own JWT configuration objects with your preferred algorithm and options. Customize them using the instructions in When to Modify jwt_config. Finally, upload the JWT configuration objects to the API Server.

Use the instructions in this section to generate configuration objects with default settings for the Default JWT Config or any API Server plugin. You can either use the Admin Console or nnl-mgmt.sh to generate JWT configuration objects.

When you use the Admin Console to generate a JWT configuration object it contains both the generate and validate objects. This is true even if the API Server plugin only generates a JWT or only validates a JWT. The API Server plugin ignores the fields in the generate or validate object if it doesn't need it.

The Default JWT Config

The Default JWT Config object is defined in the API Server's Main object.

The default settings generate and validate a JWT using the symmetric HS256 algorithm with one secret key. The generated JWT has a lifespan of 1 hour. For a production deployment, replace this with a JWT that uses an asymmetric algorithm.

Using the Admin Console

  1. Login and, if needed, switch to the desired tenant. Navigate to Configuration > API Server > Authentication API.

  2. Expand the Main panel. Find the Default JWT Config label and click its Generate button. Confirm that you want to generate a new configuration object. To view the configuration, click the Default JWT Config label.

Using nnl-mgmt.sh

Use the nnl-mgmt.sh's apiserver create command to generate a Default JWT Config. For details on apiserver create command, see API Server Configuration Commands. In the example below, replace https://myAPIServer.com with the URL for your API Server.

./nnl-mgmt.sh apiserver create -tenantid newtenant -type Main -name jwt_config -issuer "https://myAPIServer.com"

Configuring an API Server component to use the default JWT Config

You can explicitly set any API Server Component to use the Default JWT Config instead of its locally-defined JWT configuration object.

Using the Admin Console
  1. Login and, if needed, switch to the desired tenant.

  2. Navigate to Configuration > API Server.

  3. Find the panel containing the API Server plugin and expand it, click the Modify icon next to the plugin.

  1. In the plugin configuration page click the Use Default button.

  2. If the Use Default button is inactive, then the plugin is already using the Default JWT Config. If this is the case, you see a screen similar to what is shown below when you click the name of the API Server plugin.

Using nnl-mgmt.sh

Use the nnl-mgmt.sh's apiserver delete command to delete the API Server plugin's locally-defined JWT configuration object. This forces the plugin to use the Default JWT Config.

The example below deletes the JWT External Authentication plugin's JWT configuration object. For details on apiserver delete command, see reference to the API Server Configuration Commands.

./nnl-mgmt.sh apiserver delete -tenantid Marketing -type ExternalAuthenticationPlugin -name jwt_config

JWT Processor plugin

The default settings for this plugin's configuration object generate and validate a session token using the symmetric HS256 algorithm with one secret key. The generated JWT has a lifespan of 1 hour. The API Server is configured as a server that generates and issues JWTs. So the API Server appears in the validate object as an issuer. For a production deployment, replace the symmetric algorithm with an asymmetric algorithm which is more secure.

Using the Admin Console

  1. Login and, if needed, switch to the desired tenant. Navigate to Configuration > API Server > Authentication API.

  2. Expand the Session Plugins panel. Find the JWT Processor label and click the Edit icon. In the plugin’s configuration page click the Generate button. Confirm that you want to generate a new configuration object. To activate the plugin, go back to plugin list and click the activate icon.

Using nnl-mgmt.sh

Use the nnl-mgmt.sh's apiserver create command to generate new JWT configuration objects. In the example below, replace https://example.com with the URL for your API Server.

./nnl-mgmt.sh apiserver create -tenantid newtenant -type SessionPlugin -name jwt_config -issuer "https://example.com"

Transaction plugin

The default JWT configuration for this plugin generates a JWT using the symmetric HS256 algorithm with one secret key. The generated JWT has a lifespan of 1 hour. For a production deployment, replace this with a JWT that uses an asymmetric algorithm. This plugin does not validate a JWT.

Using the Admin Console

  1. Login and, if needed, switch to the desired tenant. Navigate to Configuration > API Server > Authentication API.

  2. Expand the Transaction Plugin panel. Find the JWT Transaction Processor label and click the Edit icon. In the plugin’s configuration page click the Generate button. Confirm that you want to generate a new configuration object. To activate the plugin, go back to plugin list and click the activate icon.

Using nnl-mgmt.sh

Use the nnl-mgmt.sh's apiserver create command to generate new JWT configuration objects. In the example below, replace https://example.com with the URL for your API Server.

./nnl-mgmt.sh apiserver create -tenantid newtenant -type TransactionPlugin ‑name jwt_config ‑issuer "https://myAPIServer.com"

JWT External Authentication Plugin

The default JWT configuration for this plugin validates a JWT with a lifespan of 3 minutes that was encoded using the symmetric HS256 algorithm with one secret key. This plugin does not generate a JWT.

Using the Admin Console

When you generate a JWT configuration object for the JWT External Authentication plugin using the Admin Console, the API Server appears as an issuer in the validate object. After generation, edit the JWT configuration object and replace the API Server's URL with the URL of your RP server that is responsible for authenticating the user and issuing the JWT. Refer to Adding an Additional Issuer.

  1. Login and, if needed, switch to the desired tenant. Navigate to Configuration > API Server > Authentication API.

  2. Expand the External Authentications Plugins panel. Find the JWT Authentication Method label and click the Edit icon. In the plugin’s configuration page click the Generate button. Confirm that you want to generate a new configuration object. To activate the plugin, go back to plugin list and click the Activate icon.

Using nnl-mgmt.sh

Use the nnl-mgmt.sh's apiserver create command to generate a new JWT configuration object. In the example below, replace https://example.com with the URL for your RP server that will authenticate the user and issue a JWT.

./nnl-mgmt.sh apiserver create -tenantid newtenant -type ExternalAuthenticationPlugin -name jwt_config -issuer "https://example.com"

When to modify a JWT configuration object

While the built-in support for a JWT signed with HS256 is easy and convenient, your circumstances can dictate that you use a different key, a different algorithm, a JWE instead of a JWS, and so on. This section identifies common scenarios that require updating a JWT configuration object and lists the fields that you need to change.

The instructions in the subsections below outline which jwt_config fields to modify. These instructions assume that you are familiar with the structure and fields in jwt_config. For detailed information about jwt_config, see JWT Configuration Object Fields.

Note: When you export a JWT Configuration Object, the private keys are obscured. When you import the modified JWT Configuration Object back into the API Server, the obscured keys are skipped and the corresponding keys from the existing JWT Configuration Object are preserved.

Adding an Additional Issuer

This task only applies to the JWT Processor and JWT External Authentication plugins.

The JWT Processor and the JWT External Authentication plugins can validate JWTs issued by your backend servers. Your backend servers that issue JWTs to the API Server are candidates for issuers to add to jwt_config. If you have backend servers that use the same cryptographic algorithm and sources for keys, then they are logically the same issuer and need only one issuer item in the issuers array.

Begin by exporting the JWT configuration object. Open this file in an editor. To create a new issuer object in the validate.issuers array, copy an existing issuer from that array. Update the following fields:

Field

Updated Value

issuer

The URL of your backend server

algorithm

The algorithm used by your backend servers to encrypt the JWT

Specify the JWK source. At least one of the following.

jwks_object

Your JWKS object

jwks_keystore

Your Java KeyStore

jwks_uri

Your URL

jwks_uris

Your array of URLs

{
        "issuer": "https://myApiServer.com",
        "audiences": [
          "default"
        ],
        "encryption": "",
        "token_lifetime": 3600,
        "max_clock_skew": 180,
        "algorithm": "HS256",
        "jwks_object": {
          "keys": [
            {
              "kty": "oct",
              "use": "sig",
              "kid": "hs256_key",
              "k": "-MooF_CY4pElMmcNZu93BJQUeQg_E9HwBu1LONc_WXA"
            }
          ]
        }
      }

Insert your new issuer object into the validate.issuers array and save. Then import the updated JWT configuration object into your API Server plugin.

Updating the Algorithm and Key

The fields that you update depend on whether you use a symmetric or asymmetric algorithm.

  • If you are updating the algorithm and key in the JWT Processor plugin's JWT configuration object, follow the instructions below to update both the generate and validate objects.

  • For the Transaction plugin, only update the generate object.

  • If you are updating your backend server's algorithm and key, update your server's issuer object in the validate.issuers array. No changes are needed to the generate object. This applies to the JWT Processor or External Authentication plugins.

Symmetric Algorithm

Export the JWT configuration object.

In the generate object, modify the following properties. For a list of valid algorithms, see Supported Algorithms.

  • algorithm: Assign the algorithm you are using

  • kid: Assign your secret key's ID

  • jwks_object: If you use this as your key source, update an existing JSON Web Key (JWK) object with your key's JWK or insert your key's JWK in the keys array.

  • jwks_keystore: Technically, you aren't changing this field's value. If you've set up a Java KeyStore using this object, update or insert your key's JWK in this KeyStore.

In the validate object, in the issuer object corresponding to the API Server, modify the following properties:

  • algorithm: Assign the algorithm you are using

  • jwks_object: If you use this as your key source, update or insert your key's JWK in the keys array.

  • jwks_keystore: Technically, you aren't changing this field's value. If you've set up a Java KeyStore using this object, update or insert your public key's JWK in this KeyStore.

Import the updated configuration object.

Asymmetric Algorithm

Asymmetric algorithms generate 2 keys: private and public. The private key's information goes into the generate object while the public key's information goes into the validate object.

Export the JWT configuration object. In the generate object, modify the following properties. For a list of valid algorithms, see Supported Algorithms.

  • algorithm: Assign the algorithm you are using

  • kid: Assign your private key's ID

  • jwks_object: If you use this as your key source, update an existing JSON Web Key (JWK) object with your private key's JWK or insert your private key's JWK in the keys array

  • jwks_keystore: Technically, you aren't changing this field's value. If you've set up a Java KeyStore using this object, update or insert your private key's JWK in this KeyStore.

In the validate object, for the issuer affected by this change, modify the following properties:

  • algorithm: Assign the algorithm you are using

  • jwks_object: If you use this as your key source, update an existing JWK object with your public key's JWK or insert your public key's JWK in the keys array

  • jwks_keystore: Technically, you aren't changing this field's value. If you've set up a Java KeyStore using this object, then update or insert your public key's JWK in this KeyStore.

  • jwks_uri: Assign a server URL, if this field is blank and you choose to use this as your key source. In the JWK set stored at the server, update or insert the public key in the JWK set.

  • jwks_uris: Update an existing server URL in the array or add a new one if you choose to use this as your key source. In the JWK set stored at the servers, update or insert the public key in the JWK set.

Import the updated configuration object.

The example below shows a jwt_config for the JWT Processor plugin that was modified to use an RSA 256 algorithm with a private key of "EPoe1856". This configuration object uses a jwks_object as the key source. The updated fields and their values are highlighted.

{
  "generate":{
    "issuer":"https://example.com:8443",
    "audiences":[
      "default"
    ],
    "nbf_delta":0,
    "encryption":"",
    "token_lifetime":3600,
    "kid":"EPoe1856",
    "algorithm":"RS256",
    "jwks_object":{
      "keys":[
        {
          "p":"63LVPDjFtKRRMNrjq1-PPj4d1z5Re8lRySH67OMIrlpYtmoutpIgKb2av2DBBkGzK_48gxIlpZdusw9AOHqksdQ7vIshBz1OA1odBs3dVPeBUvdZNQ3EBJ_wGLEOCHbrWnPxFxWkeUH8x0xhXxeQUepBI-dLh0cx1IZhu48ZoHE",
          "kty":"RSA",
          "q":"qujNF7q3HsfRS2bRxdfjcBdCh1acUMIhrM7DZthgLTuHhtq2oentMeKic3dWUdaKvpi2jU2_E63A96no5lZJ3JIUH1ldpG5eLwpbkT1uv0sapEVjCW0WJWwt5w0cCPOGsAOJeMnbKWrGZZFKb_88qzaV2zvdnJLyGx-8poj-Jcc",
          "d":"h11990yS4m_vm6sdr7LfjDm1nOFxBiEtJLzWuBwlaRuoMMOP-e2kmpY5q_JFv_M78_TdO5GbUbuLQV3K9AkpzZRVqavXd9HfBQlCN_kBg3bQH9fl_KabSd6tRtQHuhIcfGTmYdDpY7FjlcRzlXuKqvcHEkl7UlIZM1sSUIwD6PbAK66g4DIM_lMCJEvE2c6GPME-P5y5KVc7SuU_yjjeOdV2vGxhMoTn9FVp34_qB0_T787_E0JY6c6GZt6baXvFeoSAF6E060ovzMNmGt3fckvzw_Pco6De6Y3NsOVQ5_FZxgYimKOWcsXvxzHlYAV4GiRcycUNOEzOhN20TL0NwQ",
          "e":"AQAB",
          "use":"sig",
          "kid":"EPoe1856",
          "qi":"6CF-N3u2ex-1ZfrlzNTrIPwQVrHoExOEj84T295vEYTudW-xYMzZU95GCLL0C0x8j7zqqAN5WVkVcKPP8w6bBRGcMC3ZkjOIJ9zS_SYxlK1cJe22dOu3U5AOrONsryGYQhrRRDEmLF54EBXv3_UeJ71fLJgRNLzaohnIgglqIt8",
          "dp":"KgemvwhXaqbGg5UffTEizfaitxC91P4cJm51b6Ibo5wnJ_EOg7LUIP9ix3ULIAXMaTcKME-l_shoj3hSe4KRMdl0DHU9oSA1c-27LsLDFu7T3C6hcxIRAs5WOuIoYiRwYQY_bGKFqMu5xw4Ad8wqDCVoGXOpjO2NnKWcfrHN3lE",
          "alg":"RS256",
          "dq":"SMTWjkPxtClf87rTlmlVbWR57yXxaHE_5VQj3qZCTQALtF9rY4U2eQcGJCOrnSy75msfTwrLUJWqk8jEYU5cJI4OA0sJk_lqIJ1IX47ImKphrY_dmyXXSBfHc5khVq5ZqpfW8JcBuaC82IIEL6t9KWkUZUQYF5J5gxMAP-gUTgE",
          "n":"nTBeTAQS-VOpSfm_HMUAg1SfOT-cmzZKwtr0-2CTyXbt8JOfEH2xkLykbdL-L8bv8rjx971DFW6HB8Lf_ll1ETNxfVEnQKlZWB3cf4d-32f4oKU1J56j293QLgTD6H50rQ_X0uQsQWcimwCvv-mAmwdB979Ahwz_dAWT5cGo81OhM2m0IpopJP4sM_uJdr-18QnyLSjqPxXlXwPP16Tzup2gf0BcwKCNOkbvBukKDf_AlciOmijfZB5sEepmBZvTKn3iK8Bc2y2aeDndm9JRR1CYwMHMeuU1C14SBqBNHVgz7CbuUvnELdSBTaBBASsHV2sizLIYDkIx07JqKToM1w"
        }
      ]
    }
  },
  "validate":{
    "issuers":[
      {
        "issuer":"https://example.com:8443",
        "audiences":[
          "default"
        ],
        "encryption":"",
        "token_lifetime":3600,
        "max_clock_skew":180,
        "algorithm":"RS256",
        "jwks_object":{
          "keys":[
            {
              "kty":"RSA",
              "e":"AQAB",
              "use":"sig",
              "kid":"EPoe1856",
              "alg":"RS256",
              "n":"nTBeTAQS-VOpSfm_HMUAg1SfOT-cmzZKwtr0-2CTyXbt8JOfEH2xkLykbdL-L8bv8rjx971DFW6HB8Lf_ll1ETNxfVEnQKlZWB3cf4d-32f4oKU1J56j293QLgTD6H50rQ_X0uQsQWcimwCvv-mAmwdB979Ahwz_dAWT5cGo81OhM2m0IpopJP4sM_uJdr-18QnyLSjqPxXlXwPP16Tzup2gf0BcwKCNOkbvBukKDf_AlciOmijfZB5sEepmBZvTKn3iK8Bc2y2aeDndm9JRR1CYwMHMeuU1C14SBqBNHVgz7CbuUvnELdSBTaBBASsHV2sizLIYDkIx07JqKToM1w"
            }
          ]
        }
      }
    ]
  }
}

Managing Keys for a JWT

The API Server caches the keys for the JWT to speed up processing. The cache is formed from keys specified by the jwks_object, the jwks_keystore, and either the jwks_uri or the jwks_uris in the jwt_config. Export the JWT configuration object then make the updates described in the sections below. When you are finished, import the JWT configuration object.

Specifying Keys in the jwks_object

To add more keys to or to modify keys in the JWKS (JSON Web Key Set) object, edit the JWT configuration object. In the generate object and for issuers in the validate object, add your JSON Web Keys to the array of keys in the jwks_object field.

Specifying a KeyStore in the jwks_keystore

To specify an external KeyStore as the source for the JWKS, update the subfields of the jwks_keystore field in the generate object and for issuers in the validate object. See JWT Configuration Object Fields for a detailed description of expected values in the subfields of the jwks_keystore field.

Specifying a URL in jwks_uri or in jwks_uris

Only use the jwks_uri or the jwks_uris field when you have public keys for an asymmetric algorithm. Assign a server URL to the jwks_uri field, or add a server URL into the jwks_uris array, for issuers in the validate object. The server returns a set of public keys (JWK set) for JWT validation.

Rotating Private Keys for JWT Generation

If you use an external keystore, you can automate the update of the private keys used for JWT generation. When the API Server generates a JWT, it first checks the jwks_cache_refresh_interval. If the JWKS cache is stale, the API Server updates the cache from the keystore. Since no generate.kid is specified in the keystore, the Server looks for the first private key in the JWKS cache that matches generate.algorithm. The API Server then sets the kid attribute of the generated JWT header to be the alias of this private key. This mechanism allows you to rotate keys during token generation.

To automatically rotate the private keys for JWT generation:

  1. Remove the old private key from the external keystore and add the new one.

  2. Do not specify the generate.kid field in jwt_config.

  3. Use the jwks_keystore field specified in the generate section of jwt_config to specify the path to the key storage that contains the private key. When a key is fetched from a keystore, the alias of the key is the key id for the generated JWT.

  4. Set the jwks_cache_refresh_interval field in the generate object of jwt_config. See generate Fields.

Rotating Public Keys for JWT Validation

If you use an external URI as the source for your public keys, you can automate the update of the public keys used for JWT validation. To find the right key in the JWKS for JWT validation, the API Server first looks at the key id in the JWT header. If the key id is not there, then the API Server downloads the keys from the location specified in jwks_uri or from the locations specified in jwks_uris and updates the cached JWK set. This mechanism allows you to rotate keys during token validation.

To automatically rotate the public keys for JWT validation:

  1. Set the jwks_uri or the jwks_uris field in the validate section of jwt_config for your issuer.

  2. If your JWT header can include the key id, then add a new key and new key id at one of the endpoints given in the jwks_uri or the jwks_uris field. The JWT headers of all new JWTs must be signed with this new key and new key id.

The approach above is the recommended approach for rotating public keys. If your JWT header cannot include the key id, do the following instead:

Set the jwks_cache_refresh_interval field in the validate object of jwt_config. See validate Fields.

Exporting a JWT Configuration Object

This section provides instructions using either the Admin Console or nnl-mgmt.sh to export the Default JWT Config or the JWT configuration object from any API Server plugin.  For details about nnl-mgmt.sh's apiserver export command, see subsection Export in API Server Configuration Commands.

Note: When you export a JWT Configuration Object, the private keys are obscured. When you import the modified JWT Configuration Object back into the API Server, the obscured keys are skipped and the corresponding keys from the existing JWT Configuration Object are preserved.

Default JWT Config

The Default JWT Config is defined on the API Server's Main object.

Using the Admin Console

  1. Login to the Admin Console and, if needed, switch to the correct tenant.

  2. Navigate to Configuration > API Server > Authentication API > Main.

  3. Click the label Default JWT Config label.

  1. The Admin Console displays jwt_config in a dialog. Copy and save the contents to a file.

Using nnl-mgmt.sh

The command below exports the Default JWT Config from the default tenant's Main object into the file jwtconfig.json.

./nnl-mgmt.sh apiserver export -tenantid default -type Main -name jwt_config -file jwtconfig.json

JWT Processor Plugin

Using the Admin Console

  1. Login to the Admin Console and, if needed, switch to the correct tenant.

  2. Navigate to Configuration > API Server > Authentication API > Session Plugins.

  3. Click the Modify icon for JWT Processor.

  4. The Admin Console displays the jwt_config object for the JWT Processor. Copy and save the contents to a file.

Using nnl-mgmt.sh

The example below shows how to export the JWT Processor plugin's jwt_config from the default tenant into the file my_jwt_config.json.

./nnl-mgmt.sh apiserver export -tenantid default -type SessionPlugin -name jwt_config -file my_jwt_config.json

Transaction Plugin

Using the Admin Console

  1. Login to the Admin Console and, if needed, switch to the correct tenant.

  2. Navigate to Configuration > API Server > Authentication API > Transaction Plugin.

  3. Click the edit icon for JWT Transaction Processor.

  4. The Admin Console displays the jwt_config object for the JWT Transaction Processor. Copy and save the contents to a file.

Using nnl-mgmt.sh

The example below shows how to export the Transaction plugin's jwt_config from the Marketing tenant into the file TransJWTConfig.json.

./nnl-mgmt.sh apiserver export -tenantid Marketing -type TransactionPlugin -name jwt_config -file TransJWTConfig.json

JWT External Authentication Plugin

Using the Admin Console

  1. Login to the Admin Console and, if needed, switch to the correct tenant.

  2. Navigate to Configuration > API Server > Authentication API > External Authentication Plugins.

  3. Click the Edit icon for JWT Authentication Method.

  4. The Admin Console displays the jwt_config object for the JWT External Authentication Method. Copy and save the contents to a file.

Using nnl-mgmt.sh

The example below shows how to export the JWT External Authentication plugin's jwt_config from the Marketing tenant into the file ExtAuthJWTConfig.json.

./nnl-mgmt.sh apiserver export -tenantid Marketing -type ExternalAuthenticationPlugin -name jwt_config -file ExtAuthJWTConfig.json

Importing a JWT Configuration Object

This section provides instructions using either the Admin Console or nnl-mgmt.sh to import a Default JWT Config or JWT configuration object into any API Server plugin. For details about nnl-mgmt.sh's apiserver import command, see subsection Import in the reference API Server Configuration Commands.

Note: When you export a JWT Configuration Object, the private keys are obscured. When you import the modified JWT Configuration Object back into the API Server, the obscured keys are skipped and corresponding keys from the existing JWT Configuration Object are preserved.

Default JWT Config

The Default JWT Config is defined on the API Server's Main object.

Using the Admin Console

  1. Login to the Admin Console and, if needed, switch to the correct tenant.

  2. Navigate to Configuration > API Server > Authentication API > Main.

  3. Click Upload.

  4. The Upload configuration dialog appears, navigate to your modified jwt_config.

Using nnl-mgmt.sh

The command below imports the Default JWT Config into the NorthAmerica tenant's Main object from the file jwtconfig.json.

./nnl-mgmt.sh apiserver import -tenantid NorthAmerica -type Main -name jwt_config -file jwtconfig.json -overwrite yes

JWT Processor Plugin

Using the Admin Console

  1. Login to the Admin Console and, if needed, switch to the correct tenant.

  2. Navigate to Configuration > API Server > Session Plugins.

  3. Locate the JWT Processor label, click its Modify button.

  4. On the plugin configuration page click the Import button.

  5. The Upload configuration dialog appears, navigate to your modified jwt_config.

Using nnl-mgmt.sh

The example below imports the JWT Processor plugin's jwt_config into the NorthAmerica tenant from the file my_jwt_config.json.

./nnl-mgmt.sh apiserver import -tenantid NorthAmerica -type SessionPlugin -name jwt_config -file my_jwt_config.json -overwrite yes

Transaction Plugin

Using the Admin Console

  1. Login to the Admin Console and, if needed, switch to the correct tenant.

  2. Navigate to Configuration > API Server > Authentication API > Transaction Plugin.

  3. Locate the JWT Transaction Processor label, click its Modify button.

  4. On the plugin configuration page click the Import button.

  5. The Upload configuration dialog appears, navigate to your modified jwt_config.

Using nnl-mgmt.sh

The example below imports the Transaction plugin's jwt_config into the NorthAmerica tenant from the file TransJWTConfig.json.

./nnl-mgmt.sh apiserver import -tenantid NorthAmerica -type TransactionPlugin -name jwt_config -file TransJWTConfig.json -overwrite yes

JWT External Authentication Plugin

Using the Admin Console

  1. Login to the Admin Console and, if needed, switch to the correct tenant.

  2. Navigate to Configuration > API Server > Authentication API > External Authentications Plugins.

  3. Locate the JWT Authentication Method label, click its Modify button.

  4. On the plugin configuration page click the Import button.

  5. The Upload configuration dialog appears, navigate to your modified jwt_config.

Using nnl-mgmt.sh

The example below imports the JWT External Authentication plugin's jwt_config into the NorthAmerica tenant from the file ExtAuthJWTConfig.json.

./nnl-mgmt.sh apiserver import -tenantid NorthAmerica -type ExternalAuthenticationPlugin -name jwt_config -file ExtAuthJWTConfig.json -overwrite yes

Rotating Keys for Your RP Servers

If you have backend servers that validate JWTs issued by the API Server, you want to avoid updating those server's JWT configuration when the API Server changes its private key. You can accomplish this by using an appropriate JWKS endpoint to implement key rotation and retrieve the new public key needed to verify the JWTs generated by the API Server.

The API server exposes the URL endpoints where the JWKS is stored. Notice that the endpoint identifies the specific tenant and API Server plugin to which it applies. Each JWKS is unique to that API Server plugin and tenant combination.

Use the HTTP GET method with an endpoint. The JWKS endpoint for each API Server plugin is shown below. <api-server> is the URL where your Nok Nok API Server is hosted.

  • Session plugin's JWT Processor
    https://<api-server>/nnlgateway/jwks/<tenant-id>/session

  • JWT External Authentication plugin
    https://<api-server>/nnlgateway/jwks/<tenant-id>/external

  • Transaction plugin
    https://<api-server>/nnlgateway/jwks/<tenant-id>/transaction

  • EMV 3DS generator
    https://<api-server>/nnlgateway/jwks/<tenant-id>/emv3ds