Understanding and Validating JWT using Json Web Key Sets in Microservices

Before we jump on the approach of validating the JWT Token we need to know a few basics and then we can discuss about the below points.

  1. How we can sign the JWT Token.
  2. Why do we require a JWT Token to be signed.
  3. What is JSON Web Key Set ?
  4. Why and How to use JSON Web Key Set ?
  5. Locate JSON Web Key Set.

So, What is JSON Web Token?

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object.

-jwt.io

The above image shows how a JWT Content looks like and can be broken down to two main parts, one being the header and the other being the payload. We also need a secret to sign the token. These are separated by (.) dot.

Therefore, a JWT typically looks like the following.

xxxxx.yyyyy.zzzzz

Why Do we sign the TOken

So that the information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.

Although JWTs can be encrypted to also provide secrecy between parties, we will focus on signed tokens. Signed tokens can verify the integrity of the claims contained within it, while encrypted tokens hide those claims from other parties. When tokens are signed using public/private key pairs, the signature also certifies that only the party holding the private key is the one that signed it.

What is Jwks ?

The JSON Web Key Set (JWKS) is a set of keys containing the public keys used to verify any JSON Web Token (JWT) issued by the authorization server and signed using the RS256 signing algorithm.

Why and How to use JSON Web Key Set ?

We have been in the the world on Monolithic Architecture API from the past decades. So, Authentication and Claims Based Authorization was in this regard was easy in a monolithic. Now, we are heading to the more granular services which we call microservices.

In this previous era of Monolithic Architecture API we didn’t have any separation between the authentication/Authorization and other services.

Now, that we are moving towards microservices, each services has its own responsibility. But we also need to authenticate and authorize the user for each and every request. Now how do we do that?

If we create a symmetric key and use this to create a Token we would have to share this key to all the services that require to use the JWT token. But there are multiple draw back to this approach.

  1. We have to share the key with other services.
  2. IF a key from one service get compromised, the whole service ecosystem will be prone to be compromised.
  3. IF we need to change the secret to sign JWT we would have to update everywhere the token is being used.

How it works ?

When a user signs in to your application, we create a token that contains information about the user and sign the token using its private key before we send it back to your application. Auth0 secures the private key, which is unique per tenant.

To verify that the token is valid and originated from Identity Server, your application validates the token’s signature using the public key. 

This specification defines two high-level data structures: JSON Web Key (JWK) and JSON Web Key Set (JWKS). Here are the definitions from the specification:

ItemDescription
JSON Web Key (JWK)A JSON object that represents a cryptographic key. The members of the object represent properties of the key, including its value.
JSON Web Key Set (JWKS)A JSON object that represents a set of JWKs. The JSON object MUST have a keys member, which is an array of JWKs.

Here is an example of the JSON Web Key Set (JWKS) used by a sample tenant, containing a single JSON Web Key (JWK):

{
"keys": [
  {
    "alg": "RS256",
    "kty": "RSA",
    "use": "sig",
    "x5c": [
      "MIIC+DCCAeCgAwIBAgIJBIGjYW6hFpn2MA0GCSqGSIb3DQEBBQUAMCMxITAfBgNVBAMTGGN1c3RvbWVyLWRlbW9zLmF1dGgwLmNvbTAeFw0xNjExMjIyMjIyMDVaFw0zMDA4MDEyMjIyMDVaMCMxITAfBgNVBAMTGGN1c3RvbWVyLWRlbW9zLmF1dGgwLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMnjZc5bm/eGIHq09N9HKHahM7Y31P0ul+A2wwP4lSpIwFrWHzxw88/7Dwk9QMc+orGXX95R6av4GF+Es/nG3uK45ooMVMa/hYCh0Mtx3gnSuoTavQEkLzCvSwTqVwzZ+5noukWVqJuMKNwjL77GNcPLY7Xy2/skMCT5bR8UoWaufooQvYq6SyPcRAU4BtdquZRiBT4U5f+4pwNTxSvey7ki50yc1tG49Per/0zA4O6Tlpv8x7Red6m1bCNHt7+Z5nSl3RX/QYyAEUX1a28VcYmR41Osy+o2OUCXYdUAphDaHo4/8rbKTJhlu8jEcc1KoMXAKjgaVZtG/v5ltx6AXY0CAwEAAaMvMC0wDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUQxFG602h1cG+pnyvJoy9pGJJoCswDQYJKoZIhvcNAQEFBQADggEBAGvtCbzGNBUJPLICth3mLsX0Z4z8T8iu4tyoiuAshP/Ry/ZBnFnXmhD8vwgMZ2lTgUWwlrvlgN+fAtYKnwFO2G3BOCFw96Nm8So9sjTda9CCZ3dhoH57F/hVMBB0K6xhklAc0b5ZxUpCIN92v/w+xZoz1XQBHe8ZbRHaP1HpRM4M7DJk2G5cgUCyu3UBvYS41sHvzrxQ3z7vIePRA4WF4bEkfX12gvny0RsPkrbVMXX1Rj9t6V7QXrbPYBAO+43JvDGYawxYVvLhz+BJ45x50GFQmHszfY3BR9TPK8xmMmQwtIvLu1PMttNCs7niCYkSiUv2sc2mlq1i3IashGkkgmo="
    ],
    "n": "yeNlzlub94YgerT030codqEztjfU_S6X4DbDA_iVKkjAWtYfPHDzz_sPCT1Axz6isZdf3lHpq_gYX4Sz-cbe4rjmigxUxr-FgKHQy3HeCdK6hNq9ASQvMK9LBOpXDNn7mei6RZWom4wo3CMvvsY1w8tjtfLb-yQwJPltHxShZq5-ihC9irpLI9xEBTgG12q5lGIFPhTl_7inA1PFK97LuSLnTJzW0bj096v_TMDg7pOWm_zHtF53qbVsI0e3v5nmdKXdFf9BjIARRfVrbxVxiZHjU6zL6jY5QJdh1QCmENoejj_ytspMmGW7yMRxzUqgxcAqOBpVm0b-_mW3HoBdjQ",
    "e": "AQAB",
    "kid": "NjVBRjY5MDlCMUIwNzU4RTA2QzZFMDQ4QzQ2MDAyQjVDNjk1RTM2Qg",
    "x5t": "NjVBRjY5MDlCMUIwNzU4RTA2QzZFMDQ4QzQ2MDAyQjVDNjk1RTM2Qg"
  }
]}


Each property in the key is defined by the JWK specification RFC 7517 Section 4 or, for algorithm-specific properties, in RFC 7518].

Property nameDescription
algThe specific cryptographic algorithm used with the key.
ktyThe family of cryptographic algorithms used with the key.
useHow the key was meant to be used; sig represents the signature.
x5cThe x.509 certificate chain. The first entry in the array is the certificate to use for token verification; the other certificates can be used to verify this first certificate.
nThe modulus for the RSA public key.
eThe exponent for the RSA public key.
kidThe unique identifier for the key.
x5tThe thumbprint of the x.509 cert (SHA-1 thumbprint).

Locate JSON Web Key Sets

Use this Discovery endpoint to configure your application or API to automatically locate the JSON Web Key Set (JWKS) endpoint (jwks_uri), which contains the JWKS used to sign all issued JSON Web Tokens (JWTs) signed. The endpoint exists at:

https://YOUR_DOMAIN/.well-known/openid-configuration.

When validating a JWT using a JWKS, you will need to:

  • Retrieve the JWKS from the well-known Discovery endpoint, and filter for potential signing keys (e.g., any keys missing a public key or with a kid property).
  • Grab the kid property from the Header of the decoded JWT.
  • Search your filtered JWKS for the key with the matching kid property.
  • Build a certificate using the corresponding x5c property in your JWKS.
  • Use the certificate to verify the JWT’s signature.