Unable to verify Cognito JWT token in node/express

21 Views Asked by At

auth.middelware.js

const jwt = require("jsonwebtoken");
const jwkToPem = require("jwk-to-pem");
const fetch = require("node-fetch");

let pems = {};                               // <########### pems object initialization and at some point in time, it get undefined

class AuthMiddleWare {

  constructor() {
    this.setUp();
  }

  verifyToken(req, res, next) {
    const token = req?.headers?.authorization;

    if (!token) {
       console.log("no tken")
    }

    let decodeJWT = jwt.decode(token, { complete: true });

    if (!decodeJWT) {
      console.log("error")
    }

    let kid = decodeJWT.header.kid;
    let pem = pems[kid];                            //%%%%%%% in some case pems become undefined automatically

    if (!pem) {                                     
      console.log("No PEM found")                   // <######## since there is no pem, it logs this error msg.
    }

    jwt.verify(token, pem, (err, decodedToken) => {
      if (err) {
       console.log("error occurred while verifying token", err);
      }
      next();
    });
  }

  async setUp() {
    const URL = `https://cognito-idp.eu-west-1.amazonaws.com/{environment.POOL_ID}/.well-known/jwks.json`

    try {
      const response = await fetch(URL);

      if (response.status !== 200) {
        throw new Error("request was not successful");
      }

      const data = await response.json();

      const { keys } = data;

      for (let index = 0; index < keys.length; index++) {
        const key = keys[index];
        const key_id = key.kid;
        const modulus = key.n;
        const exponent = key.e;
        const key_type = key.kty;
        const jwk = { kty: key_type, n: modulus, e: exponent };

        const pem = jwkToPem(jwk);

        pems[key_id] = pem;                   // <###### This store two keys/pems in pems object
      }
    } catch (error) {
      console.error("sorry couldn't fetch JWT", error);

    }
  }
};


module.exports = AuthMiddleWare;

index.js

const express = require("express");
const app = express();
const AuthMiddleWare = require("../auth.middleware");
...
...
...

const auth = new AuthMiddleWare();                // initialize auth class so it will fetch PEMs


// routes are defined below

app.use(`api/products`, auth.verifyToken, productsRoute);    // auth.verifyToken
app.use(`api/customers`, auth.verifyToken, customerRoute);   // auth.verifyToken
...
...
...

app.listen(PORT, () => {
    console.log(`node-express server running in ${process.env.NODE_ENV} mode on ${PORT}`);
});

My Problem:

When I run my node/express app, it initializes auth class and runs setUp function and fills pems ={} object with two kid or key;

So at this time pems object is not empty and contains two properties (key as property).

Now, through my app, when different APIs (almost 6-7 APIs are being called) simultaneously, randomly, at some point of time, pems object get undefined.

Now as you can see in above code, each api uses auth middleware auth.verifyToken so even when right token is being passed but since pems object becomes undefined (don't know why it becomes undefined), it stops my app.

NOTE: it happens randomly. It fails for any api. There is no way you can reproduce this issue same way again n again. pems gets undefined at random time and it is really hard to debug it.

Question How can I make sure that pems object doesn't get undefined?

Or if any better approach is there then you can suggest.

0

There are 0 best solutions below