Skip to content
Connect2id

Key store

1. Key usage contexts and key store modes

The Connect2id server requires cryptographic keys to secure the issued tokens and other objects. Each usage context has its own set of keys that can be configured and managed independently:

  • A JSON Web Key (JWK) set for the OpenID provider / OAuth 2.0 authorisation server context.
  • A separate JWK set for the optional OpenID Federation 1.0 context. Not required if federation is disabled.

Starting with Connect2id server 17.0, deployments can choose from three key store modes. The static key configuration from server versions 1.x - 16.x remains supported. For a seamless migration from a legacy or static configuration to a dynamic mode, refer to the guide.

Dynamic Static PKCS#11 + static
  • Enables online generation, rotation, revocation, and archival of server keys
  • The server keys are stored encrypted in the database
  • The default key store mode since v17.0
  • The server keys are statically configured
  • The database is not utilised
  • HSM-based server keys
  • Supplemented with statically configured keys
  • The database is not utilised

The key store configuration is located in the properties file

WEB-INF/keyStore.properties

Any property in the configuration file can be overridden with a Java system property, e.g. by setting the optional -D argument at JVM startup:

-DkeyStore.encJWK=eyJrdHkiOiJvY3QiLCJ1c2UiOiJlbmMiLCJraWQiOiJrSUtPIiwiayI6IlNhX1pKbHlBamxBWDkxUTA5MFM0TkEiLCJpYXQiOjE3MzQ5Njk4Mzl9

The external configuration guide has tips how to import system properties from environment variables, local files and other sources.

2. Dynamic mode

This is the default key store mode. The initial server JWK sets are automatically generated for a new deployment. If the key store web API is enabled, dynamic mode supports frequent online rotation of server keys.

In dynamic mode, the only required configuration is an encryption key to secure the private and secret key material in the store. All other configuration properties are optional.

keyStore.encJWK

128-bit AES key for encrypting the stored private key material. Required, unless the Connect2id server is configured with static JWK sets and / or a PKCS#11 (HSM) store. The key must be a JWK of type oct (octet sequence key), with use (key use) enc (encryption) and an optional kid (key ID). The JSON string may be additionally BASE64URL encoded, to prevent character escape issues in shell environments.

Use the provided generator to create a key store encryption key.

Example encryption JWK, BASE64URL encoded:

keyStore.encJWK=eyJrdHkiOiJvY3QiLCJ1c2UiOiJlbmMiLCJraWQiOiJrSUtPIiwiayI6IlNhX1pKbHlBamxBWDkxUTA5MFM0TkEiLCJpYXQiOjE3MzQ5Njk4Mzl9

When specified, this configuration property overrides any encryption key in the optional WEB-INF/keyStoreEncJWK.json file.

The Connect2id server comes with a demo keyStoreEncJWK.json that must be deleted or overridden in production:

{
  "kty" : "oct",
  "use" : "enc",
  "k"   : "BuSbZycIAbLy9mrFlxGbwg"
}

keyStore.apiAccessTokenSHA256

The access token for the key store web API, represented by its SHA-256 hash (in hexadecimal format). The hash is a measure to prevent accidental leakage of the token through configuration files, logs, etc. The token is of type Bearer, non-expiring and must contain at least 32 random alphanumeric characters to make brute force guessing impractical. If not specified the web API is disabled.

Additional access tokens, for token roll-over or other needs, can be configured by appending a dot (.) with a unique label to the property name, e.g. as keyStore.apiAccessTokenSHA256.1=abc....

The hash for a token with value ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6:

keyStore.apiAccessTokenSHA256=cca68b8b82bcf0b96cb826199429e50cd95a042f8e8891d1ac56ab135d096633

keyStore.defaultRSAKeySize

The default size of new generated RSA JWKs. The supported sizes are 2048, 3072 and 4096 bits. The default value is 2048.

keyStore.defaultRSAKeySize=2048

keyStore.generateIfEmpty.{op|federation}

When true and the specified JWK set context (op for OpenID provider, federation for OpenID Federation 1.0) is empty, the key store will automatically generate the required JWK set. The default value is true (enabled).

keyStore.generateIfEmpty.op=true
keyStore.generateIfEmpty.federation=true

keyStore.importIfEmpty.{op|federation}

JWK set to import into the key store if the specified context (op for OpenID provider, federation for OpenID Federation 1.0) is empty. The JSON string may be additionally BASE64URL encoded, to prevent character escape issues in shell environments. The default value is none.

This configuration is intended when migrating from a legacy or static mode configuration, or another OpenID provider server.

Example import of a JWK set for the OpenID provider context:

keyStore.importIfEmpty.op=eyJrZXlzIjpbeyJwIjoiOFhBZnBxVnlvVTVRdVZsaXFZbjgzc1...

Example import of a JWK set for the OpenID Federation 1.0 context:

keyStore.importIfEmpty.federation=eyJrZXlzIjpbeyJwIjoiODRDWkllVnNFcjFNTkpQN3...

keyStore.importExp

Time, as seconds since the Unix epoch, after which any configured JWK sets for import will be ignored. Must be not more than 1 day ahead of the current time when the Connect2id server starts up.

Example expiration at 23:59:59, 31 December 2024:

keyStore.importExp=1735682399

keyStore.jwkSetCacheLifetime

Controls the local caching of JWK sets retrieved from the key store. The cache lifetime is specified in seconds. Zero or negative disables caching. Must not exceed 600 seconds (10 minutes). The default value is 60 seconds (1 minute).

keyStore.jwkSetCacheLifetime=60

3. Static mode

The server keys are statically configured. Key rotation and revocation is performed by configuring a new static JWK set. This mode is equivalent to the legacy key configuration in Connect2id server releases 1.x to 16.x.

keyStore.staticJWKSet.{op|federation}

Static JWK set for the specified context (op for OpenID provider, federation for OpenID Federation 1.0). The JSON string may be additionally BASE64URL encoded, to prevent character escape issues in shell environments. The default value is none.

When a static JWK set is specified for a given context the key store web API operations for key rotation and revocation are disabled.

Use the provided generator to:

  • Create a new static JWK set;
  • Create and prepend a new set of rotating keys to an existing static JWK set (for key-rollover).

Example static JWK set for the OpenID provider context:

keyStore.staticJWKSet.op=eyJrZXlzIjpbeyJwIjoiOFhBZnBxVnlvVTVRdVZsaXFZbjgzc1...

Example static JWK set for the OpenID Federation 1.0 context:

keyStore.staticJWKSet.federation=eyJrZXlzIjpbeyJwIjoiODRDWkllVnNFcjFNTkpQN3...

Rollover of rotated keys:

The Connect2id server picks the first JWK from the set that matches the required algorithm and key use when it needs to sign or encrypt a token (unless the key has an X.509 certificate, in which case the validity time window of the certificate applies). All public keys found in the JWK set will be published, so clients can still validate tokens secured with an expired key.

{
  "keys": [
    { ... new key ... },
    { ... new key ... },
    { ... old key ... },
    { ... old key ... }
  ]
}

Important:

The permanent keys, they have the following kid (key ID) values, are not intended to be rotated:

  • hmac
  • refresh-token-encrypt
  • subject-encrypt

Changing these keys is equivalent to revoking them and will invalidate all existing sessions, identifier-based tokens and pairwise subject IDs.

4. PKCS#11 (HSM) + static mode

Selected signing keys are loaded from a PKCS#11 compliant key store (HSM) and the rest are statically configured. Check the HSM guide for the
supported key types and how to generate them on the device.

keyStore.pkcs11.{op|federation}.enable

Enables / disables PKCS#11 (HSM) support for the specified context (op for OpenID provider, federation for OpenID Federation 1.0). The default value is false (disabled).

To enable PKCS#11 for the OpenID provider context:

keyStore.pkcs11.op.enable=true

To enable PKCS#11 for the OpenID Federation 1.0 context:

keyStore.pkcs11.federation.enable=false

keyStore.pkcs11.{op|federation}.configFile

The location of the Sun PKCS#11 provider configuration for the specified context (op for OpenID provider, federation for OpenID Federation 1.0). The configuration can be alternatively passed inline as a string. The string may be additionally BASE64URL encoded, to prevent character escape issues in shell environments.

The PKCS#11 provider configuration specifies the driver to load for the HSM device, a slot number for it (as multiple HSM devices may be attached), and other attributes. These are explained in the Java PKCS#11 Reference Guide. The manual of your HSM device should also provide information.

To use the sample PKCS#11 configuration file:

keyStore.pkcs11.op.configFile=/WEB-INF/hsm.cfg

The sample PKCS#11 configuration file content:

name = NitroKeyHSM
library = /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so
slotListIndex = 0
attributes(*,CKO_PRIVATE_KEY,CKK_RSA) = {
  CKA_SIGN = true
}

Passing the content of the sample PKCS#11 configuration file as a string:

keyStore.pkcs11.op.configFile=bmFtZSA9IE5pdHJvS2V5SFNNCmxpYnJhcnkgPSAvdXNyL2xpYi94ODZfNjQtbGludXgtZ251L29wZW5zYy1wa2NzMTEuc28Kc2xvdExpc3RJbmRleCA9IDEKYXR0cmlidXRlcygqLENLT19QUklWQVRFX0tFWSxDS0tfUlNBKSA9IHsKICBDS0FfU0lHTiA9IHRydWUKfQ

keyStore.pkcs11.{op|federation}.password

The password (PIN) required to unlock the HSM for the specified context (op for OpenID provider, federation for OpenID Federation 1.0).

Example password:

keyStore.pkcs11.op.password=648219

keyStore.pkcs11.{op|federation}.keyIDs

Optional list of identifiers (aliases) of PKCS#11 keys to load from the HSM for the specified context (op for OpenID provider, federation for OpenID Federation 1.0). If omitted or blank all recognised and supported keys will be loaded.

Example list of four key IDs to load:

keyStore.pkcs11.op.keyIDs.1=rsa-sign-1
keyStore.pkcs11.op.keyIDs.2=rsa-sign-2
keyStore.pkcs11.op.keyIDs.3=ec-sign-1
keyStore.pkcs11.op.keyIDs.4=ec-sign-2

keyStore.staticJWKSet.{op|federation}

Static JWK set to complement the PKCS#11 keys for the specified context (op for OpenID provider, federation for OpenID Federation 1.0). The JSON string may be additionally BASE64URL encoded, to prevent character escape issues in shell environments. The default value is none.

Example static JWK set for the OpenID provider context:

keyStore.staticJWKSet.op=eyJrZXlzIjpbeyJwIjoiOFhBZnBxVnlvVTVRdVZsaXFZbjgzc1...

5. Legacy configuration

The static key configuration properties from Connect2id server versions 1.x - 16.x remain supported.

jose.jwkSet

Static JWK set for the OpenID provider context. The JSON string may be additionally BASE64URL encoded, to prevent character escape issues in shell environments.

The legacy WEB-INF/jwkSet.json file for setting the JWK set also remains supported and is overridden by this property.

Deprecated in v17.0, use keyStore.staticJWKSet.op instead.

jose.jwkSet=eyJrZXlzIjpbeyJwIjoiOFhBZnBxVnlvVTVRdVZsaXFZbjgzc1...

jose.federation.jwkSet

Static JWK set for the OpenID provider context. The JSON string may be additionally BASE64URL encoded, to prevent character escape issues in shell environments.

The legacy WEB-INF/federationJWKSet.json file for setting the JWK set also remains supported and is overridden by this property.

Deprecated in v17.0, use keyStore.staticJWKSet.federation instead.

jose.federation.jwkSet=eyJrZXlzIjpbeyJwIjoiODRDWkllVnNFcjFNTkpQN3...

pkcs11.enable

Deprecated in v17.0, use keyStore.pkcs11.op.enable instead.

pkcs11.configFile

Deprecated in v17.0, use keyStore.pkcs11.op.configFile instead.

pkcs11.password

Deprecated in v17.0, use keyStore.pkcs11.op.password instead.

pkcs11.keyIDs.*

Deprecated in v17.0, use keyStore.pkcs11.op.keyIDs.* instead.

6. Offline key generation

Use the Connect2id JWKs generator (JAR download) to generate server keys.

The generator is available as standalone executable JAR (jwks-gen.jar) and a library (JavaDocs). The signature file of the jwks-gen.jar can be validated with the Connect2id software delivery public key.

Invoke the jwks-gen.jar without arguments to get a printout of its usage.

java -jar jwks-gen.jar

Key store encryption JWK

To generate a new key store encryption JWK:

java -jar jwks-gen.jar key-store jwk.json

To BASE64URL-encode the output JWK:

java -jar jwks-gen.jar key-store -b64 jwk.json.b64

OpenID provider JWK set

To generate a new JWK set for the keyStore.staticJWKSet.op configuration property:

java -jar jwks-gen.jar op jwkSet.json

Sample console output:

JWKs generator for Connect2id server v6.x+

[1] Generated new signing RSA 2048 bit key with ID mCM5
[2] Generated new signing EC P-256 key with ID r4tz
[3] Generated new signing EC P-384 key with ID FQwD
[4] Generated new signing EC P-521 key with ID WrGz
[5] Generated new signing EC secp256k1 key with ID XiFW
[6] Generated new signing Ed25519 key with ID EVPK
[7] Generated new encryption RSA 2048 bit key with ID HIsQ
[8] Generated new encryption EC P-256 key with ID KRVD
[9] Generated new encryption EC P-384 key with ID QCkW
[10] Generated new encryption EC P-521 key with ID J5DG
[11] Generated new symmetric encryption 128 bit key with ID s8nJ
[12] Generated new HMAC SHA 256 bit key with ID hmac
[13] Generated new subject encryption AES SIV 256 bit key with ID subject-encrypt
[14] Generated new refresh token encryption AES SIV 256 bit key with ID refresh-token-encrypt

To BASE64URL-encode the output JWK set:

java -jar jwks-gen.jar op -b64 jwkSet.json.b64

To generate a new set of rotating keys and prepend them to an existing static OpenID provider JWK set:

java -jar jwks-gen.jar op oldJWKSet.json 

If the oldJWKSet.json is missing a required permanent key it will also be generated and included in the newJWKSet.json. This is intended when upgrading to a new Connect2id server release that introduces a new type of permanent key.

OpenID Federation 1.0 JWK set

To generate a new BASE64URL-encoded JWK set for the keyStore.staticJWKSet.federation configuration property:

java -jar jwks-gen.jar federation -b64 jwkSet.json.b64

7. Public JWKs for historical purposes

A static JWK set may include JWK instances without private parameters. The Connect2id server will publish them at the /jwks.json endpoint, and will not use them otherwise.

Similarly, the OpenID Federation 1.0 JWK set may also include public-only JWK instances. The Connect2id server will include them in issued Entity Configurations.

8. PKIX / X.509 certificates

The public keys in a static JWK set may be furnished with X.509 certificates. An X.509 certificate enables client applications and resource servers to perform PKIX validation of the signing key for an issued JWT (ID token, self-contained access token, etc).

A certificate is added to a JWK in the x5c parameter. The parameter can include either the client certificate or a certificate chain (partial or complete).

When the Connect2id server publishes a JWK at the jwks.json endpoint the x5c parameter is always included when present. The certificate will also appear in the x5c header parameter of JWTs signed with its private key, unless the Connect2id server is configured otherwise:

When signing JWTs with a certificate-based JWK the Connect2id server will always select a JWK with an active certificate according to its not-before and not-after attributes. The selection will be biased towards the farthest expiring JWK to ensure optimal roll-over. If no active JWK is found the Connect2id server will log an SE2000 error and use the most recent expired certificate.

[main] ERROR MAIN - [SE2000] No signing RSA key with active (nbf < now < exp) X.509 certificate, using the first available. Add new key(s)!

Guarantees:

  • The Connect2id server will always use a signing JWK with an active X.509 certificate (nbf < now < exp), if such is present in the configured JWK set.

  • The Connect2id server will always use a signing JWK with an X.509 certificate when at least one is present for the key type (e.g. RSA) and key use (signing), ignoring any plain JWKs.

These guarantees also apply to keys stored in a HSM, as those keys by rule must be provisioned with an X.509 certificate.

Notes:

  • The Connect2id server will not perform PKIX validation of the X.509 certificate in a configured JWK.

  • Including an x5c header in JWTs can easily end up multiplying the size of the issued tokens.

9. Hardware Security Module (HSM)

As explained in the PKCS#11 + static mode, the Connect2id server can load keys from a PKCS#11 compliant
HSM to sign ID tokens and self-contained (JWT) access tokens.

Keys generation on the HSM

The HSM must be provisioned with the required keys before they can be used by the Connect2id server.

  • For signing tokens with an RSA key, provision at least one RSA key with a size of 2048, 3072 or 4096 bits.

  • For signing tokens with an EC key, provision at least one EC key with curve P-256 (for JWS algorithm ES256), P-384 (for ES384) and / or P-521 (for ES512).

  • Every private key must be paired with an X.509 certificate (also stored on the HSM). The certificate can be signed by a CA or self-signed. Its not-before and not-after attributes delimit the time window during which the Connect2id server will use the private key for signing, as explained in the JWKs with certificates section.

  • When rotating an HSM-based key, the certificate validity windows of the old and the new key must overlap, so the Connect2id server can seamlessly roll-over from an expiring key to the next.

  • Every pairing of a private key and its X.509 certificate must be given a unique CKA_ID (identifier), also called “alias” in the Java KeyStore API. This identifier will become the kid (key ID) parameter of the JWK.

  • HSM must be able to keep up with the signing rate of the Connect2id server deployment. If the HSM bandwidth is exceeded the token signing will slow-down or fail, resulting in server timeouts or HTTP 500 errors.

Loading, merging and publishing of PKCS#11 keys

  • The Connect2id server will load from the HSM only those keys that it can use for RSA and ECDSA signing, as explained above, and ignore any other key types on the HSM.

  • The keys loaded from the HSM will be prepended to the configured static JWK set and published together at the jwks.json endpoint. The X.509 certificates of the PKCS#11 keys will be included in the JWK x5c parameter.

  • If the Connect2id server deployment is new (never issued tokens before) there should be no signing JWKs in the static JWK set that match the type and use of the PKCS#11 key loaded from the HSM key. For example, if the deployment is going to use an RSA HSM key, make sure the static JWK set has no JWK with "kty":"RSA" and "use":"sig". This should be done to avoid the publishing of static keys that will not be used.

  • If an existing Connect2id server deployment is switching to an HSM, keep the configured static JWK set just as it is.

PKCS#11 key selection guarantees

The Connect2id server applies to PKCS#11 keys the exact same key selection as for JWKs with X.509 certificates. What does this mean for existing deployments that plan to switch to an HSM?

  • If the deployment is using plain JWKs or JWKs with X.509 certificates, the Connect2id server can seamlessly roll-over to the JWKs loaded from an HSM.

  • A seamless roll-over (revert) from HSM-loaded JWKs to JWKs with certificates is also possible.

Debugging HSM issues

The Connect2id server logs the PKCS#11 keys loaded from the HSM device. Ignored keys will not appear in the log.

[KS0154] Key store mode for OP JWK set context: PKCS11_WITH_STATIC
[KS0160] Key store PKCS#11 enabled for OP JWK set: true
[KS0161] Key store PKCS#11 OP configuration file: /WEB-INF/hsm.cfg
[KS0162] Key store PKCS#11 OP password configured: true
[KS0163] Key store PKCS#11 OP key IDs to load: all
[SE1006] Loaded PKCS#11 provider SunPKCS11-NitroKeyHSM
[SE1007] Loaded PKCS#11 key store with 1 entries
[SE1009] Extracted JWK set with 1 keys from PKCS#11 key store SunPKCS11-NitroKeyHSM
[KS0164] Key store loaded PKCS#11 op JWK set:
[SE1008] JWK set:
[SE3000] [1] JWK type=RSA id=c2id-rsa-1 private=true use=sig size=2048 x5c=true pkcs#11=true thumbprint=Ft3-NA3jvcrnBu2_ZXV_nP4pcXtvK_i8MMd19woqwfI nbf=2024-12-18T18:02:48Z exp=2025-12-18T18:02:48Z
[SE1010] Assuming signature key use for RSA PKCS#11 JWK with ID c2id-rsa-1
[KS0157] Key store static OP JWK set:
[SE1008] JWK set:
[SE3000] [1] JWK type=EC id=c6kW private=true use=sig size=256 x5c=false pkcs#11=false thumbprint=ko4gUhJozvmjqFQYMU4PicL0uYQj7P2TvublrZN71YQ 
[SE3000] [2] JWK type=EC id=ogJz private=true use=sig size=384 x5c=false pkcs#11=false thumbprint=ZUeuqUPa3tQWT48E0-IzGTKYdF0UZX-euxPM2jUdKes 
[SE3000] [3] JWK type=EC id=JgQ6 private=true use=sig size=521 x5c=false pkcs#11=false thumbprint=MrYieuuepjrdA0rmulZZSPxUjVgN6osEouiROKKMiiA 
[SE3000] [4] JWK type=EC id=WtjM private=true use=sig size=256 x5c=false pkcs#11=false thumbprint=Fj_KAGkRQbS8x3AxQ2dngEvYNcUKZkYQkvN78F4s8ME 
[SE3000] [5] JWK type=OKP id=klr5 private=true use=sig size=256 x5c=false pkcs#11=false thumbprint=C4qsmT3lNmmOM8uhL5Wbt7bOA4YxoNe6Z3uqXvfTHdw 
[SE3000] [6] JWK type=RSA id=hlQj private=true use=enc size=2048 x5c=false pkcs#11=false thumbprint=jDt3TYMCus_aYct0FLOE-sqgvphGZtmOMxR_gWJBscg 
[SE3000] [7] JWK type=EC id=VArh private=true use=enc size=256 x5c=false pkcs#11=false thumbprint=iG1tTOt9ecWxqRjS2-Kfg_vLVUWHi0jehimXmBS0Hyc 
[SE3000] [8] JWK type=EC id=5uTk private=true use=enc size=384 x5c=false pkcs#11=false thumbprint=vhyKJBYD-JywtG_s56_sEbOZfY_AcFN5LuLmaJwy0b8 
[SE3000] [9] JWK type=EC id=iRYG private=true use=enc size=521 x5c=false pkcs#11=false thumbprint=ESyQLHvnilAUSEct52q_SnnHpRlOLnakS12I5yAbHfU 
[SE3000] [10] JWK type=oct id=Gdti use=enc size=128 x5c=false pkcs#11=false thumbprint=88CDlcqnV3ABZDMI9UZ3N81881MfpkjohOo4UyL-g18 
[SE3000] [11] JWK type=oct id=hmac use=sig size=256 x5c=false pkcs#11=false thumbprint=Fm7zaUubUYJpJbl9Y-ya8p2mOhaQwPbWzLyfppxnCT0 
[SE3000] [12] JWK type=oct id=subject-encrypt use=enc size=256 x5c=false pkcs#11=false thumbprint=JHqeGbu7dkFmAVaEkrxG0C8Xxd1ykTmk55iwPI90qJE 
[SE3000] [13] JWK type=oct id=refresh-token-encrypt use=enc size=256 x5c=false pkcs#11=false thumbprint=x0STKoEiQfddmz9QACOVd4S2w9tUx7inx2xgvjgzT6M 

The Java PKCS#11 provider and key store can be instructed to output additional logging.

10. Migration from a legacy or static JWK set

Connect2id server deployments with a legacy or static key configuration can seamlessly migrate to the dynamic mode, to benefit from the new key store API which allows easy and frequent key rotation, while keeping a history of all key changes.

Configure the server to use the dynamic key store mode and use the keyStore.importIfEmpty.op property to import the existing static JWK set on startup.

The keyStore.importExp property prevents an accidental repeat of the import if the imported JWK set gets revoked at some future time.

11. Key description

OpenID provider context

  • JWT signing keys – Public / private key pairs for signing issued JWTs that are access tokens, ID tokens, signed UserInfo, signed authorisation responses and signed token introspection responses:

    • RSA key pair of size 2048, 3072 or 4096 bits.
    • EC key pair with P-256 curve.
    • EC key pair with P-384 curve.
    • EC key pair with P-521 curve.
    • EC key pair with secp256k1 curve.
    • Ed key pair with Ed25519 curve.

    Each key must specify a unique key ID (kid) and its use must be sig (signature). The RSA and EC keys can be stored in a PKCS#11 compliant HSM. The public keys are published so that clients can download them to validate the JWTs.

    Rotated: Yes

  • JWT encryption keys – Public / private keys pairs for letting clients encrypt JWTs that are request objects (JAR) to the Connect2id server:

    • RSA key pair of size 2048, 3072 or 4096 bits.
    • EC key pair with P-256 curve.
    • EC key pair with P-384 curve.
    • EC key pair with P-521 curve.

    Each key must specify a unique key ID (kid) and its use must be enc (encryption). The public keys are published so that clients can download them to encrypt JWTs.

    Rotated: Yes

  • Access token encryption key – Optional AES key for applying encryption over a signed access token (JWT), in order to provide confidentiality of the token content while in transit. This AES key must be shared securely and out-of-band with all servers which will consume encrypted access tokens. This key must specify a unique key ID (kid). Its use must be enc (encryption). The supported AES key sizes are 128, 192 and 256 bits.

    If the JWT-encoded access tokens are not going to be encrypted this key can be omitted.

    Rotated: Yes

  • Secret HMAC key – Secret 256-bit key for applying HMAC-SHA-256 protection to the issued session identifiers, authorisation codes, identifier-based access tokens and PAR URIs. This key must have a key ID (kid) of hmac and its use must be sig (signature).

    Rotated: No

  • Refresh token encryption key – Secret 256-bit key for encrypting refresh token metadata and authenticating the entire refresh token. This key must have a key ID (kid) of refresh-token-encrypt and its use must be enc (encryption).

    Rotated: No

  • End-user ID encryption key – Secret 256-bit key for encrypting pairwise subject identifiers with AES in SIV mode. This key must have a key ID (kid) of subject-encrypt and its use must be enc (encryption).

    Rotated: No

OpenID Federation 1.0 context

  • Federation entity statement signing keys – If OpenID Federation 1.0 is enabled, a public / private key pair for signing the issued entity statements:

    • RSA key pair of size 2048 bits.

    Each key must have its algorithm (alg) set to RS256, have a unique key ID (kid) and its use must be sig (signature). The private RSA keys can be stored in a PKCS#11 compliant HSM. The public keys are published so that federation clients can download them in order to validate the issued statements.

    Rotated: Yes

12. Sample JWK sets

Sample OpenID provider JWK set

{ "keys" : [ { "kty" : "RSA",
               "use" : "sig",
               "kid" : "CXup",
               "n"   : "hrwD-lc-IwzwidCANmy4qsiZk11yp9kHykOuP0yOnwi36VomYTQVEzZXgh2sDJpGgAutdQudgwLoV8tVSsTG9SQHgJjH9Pd_9V4Ab6PANyZNG6DSeiq1QfiFlEP6Obt0JbRB3W7X2vkxOVaNoWrYskZodxU2V0ogeVL_LkcCGAyNu2jdx3j0DjJatNVk7ystNxb9RfHhJGgpiIkO5S3QiSIVhbBKaJHcZHPF1vq9g0JMGuUCI-OTSVg6XBkTLEGw1C_R73WD_oVEBfdXbXnLukoLHBS11p3OxU7f4rfxA_f_72_UwmWGJnsqS3iahbms3FkvqoL9x_Vj3GhuJSf97Q",
               "e"   : "AQAB",
               "d"   : "bmpuqB4PIhJcndRs_i0jOXKjyQzwBXXq2GuWxPEsgFBYx7fFdCuGifQiytMeSEW2OQFY6W7XaqJbXneYMmoI0qTwMQcD91FNX_vlR5he0dNlpZqqYsvVN3c_oT4ENoPUr4GF6L4Jz74gBOlVsE8rvw3MVqrfmbF543ONBJPUt3d1TjKwaZQlgPji-ycGg_P7K-dKxpyfQsC8xMmVmiAF4QQtnUa9vMgiChiO8-6VzGm2yWWyIUVRLxSohrbSNFhqF2zeWXePAw0_nzeZh3IDIMS5ABo92Pry4N3X-X7v_7nf8MGngK4duQ_1UkkLk-3u0I3tk_glsarDN0tYhzPwAQ" },
             { "kty" : "EC",
               "crv" : "P-256",
               "use" : "sig",
               "kid" : "yGvt",
               "d"   : "XnnhYQD6olmXKNQ2mBQ-ZOHEMUpYENnvGDNU3z9VVZ0",
               "x"   : "pvgdqM3RCshljmuCF1D2Ez1w5ei5k7-bpimWLPNeEHI",
               "y"   : "JSmUhbUTqiFclVLEdw6dz038F7Whw4URobjXbAReDuM" },
             { "kty" : "EC",
               "crv" : "P-384",
               "use" : "sig",
               "kid" : "9nHY",
               "d"   : "3zS7ECyMqZlENI9Xk6TqptEbZtoso3LmO4Hc9zs-VytU3Sgd8yHw2uUePAkGv_Fu",
               "x"   : "JPKhjhE0Bj579Mgj3Cn3ERGA8fKVYoGOaV9BPKhtnEobphf8w4GSeigMesL-038W",
               "y"   : "UbJa1QRX7fo9LxSlh7FOH5ABT5lEtiQeQUcX9BW0bpJFlEVGqwec80tYLdOIl59M" },
             { "kty" : "EC",
               "crv" : "P-521",
               "use" : "sig",
               "kid" : "tVzS",
               "x"   : "AZgkRHlIyNQJlPIwTWdHqouw41k9dS3GJO04BDEnJnd_Dd1owlCn9SMXA-JuXINn4slwbG4wcECbctXb2cvdGtmn",
               "y"   : "AdBC6N9lpupzfzcIY3JLIuc8y8MnzV-ItmzHQcC5lYWMTbuM9NU_FlvINeVo8g6i4YZms2xFB-B0VVdaoF9kUswC",
               "d"   : "AAnqLI9s0-hKAXtp0mXQHKoPBMDsnhgeh6HQP-1ScEVMl9-7WcJm2m_msXPyfT0O9Xbh4UDn9wdAi9bqt_4qEEjy" },
             { "kty" : "EC",
               "crv" : "secp256k1",
               "use" : "sig",
               "kid" : "iRTU",
               "x"   : "tcjSy7nIVZ2DVz-RKjqHIJqr5WDqZLS6fq4rEN6pfGY",
               "y"   : "2oqx5jvggJKy-LXFjpDOpL0g_SbiLylu_8xx-dBMQeQ",
               "d"   : "rtnqI1fWogLX3QaG_PykfGJyOZPNEwHo7glIJl3mrqE" },
             { "kty" : "OKP",
               "crv" : "Ed25519",
               "use" : "sig",
               "kid" : "27zV",
               "x"   : "0I6olrZGYml7JGusuKJW9G7D0DZ9UormSady9kR7V4Q",
               "d"   : "tYXIC35n-nNoVwZ5Rck02ndqFLyYcC8fNwhVFJjWB3c" },
             { "kty" : "RSA",
               "use" : "enc",
               "kid" : "IHMc",
               "n"   : "lLrhwERiPmq7XOz6Rwk8q4ey_OGcL4P56Ip01mzKMUfysIwo-nUdwDI_9ntYohpvqiTjnrtZOENhhoqne5M4hqpSfBMmCWSvWL_3wa8FanRWd6lPgGdKJ1a3vV0gLxnCbmdho1CSuSszV4736WkjdDhLcXSRN1kWwWbok94FdPD_egCyBY3cwhvuRzmUgE8LDh-VnNRh1BYc7e9yEMublza8qJpW-N5ljHEU0on08X-lsyl4djEac74H7taDcmtchPLYZy0-ZIxgLmosQ2aYIt6xycfPYsm5x9CGetUqhClpLLaTcyTGq_pH4ECdZtkYHcYJM-3q-XDZTqB6wUaggw",
               "e"   : "AQAB",
               "d"   : "N_IEMRqICgqD5_SMQGRNGgi1X0JOSeFPBBXw1See9uKle5t9XpjnVACS5tiHApMHJe0yYeb_LJbL_JvzXByIyr8Ov_VD_YyOGMg9HfIEC4Mvc1uQuDAiSKHqA6UgEheSd40TwSbxyg1iBrGUt4wA9hqm5kp-xV8RnDZljhmZ296nVPNNW3aXrqq2FPFn00s2Rh6gJbSTWhg6qQxTSVOO1n601TbWQGlP6mlXdIqXyzlwqwwOCcQIW88ws2jLmY3Hr4Le8nxL20xBACMYjR-9bO0senxbYUcew6GGscyiPe7I5X3P9cpZcRNeERIzsmtin1swvsyCK2cUUCtGpLpN4Q" },
             {
               "kty" : "EC",
               "crv" : "P-256",
               "use" : "enc",
               "kid" : "1yFA",
               "x"   : "_-aKZeuwWDv4v89dPGdKtpOuOepc_0qDZDhcv3omzX0",
               "y"   : "Gc5b7muOqbi4QvYJO24a4IqQoOY1pPM69DcpI605Vmw",
               "d"   : "lFj2hl_0MDs7D3yyTgU6LedcJ7NUZAs6noGzhZszsRA" },
             {
               "kty" : "EC",
               "crv" : "P-384",
               "use" : "enc",
               "kid" : "TqZ6",
               "x"   : "3Ex0yUSLvhaOriP8U78kZEEJXxkC0oQmwo1zHTe_nhgKx2YPS97-qmDdRMkByxJ9",
               "y"   : "MCosrhjIYP4lkoan45MxAZE3QB6IKau5nZHpQ_qDXH8jgcIo2l3M8wdN6iI08kcW",
               "d"   : "W4OifZsTcoIBwBteTM_8fwNKu7xFVlJEzVS-9YfJJK_QenjbedvcqTfzyiwh1b9F" },
             {
               "kty" : "EC",
               "crv" : "P-521",
               "use" : "enc",
               "kid" : "h38C",
               "x"   : "AVMBSexPHgq536pZQjN6Si1HAdUdfiW4xrdYzNHR2A9z4zovnKi5xrQ9hWX8QUs4ejVQ3bE9ufhOYL3D7oTwx9Jb",
               "y"   : "AeMeo858k_6ktxNhlpxBSwGL2hmTI1nBeGi2ZrMVl2qzdjOFf-AVFRSsE9DhAD9sWVUrGrzwONbfmqwIlgbjeH7L",
               "d"   : "AJGiS9ovRl2PrJz8ZSKokMaGXk-nJObJPtPiISPSxFJe1PHJWpEXollGAAYTI8DSiyO4gi7BHGq6T5JGB_zS2TqU" },
             { "kty" : "oct",
               "use" : "enc",
               "kid" : "5C93",
               "k"   : "MaLXergNZ0bec14LDJkXTQ" },
             { "kty" : "oct",
               "use" : "sig",
               "kid" : "hmac",
               "k"   : "m5JZeVoU9lBV6y-d2jNelbjrxwosYjrSGg4STHLLm4g" },
             { "kty" : "oct",
               "use" : "enc",
               "kid" : "subject-encrypt",
               "k"   : "QA4js08rUQsZfEoEoxu6LGgJgbHdmPG08XCKYSJTNJ0" },
             { "kty" : "oct",
               "use" : "enc",
               "kid" : "refresh-token-encrypt",
               "k"   : "pNzHVtVWJ8oluOGvesrmLgyVEVCkT6Os5f8e2PFEK9Y" } ] }

Sample OpenID Federation 1.0 JWK set

{ "keys" : [ { "kty" : "RSA",
               "alg" : "RS256",
               "use" : "sig",
               "kid" : "exR5",
               "n"   : "l9TeUfN0jztln5hVq6Z3vwS47MCyonpO-kJSVMqccKgoUkxLzo_IH1ekKf-3X1Tu4KrKoDn7Nk6Wrusw9gOI9JCszV8rCE1_SCYnKI4mCwI9RXhCgXC0NkvXg-1ySHn9PjNEurGsgpIFqA2u-66KItFP_BLsUKGDfC1w73EymUJ6ZHGc1FnAXCusWgLARceOep4oAO8q3_oFNW4A__1IphYnJ6zdqYwBHK6PWf210SKP8LAJ0tlq7RTZyiB0DG9ina95UHNFIoJnc_g-AOCa1-ShDcUNpWtpL1j3vZnAHyG3pB_9xi4Ngo2-vlZQXnalZmDbk1Cog4N3hI-3DXTTMw",
               "e"   : "AQAB",
               "d"   : "YydZ9Oznzu48RIhoUkvJYc7EsaB6SE9VqmuLduJGXfADPROkYgZV69oBVIgyCajew4vl_dM_skyKbTsc41yVoRmmMAyZfreVitmXsw153LCesPKDhCLFHbxTx01W1-wKrQcwODf17-NKnGArSSPIBErrUDRPbay8wGiwmz4yjBDydZKYlFGwnt4R3MBzUB0nEhR_aKelUamdXyfOAT1gZh2cTJEMt7jzUbOKokJlaH3Yb3JOjI1n1RROxrwLW2tGoU7fPXSEULK5N9fddthXpDy1vwezYrdihIWdhSJd5xyvU85SuTYt0XHi3sDl1rc2iuJYpXOrQ3R92C-sLX00YQ" } ] }

13. Tips

The jq tool can be used to extract keys from a JWK set.

To extract a JWK with a given kid (key ID), e.g. subject-encrypt:

cat jwkSet.json | jq '.keys[] | select(.kid=="subject-encrypt")'

To extract the Ed25519 signing key(s):

cat jwkSet.json | jq '.keys[] | select(.kty=="OKP" and .crv=="Ed25519" and .use=="sig")'

To extract the shared encryption key(s) for JWT-encoded access tokens:

cat jwkSet.json | jq '.keys[] | select(.kty=="oct" and .use=="enc" and .kid!="subject-encrypt" and .kid!="refresh-token-encrypt")'