Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moving from 6.1.2 to 7.4.2 breaks #281

Closed
nsshunt opened this issue Apr 21, 2022 · 14 comments
Closed

Moving from 6.1.2 to 7.4.2 breaks #281

nsshunt opened this issue Apr 21, 2022 · 14 comments

Comments

@nsshunt
Copy link

nsshunt commented Apr 21, 2022

When I upgraded from v 6.1.2 to 7.4.2 I get this error;

TypeError: cb is not a function

Error occurs within expressJwtSecret @ highlighted line

module.exports.expressJwtSecret = function (options) {
if (options === null || options === undefined) {
throw new ArgumentError('An options object must be provided when initializing expressJwtSecret');
}

const client = new JwksClient(options);
const onError = options.handleSigningKeyError || handleSigningKeyError;

return function secretProvider(req, header, payload, cb) {
if (!header || !supportedAlg.includes(header.alg)) {
### return cb(null, null);
}

client.getSigningKey(header.kid)
  .then(key => {
    cb(null, key.publicKey || key.rsaPublicKey);
  }).catch(err => {
    onError(err, (newError) => cb(newError, null));
  });

};
};

@nsshunt
Copy link
Author

nsshunt commented Apr 21, 2022

In 7.2.1, the secretProvider(req, header, payload, cb) gets;
req - ok (appears to be the req object)
header - this is actually the decoded token
payload = undefined
cd = undefined

So the caller is passing the wrong parameters.

Further, the caller is using 'option 3' when invoking this function.

@JClackett
Copy link

Can confirm that it also breaks for me too after simply upgrading (and changing the imports). I just get a "expired token" error every time

@jfromaniello
Copy link
Member

The doc was outdated in 7.2.1, sorry about that. I made a major version (v7) because there are breaking changes. I fixed the readme arround 7.4

The secret function receives two parameters only:

  • req: the express.js request
  • token: contains payload and header

https://github.com/auth0/express-jwt#retrieve-key-dynamically

in your case, your function can be replaced to this:

module.exports.expressJwtSecret = function (options) {
  if (options === null || options === undefined) {
    throw new ArgumentError('An options object must be provided when initializing expressJwtSecret');
  }

  const client = new JwksClient(options);
  const onError = options.handleSigningKeyError || handleSigningKeyError;

  return function secretProvider(req, token) {
    const { header } = token;
    if (!header || !supportedAlg.includes(header.alg)) {
      return;
    }
    return client.getSigningKey(header.kid)
      .then(key => {
        return key.publicKey || key.rsaPublicKey;
      }).catch(err => {
        return new Promise((resolve, reject) => {
          onError(err, (newError) => reject(newError));
        });
      });
  }
};

@nsshunt
Copy link
Author

nsshunt commented Apr 21, 2022 via email

@kevinrutherford
Copy link

+1, rolled back until this integration is fixed

@rene-leanix
Copy link

The following rough replacement works for us for now until the integration is fixed. (I removed the options check and onError callback, as neither are needed in our case.)

import { GetVerificationKey } from 'express-jwt';
import { Jwt, Secret } from 'jsonwebtoken';
import { ExpressJwtOptions, JwksClient } from 'jwks-rsa';

export function expressJwtSecret(options: ExpressJwtOptions): GetVerificationKey {
  const supportedAlg = require('jwks-rsa/src/integrations/config.js') as string[];
  const client = new JwksClient(options);
  return async function secretProvider(_req, token: Jwt | undefined): Promise<Secret> {
    if (token) {
      const { header } = token;
      if (header && supportedAlg.includes(header.alg)) {
        const key = await client.getSigningKey(token.header.kid);
        return key.getPublicKey();
      }
    }
    return '';
  };
}

We're currently on:

  "express-jwt": "7.4.3",
  "jsonwebtoken": "8.5.1",
  "jwks-rsa": "2.0.5",
  "@types/jsonwebtoken": "8.5.8",

@jfromaniello
Copy link
Member

thanks for the heads up. I will try to fix jwks-rsa

@jfromaniello
Copy link
Member

I just send a PR, you can use npm i "jfromaniello/node-jwks-rsa#express_jwt_7" until it gets merged.

@jfromaniello
Copy link
Member

Fixed in jwks-rsa@2.1

@rene-leanix
Copy link

Thanks a lot for the fix, José!

@rene-leanix
Copy link

@jfromaniello, there is a small typing issue. The newest versions of express-jwt use GetVerificationKey as the type of this callback. SecretCallbackLong seems to be the interface that was used by @types/express-jwt up to express-jwt@7.

@jfromaniello
Copy link
Member

@rene-leanix I don't understand this.. Where is that SecretCallbackLong ? Thanks!

@rene-leanix
Copy link

@jfromaniello, it's being imported here and used here. This should be changed to GetVerificationKey. (SecretCallback may also need to be replaced.)

Missing interface definitions are just interpreted as any, so shouldn't lead to TS errors. In our case, ESLint picked this up as we've got a rule to avoid assignments of any types. A temporary workaround was to cast it to GetVerificationKey.

@jfromaniello
Copy link
Member

@rene-leanix you are absolutely right. I was able to reproduce the issue ,but as I wanted to leave jwks-rsa compatible with the previous version of express-jwt , I added a type alias for SecretCallback and SecretCallbackLong.

So, the fix the issue just install express-jwt@7.6.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants