Javascript Passport.js可选身份验证

Javascript Passport.js可选身份验证,javascript,node.js,authentication,oauth-2.0,passport.js,Javascript,Node.js,Authentication,Oauth 2.0,Passport.js,Passport.js中是否有可选的身份验证中间件 假设我有一条路线,/api/users。我只想向公众提供一个用户列表,但对于经过身份验证的用户,我想添加更多字段 目前,我只有一个愚蠢的自定义方法可以做同样的事情,但我想知道: Passport.js已经提供了这样的东西或服务 我怎样才能使它成为passport的一部分,就像插件一样 我的方法大致如下 function optionalAuth(req, res, next) { var authHeader = req.head

Passport.js中是否有可选的身份验证中间件

假设我有一条路线,
/api/users
。我只想向公众提供一个用户列表,但对于经过身份验证的用户,我想添加更多字段

目前,我只有一个愚蠢的自定义方法可以做同样的事情,但我想知道:

  • Passport.js已经提供了这样的东西或服务
  • 我怎样才能使它成为passport的一部分,就像插件一样
我的方法大致如下

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();
    });
}
然而,这在我看来似乎是愚蠢的,而且在passport-auth-strategies.js或其他我认为应该是的身份验证层中也是如此。更好的方法是什么

如果我找到一个令牌但它无效,告诉我我是否做了正确的事情,并返回401,这将获得额外的积分:)

这里有一个简单的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);
});
它正在调用
passport.authenticate
“手动”在
/api
端点中进行身份验证。这样,您就可以更好地控制如何处理身份验证错误(在您的情况下,不应将其视为错误,而应将其视为限制输出的一种方式)

以下是未经适当验证的输出:

$ curl 'localhost:3012/api?username=foo&password=wrong'
{"hello":"world"}
以下是:

$ curl 'localhost:3012/api?username=foo&password=bar'
{"hello":"world","secret":"3133753CR37"}
要用作中间件,请执行以下操作:

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);
});

现在可能要晚了,但有一个
匿名
Passport策略允许这样做。通过这种方式,公共路由可以进行身份验证,也可以不进行身份验证,但当它们进行身份验证时,您仍将拥有与经过身份验证的用户相关的所有信息。在这里查看:

假设您的基础工作正常(验证用户),我认为您可以使用
req.isAuthenticated()
(这是Passport定义的内容)来检查是否要返回额外字段。我不能使用req.isAuthenticated,因为我不能将Passport.authenticate()放在前面。为什么?因为未经身份验证的用户将被拒绝。我没有会话,它是一个无状态API,只是一个承载令牌。如果我将passport.authenticate()放在路由中,一些用户将获得401。我希望他们通过,只得到有限的信息。谢谢。在某种程度上,它比我的尝试要好,因为它使用passport进行身份验证。但它有点笨拙,我不能把它作为未经验证的路由上的中间件。但这可能是包装成某种插件。不过我还是得试试。@Zlatko我编辑了我的答案,想告诉大家如何将其转变为中间件。太棒了,就是这样,比我多管闲事要好。现在做这项工作已经晚了,但可能对未来的工作有所帮助:)