Is there an optional authentication middleware from Passport.js?
Let's say I have a route, /api/users
. I want to give just a list of users to the public, but to authenticated people, I want to add more fields.
Currently I have just a dumb custom method that does the same thing, but I wonder if:
My method, roughly, looks like
function optionalAuth(req, res, next) {
var authHeader = req.headers.authorization;
var token = parseToken(authHeader); // just getting the OAuth token here
if(!token) {
return next();
}
User.findOne({
token: token
}, function(err, user) {
if(err) {
return res.json(401, {message: 'auth expired'});
};
if(user) {
req.user = user;
}
next();
});
}
This, however, seems dumb to me, and also not in passport-auth-strategies.js or some other auth layer where I think it should be. What is the better way to do it?
Bonus points for telling me if I'm doing the proper thing returning 401 if I find a token but it's invalid :)
Here's a simple PoC:
var express = require('express');
var app = express();
var server = app.listen(3012);
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
app.use(passport.initialize());
passport.use(new LocalStrategy(function(username, password, done) {
if (username === 'foo' && password === 'bar') {
return done(null, { username : 'foo' });
}
return done(null, false);
}));
app.get('/api', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
var data = { hello : 'world' };
// Only if the user authenticated properly do we include secret data.
if (user) {
data.secret = '3133753CR37';
}
return res.send(data);
})(req, res, next);
});
It's calling passport.authenticate
'manually' in the /api
endpoint. That way, you get more control over how to deal with authentication error (which—in your situation—shouldn't be treated as errors but as a way of limiting the output).
Here's the output without proper authentication:
$ curl 'localhost:3012/api?username=foo&password=wrong'
{"hello":"world"}
And here's with:
$ curl 'localhost:3012/api?username=foo&password=bar'
{"hello":"world","secret":"3133753CR37"}
To use as a middleware:
var middleware = function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
req.authenticated = !! user;
next();
})(req, res, next);
};
app.get('/api', middleware, function(req, res, next) {
var data = { hello : 'world' };
if (req.authenticated) {
data.secret = '3133753CR37';
}
return res.send(data);
});
Might be late now, but there's an anonymous
Passport strategy to allow exactly this. That way the public routes can either take authentication or not, but when they do you'll still have all of the information associated with the authenticated user. Check it out here: https://github.com/jaredhanson/passport-anonymous
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.