NodeJS passport-jwt 401未经授权

mqxuamgl  于 2023-06-22  发布在  Node.js
关注(0)|答案(4)|浏览(171)

我试图实现passport-jwt身份验证,但在尝试调用端点时总是出现401 Unauthorized。
这是我的设置
passport.js

var passport = require('passport');
var User = require('../models/user');
var config = require('./auth');
var JwtStrategy = require('passport-jwt').Strategy;
var ExtractJwt = require('passport-jwt').ExtractJwt;
var LocalStrategy = require('passport-local').Strategy;

var localOptions = {
    usernameField: 'email'
};

var localLogin = new LocalStrategy(localOptions, function(email, password, done) {

    User.findOne({
        email: email
    }, function(err, user) {
        if (err) {
            return done(err);
        }
        if (!user) {
            return done(null, false, { error: 'Login failed. Please try again' });
        }

        user.comparePassword(password, function(err, isMatch) {
            if (err) {
                return done(err);
            }
            if (!isMatch) {
                return done(null, false, { error: 'Login Failed. Please try again.' });
            }

            user.status = 'online';
            user.save(function(err, user) {
                if (err) {
                    return done(err);
                }
            });

            return done(null, user);
        });
    });
});

var jwtOptions = {
    jwtFromRequest: ExtractJwt.fromHeader('Authorization'),
    secretOrKey: config.secret
};

var jwtLogin = new JwtStrategy(jwtOptions, function(payload, done) {
    console.log(payload);
    User.findById(payload._id, function(err, user) {
        if (err) {
            return done(err, false);
        }
        if (user) {
            done(null, user)
        } else {
            done(null, false);
        }
    });
});

passport.use(localLogin);
passport.use(jwtLogin);

module.exports = {
    initialize: () => passport.initialize(),
    authenticateJWT: passport.authenticate('jwt', { session: false }),
    authenticateCredentials: passport.authenticate('local', { session: false }),
};

user.js

var express = require('express');
var router = express.Router();
var AuthController = require('../controllers/authentication');
var passportService = require('../config/passport');
var passport = require('passport');

const requireToken = passportService.authenticateJWT;
const requireCredentials = passportService.authenticateCredentials;

router.post('/signup', AuthController.register);
router.post('/signin', requireCredentials, AuthController.login);

router.get('/protected', requireToken function(req, res, next){
res.send({msg:'Success!'});
});

module.exports = router;

我已经确保我的头包含:'JWT ' + [some token]...也尝试没有'JWT '仍然没有什么...
我已经检查了关于同样问题的其他帖子,但仍然无法解决它。

9wbgstp7

9wbgstp71#

遗产
'JWT ' + [some token]
版本0.4.0
'bearer ' + [some token]

示例

所以当你现在发送代币是这样的:
遗产
res.json ({ success: true, token: 'JWT ' + token })
版本0.4.0
res.json ({ success: true, token: 'bearer ' + token })

深入

也许还有其他方法可以做到这一点
如果查看/node_module/passport-jwt/lib/extract_jwt.js文件,可以看到有一个名为versionOneCompatibility(options)的函数

knpiaxh1

knpiaxh12#

经过几个小时的尝试,我终于设法使用ExtractJwt.fromAuthHeaderWithScheme('Bearer')方法解决了这个问题。由于某种原因,提取器无法通过其他方法获得令牌。

0tdrvxhp

0tdrvxhp3#

我也遇到了同样的问题,经过研究,我发现了导致这个问题的原因。当你在路由中创建res.json时

//Authenticate
router.post('/authenticate', (req, res, next) => {
  const username = req.body.username;
  const password = req.body.password;

  User.getUserByUsername(username, (err, user) => {
    if (err) throw err;
    if (!user) {
      return res.json({
        success: false,
        msg: 'User not found'
      });
    }

    User.comparePassword(password, user.password, (err, isMatch) => {
      if (err) throw err;
      if (isMatch) {
        const token = jwt.sign(user.toJSON(), config.secret, {
          expiresIn: 604800 // 1 week
        });
        res.json({
          success: true,
          token: 'jwt ' + token, //Here you have to put space after name inside quotes
          user: {
            id: user._id,
            name: user.name,
            username: user.username,
            email: user.email
          }
        });
      } else {
        return res.json({
          success: false,
          msg: 'Wrong password'
        });
      }
    });
  });
});

在token:'jwt' + token中,在名称jwt后面放一个空格非常重要,还有你放在' '引号中的名称,你必须把这个名称放在你的

var opts = {};
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderWithScheme('jwt');//Here you have to put the same name inside quotes '' like you put inside token but without space after name
opts.secretOrKey = config.secret;
passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
    console.log(jwt_payload);
    User.findOne({
        id: jwt_payload.sub
    }, function(err, user) {
        if (err) {
            return done(err, false);
        }

        if (user) {
            return done(null, user);
        } else {
            return done(null, false);
        }
    });
}));

这两个必须匹配,如果你放jwt或JWT或bearer或其他任何东西都没关系,重要的是它们必须匹配,并且在创建token:'name'时必须有空间。

34gzjxbg

34gzjxbg4#

【我在这里回复答案是为了提问,因为我没有足够高的声望来评论。】
我在/login路由中这样做了:

await user.save();
res.cookie("refreshToken", refreshToken, COOKIE_OPTIONS);
res.send({ success: true, token: `Bearer ${token}`, user });

在配置中:

opts.jwtFromRequest = ExtractJwt.fromAuthHeaderWithScheme("Bearer");

但我还是有同样的问题
我还将发送Authorization头和刷新令牌的请求。
很抱歉在这里问一个问题。我注意到它说我不应该,但我不能帮助,因为我不能做一个正常的评论。
编辑:使用“jwt”而不是“Bearer”对我也不起作用。
那我该怎么解决呢?
Edit2:我注意到我的req.cookies对象是空的,而req.signedCookies只是:我完全迷路了。我试着做研究,但我找不到任何东西(虽然也许我没有在足够的地方寻找)。

相关问题