JSON web keys

A JSON Web Key (JWK) provides a standard method for representing a cryptographic key using JSON (JavaScript Object Notation). In the case of Hosted Login, these web keys are used to verify the signature on JSON Web Tokens. As a general rule, you don’t have to worry much about you JSON web keys: when you subscribe to Hosted Login, ​Akamai​ Identity Cloud personnel will create your web keys and publish them for you. You can view these keys at any time by accessing your JWK endpoint; that endpoint will have a URL similar to this:

https://v1.api.us.janrain.com/00000000-0000-0000-0000-000000000000/login/jwk


📘

As we mentioned, the keys found on your JWK endpoint can only be used for verifying signatures. That’s why there are no security concerns about making them publicly available: these keys are supposed to be publicly available.


As published on the JWK page, a hosted login web key looks something like this:

{
    "use":"sig",
    "kty":"RSA",
    "kid":"51300370a8e1ac0a14a59cdd9c881d3f24c01f78",
    "alg":"RS256",
    "n":"w9OLNr_6sIuqr8OO3nPzorbv8tkmXC-m0k0O3W6gdk1QipvJ2pZkRSzD_iIWnEvYV11RuOBSAb7e_nU7mwNnxX6mORyJIEwnHKucBwaHQhuo56uVUjNTsRI6OuLB6REwxLM0ePPQPJNaXncWzt83oYdHU10VPmp5x0Sj-GjTvMpm2Y4I14KnFUXMEvIC-e5lf2P7q6KMXNw3PchEvmO5fVCgXf5-FgzDzEyn0qXrerdui4lGUtzcREPFksPNLNMlqp0XL5Kz1QLLkKDtR3dVjEtViEYJ6extcI-xFEV785hO4Ok36N99ht41EZk8ibrflNnYkJIEXAw_LKkmtxyZKw",
    "e":"AQAB"
}

The preceding key properties (such as use and kty) are explained in the following sections.


use

Identifies whether a public key is used for: 

  • Encrypting data (enc)
  • Verifying the signature on data (sig)

For hosted login, the use will always be set to sig; that’s because these keys are only used for verifying signatures on identity tokens.


kty

The "kty" (key type) parameter identifies the cryptographic algorithm family used with the key; the two most-common values are RSA(Rivest–Shamir–Adleman, the default value for hosted login) and EC(Elliptic Curve Cryptography).  kty values are case-sensitive and must be included in all JSON Web Keys.


kid

Identifier for a specific JSON Web Key. Key identifiers are only required if you have multiple keys within your JSON Web Key Set; this enables you to distinguish between individual keys in the key set. If you only have one such key, there’s no need for a key identifier because there aren’t any other keys in the key set.

Despite the fact that these values are used to identify individual keys, kid values do not have to be unique. Instead, two keys can have the same kid as long as they differ in other ways (such as key use or key type). 


alg

Identifies the cryptographic algorithm used to sign the token: a token signature is not valid if the alg value does not represent a supported algorithm. By default, Hosted Login uses RS256 (RSA Digital Signature Algorithm with SHA-256) as its encryption algorithm. This is a public key/private key system in which public keys are generated using the modulus and the exponent.

Similar to key identifiers, alg values are case-sensitive.


n

Along with the exponent (e), the modulus is used to generate public key values.  


e

Along with the modulus (n), the exponent is used to generate public key values. The exponent, which is stored as a Base64urlUInt-encoded value, is typically set to 65537 (AQAB when Base64urlUInt-encoded).


Retrieve web keys by making an API call

Information about your JSON Web Keys can also be returned by calling the /{customerId}/login/jwk endpoint. For example, this Curl command returns JSON Web Key information for the customer with the customer ID 00000000-0000-0000-0000-000000000000:

curl https://v1.api.us.janrain.com/00000000-0000-0000-0000-000000000000/login/jwk

In turn, you should get back something similar to this (note: color coding has been added to help distinguish the individual keys):

{
    "keys": [
 {
 "use": "sig",
 "kty": "RSA",
 "kid": "51300370a8e1ac0a14a59cdd9c881d3f24c01f78",
 "alg": "RS256",
 "n": "w9OLNr_6sIuqr8OO3nPzorbv8tkmXC-m0k0O3W6gdk1QipvJ2pZkRSzD_iIWnEvYV11RuOBSAb7e_nU7mwNnxX6mORyJIEwnHKucBwaHQhuo56uVUjNTsRI6OuLB6REwxLM0ePPQPJNaXncWzt83oYdHU10VPmp5x0Sj-GjTvMpm2Y4I14KnFUXMEvIC-e5lf2P7q6KMXNw3PchEvmO5fVCgXf5-FgzDzEyn0qXrerdui4lGUtzcREPFksPNLNMlqp0XL5Kz1QLLkKDtR3dVjEtViEYJ6extcI-xFEV785hO4Ok36N99ht41EZk8ibrflNnYkJIEXAw_LKkmtxyZKw",
 "e": "AQAB"
 },
 {
 "use": "sig",
 "kty": "RSA",
 "kid": "f63eecd7318b6a6bcfae82f9607689756c6dd83e",
 "alg": "RS256",
 "n": "2kTH-jB0XDAb4yJy9rRMKNTNk4FEz7n3mbzj7nvupGvozyrpgHNFzSNW-Faxfo8v3cMdekd0-3S1ioNquAn9bbKZ8j2D4wK7rYtJgwOE8vnHkLUPAQuv_ymUgdgRAz7iQhsUN-vs8QLIDTddzEGnKWZASndLb-CYN_3eSWCDL7J8kQGkm9EI91OY1tKUUdIxlHpr90zAR36CFWWIJY1hpgFFnC1Po2r4nBtkBZD-SG_tmWB7fmWmF9v9MNnpmY00h3PsvUfzb6dSzLNt3H2ocSys7F5syaulRGLiKFiTalPPri_wAj-CPVfqiZuEys8PNTVd6T969PM4dIFdIsR0gw",
 "e": "AQAB"
 },
 {
 "use": "sig",
 "kty": "RSA",
 "kid": "a964a617a74b6cece03857daa1e8e144d11132a9",
 "alg": "RS256",
 "n": "7-LW8dGJKFsxU6ztkRA_qdhzvuHkoeWlRGL6ejqW9z_PxtDnQbLIpiy0vFm_DYAyNyFXt1EbuVMzESd4XRCKue4Lw2tGS_iiVQhlq7RkwAYG-hOkiiIHCcLVVCxtPm8gdmW-Cp4sdDozG0Yc99os-nyBtm2YzZ3ECAMsQsQVIjR03_JD3l1u79F4EzWcs2aBMOQ0NFDHqoQyk16Gf6Ww5QMXBtFhI508kYDMg71-0cxpssOrkztBBkxH1WPDpeliEAO91Sy1HDgXkuKdEuPkB3JxUqGXiw_UAez0a4XXBMFNkc5pV8byrKWokKmzNSgSfObqaRx13wOk5xjyVpyfHQ",
 "e": "AQAB"
 }
    ]
}

In the preceding API call, we got back three different web keys, keys that have the following key identifiers:

  • 51300370a8e1ac0a14a59cdd9c881d3f24c01f78
  • f63eecd7318b6a6bcfae82f9607689756c6dd83e
  • a964a617a74b6cece03857daa1e8e144d11132a9

JSON web keys in action

Because OpenID Connect clients understand how to retrieve and decipher JSON Web Keys, you typically don’t have to deal with the process of how identity token signatures get verified: to a very large extent, they just do. If you’re interested, however, here’s a brief overview of the activities that takes place when an application needs to verify a token signature:

  1. Upon receipt of the token, the application connects to the jwk URL and retrieves the JSON Web Key Set (a web key set, as the name implies, is a collection of all the JSON web keys used in your implementation of Hosted Login). In the sample web site we looked at previously, that collection will contain three web keys, with the following kid values:

    51300370a8e1ac0a14a59cdd9c881d3f24c01f78
    f63eecd7318b6a6bcfae82f9607689756c6dd83e
    a964a617a74b6cece03857daa1e8e144d11132a9

  2. The application decodes the token header and extracts the kid (key identifier) and the alg (algorithm). For example, the token header might look like this, where the kid value is f63eecd7318b6a6bcfae82f9607689756c6dd83e and the algorithm is RS256:

{   
      "alg": "RS256",
      "typ": "JWT",
      "kid": "f63eecd7318b6a6bcfae82f9607689756c6dd83e"
    }
  1. The application searches through the JWKS to find the key that has the specified key identifier and that uses the specified algorithm:
{
        "use": "sig",
        "kty": "RSA",
        "kid": "f63eecd7318b6a6bcfae82f9607689756c6dd83e","alg":"RS256","n":"2kTH-jB0XDAb4yJy9rRMKNTNk4FEz7n3mbzj7nvupGvozyrpgHNFzSNW-Faxfo8v3cMdekd0-3S1ioNquAn9bbKZ8j2D4wK7rYtJgwOE8vnHkLUPAQuv_ymUgdgRAz7iQhsUN-vs8QLIDTddzEGnKWZASndLb-CYN_3eSWCDL7J8kQGkm9EI91OY1tKUUdIxlHpr90zAR36CFWWIJY1hpgFFnC1Po2r4nBtkBZD-SG_tmWB7fmWmF9v9MNnpmY00h3PsvUfzb6dSzLNt3H2ocSys7F5syaulRGLiKFiTalPPri_wAj-CPVfqiZuEys8PNTVd6T969PM4dIFdIsR0gw",
        "e": "AQAB" 
    }
  1. The application uses that key to verify the signature.

JSON web key rotation

From time-to-time ​Akamai​ "rotates" JSON Web Keys, replacing an existing key (e.g., Web Key A) with a replacement key (Web Key B). Key rotation, which is typically not announced in advance, is a security precaution: by limiting the lifetime of a web key you also limit the amount of time available for someone to hack that key.

The fact that web keys are occasionally rotated has important implications for anyone using those keys to validate signatures. For one thing, you must be aware that key rotation takes place. Without key rotation, you could grab a key ID, store that ID somewhere, then use that key any time you needed to validate a signature. With key rotation, however, this approach won't always work: after all, the ID you stored might point to a key that has been rotated out and, as a result, no longer exists. 

A similar issue can arise if you cache key IDs: the IDs stored in your cache might not reflect the actual key IDs used by Hosted Login. When validating signatures you must make allowances for key IDs that are no longer valid, and take steps to retrieve (and then employ) the current set of JSON Web Keys.

The main takeaway here? Key rotation is a routine procedure that helps keep your site safe and secure. Your web keys and key IDs will change from time-to-time, something which is actually for your own good. And as long as you don't rely on hard-coded key IDs (or key caches that never get refreshed) this shouldn't cause any problems.