the crux of my issue is that PassportJS appears to be validating a JWT which should be invalid as the current time exceeds the exp parameter .
I have provided the relevant code snippets and an explaination of what I think should be happening (although it clearly isn't!!)
// 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]
jsonwebtoken.verify()
) attempts to verify JWT but finds that Date.now()
exceeds the expiry on the JWT next()
I'm sure I'm missing something obvious but for the life of me I cannot figure out what is going on. Thanks for any help in advance!
Ok so I figured it out!
Turns out (from looking at examples on the jsonwebtoken documentation) that the iat property used when signing the token should be in seconds rather than miliseconds. Therefore the Date.now()
in tokens.js should actually be 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,
};
};
I think you should set the Maxage
of the jwt
token in the options
object since passport is verifying the token using jsonwebtoken
module, also if you set the ignoreExpiration
option to true passport will not validate the expritation of the token, I know this is not the case because I can't see it in your code, but my best guess is that you have to set Maxage
in your options like this { expiresIn: '1h' }
from the documentation
jsonWebTokenOptions: passport-jwt is verifying the token using jsonwebtoken. Pass here an options object for any other option you can pass the jsonwebtoken verifier. (ie maxAge)
if you wanna learn more about the jsonwebtoken
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.