Implementing JSON Web Token (JWT) Verification

Implementing JSON Web Token (JWT) Verification

In my previous article about basics of JSON Web Token (JWT) (https://www.garudax.id/post/edit/6766684652779442176/), I wrote about registered and custom claims and how the enforcement of security policy (known as PEP) can be achieved in every API call to secure APIs. I hope that this lead to some inspiration for you to do some research around it.

In this article, I would like to touch on the design and programming aspect of the validation of JWT tokens for client credential flow. For my convenience, I have used Java as a language of demonstration, but there are a lot of libraries with Python, .NET and NodeJS. The concepts below are the same whichever language is chosen.

As seen in the picture, the flow for a JWT always starts when a client application requests for some data via APIs. The client application could be operated by a user directly or could be another system. In a client credential flow, the API request with JWT token hits the Edge Gateway. The scope of Edge Gateway could vary on the architecture pattern in your organization. As an example, for monolithic architecture-based API Compute, this edge gateway could just encrypt the passage and do some route management. Another variant could be in a microservice architecture-based API Compute where the edge gateway could take a bigger role to validate and introspect the JWT. For the simplicity we are assuming a monolithic architecture-based API Compute, so lets go with the understanding that the Edge Gateway is a simple pass through.

Once the API request (with JWT token) reaches the API Compute, the validation kicks in. At first the API Compute does the signature validation via the JSON Web Key (JWK). This is followed by decoding of the JWT token to extract the registered claims from the payload like audience and expiry timer and finally the API Compute validate the claims and compares these with the legitimate values for your organization.

The JWK mentioned above is the JSON structure that represents a cryptographic key. JWKS is to pluralize this, the last "S" stands for Set. In the picture, it is visible that the JWKS is synced in from the Authorization Server and cached in the API Compute.

An example JWKS could look like:

{
  "keys": [
    {
      "kty": "RSA",
      "kid": "whatever-identifier1",
      "use": "sig",
      "n": "thisisunreadablealways1",
      "e": "AQAB"
      "x5c": "Whoopiiieeeeeee..Iamthepublickey1"
    },
    {
      "kty": "EC",
      "kid": "whatever-identifier2",
      "use": "sig",
      "n": "thisisunreadablealways2",
      "e": "AQAB"
      "x5c": "Whoopiiieeeeeee..Iamthepublickey2"

    }
  ]
}

Now, that the JWKS is cached and the JWT token is received by the API Compute, it is time to dive in the implementation.

When it comes to Java, jjwt library aims to be the easiest for verifying JSON Web Tokens (JWTs). In the pom.xml of my application I injected the jjwt artifact as a dependency.

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

Now the JWKS which has been synced from Authorization Server needs to be transformed into a X509 certificate as its public key will come in handy later. For this the x5c attribute from the JWKS can be used for the algorithm which is implemented for the JWT Token. The transformation to a X509 certificate is done with these few lines of code below:

byte[] keyBytes = Base64.decodeBase64(x5c);
CertificateFactory fact = CertificateFactory.getInstance(X.509);
X509Certificate cer = (X509Certificate) fact.generateCertificate(new ByteArrayInputStream(keyBytes));

The cer variable above contains the public key which can be used to verify the signature and in addition decode the payload of the JWT token. This can be done with the following lines as shown below:

Jws<Claims> claims = Jwts.parser()
        .setSigningKey(cer.getPublicKey())
        .parseClaimsJws(jwtToken);

The jwtToken variable is the access token which is received from the Edge Gateway into the API Compute. As we covered in the previous article this has three parts namely the header, payload and signature. The claims variable is a collection of all the decoded claims from the payload. The claims could be the registered claims and the custom claims. In good implementations, each claim is validated with legitimate values which are set in your organization (e.g. audience could be a name of your department etc).

The million dollar question now is what if the signature does not match or if the token are expired. Or what if the claims don't match the legitimate values? Simple, return a 401 UNAUTHORIZED without revealing much information.

With the above design and implementation, the APIs are secured at application level with the client credential JWT tokens. I hope you can use this to make your APIs more secure.

If you want to know more please reach out to me and I will be happy to do a live coding or pair programming around this.

To view or add a comment, sign in

More articles by Dhiraj Bahroos

Others also viewed

Explore content categories