okta / okta-oidc-js

okta-oidc-js
https://github.com/okta/okta-oidc-js
Other
394 stars 232 forks source link

Error while resolving signing key for kid "gj39h29g6Du-8EJT_lXSoTYV7EToWuroVpwR-q8Ao74" #797

Open gsaravanakumar932 opened 4 years ago

gsaravanakumar932 commented 4 years ago

Error while resolving signing key for kid "gj39h29g6Du-8EJT_lXSoTYV7EToWuroVpwR-q8Ao74"

const oktaJwtVerifier = new OktaJwtVerifier({ issuer: '{oktaIssuer}', clientId: process.env.CLIENT_ID, assertClaims: { aud: process.env.AUDIENCE, cid: process.env.CLIENT_ID }, cacheMaxAge: 5 60 60 * 1000, // 1 hour jwksRequestsPerMinute: 30 });

i am getting the above error, if i try using oktaverifier, whereas in client end, using angular its working. Even okta admin couldnt help on this. They are also saying config code everything is correct.

return oktaJwtVerifier.verifyAccessToken(accessToken, audience)
    .then((jwt) => {
      console.log('token is valid');
      req.jwt = jwt;
});

Very simple to reproduce.

  1. Signup an acc in Okta
  2. Create a app as SPA
  3. use the same config for node js backend with express.

Any scientist could help me on this ? How to fix ?

ArtyEmsee commented 4 years ago

I am having this issue as well with approximately the same repro steps.

alejandrom2 commented 4 years ago

I am wondering if you are using the default Oauth server, which may mean you do not have auth servers enabled because of your plan. Potential Workaround : #757

gsaravanakumar932 commented 4 years ago

I made it worked, but this time not with oktaVerifier, i think oktaVerifier package is not working properly.

-- This is to validate the Signature.

const jwt = require('jsonwebtoken');
const fs = require('fs');
const path = require('path');
const publicKey = fs.readFileSync(path.join(__dirname , '../../' , 'cert.pem'));

export const authenticationRequired = async (req, res, next) => {
  const headers = req.headers;
  const authorization = headers.authorization || '';
  const match = authorization.match(/Bearer (.+)/);
  const requestedUserId = headers['x-primary-mode'] || headers['x-proxy-mode'];
  const reqToken = headers['x-api-token'] || '';
  const reqId = headers['x-request-id'] || '';
  const userId = utils.decrypt(requestedUserId);
  const accessToken = match[1];
  const options = {
    algorithms: ['RS256']
  }

  if (!match || !reqId || !reqToken || !(utils.decrypt(reqId) === reqToken) || !requestedUserId) {
    return res.status(401).end();
  }

  // validate the token signature
  return jwt.verify(accessToken, publicKey, options, (err, decoded) => {
    if (err) return res.status(403).send(err.message);

    if (decoded) {
      if (req.query) {
        for (const key in req.query) {
          if (req.query.hasOwnProperty(key)) {
            req.query[key] = utils.decrypt(req.query[key]);
          }
        }
      }

      if (!req.session.hasOwnProperty(userId)) {
        req.session[userId] = userId;
      }

      return next();
    }
  });
alejandrom2 commented 4 years ago

Thanks for sharing that @gsaravanakumar932, that was the same approach I planned to next.

gsaravanakumar932 commented 4 years ago

@alejandrom2, Just paste your token in jwt.io, your public key would be generated after payload. Copy paste the content into a file and save as cert.pem and run the above code, it will work as expected.

if you dont like to create as file,

please generate dynamically,

// Verify using getKey callback
// Example uses https://github.com/auth0/node-jwks-rsa as a way to fetch the keys.
var jwksClient = require('jwks-rsa');
var client = jwksClient({
  jwksUri: 'https://sandrino.auth0.com/.well-known/jwks.json'
});
function getKey(header, callback){
  client.getSigningKey(header.kid, function(err, key) {
    var signingKey = key.publicKey || key.rsaPublicKey;
    callback(null, signingKey);
  });
}

jwt.verify(token, getKey, options, function(err, decoded) {
  console.log(decoded.foo) // bar
});
twaite commented 3 years ago

Don't know if this will help anyone else but I was getting this error when I was not fully qualifying the issuer when instantiating OktaJwtVerifier. I had:

const oktaJwtVerifier = new OktaJwtVerifier({
  issuer: process.env.OKTA_CLIEND_ID
});

Switched this to:

const oktaJwtVerifier = new OktaJwtVerifier({
  issuer: `${process.env.OKTA_CLIEND_ID}/oauth2/default`
});

That seemed to clear up the issue.

bananabrann commented 2 years ago

I spent an entire day on this error, becoming extremely frustrated. Everything I checked was correct, and I meticulously combed over our huge enterprise app countless times.

For me, what it ended being the bane of my existence was a typo in the environment file due to a change in our build agent. We used

const oktaJwtVerifier = new OktaJwtVerifier({
  issuer: `${process.env.oktaDomain}oauth2/default`
});

and our build agent was providing url.blah/ for the longest time, then was silently changed to url.blah. So if you're like me and stuck for hours and hours on this, triple, quadruple, quintuple check your .env files, especially if using a build agent or something else external. 😔