护照 JWT 认证提取令牌

3
我将使用express和jwt-simple来处理登录/注册和认证请求作为中间件api。我正在尝试创建一个.well-known端点,以便其他API可以根据发送的令牌对请求进行身份验证。
这是我的策略:
module.exports = function() {
    const opts = {};
    opts.jwtFromRequest = ExtractJwt.fromAuthHeader();
    opts.secretOrKey = securityConfig.jwtSecret;
    passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
        // User.where('id', jwt_payload.id).fetch({withRelated: 'roles'})
        console.log('jwt_payload', jwt_payload)
            User.where('id', jwt_payload.id).fetch()
            .then(user => user ? done(null, user) : done(null, false))
            .catch(err => done(err, false));
    }));
};

这是我的登录路由:

router.post('/login', function(req, res) {
    const {username, password} = req.body;
    Promise.coroutine(function* () {
        const user = yield User.where('username', username).fetch();

    if(user) {
        const isValidPassword = yield user.validPassword(password);
        if (isValidPassword) {
            let expires = (Date.now() / 1000) + 60 * 30
            let nbf = Date.now() / 1000
            const validatedUser = user.omit('password');

            // TODO: Verify that the encoding is legit..
            // const token = jwt.encode(user.omit('password'), securityConfig.jwtSecret);
            const token = jwt.encode({ nbf: nbf, exp: expires, id: validatedUser.id, orgId: validatedUser.orgId }, securityConfig.jwtSecret)
            res.json({success: true, token: `JWT ${token}`, expires_in: expires});
        } else {
            res.status(401);
            res.json({success: false, msg: 'Authentication failed'});
        }
    } else {
        res.status(401);
        res.json({success: false, msg: 'Authentication failed'});
    }
    })().catch(err => console.log(err));
});

这是我的.well-known路由:
router.get('/.well-known', jwtAuth, function(req, res) {
    // TODO: look over res.req.user. Don't seem to be the way to get those parameters.
    // We dont take those parameters from the decrypted JWT, we seem to grab it from the user in DB.
    const { id, orgId } = res.req.user.attributes;
    console.log("DEBUG: userId", id)
    console.log("DEBUG: USER", res.req.user)
    res.json({
        success: true,
        userId: id,
        orgId
    });
});

这是我的jwtAuth()函数:

const passport = require('passport');
module.exports = passport.authenticate('jwt', { session: false });

我该如何在路由函数中获取并解密令牌?现在的处理方式只是验证令牌是否有效,但是我需要能够解密令牌,以便将存储的值发送回去。我不确定res.req.user.attributes是从哪里来的,这是令牌吗?

1个回答

7
请查看 passport-jwt 并在您的 passport-config(或者无论您在哪里初始化 passport)中设置 JWT 策略:
const JwtStrategy = require('passport-jwt').Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;

const jwtAuth = (payload, done) => {
 const user = //....find User in DB, fetch roles, additional data or whatever
 // do whatever with decoded payload and call done
 // if everything is OK, call
 done(null, user);
 //whatever you pass back as "user" object will be available in route handler as req.user

 //if your user does not authenticate or anything call
 done(null, false);
}

const apiJwtOptions: any = {};
apiJwtOptions.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
apiJwtOptions.algorithms = [your.jwt.alg];
apiJwtOptions.secretOrKey = your.jwt.secret;
//apiJwtOptions.issuer = ???;
//apiJwtOptions.audience = ???;
passport.use('jwt-api', new JwtStrategy(apiJwtOptions, jwtAuth));

如果您只想要解码后的令牌,在jwtAuth中调用done(null, payload)即可。
然后在您的路由文件中,当您想要保护端点并获取有关用户的信息时,请使用以下方法:
const router = express.Router();
router.use(passport.authenticate('jwt-api', {session: false}));

在处理程序中,您应该可以使用req.user。它可以配置从auth存储数据的 req 属性的属性, req.user 只是默认值。

抱歉耽搁了。我注意到我正在使用passport-jwt来获取jwtHeader并使用密钥进行提取/解码。我在/login和/register上使用simple-jwt。我的问题是,如果我登录并从Web客户端返回一个令牌,然后半秒钟后尝试基于返回的JWT调用身份验证路由,则不会返回任何内容(未经身份验证)。但是等待2秒并调用它,它就可以正常工作...似乎在将jwt保存到passport时存在延迟。 - Joelgullander
你有几分钟私聊的时间吗? - Joelgullander
我正在度假,回来后我们可以聊天。 - PeS
这个问题对你来说还存在吗?或者你在此期间解决了它吗? - PeS
我不知道在回调函数中将用户对象作为第二个参数返回时,我们可以稍后从req.user获取信息。谢谢! - Seagull

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