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!!)
The code
// 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);
}
};
Sample payload
{
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]
What I would expect to happen
- Client sends GET request to /authenticate-with-access-token with Bearer token (JWT) in auth header
- PassportJS (via
jsonwebtoken.verify()) attempts to verify JWT but finds thatDate.now()exceeds the expiry on the JWT - PassportJS raises an error, resolving the request with a 401 Unauthorized response
What does happen
- Client sends GET request to /authenticate-with-access-token with Bearer token (JWT) in auth header
- PassportJS passes the user object into the request body and calls
next() - Final piece of middleware runs, resolving the request with a 200 OK response and passes the user details back via a JSON body
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!