护照-jwt总是返回401未经授权

4
我正在尝试使用passport-jwt身份验证策略对nodejs api进行身份验证,但它总是抛出401未经授权的错误。我尝试了各种实现,但是passport.authenticate功能似乎无法正常工作。
使用以下护照版本: "passport": "^0.4.0", "passport-jwt": "^4.0.0",
请查看我的代码:
尝试以下选项:
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken()  
jwtFromRequest: ExtractJwt.fromHeader('authorization')  
jwtFromRequest: ExtractJwt.fromAuthHeaderWithScheme('Bearer')  
jwtFromRequest: ExtractJwt.fromAuthHeaderWithScheme('jwt')  

但是没有起作用。

尝试查看passport-jwt 401 Unauthorized和其他相关链接进行参考。

app.js文件:

最初的回答

const express = require('express');
const bodyParser = require('body-parser');
const passport = require('passport');
const cors = require('cors');

const app = express();
const login = require('./routes/login');

app.use(cors());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// app.use(passport.initialize());

app.use('/', login);

app.listen(8000, () => console.log('Server running on http://localhost:8000/'));

login.js file in route folder:

const express = require('express');
const router = express.Router();
const passport = require('passport');
const passportref = require('./../controllers/passport');
const loginController = require('./../controllers/loginController');

router.post('/putemailregistration',loginController.putEmailregistration);
router.get('/login', passportref.authenticate,loginController.verifyLogin);

module.exports = router;

Passport.js file:

const passport = require('passport');
const JWTStrategy = require("passport-jwt").Strategy;
const  ExtractJwt = require('passport-jwt').ExtractJwt;
const models = require('./../models');

const opts = {
  jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
  secretOrKey: 'incredible',
}
passport.use(new JWTStrategy(opts,async (payload, done) => {
 try {
     console.log(`inside jwt strategy func`);
     const user = models.Userabout.findById({
         where: { email: { [Op.eq]: payload.email } },
         attributes: ['id', 'email', 'password'],
     });
     console.log(`value of user: ${user}`);
     if (typeof user !== 'undefined' && user !== null) {
        return done(null, user);
     }
     else {
        return done(null, false);
     }
 } catch (err) {
     done(err, false);
 }
 }));


module.exports = {
    initialize: () => passport.initialize(),
    authenticate: passport.authenticate("jwt", { session: false }),
};

loginController.js文件:

const { Op } = require('sequelize');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const models = require('./../models');
const saltRounds = 10;

module.exports.putEmailregistration = async (req, res) => {
  try {
      console.log(`inside put email registration`);

      if (req.body.email === null || req.body.password === null) {
          res.sendStatus(400).json('no data');
      } else {
         const emailregister = await models.Userdata.create({
             email: req.body.email,
             password: bcrypt.hashSync(req.body.password, 
              bcrypt.genSaltSync(saltRounds)),
         });
        const tokenid = jwt.sign({
            id: emailregister.id,
            email: emailregister.email,
        }, process.env.JWT_SECRETKEY,
        { expiresIn: 3600 });
        res.json({ success: true, token: 'bearer ' + tokenid });
     }
   } catch (err) {
    console.log(`error at put email registration: ${err}`);
   }
}


module.exports.verifyLogin = (req, res) => {
  console.log(`i managed to get here`);

  // console.log(`user: ${req.user}`);
 // res.send(req.user.email);
}

已经发布请查看:https://stackoverflow.com/questions/45897044/passport-jwt-401-unauthorized - Vijay Chauhan
是的@Vijay,我已经尝试过了。我在我发布的问题中也附上了那个链接的参考资料。但似乎不起作用。 - Priyanka
6个回答

2
经过长时间的调试,我终于解决了问题。希望这能帮助到其他人。
  1. 我的错误在于在passport.js文件中指向了错误的模型。它应该是Userabout而不是Userdata。
  2. 在loginController.js文件中,我做出以下更改:
    const payload = { id: emailregister.id }
    const token = jwt.sign(payload, jwtOptions.secretOrKey);
  3. 使用以下选项效果很好。
    jwtOptions.jwtFromRequest = ExtractJwt.fromAuthHeaderWithScheme('Bearer');
注:Original Answer翻译成“最初的回答”。

2
为了解决这个问题,你可以在你的中间件中进行管理。
function authorized(request, response, next) {
    passport.authenticate('jwt', { session: false, }, async (error, token) => {
        if (error || !token) {
            response.status(401).json({ message: 'Unauthorized Message' });
        } 
        try {
            console.log('token',token)
            const user = await User.findOne(
                {_id: token._id}
            );
            request.user = user;
        } catch (error) {
            next(error);
        }
        next();
    })(request, response, next);   
}

router.get(
  '/',
  authorized,
  trimRequest.all,
  user.getItems
)


1
在我的情况下,我使用了环境变量中的expiresIn值。环境变量的值将是String类型的,如果我们将一个字符串值传递给expiresIn,它将以毫秒为单位进行计算。因此,3600的值被转换为3秒,当我从登录响应中复制令牌到授权标头时,它已经过期了。

https://www.npmjs.com/package/jsonwebtoken#usage


0
在我的情况下,错误是调用了 done(null) 而不是 done(null, jwtPayload),导致了 401 错误。
passport.use(new JwtStrategy({
  jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
  secretOrKey: secret,
}, function (jwtPayload, done) {
  done(null, jwtPayload); // I was calling just done(null)
})).authenticate('jwt', { session: false })

0

passport.js 中使用 passport.use('jwt', new JWTStrategy({opts}, verify_callback(){})


0

似乎有许多不同的问题可能导致这个问题。在我的情况下,它是公钥格式错误 - 公钥必须是PEM格式:

const opts = {
    jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
    secretOrKey: `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyn2vP592Ju/iKXQW1DCrSTXyQXyo11Qed1SdzFWC+mRtdgioKibzYMBt2MfAJa6YoyrVNgOtGvK659MjHALtotPQGmis1VVvBeMFdfh+zyFJi8NPqgBTXz6bQfnu85dbxVAg95J+1Ud0m4IUXME1ElOyp1pi88+w0C6ErVcFCyEDS3uAajBY6vBIuPrlokbl6RDcvR9zX85s+R/s7JeP1XV/e8gbnYgZwxcn/6+7moHPDl4LqvVDKnDq9n4W6561s8zzw8EoAwwYXUC3ZPe2/3DcUCh+zTF2nOy8HiN808CzqLq1VeD13q9DgkAmBWFNSaXb6vK6RIQ9+zr2cwdXiwIDAQAB
-----END PUBLIC KEY-----`
};

为了调试,将回调函数作为第三个参数添加到 passport.authenticate() 方法中会很有帮助:

passport.authenticate('jwt', 
  { session: false }, 
  (err, user, info, status) => { /* do some logging here */ })

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接