Skip to content

Instantly share code, notes, and snippets.

@PaperNick
Forked from westmark/auth0-verify.js
Last active August 17, 2022 19:21
Show Gist options
  • Save PaperNick/1fa0fa9f280b1d29a0a8f8e1b31df1e2 to your computer and use it in GitHub Desktop.
Save PaperNick/1fa0fa9f280b1d29a0a8f8e1b31df1e2 to your computer and use it in GitHub Desktop.
Auth0 JWT Verification
/**
* The MIT License (MIT)
* Copyright (c) 2022 PaperNick
*
* Resouces used:
* https://github.com/auth0/node-jwks-rsa
* https://github.com/auth0/node-jsonwebtoken
* https://auth0.com/blog/navigating-rs256-and-jwks/
* https://gist.github.com/westmark/faee223e05bcbab433bfd4ed8e36fb5f
* https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/
*/
const AUTH0_AUTHORITY = 'https://auth0.tenant.com';
const AUTH0_AUDIENCE = 'https://api.yourapp.com/';
const jwksRsa = require('jwks-rsa');
const jwt = require('jsonwebtoken');
const jwksClient = jwksRsa({
jwksUri: `${AUTH0_AUTHORITY.replace(/\/+$/, '')}/.well-known/jwks.json`,
});
/**
* Attempt to parse the given JWT token. Throws an Error if token is invalid.
*
* @param {string} token JWT token without "Bearer " in the beginning
* @throws {Error}
* @returns {JwtPayload}
*/
async function parseJwtToken(token) {
if (!token) {
throw new Error('Missing authorization token');
}
// Decode without verifying if the signature is valid.
// Warning: do not access decoded token payload before verifying with jwt.verify()
const decodedToken = jwt.decode(token, { complete: true });
if (!decodedToken || decodedToken.header.alg !== 'RS256') {
// Only RS256 tokens are supported at the moment
throw new Error('Invalid token or algorithm');
}
let signingKey;
try {
signingKey = await jwksClient.getSigningKey(decodedToken.header.kid);
} catch (error) {
throw new Error('Could not retrieve key to verify token');
}
try {
const jwtPayload = jwt.verify(token, signingKey.getPublicKey(), { audience: AUTH0_AUDIENCE });
return jwtPayload;
} catch (error) {
throw new Error('The token is invalid or has expired');
}
}
/**
* Attempt to parse the given JWT token. Returns undefined on error.
*
* @param {string} token
* @returns {JwtPayload|undefined}
*/
async function parseJwtTokenQuiet(token) {
try {
return await parseJwtToken(token);
} catch (error) {
return;
}
}
module.exports = { parseJwtToken, parseJwtTokenQuiet };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment