Passport JS 验证过期的 JWT
PassportJS Validates Expired JWT
我的问题的症结在于 PassportJS 似乎正在验证一个 JWT,它应该是无效的,因为当前时间超过了 exp 参数。
我已经提供了相关的代码片段并解释了我认为应该发生的事情(尽管显然不是!!)
密码
// In server.js
// ...
const passport = require("passport");
// ...
require("./config/passport")(passport);
app.use(passport.initialize());
// ...
// In token.js (used to issue JWT)
const jsonwebtoken = require("jsonwebtoken");
// ...
const issueJWT = (user) => {
const _id = user._id;
const expiresIn = 30000; // 30s for testing purposes
const payload = {
sub: _id,
iat: Date.now(),
};
const signedToken = jsonwebtoken.sign(payload, PRIV_KEY, {
expiresIn: expiresIn,
algorithm: "RS256",
});
return {
token: "Bearer " + signedToken,
expires: expiresIn,
};
};
// In passport.js
const JwtStrategy = require("passport-jwt").Strategy;
const ExtractJwt = require("passport-jwt").ExtractJwt;
// ...
const options = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: PUB_KEY,
algorithms: ["RS256"],
};
module.exports = (passport) => {
passport.use(
new JwtStrategy(options, (jwt_payload, done) => {
User.findOne({ _id: jwt_payload.sub }, (err, user) => {
if (err) {
return done(err, false);
}
if (user) {
return done(null, user);
} else {
return done(null, false);
}
});
})
);
};
// In routes.js
// ...
const passport = require("passport");
const { authenticateWithAccessToken } = require("../controllers/usersController");
// ...
router
.route("/authenticate-with-access-token")
.get(
passport.authenticate("jwt", { session: false }),
authenticateWithAccessToken
);
// In usersController.js
exports.authenticateWithAccessToken = async (req, res, next) => {
try {
const user = req.user;
res.status(200).json({
success: true,
name: user.name,
email: user.email,
});
} catch (err) {
next(err);
}
};
有效负载示例
{
alg: "RS256",
typ: "JWT"
}.
{
sub: "5eec9f1c4a416c1e50fc0a8e", // user._id
iat: 1593258411458, // 2020-06-27 11:46:51
exp: 1593258441458 // 2020-06-27 11:47:21
}.
[signature]
我希望发生的事情
- 客户端在 auth header
中使用不记名令牌 (JWT) 向 /authenticate-with-access-token 发送 GET 请求
- PassportJS(通过
jsonwebtoken.verify()
)尝试验证 JWT,但发现 Date.now()
超过了 JWT 的到期时间
- PassportJS 引发错误,使用 401 未授权响应解决请求
发生了什么
- 客户端在 auth header
中使用不记名令牌 (JWT) 向 /authenticate-with-access-token 发送 GET 请求
- PassportJS 将用户 object 传递到请求 body 并调用
next()
- 中间件的最后一块运行,用 200 OK 响应解析请求并通过 JSON body
传回用户详细信息
我确定我遗漏了一些明显的东西,但对于我来说,我无法弄清楚发生了什么。提前感谢您的帮助!
我认为你应该在 options
对象中设置 jwt
标记的 Maxage
由于 passport 正在使用 jsonwebtoken
模块验证令牌,如果您将 ignoreExpiration
选项设置为 true passport 将不会验证令牌的 expritation,我知道情况并非如此,因为我看不到它在你的代码中,但我最好的猜测是你必须在你的选项中设置 Maxage
像这样 { expiresIn: '1h' }
jsonWebTokenOptions: passport-jwt is verifying the token using jsonwebtoken. Pass here an options object for any other option you can pass the jsonwebtoken verifier. (i.e maxAge)
如果您想了解有关 jsonwebtoken
的更多信息
好的,我明白了!
事实证明(通过查看 jsonwebtoken 文档中的示例)签署令牌时使用的 iat 属性 应该以秒而不是毫秒为单位。因此 tokens.js 中的 Date.now()
实际上应该是 Math.floor(Date.now / 1000)
:
// In token.js (used to issue JWT)
const jsonwebtoken = require("jsonwebtoken");
// ...
const issueJWT = (user) => {
const _id = user._id;
const expiresIn = 30; // 30s for testing purposes
const payload = {
sub: _id,
iat: Math.floor(Date.now() / 1000),
};
const signedToken = jsonwebtoken.sign(payload, PRIV_KEY, {
expiresIn: expiresIn,
algorithm: "RS256",
});
return {
token: "Bearer " + signedToken,
expires: expiresIn,
};
};
我的问题的症结在于 PassportJS 似乎正在验证一个 JWT,它应该是无效的,因为当前时间超过了 exp 参数。
我已经提供了相关的代码片段并解释了我认为应该发生的事情(尽管显然不是!!)
密码
// In server.js
// ...
const passport = require("passport");
// ...
require("./config/passport")(passport);
app.use(passport.initialize());
// ...
// In token.js (used to issue JWT)
const jsonwebtoken = require("jsonwebtoken");
// ...
const issueJWT = (user) => {
const _id = user._id;
const expiresIn = 30000; // 30s for testing purposes
const payload = {
sub: _id,
iat: Date.now(),
};
const signedToken = jsonwebtoken.sign(payload, PRIV_KEY, {
expiresIn: expiresIn,
algorithm: "RS256",
});
return {
token: "Bearer " + signedToken,
expires: expiresIn,
};
};
// In passport.js
const JwtStrategy = require("passport-jwt").Strategy;
const ExtractJwt = require("passport-jwt").ExtractJwt;
// ...
const options = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: PUB_KEY,
algorithms: ["RS256"],
};
module.exports = (passport) => {
passport.use(
new JwtStrategy(options, (jwt_payload, done) => {
User.findOne({ _id: jwt_payload.sub }, (err, user) => {
if (err) {
return done(err, false);
}
if (user) {
return done(null, user);
} else {
return done(null, false);
}
});
})
);
};
// In routes.js
// ...
const passport = require("passport");
const { authenticateWithAccessToken } = require("../controllers/usersController");
// ...
router
.route("/authenticate-with-access-token")
.get(
passport.authenticate("jwt", { session: false }),
authenticateWithAccessToken
);
// In usersController.js
exports.authenticateWithAccessToken = async (req, res, next) => {
try {
const user = req.user;
res.status(200).json({
success: true,
name: user.name,
email: user.email,
});
} catch (err) {
next(err);
}
};
有效负载示例
{
alg: "RS256",
typ: "JWT"
}.
{
sub: "5eec9f1c4a416c1e50fc0a8e", // user._id
iat: 1593258411458, // 2020-06-27 11:46:51
exp: 1593258441458 // 2020-06-27 11:47:21
}.
[signature]
我希望发生的事情
- 客户端在 auth header 中使用不记名令牌 (JWT) 向 /authenticate-with-access-token 发送 GET 请求
- PassportJS(通过
jsonwebtoken.verify()
)尝试验证 JWT,但发现Date.now()
超过了 JWT 的到期时间
- PassportJS 引发错误,使用 401 未授权响应解决请求
发生了什么
- 客户端在 auth header 中使用不记名令牌 (JWT) 向 /authenticate-with-access-token 发送 GET 请求
- PassportJS 将用户 object 传递到请求 body 并调用
next()
- 中间件的最后一块运行,用 200 OK 响应解析请求并通过 JSON body 传回用户详细信息
我确定我遗漏了一些明显的东西,但对于我来说,我无法弄清楚发生了什么。提前感谢您的帮助!
我认为你应该在 options
对象中设置 jwt
标记的 Maxage
由于 passport 正在使用 jsonwebtoken
模块验证令牌,如果您将 ignoreExpiration
选项设置为 true passport 将不会验证令牌的 expritation,我知道情况并非如此,因为我看不到它在你的代码中,但我最好的猜测是你必须在你的选项中设置 Maxage
像这样 { expiresIn: '1h' }
jsonWebTokenOptions: passport-jwt is verifying the token using jsonwebtoken. Pass here an options object for any other option you can pass the jsonwebtoken verifier. (i.e maxAge)
如果您想了解有关 jsonwebtoken
的更多信息好的,我明白了!
事实证明(通过查看 jsonwebtoken 文档中的示例)签署令牌时使用的 iat 属性 应该以秒而不是毫秒为单位。因此 tokens.js 中的 Date.now()
实际上应该是 Math.floor(Date.now / 1000)
:
// In token.js (used to issue JWT)
const jsonwebtoken = require("jsonwebtoken");
// ...
const issueJWT = (user) => {
const _id = user._id;
const expiresIn = 30; // 30s for testing purposes
const payload = {
sub: _id,
iat: Math.floor(Date.now() / 1000),
};
const signedToken = jsonwebtoken.sign(payload, PRIV_KEY, {
expiresIn: expiresIn,
algorithm: "RS256",
});
return {
token: "Bearer " + signedToken,
expires: expiresIn,
};
};