Server JSON Web Key (JWK) set

The Connect2id server must be supplied with a set of cryptographic keys to secure issued tokens and other objects:

  • 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 (note on weak 1024 bit keys).
    • 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 set to sig (signature). The private RSA and EC keys can be stored in a PKCS#11 compliant HSM. The public keys will be published so that clients can download them to validate the JWTs.

    Rotation supported: Yes

  • JWT encryption keys -- Public / private keys pairs for letting clients encrypt JWTs that are request objects (JAR) to the Connect2id server (can be stored in a PKCS#11 compliant HSM):

    • 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 set to enc (encryption). The public keys will be published so that clients can download them to encrypt JWTs.

    Rotation supported: 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 also specify a unique key ID (kid). Its use must be set to 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.

    Rotation supported: 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) set to hmac and its use must be set to sig (signature).

    Rotation: 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) set to refresh-token-encrypt and its use must be set to enc (encryption).

    Rotation: 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) set to subject-encrypt and its use must be set to enc (encryption).

    Rotation: No

  • 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 set to sig (signature). The private RSA keys can be stored in a PKCS#11 compliant HSM. The public keys will be published so that federation clients can download them in order to validate the issued statements.

    Rotation supported: Yes

Server JWK sets

The main server keys are stored in JSON Web Key Set (JWK set) format in the following file:

WEB-INF/jwkSet.json

The OpenID federation entity keys are kept separately (required only if OpenID federation is enabled):

WEB-INF/federationJWKSet.json

The JWK set can be alternatively passed via a jose.jwkSet Java system property. The property value is the JSON representation of the JWK set. Applying additional BASE64URL encoding to the JSON string is recommended, for safe passing of the value in the shell (otherwise all special characters in the JSON must be escaped):

-Djose.jwkSet=eyAia2V5cyIgOiBbIHsgImt0eSIgOiAiUlNBIiwNCiAgICAgICAgICAgICAgIC...

For the federation JWK set use the jose.federation.jwkSet property:

-Djose.federation.jwkSet=eyAia2V5cyIgOiBbIHsgImt0eSIgOiAiUlNBIiwKICAgICAgICAg...

The external configuration guide has tips for setting system properties from environment variables, local files and other locations.

Important

Before you put a Connect server in production you must generate a new JWK set to replace the sample JWK set that comes with the original installation package.

The private and secret keys must be kept secure at all times, and must never be disclosed to other parties!

How to generate a new JWK set

Use the Connect2id JWK generator (JAR download), by invoking it with the following command line arguments:

java -jar jwkset-gen.jar jwkSet.json

Sample console output:

JWK set generator v1.24 for Connect2id server v6.x+
[1] Generated new signing RSA 2048 bit key with ID JPnL
[2] Generated new signing EC P-256 key with ID yRxr
[3] Generated new signing EC P-384 key with ID l9uu
[4] Generated new signing EC P-521 key with ID DUKL
[5] Generated new signing EC secp256k1 key with ID 8CEC
[6] Generated new signing Ed25519 key with ID MsAA
[7] Generated new encryption RSA 2048 bit key with ID HuzW
[8] Generated new encryption EC P-256 key with ID YdaE
[9] Generated new encryption EC P-384 key with ID CiHc
[10] Generated new encryption EC P-521 key with ID TXpW
[11] Generated new symmetric encryption 128 bit key with ID jBLi
[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

Replace the sample WEB-INF/jwkSet.json file, then restart the server.

If you are passing the JWK set via the jose.jwkSet Java system property on the command line, enable the -b64 option to BASE64URL-encode the JSON (saves the need to escape all special JSON characters in the shell):

java -jar jwkset-gen.jar -b64 jwkSet.json.b64

To generate a federation entity JWK set simply add the -federation option:

java -jar jwkset-gen.jar -federation federationJWKSet.json

The Connect2id server performs a check of the JWK set during startup. If a key is found to be missing or non-compliant, the server will log an error message and abort on the spot.

JWK rotation and roll-over

To change the public keys for signing and encrypting JWTs generate a new JWK with unique kid for each key type and use, then add the new JWKs at the top of the existing JWK.

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). All public keys found in the JWK set will be published, so clients can still validate tokens secured with an expired key.

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

Important: The HMAC-SHA key (kid : hmac), the refresh token encryption key (kid : refresh-token-encrypt) and the subject encryption key (kid : subject-encrypt) are intended to be permanent and must not be rotated / updated in a production Connect2id server deployment! Updating them will invalidate all sessions, identifier-based tokens and pairwise subject IDs.

The easiest way to generate new public signing and encryption JWKs and add them to an existing JWK set file is again the JWK generator. The first argument is the existing JWK set file, tne second the new file with the updated JWK set:

java -jar jwkset-gen.jar jwkSet.json updatedJWKSet.json

With the above command the tool (v1.14+) will also check for any missing required permanent keys, such as the refresh-token-encrypt JWK, and automatically generate and add them. This is useful when upgrading the Connect2id server to a new release that needs a new type of permanent key.

Sample console output:

JWK set generator v1.24 for Connect2id server v6.x+
[1] Generated new signing RSA 2048 bit key with ID HKy9
[2] Generated new signing EC P-256 key with ID eXTV
[3] Generated new signing EC P-384 key with ID 3izX
[4] Generated new signing EC P-521 key with ID Et6T
[5] Generated new signing EC secp256k1 key with ID 7pDQ
[6] Generated new signing Ed25519 key with ID vUDy
[7] Generated new encryption RSA 2048 bit key with ID YFcf
[8] Generated new encryption EC P-256 key with ID K2jJ
[9] Generated new encryption EC P-384 key with ID 0Ckl
[10] Generated new encryption EC P-521 key with ID pQsA
[11] Generated new symmetric encryption 128 bit key with ID PDrr
[12] Prefixed newly generated keys to existing JWK set

To roll-over to the new keys, replace the old WEB-INF/jwkSet.json file, then restart the server.

If you are passing the JWK set via the jose.jwkSet Java system property on the command line, enable the -b64 option to BASE64URL-encode the JSON (saves the need to escape all special JSON characters in the shell):

java -jar -b64 jwkset-gen.jar jwkSet.json updatedJWKSet.json.b64

Public JWKs for historical purposes

The JWK set may include JWK instances without private parameters. These keys will be published at the /jwks.json endpoint and not used internally by the Connect2id server.

The OpenID Federation entity JWK set may also include public-only JWK instances. These keys will be included in issued Entity Configurations and not used internally by the Connect2id server.

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")'

PKIX / X.509 certificates

A Connect2id server deployment can furnish its public JWKs for signing and encryption with X.509 certificates. An X.509 certificate enables OAuth 2.0 clients and / or 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 JWK is published 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.

Important:

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

Weak 1024 bit RSA keys

The Connect2id server expects to be supplied with 2048 bit or longer RSA keys and if a weaker RSA key is detected it will about startup with an error.

FATAL MAIN - [SE1030] Found weak RSA key(s) shorter than 2048 bits with IDs: [CXup]

To set the Connect2id server up with one more more weak 1024 bit RSA keys, for purposes of migration or key roll-over, edit the following configuration file

WEB-INF/jose.properties

and set the jose.allowWeakKeys property to true. The default value is false.

jose.allowWeakKeys = true

This configuration can also be passed as a Java system property:

-Djose.allowWeakKeys=true

If weak RSA keys are allowed and detected in the JWK set, the Connect2id server will log a warning at startup.

WARN MAIN - [SE1030] Found weak RSA key(s) shorter than 2048 bits with IDs: [CXup]

Sample 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 federation entity 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" } ] }

Hardware Security Module (HSM) for signing tokens

The Connect2id server can use PKCS#11 compliant HSMs to sign the issued ID and self-contained (JWT) access tokens.

The JWK set utilised by the Connect2id server can be composed of HSM-based keys as well as plain file-based keys.

HSM configuration

The HSM configuration is located in the properties file

WEB-INF/jose.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:

-Dpkcs11.enable=true

The external configuration guide has tips for setting system properties from environment variables, local files and other locations.

pkcs11.enable

Enables / disables PKCS#11 HSM support. HSM support is normally disabled, to enable it set the property to true.

pkcs11.enable=true

pkcs11.configFile

The location of the Sun PKCS#11 provider configuration:

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

The PKCS#11 provider configuration can be alternatively passed inline instead of by file reference. The property value must be the configuration string. Applying additional BASE64URL encoding to the string is recommended, for safe passing of the value in the shell (otherwise all special characters in the string must be escaped):

-Dpkcs11.configFile=bmFtZSA9IE5pdHJvS2V5SFNNCmxpYnJhcnkgPSAvdXNyL2xpYi94ODZfNjQtbGludXgtZ251L29wZW5zYy1wa2NzMTEuc28Kc2xvdExpc3RJbmRleCA9IDEKYXR0cmlidXRlcygqLENLT19QUklWQVRFX0tFWSxDS0tfUlNBKSA9IHsKICBDS0FfU0lHTiA9IHRydWUKfQ

The PKCS#11 provider configuration specifies the driver to load for the HSM device, its slot number (as multiple HSM devices may be attached), plus additional attributes. These are explained in the Sun PKCS#11 provider documentation. The manual of your HSM device may also include useful information.

Example hsm.cfg:

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

pkcs11.password

The password (PIN) required to unlock the HSM.

pkcs11.password = 648219

pkcs11.keyIDs.*

Optional list of identifiers (aliases) of PKCS#11 keys to load from the HSM. If omitted or blank all recognised and supported keys will be loaded. Since v14.7.

This configuration property can be used in Connect2id server deployments sharing the HSM with other applications.

Example list of three key IDs:

pkcs11.keyIDs.1=9d64c4f5-724f-4057-af36-1dd2679c00a4
pkcs11.keyIDs.2=cb8dc79c-7ec9-4488-8723-e50fe32a2ff3
pkcs11.keyIDs.3=d274a2c2-9af7-4fbd-b669-8e337672443c

Generating keys on the HSM

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

  • For signing tokens with an RSA key, provision one or more RSA keys on the HSM. The RSA keys must be 2048, 3072 or 4096 bits long.

  • For signing tokens with an EC key, provision one or more EC keys with curve P-256 (for JWS algorithm ES256), P-384 (for ES384) and / or P-521 (for ES512). Note that HSMs with EC support are less common.

  • 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 parameter of the JWK.

  • Make sure the HSM can maintain the signing rate required by the IdP. If the HSM bandwidth is exceeded the token signing will slow-down or fail, resulting in server timeouts or HTTP 500 errors.

How do HSM keys get merged and published?

  • The Connect2id server will only import HSM keys that it can use for RSA or ECDSA signing and ignore any other key types in the store.

  • The imported HSM keys will be added at the top of the configured local JWK set. The resulting JWK set will have all its public keys exported and published at the jwks.json endpoint of the Connect2id server. The X.509 certificates of the HSM-based keys will be included in the JWK x5c parameter.

  • If the Connect2id server deployment is new (never issued tokens before) make sure there are no signing JWKs in the local JWK set that match the type and use of the imported HSM key. For example, if the deployment is going to use an RSA HSM key, make sure the configured JWK set property has no JWKs with "kty":"RSA" and "use":"sig". This should be done to avoid the publishing of local keys that won't be used.

  • If an existing Connect2id server deployment is migrating to HSM-based keys keep the configured local JWK set just as it is.

Guarantees

The Connect2id server applies to HSM-based keys the exact same key selection guarantees that apply to JWKs with X.509 certificates. What does this mean for deployments that plan to introduce an HSM?

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

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

Debugging HSM issues

The Connect2id server logs the loading of the HSM device and which keys in it are selected for signing. Keys that don't match the server requirements, in terms of key type, use or size, will be ignored.

INFO MAIN - [SE0001] JOSE configuration: PKCS#11 enabled: true
INFO MAIN - [SE0002] JOSE configuration: PKCS#11 configuration file: /WEB-INF/hsm.cfg
INFO MAIN - [SE0003] JOSE configuration: PKCS#11 password: true
INFO MAIN - [SE1001] Loaded JWK set file with 7 keys: /WEB-INF/jwkSet.json
INFO MAIN - [SE1006] Loaded PKCS#11 provider SunPKCS11-NitroKeyHSM
INFO MAIN - [SE1007] Loaded PKCS#11 key store with 2 entries
INFO MAIN - [SE1009] Extracted JWK set with 2 keys from PKCS#11 key store SunPKCS11-NitroKeyHSM
DEBUG MAIN - [SE1010] Assuming signature key use for RSA PKCS#11 JWK with ID 1
DEBUG MAIN - [SE1010] Assuming signature key use for RSA PKCS#11 JWK with ID 2
INFO MAIN - [SE1008] Loaded JWK set:
INFO MAIN - [SE3000] [1] JWK type=RSA id=1 private=true use=sig size=2048 pkcs#11=true nbf=2017-01-30T11:47:41Z exp=2017-02-28T11:47:41Z
INFO MAIN - [SE3000] [2] JWK type=RSA id=2 private=true use=sig size=2048 pkcs#11=true nbf=2017-01-30T11:51:23Z exp=2017-02-28T11:51:23Z
INFO MAIN - [SE3000] [3] JWK type=RSA id=CXup private=true use=sig size=2048 pkcs#11=false 
INFO MAIN - [SE3000] [4] JWK type=EC id=yGvt private=true use=sig size=256 pkcs#11=false 
INFO MAIN - [SE3000] [5] JWK type=EC id=9nHY private=true use=sig size=384 pkcs#11=false 
INFO MAIN - [SE3000] [6] JWK type=EC id=tVzS private=true use=sig size=521 pkcs#11=false 
INFO MAIN - [SE3000] [7] JWK type=oct id=5C93 use=enc size=128 pkcs#11=false 
INFO MAIN - [SE3000] [8] JWK type=oct id=hmac use=sig size=256 pkcs#11=false 
INFO MAIN - [SE3000] [9] JWK type=oct id=subject-encrypt use=enc size=256 pkcs#11=false 

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