mikenicholson / passport-jwt Goto Github PK
View Code? Open in Web Editor NEWPassport authentication using JSON Web Tokens
License: MIT License
Passport authentication using JSON Web Tokens
License: MIT License
Add option for algorithms such that it can be passed through to jwt.verify.
More info on why this is important:
https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/
can you please upload this version to npm repo? Thank you.
So, it is posible use bcrypt to avoid the secret hash in jwt protocol, in order to inprove the security?
Hi,
thanks for this very helpful package.
Is there a way to chain multiple extractor ?
i could write a custom extractor that do that but there might be a simple way if all the extractors i wanna use are already built in
findOne always returns first record from my DB. When i print jwt_payload.sub in console, it sayd jwt_payload.sub is undefined. can somebody help understanding this?
Can't find option expiresIn in the document.
When supplying a callback to passport.authenticate
, the callback should receive the user object if JWT is valid:
app.get('/', function (req, res, next) {
passport.authenticate('jwt',
function (err, user, info) {
... // user should be populated if authentication succeeded
}
)(req, res, next);
});
However, when passing a callback to passport.authenticate
, user
is always false, even if authentication succeeds. In the callback function, I can even see that req.user
is populated with the user when authentication succeeds. Please look here for what the callback should look like
Is it possible to specify no scheme and have passport-jwt just match the contents of Authorization
header and/or configure the header? It's not really possible to accurately use this plugin with Swagger's security credentials object with this requirement.
The code I have, (the signature is from http://passportjs.org/docs/authenticate)
passport.authenticate('jwt', { session: false }, (err, user, info) => {
if (err) {
return next(err);
}
if (!user) {
return next(AuthenticationError(401, info));
}
req.user = user;
return next();
})(req, res, next);
However, in the case of malformed jwt or expired jwt, the err
object is always null
while the info
object is carrying the error information.
Is this designed on purpose or should be a bug?
Hope it should expiry previous token of the user if he created new one. But its not doing it, I hit login and created n number of jwt token for same user...
All these generated jwt tokens are generated for same user id, when i validate those token with passport-jwt all returns valid..
I hope it should have only one jwt active for one user at a time, When we generate another token for the same user, it should invalidate previous token
Am using jsonwebtoken to generate jwt token, Am able to verify it successfully with passport-jwt
We are currently using this module and ran into an issue with this module where it seem to miss a variable declaration (missing var for matches) and pushes the variable to global scope (essentially global variable leak).
https://github.com/themikenicholson/passport-jwt/blob/master/lib/auth_header.js#L9
Hi,
I'm using passport-jwt
to authenticate some endpoints that accept request both with and without a jwt token in the header.
Right now it looks like passport-jwt
handles this by returning a 401
status code when there is no header/authorization in payload.
Would it be possible to handle such logic inside the custom function?
I was originally using my own middleware to handle this, but I couldn't figure out how to modify the req.user
object without express complaining about having only a getter on req.user
.
Ge
Hi, I'm using the new version from firebase to generate a custon token using jwt, it's using the private key of the google service account to sign the token, but when I'm using JwtStrategy to verify the token it is returning Error: PEM_read_bio_PUBKEY failed
.
the structure of the key is:
-----BEGIN PRIVATE KEY-----\n
......
.....
....
-----END PRIVATE KEY-----\n
This might be a rookie mistake, but I got the initial /authenticate route working, and it returned the correct token, but on every subsequent request, the payload information was being lost.
I eventually figured out that it had something to do with the size of the payload I was including. I was including all the user properties in the payload. If you limit it to one or two, things started to work!
What do you think about updating the readme to mention this limit. Might save some others some grief! Happy to open a PR if you think it's a useful addition.
Hi, plugin works well, thanks for your strategy!
If there is any possibility to callback some action on token revoke? I want to compare it against refresh token and allow to recreate access token instead of throwing 401.
If not, could you let me know where should i start looking for modifying your strategy to fit my needs?
Thanks.
move secret
into options
in order to ease programmatical loading of strategies. see:
https://github.com/tjwebb/sails-auth/blob/master/api/services/passport.js#L276
I want to send to the client only the JWT token without the header with the algo informations.
To do this, there should be a passport-jwt option to specify a string that will be prepended to the token, before its decodification.
Example:
The client sends to the server the request with this header:
Authorization: JWT eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
You may notice that the "header." is missing. passport-jwt, after detected the jwt in the header, will prepend the string "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9." before trying to decode it, to have the final token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
ExtractJwt.fromHeader and the default token parser are inconsistent in functionality.
The default token parser accepts tokens in this form:
Authorization: JWT JSON_WEB_TOKEN_STRING.....
fromHeader, however, does not work with the previous form. Instead it requires the following:
Authorization: JSON_WEB_TOKEN_STRING.....
I wish this was mentioned in the documentation. Consistent implementation would be even better. Thanks for the library in any case!
Hi,
I would be greatly helped and appreciative if there were an available example of how to implement jwt and social (in my case, instagram) strategies in a sessionless approach, for an app where routing is being handled by the frontend.
Thanks!
TypeError: Cannot read property 'auth_token' of null
at JwtStrategy.authenticate(<mypath>/node_modules/passport-jwt/lib/strategy.js:97:47)
This is at line 97:47
token = url.parse(req.url, true).query[self._tokenQueryParameterName];
Are there any support for this ?
passport.use('jwt', new JwtStrategy({
secretOrKey: authConfig.secret,
jwtFromRequest: ExtractJwt.fromAuthHeader(), //If return null, finishes with empty message
algorithms: authConfig.algorithms
},
function(jwt_payload, done) {
//Never had the chance to call done with custom message
Account.findById(jwt_payload.userId, function(err, account) {
if (err) return done(err);
if (!account) return done(null, false, 'invalid Token');
return done(null, account, 'valid Token');
});
})
);
in the example the require statement is written as such var "JwtStrategy = require('passport-jwt')"
i had to add ".Strategy" so it would work
"var JwtStrategy = require('passport-jwt').Strategy"
otherwise it gives me an error
"passport.use(new JwtStrategy('secret', opts, function(jwt_paylaod, done) {
^
TypeError: object is not a function
"
passport-jwt's ExtractJwt.fromAuthHeader()
uses the following http header:
Authorization: JWT JSON_WEB_TOKEN_STRING.....
But RFC 6750 clearly specifies that access token based authentication must use Bearer
as the authentication token. The non-recommended scheme specification would lead to conflicts.
I would like to do custom handling of the expiration verification, but the passport strategy calls jwt.verify which automatically verifies the timestamp. There is an option to disable that but the passport strategy ignores it when it sets the _verifOptions to only include the issuer and audience.
When using the extractor fromUrlQueryParameter
, I get the error TypeError: parsed_url.query.hasOwnProperty is not a function, which probably has to do with this.
An example app is needed to fully demonstrate how this works, and includes JWT generation in the code.
In Strategy.js
if (!token) {
return self.fail(new Error("No auth token"));
}
if (jwt_err) {
return self.fail(jwt_err);
} else {
under above two situation, verify callback will not be called.
should it uses self.error instead??
Is this lib responsible for the jwt generation (during the auth process), or is it only responsible for checking a token ?
Hey, is there any way we can possibly customize the error response in case of an error ? Instead of "Unauthorized" , i need to use this with swagger and integrate the default swagger error code but i have no way of doing it.
Hey Guys,
Tried working with default example but there are no errors passed.
I'm using passport-local to signup users - signup & login goes fine, token is sent to client in electron browser and manually sent back in Authorization header but then nothing happens.
In the route I see correct header, but jwt strategy doesn't start.
Can you please explain why this is happening?
Jwt route:
router.get('/login/check', function(req, res, next) {
console.log(JSON.stringify(req.headers));
passport.authenticate('jwt', { session: false }, function(err, user, info) {
console.log(err)
res.json({'success' : true});
})
})
JWT strategy
var JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
var opts = {}
opts.secretOrKey = 'secret';
opts.issuer = "http://localhost:3000";
opts.audience = "http://localhost:3000";
opts.jwtFromRequest = function(req, res){
console.log('in custom')
var token = req.get('Authorization').split(' ');
console.log(token)
return token
}
passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
console.log(1)
return User
.findOne({where : {username : jwt_payload.email } })
.then(function (user) {
if(user === null){
return TempUser
.findOne({where : {username : jwt_payload.email } })
.then(function(user){
return user === null ?
done(null, false, 'login error, please try again') :
done(null, false, 'email verification needed');
});
} else {
if (bcrypt.compareSync(password, user.dataValues.password)){
done(null, user);
} else {
done(null, false, 'login error, please try again');
}
}
});
I'm wondering how to create and deliver the token, when you want to login you're user from a SPA using a password and a username. Would be really cool, if you could provide an example for that too.
It seems that to protect from both XSS and XSRF, storing tokens in Http-Only/Secure cookies is still being recommended as part of an overall auth strategy. Here is a recent article by Stormpath (among others) suggesting to store tokens in cookies - https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/.
The strategy I am looking to implement is to store the JWT token in an Http-Only/Secure cookie with a unique generated XSRF claim, and then store a separate JavaScript accessible XSRF cookie containing the claim that is added as a custom header on each request. On the server, I need to validate the JWT token stored in the cookie, and extract and compare the XSRF cookie value with the XSRF claim stored on the JWT Token (synchronizing token strategy).
Long story short, it would be a nice feature if this strategy could support specifying and looking for the JWT token in a cookie.
Hi!
I got the error "No auth token" when I try to authenticate the user. I followed the instructions that appear in this web but I can not dismiss the error. I don't know what's the problem exactly.
With 'local' strategy workflow is ok and scripts executes 'passport.use' function. But with 'jwt' strategy I think when script creates 'new JwtStrategy' and tries to extract auth from header can't do it and shows the error inside 'passport.autheticate'.
There are any error?
It appears that this package in on npm, but readme still says it's not there.
My application needs to be able to defer the use of the secretOrKey
until after the jwt
is unpacked as it's a multi-tenanted application where each issuer has been issued its own unique key.
In this case the secretOrKey
option needs to be a function whose callback returns the correct secret or key, rather than it being a value.
This requires a small enhancement to verify_jwt.js
which I'd be happy to do.
When first implementing the sample code I was getting an error that 'jwt_payload.sub' was undefined. Looking a little closer I discovered that the verify function takes 3 args - the request, the payload, and callback. So:
passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
Should be
passport.use(new JwtStrategy(opts, function(req, jwt_payload, done) {
Is there a way to set expiring time when generating a token ?
I realized we could ignore expiration but I couldn't find a way to set that expiration.
I noticed that options.authScheme is a valid option accordingly to the readme, but I am not sure if there is a description that goes along with the option
I've updated some dependencies and now my protected GET endpoints are no longer working :(
Does anyone know why this could be happening, and how to resolve?
EG:
router.route('/private')
.get(
passport.authenticate('jwt', { session: false }), (req, res, next) => {
res.json({ allTheThings: true });
})
If I remove the passport.authenticate
and simply send a json response, it works as expected.
With passport.authenticate
included - if I send a JWT Authorization header, I get nothing back - nothing at all. In unit tests this can also result in 'socket hang up' errors.
If I remove the JWT Authorization header, still with passport.authenticate
, it returns unauthorized, as expected.
Any help appreciated!
Relevant dependancies:
"body-parser": "^1.14.2",
"express": "^4.14.0",
"passport": "^0.3.2",
"passport-jwt": "^2.2.1",
This is happening with node 6.9.2 and 7.
Hello I am working on passport jwt authentication using sails.
The files I have are given below:
In the User.js
//Information about the user
var bcrypt = require('bcrypt');
module.exports = {
autoCreatedAt: false,
autoUpdatedAt: false,
attributes: {
name: 'string',
email: 'string',
password: 'string',
age: 'string',
contact: 'string'
},
beforeCreate: function(user, cb){
bcrypt.genSalt(10, function(err, salt){
bcrypt.hash(user.password, salt, function(err,hash){
if(err){
console.log(err);
done(err);
}
else{
user.password = hash;
cb();
}
});
});
}
};
In the config/express.js :
//middleware
var passport = require('passport'),
JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
var jwtConfiguration = {
jwtFromRequest : ExtractJwt.fromAuthHeader(),
secretOrKey : 'mysecret',
issuer : 'Devendra',
audience : 'comparemunafa'
};
var verifyHandler = function(payload, done){
console.log('passport');
User.findOne({id: payload.id}).exec(function(err, user){
console.log('test');
if(err){
return done(err, false);
}
if(user){
done(null,user);
} else{
done(null, false);
}
});
};
module.exports.http = {
customMiddleware: function(app) {
passport.use(new JwtStrategy(jwtConfiguration, verifyHandler));
app.use(passport.initialize());
app.use(passport.session());
}
};
In the api/controllers/AuthController.js
//authentication
var jwt = require('jsonwebtoken');
var passport = require('passport');
var bcrypt= require('bcrypt');
module.exports = {
register: function(req,res){
if(!req.param('email') || !req.param('password')){
res.redirect('/index');
} else{
User.create(req.params.all()).exec(function(user, err){
res.redirect('/home');
});
}
},
authentication: function(req,res){
User.findOne({
email: req.param('email')
}).exec(function(err, user){
if(err) throw err;
if(!user){
res.redirect('/index');
} else{
bcrypt.compare(req.param('password'),user.password,function(err, isMatch){
if(err) {
res.redirect('/index');
} else{
var token = jwt.sign(user,'mysecret',{
expiresIn: 1000
});
res.redirect('/home');
}
});
}
});
},
home: function(req,res){
passport.authenticate('jwt',{session: false},function(req,res){
console.log('Hello');
res.view();
});
}
};
in the config/routes:
module.exports.routes = {
'/': {
view: 'index'
},
'/index': {
view: 'index'
},
'/home': {
controller: 'AuthController',
action: 'home'
},
'/register': {
controller: 'AuthController',
action: 'register'
},
'/authentication': {
controller: 'AuthController',
action: 'authentication'
}
};
i have made index.ejs and form action defined as '/authentication'.
But when i click on login its just hang on and nothing happens in console or browser.
I have already checked the database connections and its just hangs up on the login screen even after i click on the login button. Is there is any problem in using passport strategy or i am calling with wrong way in AuthController. I am new to passport so please help me where i am wrong
I believe that it makes sense that if the auth type is not specified in the header then it should default to JWT.
So when a user logs in how to I generate the JWT token to send back to the client which is attached to future requests?
How can I destroy current jwt on server when user logout?
npm install --save passport-jwt
(node) warning: possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit.
Trace
at TLSSocket.addListener (events.js:252:17)
at TLSSocket.Readable.on (_stream_readable.js:673:33)
at Request. (/usr/local/Cellar/node5/5.11.1/lib/node_modules/npm/node_modules/npm-registry-client/lib/request.js:153:7)
at emitOne (events.js:90:13)
at Request.emit (events.js:182:7)
at ClientRequest. (/usr/local/Cellar/node5/5.11.1/lib/node_modules/npm/node_modules/request/request.js:791:10)
at emitOne (events.js:95:20)
at ClientRequest.emit (events.js:182:7)
at tickOnSocket (_http_client.js:541:7)
at onSocketNT (_http_client.js:553:5)
[email protected] /Users/mark/Code/project/backend
└── [email protected]
Hi, so my route looks like this:
// validating using JWT
router.post('/profile', passport.authenticate('jwt', {session: false}), function (req, res) {
res.json({'success': true});
}
);
// validating using LOCAL
router.post('/profile', authenticationHelpers.isAuth, function (req, res) {
res.json({'success': true});
}
);
// authenticationHelpers.isAuth
function isAuth(req, res, next) {
if (req.isAuthenticated())
return next();
res.status(401).json({"authenticated": false});
}
So, how do i use both Local & JWT Strategy on same app (on same route) ?
Note: Local for web app, JWT for mobile app
Is it me or is the custom extractor function extremely limited. In my authorization flow, when users sign in, they are issued a new token. When users sign out, their token is stored in a Redis database. Then, if someone tries to use that token again, I can invalidate it by comparing it against the database.
I am trying to accomplish the step of invalidating tokens with the custom extractor function; however, everytime I try to write a complex procedure within it using callbacks or promises, it can never authenticate.
For example, here is the callback version of my extractor function and authorization strategy:
function myTokenExtractor(req) {
return token.verify(req, (err, token) => {
return token;
});
}
passport.use('jwt', new jwtStrategy({
session: false,
jwtFromRequest: myTokenExtractor,
secretOrKey: globals.secret
}, function(jwt_payload, done) {
User.findOne({ _id: jwt_payload.id }, function(err, user) {
if (user) { return done(null, user); }
if (err) { return done(err, null); }
return done(null, null);
});
}));
It seems like myTokenExtractor
is running (console
works within it), but the return is evaluated before token can actually be returned, thus function(jwt_payload, done)
never runs.
The same thing happens if I structure the extractor function as a Promise
; function(jwt_payload, done)
receives the pending promise and not the actual token.
Am I doing something wrong? Does anyone have any ideas on how I can include callbacks/promises in the extractor function?
Note: extractJwt.fromAuthHeader()
works as expected.
The User.findOne(jwt_payload.sub)
is returning the first user always because the sub
property is undefined.
This is the actual object that is coming from the passport.use
callback.
{ '$__':
{ strictMode: true,
getters: {},
wasPopulated: false,
activePaths: { paths: [Object], states: [Object], stateNames: [Object] },
emitter: { domain: null, _events: {}, _eventsCount: 0, _maxListeners: 0 } },
isNew: false,
_doc:
{ role: 'regular',
__v: 0,
password: '$2a$10$Q850U/ZpKf01DpQMN48vu.eltoQ6q9syACfy9EE/0WYl5gWYYzzSi',
email: '[email protected]',
_id: '5786f0419ec755449dac6551' },
_pres:
{ '$__original_save': [ null, null, null ],
'$__original_remove': [ null ] },
_posts: { '$__original_save': [], '$__original_remove': [] },
iat: 1468461125,
exp: 1468547525 }
Using version 2.1.0
.
I am missing something or the docs are outdated?
I think token might be misspelled on:
"audience: If defined the toekn audience (aud) will be verified against this value."
thanks for this great library!
What is the standard way to setup for testing api endpoints behind this? I am not testing the jwt authorization, but just the api endpoints behind it.
In the past using passport-local
, I was able to mock the login and logout using passport-stub
.
What I have so far:
var _ = require('underscore'),
app = require('../app.js'),
request = require('supertest'),
superagent = require('superagent'),
expect = require('expect.js'),
should = require('should'),
passportStub = require('passport-stub'),
data = require('./auth.data.js');
passportStub.install(app);
describe('API Endpoint 1 Test - ', function (done) {
beforeEach(function () {
passportStub.login(data.user1Stub); // use user1 as the test subject
});
afterEach(function () {
passportStub.logout();
});
it('testing endpoints behind the jwt, not jwt itself', function (done) {
request(app).post('/api/v1/some-endpoint/').send({payload}).expect(201).end(function (err, res) {
console.log(res.body);
// some test code here.
done();
});
});
});
Hi,
I have been looking at JWT in my app. I like the look of passport and your library but I think I may be missing some concepts such as how to generate the JWT and how exactly the jwt_payload is populated.
I think what would be super helpful for me and perhaps others would be an end-to-end example from username / password login to getting the token then using that to get some protected api data.
Do you think this would be possible?
Cheers
Mike
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.