简体   繁体   English

节点快递护照(JWT) - 认证后的回叫

[英]Node express passport (JWT) - callback after auth

I have authentication working with passport JWT, but I am having difficulty running a callback function/response, only if a user is authenticated. 我有使用护照JWT的身份验证,但是只有在用户通过身份验证后才能运行回调函数/响应。 How can this be done? 如何才能做到这一点?

In my routes: 在我的路线:

import express from 'express';
import passport from '../../config/passport';
import memberInfoCtrl from '../controllers/memberInfo';

const router = express.Router();

router.route('/members')
  .get(membersCtrl.tokenCheck, passport.authenticate('jwt', { session: false }), membersCtrl.doSomethingElse);

export default router;

I want membersCtrl.doSomethingElse to be run if authentication is successful. 如果身份验证成功,我希望运行membersCtrl.doSomethingElse

Here is my tokenCheck function: 这是我的tokenCheck功能:

function tokenCheck(req, res, next) {
  const token = getToken(req.headers);
  if (token) {
    const decoded = jwt.decode(token, config.secret);
    User.findOne({
      email: decoded.email
    }, (err, user) => {
      if (err) throw err;

      if (!user) {
        return res.status(403).send({
          success: false, msg: 'Authentication failed. User not found.'
        });
      }
      // res.json({ success: true, msg: 'Welcome to the member area!' });
      return next();
    });
  } else {
    return res.status(403).send({ success: false, msg: 'No token provided.' });
  }
}

Using res.json in tokenCheck works fine, but the doSomethingElse function is not getting called afterwards. tokenCheck使用res.json工作正常,但之后不会调用doSomethingElse函数。

I thought it's because we send a response like this: 我以为是因为我们发送了这样的回复:

res.json({ success: true, msg: 'Welcome to the member area!' });

Replacing the res.json with return next(); return next();替换res.json return next(); returns the error: 返回错误:

Error: Unknown authentication strategy \\"jwt\\"

Why does this happen - how can I check for authentication before executing another function, for the same route? 为什么会发生这种情况 - 如何在执行另一个功能之前检查相同路由的身份验证?

I'm sure it's something silly i'm missing. 我确定这是一件我很想念的傻事。 Any help is appreciated! 任何帮助表示赞赏!

Here is part of my main express script that initialises passport: 这是我的主要快递脚本的一部分,初始化护照:

import passport from 'passport';
...
app.use(passport.initialize());

app.use('/api', routes);
...

Passport config: 护照配置:

const JwtStrategy = require('passport-jwt').Strategy;
import User from '../server/models/user';
import config from './env';

module.exports = (passport) => {
  const opts = {};
  opts.secretOrKey = config.secret;
  passport.use(new JwtStrategy(opts, (jwtPayload, done) => {
    User.findOne({ id: jwtPayload.id }, (err, user) => {
      if (err) {
        return done(err, false);
      }
      if (user) {
        done(null, user);
      } else {
        done(null, false);
      }
    });
  }));
};

Your general approach is correct. 你的一般方法是正确的。 To protect a route depending on some conditions write a custom middleware calling next() if those conditions are fulfilled. 要根据某些条件保护路由,请编写调用next()的自定义中间件next()如果满足这些条件next()

But in your case this is not necessary as this is what passport-jwt does. 但在你的情况下,这不是必要的,因为这是passport-jwt作用。 So assuming that you configured passport and passport-jwt correctly all you need to write is this: 所以假设您正确配置了passportpassport-jwt ,您需要编写的是:

router.route('/members')
    .get(passport.authenticate('jwt', { session: false }), membersCtrl.doSomethingElse);

passport-jwt will extract the JWT from the request and verify it against your provided secret or key. passport-jwt将从请求中提取JWT并根据您提供的秘密或密钥进行验证。 Afterwards it will use passport's verify callback to populate req.user ( source ). 之后,它将使用passport的verify回调来填充req.user )。

Additionally: Yes after using res.json() a response is sent which is why your passport middleware and anything beyond is not reached in that case. 另外:使用res.json()后发送一个响应,这就是为什么你的护照中间件和其他任何东西都没有达到的原因。

Regarding your error Error: Unknown authentication strategy \\"jwt\\" : This usually happens if you did not configure your passport authentication correctly. 关于您的错误Error: Unknown authentication strategy \\"jwt\\" :如果您没有正确配置您的护照身份验证,通常会发生这种情况。 If you include it in your question I will take a look at it and extend my answer accordingly. 如果你把它包含在你的问题中,我会看一下并相应地扩展我的答案。

Update: Your code looks good to me except one thing: You did not specify the jwtFromRequest attribute in your passport-jwt options which is mandatory. 更新:您的代码看起来不错,除了一件事:您没有在passport-jwt选项中指定jwtFromRequest属性,这是强制性的。 Or did you by any chance forget to invoke your passport config? 或者你有没有机会忘记调用你的护照配置?

Update 2: Further clarification regarding my comment below: 更新2:关于我的评论的进一步说明如下:
1.) Import your ES6 passport config module ( where you added the jwtFromRequest option ) in your main express script and invoke it: 1.)在主快捷脚本中导入您的ES6护照配置模块( 您在其中添加了jwtFromRequest选项 )并调用它:

import passport from 'passport';
import passportConfig from 'path/to/passport/config';
...
app.use(passport.initialize());
passportConfig(passport);
...

2.) Make sure to remove your tokenCheck function, you don't need it. 2.)确保删除tokenCheck功能,您不需要它。 See the first part of this answer. 请参阅本答案的第一部分。

Update 3: 'Unauthorized' is great because it means that you are successfully protecting your /members route now. 更新3: '未授权'很棒,因为这意味着您现在成功保护您的/members路线。 To implement a token-based authentication you now need an additional route /authenticate where users can request access to your web service eg by providing credentials (your route will verify these credentials and respond with a JWT which must be signed with the same secret you are using for passport-jwt - otherwise passport-jwt will not be able to verify the token signature later). 要实现基于令牌的身份验证,您现在需要一个额外的路由/authenticate ,用户可以请求访问您的Web服务,例如通过提供凭据(您的路由将验证这些凭据并使用JWT进行响应,必须使用相同的秘密进行签名)用于passport-jwt - 否则passport-jwt将无法在以后验证令牌签名。

But this goes beyond the scope of this question. 但这超出了这个问题的范围。 There should be many resources out there covering this. 应该有很多资源可以解决这个问题。 You can for example implement an /authenticate route using jsonwebtoken which is shown in this article (they are not using passport at all but use jsonwebtoken for token creation and validation). 例如,您可以实施/authenticate中使用路由jsonwebtoken这是在显示这篇文章 (他们没有用passport都而是用jsonwebtoken令牌创建验证)。

Note: If you are also implementing a client you have to include some additional logic there to store the JWT and to include it in your requests to the express app. 注意:如果您还要实现客户端,则必须在其中包含一些额外的逻辑来存储JWT并将其包含在您对Express应用程序的请求中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM