Verify Auth0 JWT with Node - node.js

Im getting a JWT from Auth0. I can decode it with the following middleware function on my Node server (using https://www.npmjs.com/package/jwt-node)
function authoriseToken(req, res, next) {
const token = req.headers.authorization.replace('Bearer ', '');
const decodedToken = jwt.decode(token);
console.log('decodedToken ', decodedToken);
next();
}
How can I verify the token? I keep getting an error JsonWebTokenError: invalid algorithm
function authoriseToken(req, res, next) {
const token = req.headers.authorization.replace('Bearer ', '');
const verifyedToken = jwt.verify(token, "my-secrete");
console.log('verifyedToken ', verifyedToken);
next();
}
Im not sure if I should be using a secrete or a jwksUri or what the difference is
Here is the actual token:
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ik16QkJRa1k0T0RRNE9VWTJORVZGT1VJNFFrSXpNRUZDT0RaQ01VSTBOVGN4TWpVeU1UYzNRdyJ9.eyJpc3MiOiJodHRwczovL25vbWFkZ3JvdXBzLmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw1YjMxMDhkNjc4NzFkNTBkZTA0Njc2NWEiLCJhdWQiOiJTZkQyMEVPZVdRbHlnWXIwUHNXODdtYjd0OGFBOFI2NiIsImlhdCI6MTUzMDAxMzQwMCwiZXhwIjoxNTMwMDQ5NDAwLCJhdF9oYXNoIjoiUi1mRGc3SVRzUUdqemplX3VUR01RdyIsIm5vbmNlIjoiQnN-VmZxNzdtNERuaTJ1LjlIUVJlSEpzeHA4UjF2aDcifQ.CwZb6j3DshbD5M-OWBQpc10EIpAd3D-TuZTA1p7alePobSRVM7bE9Yzr5DIRyc2YUQZQ_OBwVLfFPq0pEBTWFYq2O43FJZ726xP1zK7Ty4PvAoLe4Cx6E0Ow8V8Ymo87XCIKX8J1ndg47q5glKzsnSMToutEWRZ2lnxJyirD4m4EwFykDF8DalA1sWvqnYXEwWraY3VLroqyZH2nkeLDcpcMdJ0tWwmzldwi7ym9OmegV5GBl7F6BgrZNIJfdoT88Rs4AKzogJyJuVQ1XlD7Up_nYlAKBmRMgkFt3t_4iq7pTkgdrWl1tXuJQsnmkkVH6_yffNYrWDnuirWwTCG4XQ

verify takes algorithms option in third parameter, adjust value with the correct one.
You can find it under applications > advanced settings > oauth > JsonWebToken Signature Algorithm

Expanding on Gabriel Bleu's answer here is my complete code:
const jwt = require('jsonwebtoken');
const pemCert = `-----BEGIN CERTIFICATE-----
// <<CERT CODE HERE>>
-----END CERTIFICATE-----`;
function authoriseToken(req, res, next) {
const token = req.headers.authorization;
// If there is no token user is not logged in
if (!token || token.length === 0) {
next();
return;
}
// If there is a token then add it to the res
const tokenCrop = token.replace('Bearer ', '');
const decodedToken = jwt.verify(tokenCrop, pemCert, { algorithm: 'RS256' });
const userId = decodedToken.sub.replace('auth0|', '');
req.authUserId = userId;
next();
}
module.exports = authoriseToken;

Related

Userfront.js Middleware Express JsonWebTokenError: invalid signature

I am using userfront.js that will create a token on their side of things.
https://userfront.com/test/dashboard/jwt/usage
to verify the token I am using the token creatred from userfront.js and public key from my user front account.
keep getting this error though: JsonWebTokenError: invalid signature
here is my code.
Middlware.js
var jwt = require("jsonwebtoken")
const key = Buffer.from(process.env.PUBLIC_KEY_64, "base64").toString("ascii")
const isAdmin = async (req, res, next) => {
try {
const token = req.cookies["access.pn4qd8qb"]
const payload = jwt.verify(token, key, { algorithm: "RS256" })
console.log({ payload })
next()
} catch (error) {
console.log(error)
}
}
module.exports = { isAdmin }
Note: not the full key not sure if I should post full key online
{
key: '-----BEGIN PUBLIC KEY-----\n' +
'MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAyYWU4VNpO0GecWJhsvTH\n' +
'pXLyOrCvXd9m0gkWCnw67HleZTfRt2xqegwY0d/oMg8zSP9kS4Uf6hRX4uu3E0hF\n' +
'EoqEgAmIohoedBN+HAFNoM3ac1svv30efLeVwg5CHEkX3JquduIdOqowte6tNZU/\n' +
'IVFUk8lyDk4RXIR/ncJ0AG+cqMjyj5JVVimAWNltX8TQKlhpnjh3DCMM2QiG81+r\n' +
'QfCleCF1Ju91CCKKHQnPcT6qIKID/CoXThs7FRFUK5kWpSz/N3V5+KANpNBZUk8E\n' +
'ZJncGqXru7O6xkWqh3uy16C1fQcyVkUdM32vbKiEjhHs/p8M4simHYT1TOZw+WP0\n' +
'6wnWsrlWEBnWCUZX9ekzLwDR+DgOKIPHvIZsXdyQXi+JzhoojgW5D32nK7ebcX1B\n' +
'XXO7+HUsvbIPgFaxlyN+k9UCAwEAAQ==\n' +
'-----END PUBLIC KEY-----'
}
{
token: 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImE1NTNiNGM1LTAwNDMtNGFkNi05MjgxLTVhOTdhMjJmN2FlOSJ9.eyJtb2RlIjoidGVzdCIsInRlbmFudElkIjoicG40cWQ4cWIiLCJ1c2VySWQiOjIzLCJ1c2VyVXVpZCI6IjI5MDc0MzQ3LWM4MjYtNGY4NS1iMTNmLTgzOTQ4YjRkZjVmMSIsImlzQ29uZmlybWVkIjpmYWxzZSwiYXV0aG9yaXphdGlvbiI6eyJwbjRxZDhxYiI6eyJyb2xlcyI6WyJhZG1pbiIsInN1cHBvcnQiLCJtZW1iZXIiXX19LCJpc3MiOiJ1c2VyZnJvbnQiLCJzZXNzaW9uSWQiOiI4ZDU4ZDhjOC0wN2VmLTQwNzQtYjhjMS1lN2JiYmFkY2RjZjEiLCJpYXQiOjE2NjM0ODgwMDMsImV4cCI6MTY2NDA5MjgwM30.pa1egSWlsdZ7INz282OBgNVl6x1Hv5x7oPgwdPPvpynNjWz6NfgQOrBIRZOJuYCmzuS4wOUo3N7gzGptVayjPH6PUrak4zgWZlbUfABw3Z4gJ9OcgEl28i_pgVMZm-uEsAuDSc_YF79hj4SgJ-hf9Ntww3AFUKq1VvRGyTncepr2GLQUjrDR0AaU4g_K_z809gPXyXfaIvvTQJLWr0WvNtqSE0yda8tyPBiw5RkeYye7RXcstBHSZVNFNeQ9oT4ru9830RGZUqniWbF5KTwGI4v7mrqFVPSJ0xGagk3YkZEKYInJEgHbhXB5CKuJB6QvCz8bixhnzk0Q2TYD5Oa7ZIHW_OQyvUuok2MXBGaBaUjQy24I_TZwl0n8Ob2HbOy5RXULIjBrwUPyjaKkbIx6bg6e25314Cj1vkGdwmacF939hdE6UXIjUMKXa-tDimOu3xuUlVH9ZwGe5UGgh_lPITwc2m4RAW2sEukwQ19zai18mSx1cOny7CUYWwHx8BYPqJbazVrYviQhRkf7BV2U-SI0ABS_hJEtAFQiSMvf8U8uq52LoSfeK0PWn8omUYWZIzBUUDfQy4AMxXWCKY0P9yJsQfxNN1oNs8XNs4wmhy9SDvGQws1yIHpJ8Hb1CrskVdBNEczUeJnRwXqaJGJu83uZl2glBkH29JpsqROPJHI'
}
any idea what i'm doing wrong?

How can I make my code to generate token and return it to authenticate a user?

I have the code below for token generation. I follow this tutorial. When I use postman to test the code with a registered username and password, it returned the JsonWebTokenError: jwt malform. On close review, I discovered that the error comes from jwt.verify section.
What do I need to adjust so that the token can be generated?
How can I configure it so that when a users makers a log in request, say he's passing his username and password, along with email and password, the client must pass a client identity ( [payload + clientID] ), for the server to know for whom the token is to be signed.
Is there any special value I need to pass in Postman Header to test the working of the token system?
CODE EDITED
const jwt = require('jsonwebtoken');
const fs = require('fs');
// PRIVATE and PUBLIC key
const publicKey = fs.readFileSync(__dirname + '/public.key', 'utf8');
const privateKey = fs.readFileSync(__dirname + '/private.key', 'utf8');
// Returns secret only known to server at runtime
exports.getSecret = () => {
const secret = require('../config/secret.json').secret;
return secret;
};
// Returns token
exports.getToken = (payload, signOptions) => {
if (!signOptions) {
signOptions = {
issuer: "Myself",
expiresIn: "30d",
algorithm: "RS256"
}
};
const token = jwt.sign(payload, privateKey, options);
return (token);
};
// Returns result of token validation
exports.validateToken = (token, verifyOptions) => {
if (!verifyOptions) {
verifyOptions = {
issuer: "Myself",
expiresIn: "30d",
algorithm: "RS256"
}
};
try {
return jwt.verify(token, publicKey, verifyOptions);
} catch (err) {
return err;
}
};
// Returns validation result of token
exports.token_post = (req, res) => {
res.send(this.validateToken(req.header.Authorization, this.getSecret()));
};
exports.hasPermission = (token, resource) => {
const result = this.validateToken(token, this.getSecret());
console.log(result);
if (result.name === 'JsonWebTokenError') {
return false;
} else if (result.permissions) {
let permissionSet = new Set(result.permissions);
console.log('permissions in token', JSON.stringify(permissionSet));
return permissionSet.has(resource);
} else {
return false;
}
};
You're not feeding the good arguments to this.validateToken.
You should give it the verifyOptions instead of this.getSecret().
By the way, this is not a secret but a public key so I don't recommend using this name. And you are reading the public key twice.
Your hasPermission function should look like that:
exports.hasPermission = (token, resource, $Options) => {
const result = this.validateToken(token, $Options);
console.log(result);
if (result.name === 'JsonWebTokenError') {
return false;
} else if (result.permissions) {
let permissionSet = new Set(result.permissions);
console.log('permissions in token', JSON.stringify(permissionSet));
return permissionSet.has(resource);
} else {
return false;
}
};
Don't forget to change the code that call that function. $Options is the one you use to sign your token, the signOptions in the tutorial.

Do I need to pass a payload to this code to generate JWT token?

I want to use JWT to generation token to authenticate users. When I use postman to test the code with a registered username and password, it returned the JsonWebTokenError: jwt malform. On close review, I discovered that the error comes from jwt.verify section.
Do I need to pass a payload value to generate the token?
How can I configure it so that when a users makers a log in request, say he's passing his username and password, along with email and password, the client must pass a client identity ( [payload + clientID] ), for the server to know for whom the token is to be signed.
Is there any special value I need to pass in Postman Header to test the working of the token system?
THE CODE
const jwt = require('jsonwebtoken');
const fs = require('fs');
// PRIVATE and PUBLIC key
const publicKey = fs.readFileSync(__dirname + '/public.key', 'utf8');
const privateKey = fs.readFileSync(__dirname + '/private.key', 'utf8');
// Returns secret only known to server at runtime
exports.getSecret = () => {
const secret = require('../config/secret.json').secret;
return secret;
};
// Returns token
exports.getToken = (payload, signOptions) => {
if (!signOptions) {
signOptions = {
issuer: "Myself",
expiresIn: "30d",
algorithm: "RS256"
}
};
const token = jwt.sign(payload, privateKey, options);
return (token);
};
// Returns result of token validation
exports.validateToken = (token, verifyOptions) => {
if (!verifyOptions) {
verifyOptions = {
issuer: "Myself",
expiresIn: "30d",
algorithm: "RS256"
}
};
try {
return jwt.verify(token, publicKey, verifyOptions);
} catch (err) {
return err;
}
};
// Returns validation result of token
exports.token_post = (req, res) => {
res.send(this.validateToken(req.header.Authorization, this.getSecret()));
};
The remaining part of the code below is linked to a permission file that is used to validate users. The error shows that the argument is not getting to the this.validateToken part.
exports.hasPermission = (token, resource) => {
const result = this.validateToken(token, this.getSecret());
console.log(result);
if (result.name === 'JsonWebTokenError') {
return false;
} else if (result.permissions) {
let permissionSet = new Set(result.permissions);
console.log('permissions in token', JSON.stringify(permissionSet));
return permissionSet.has(resource);
} else {
return false;
}
};
I EDITED JWT.(SIGN) FUNCTION AS FOLLOWS
return jwt.sign(payload, privateKey, signOptions, function (error, token){
if(error) {
return done(new JsonWebTokenError('error in generating token: ' + error.message));
} else {
console.log("Token :" + token);
}
});
};
jwt.sign() return a callback function like this
jwt.sign(payload, expiration, function (error, token) {
if(error) {
// Faild Error
} else {
// Get token and do continue
}
});

How to get token's key kid (key id) using jwks-rsa library

I have some key id that I'll use to verify a token, but it's hardcoded and I don't want it to be so.
I'm using the jwks-rsa library to fetch the key from an API endpoint and crack the token open for verification, however the fetch is done in the jwks-rsa client object's option property and because of that I'm unsure how to go about storing the fetched 'kid' value in a variable. It's hard to explain, so I'll show some code.
'use strict'
require('dotenv').config()
const jwt = require('jsonwebtoken')
const jwks = require('jwks-rsa')
const TOKEN_SECRET = 'someweirdtokenstring'
function (request, response, next) {
const client = jwks({
jwksUri: process.env.TOKEN_KEY_PUBLIC //this is the API endpoint; responds with a json key
})
const kid = 'something' //I don't want to hardcode this
client.getSigningKey(kid, (error, key) => {
if (error) throw error
const signingKey = key.publicKey || key.rsaPublicKey
const token = TOKEN_SECRET
if (!token) return response.status(401).send('Access denied')
try {
const verified = jwt.verify(token, signingKey, { algorithms: ['RS256'] })
request.user = verified
next()
} catch (error) {
response.status(400).send({ message: error.message, stack: error.stack })
}
})
}
EDIT: It's not super-clean code, but that's not the point here.
IMO, you should create the JWT with kid in its header. And simply decode only to read the header.
Here is small snippet,
'use strict'
require('dotenv').config()
const jwt = require('jsonwebtoken')
const jwks = require('jwks-rsa')
const TOKEN_SECRET = 'someweirdtokenstring'
function (request, response, next) {
const client = jwks({
jwksUri: process.env.TOKEN_KEY_PUBLIC //this is the API endpoint; responds with a json key
})
var decoded = jwt.decode(token, {complete: true});
const kid = decoded.kid
client.getSigningKey(kid, (error, key) => {
if (error) throw error
const signingKey = key.publicKey || key.rsaPublicKey
const token = TOKEN_SECRET
if (!token) return response.status(401).send('Access denied')
try {
const verified = jwt.verify(token, signingKey, { algorithms: ['RS256'] })
request.user = verified
next()
} catch (error) {
response.status(400).send({ message: error.message, stack: error.stack })
}
})
}

In express-jwt is there any way option similar to req.isAuthenticated() similar to passportjs?

I want to find whether the user is authenticated 'jwt' inside middleware. Is there any way like req.isAuthenticated() similar to passportjs?
module.exports = function(app){
return function(req, res, next){
// How to implement the below step?
var isAuthenticated = app.use(jwt({secret: app.get('jwtTokenSecret')}))
if(isAuthenticated){
// do some logic
}
}
}
Yes there is!
1) You can use use the express-jwt module. Check out https://github.com/auth0/express-jwt
2) You can do it this way:
//get the authorization token from the request headers, or from a cookie
if (req.headers && req.headers.authorization) {
var parts = req.headers.authorization.split(' ');
if (parts.length == 2) {
var scheme = parts[0];
var credentials = parts[1];
if (/^Bearer$/i.test(scheme)) {
token = credentials;
}
}
}
else if(req.cookies && req.cookies.token)
{
token = req.cookies.token;
}
...
jwt.verify(token, config.secrets.session, function(err, decoded) {
//isAuthenticated is in here
});

Resources