NodeJS Verify and Decode Cognito JWT Token

NodeJS Verify and Decode Cognito JWT Token

Timo
Timo

In this article, I will show you how to verify and decode the Cognito JWT Token. Before we go forward, let’s quickly make sure that we understand: What is JWT and what does it have?

What is JWT?

JWT (JSON Web Token) is an open standard used to share security information between two parties — a client and a server.

JWT has 3 parts: Header, Payload, and Signature.

  • Header: consists of two parts: the type of the token, and the signing algorithm being used, such as HMAC SHA256 or RSA.
  • Payload: contains the claims (registered, public, and private claims).
  • Signature: is used to verify that the issuer of the JWT is who it says it is and to ensure that the message wasn't changed along the way.

The Cognito token, is it safe?

The cognito token is safe and reliable because the signature that identifies the token generated by Cognito is not from a 3rd party. We use the public key provided by Cognito to verify the token.

What is difference between public key and private key?

  • Public keys: can decrypt the signature.
  • Private keys: can decrypt and encrypt signature.

So there is no way to spoof the signature. It is possible to forge signatures, even stolen credentials, but they cannot forge signatures from Cognito.

How to get the Cognito public keys?

To get the public keys we can have 2 ways. Using a web browser or Postman in the URL format below:

https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json

After you send the request, you will get the result as below:

Postman

Web browser

In the results above, we see that there are 2 public keys. Do you ask the question which public key do we use? So how do we know which key we will use?

First, go to the page JWT, then you paste your id-token.

After decoding you will see a kid. Find the kid in the public key that matches the kid after deciding. You will use that public key.

Please create a jwks.json file with the required public key content.

How to verify Cognito tokens?

First, you need to install the following 2 packages

jsonwebtoken
jwk-to-pem

Next, create a file to verify the token with the name is verify-token.ts

import { NextFunction, Request, Response } from 'express';

import { readFileSync } from 'fs';
import jwt from 'jsonwebtoken';
import jwkToPem from 'jwk-to-pem';
import path from 'path';

const verifyIdToken = async (req: Request, res: Response, next: NextFunction) => {
  try {
    const data = readFileSync(path.resolve(__dirname, 'jwks.json')) as any;

    const authorization = req.headers?.['authorization'] as string;

    if (!authorization) {
      return new BadRequestResponse('Missing token.').send(res);
    }

    const token = authorization.split(' ')[1];

    const pem = jwkToPem(JSON.parse(data));

    const auth = jwt.verify(token, pem, { algorithms: ['RS256'] });

    res.locals.auth = auth;

    return next();
  } catch (error: any) {
    return next(new BadTokenError(error.message));
  }
};

Results when verifying successfully

{
   sub: 'a1f715a3-c758-443a-93ea-9939e4354b6e',
   iss: '',
   phone_number_verified: true,
   'cognito:username': '',
   origin_jti: '0698df1d-5687-46cf-a4ac-d964ed3cc629',
   aud: '',
   event_id: 'cf9115a3-0d8a-43c6-82f9-f2e7f6ef2853',
   token_use: 'id',
   auth_time: 1671875444,
   phone_number: '',
   exp: 1671879043,
   iat: 1671875444,
   jti: 'b453e27e-2086-45f0-bd3d-35542ab4e0cb'
}

Hope this article will be help to you. Good luck!


References:

https://jwt.io/introduction