I'm trying to setup JWT authentication using passport-jwt. I think I've taken the right steps, but a test GET won't succeed and I don't know how to debug it.
Here's what I've done:
setup passport-jwt straight out of the doc as much as possible
var jwtOptions = {
secretOrKey: 'secret',
issuer: "accounts.examplesoft.com", // wasn't sure what this was, so i left as defaulted in the doc
audience: "yoursite.net" // wasn't sure what this was, so i left as defaulted in the doc
};
jwtOptions.jwtFromRequest = ExtractJwt.fromAuthHeader();
passport.use(new JwtStrategy(jwtOptions, function(jwt_payload, done) {
User.findOne({id: jwt_payload.sub}, function(err, user) {
if (err) {
return done(err, false);
}
if (user) {
done(null, user);
} else {
done(null, false);
// or you could create a new account
}
});
}));
Added a token result to my user /login endpoint
var jwt = require('jsonwebtoken');
// ...
exports.postLogin = function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) throw err;
if (!user) {
return res.send({ msg: 'Login incorrect' });
}
req.logIn(user, function(err) {
if (err) throw err;
var secretOrKey = jwtOptions.secretOrKey;
var token = jwt.sign(user, secretOrKey, {
expiresIn: 631139040 // 20 years in seconds
});
res.send({ user: user, jwtToken: "JWT " + token });
});
})(req, res, next);
};
Things were looking good up to here. I can login a user (using passport local auth) and the response was a I hoped...
{ "user": { "_id": "56c8b5bd80d16ef41ec705dd", "email": "[email protected]", "password": "$2a$10$zd ... etc.", "__v": 0, }, "jwtToken": "JWT eyJ0eXAiOiJ .... etc." }
I created an unprotected test route like this...
// in my routes file
app.get('/user/tokenTest', user.tokenTest);
And in my controller, a simple endpoint...
exports.tokenTest = function(req, res) {
console.log(req.headers);
res.send("token test!!");
};
And GET-ing that works fine, too.
But then I try to protect that route like this:
app.get('/user/tokenTest', passport.authenticate('jwt', { session: false }),
user.tokenTest);
After I do that, nothing but sadness. I send a request like this:
curl -k 'https://localhost:3443/user/tokenTest' -H 'Authorization: JWT eyJ0eXAiOiJ... etc.'
And always, always get a 401:
Unauthorized
Console logs in the controller don't seem to execute, neither does logging in the passport.use
strategy method. I've tweaked and tweaked, but I'm a little lost. The passport-jwt doc just supplies the example, and virtually no other help.
Please, any ideas about either a mistake that I'm making above, or at least how to go about debugging??
A Passport strategy for authenticating with a JSON Web Token. This module lets you authenticate endpoints using a JSON web token. It is intended to be used to secure RESTful endpoints without sessions.
To authenticate a user, a client application must send a JSON Web Token (JWT) in the authorization header of the HTTP request to your backend API. API Gateway validates the token on behalf of your API, so you don't have to add any code in your API to process the authentication.
JSON Web Token and Passport can be primarily classified as "User Management and Authentication" tools. JSON Web Token and Passport are both open source tools. It seems that Passport with 15.9K GitHub stars and 936 forks on GitHub has more adoption than JSON Web Token with 2.59K GitHub stars and 259 GitHub forks.
For any poor soul that follows me here: the passport-jwt doc implies that the auth header should look like this...
Authorization: JWT JSON_WEB_TOKEN_STRING.....
That turned out to be misleading (for me, anyway).
Fortunately, thanks to this article I was able to learn how the token is built. (The token's prefix up to the first '.' is the base64 encoding of the scheme. That "JWT " at the front was noise that prevented the validation from working.
So the fix was to change the token returned by the user controller from:
res.send({ user: user, jwtToken: "JWT " + token });
To the simpler:
res.send({ user: user, jwtToken: token });
Phew. Is it me, or is it really a bummer how inadequately these things are explained in so many node package docs??
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With