fix: floor password_changed_at when comparing against JWT iat
JWT `iat` has 1-second resolution; `password_changed_at` is stored with sub-second precision. The previous comparison rejected tokens whose iat fell in the same wall-clock second as a password change — e.g. a token issued by an immediate re-login after a password reset, or by any script-driven flow that resets and logs in in quick succession. Floor the stored timestamp to whole seconds before comparing. Caught while wiring up the local E2E suite: the seeder needed a "set password_changed_at 10 s in the past" hack to avoid this race; with the fix in place that hack is gone and the suite is naturally deterministic.
This commit is contained in:
@@ -91,10 +91,16 @@ async function adminAuth(req, res, next) {
|
|||||||
return res.status(401).json({ error: 'Invalid token' });
|
return res.status(401).json({ error: 'Invalid token' });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if password was changed after token was issued
|
// Check if password was changed after token was issued. JWT `iat` has
|
||||||
|
// 1-second resolution; `password_changed_at` is sub-second. Floor the
|
||||||
|
// comparison so a token issued in the *same* second as the password
|
||||||
|
// change isn't incorrectly rejected — that race used to bite anyone
|
||||||
|
// logging in immediately after a password reset/change.
|
||||||
if (admin.password_changed_at) {
|
if (admin.password_changed_at) {
|
||||||
const passwordChangedTime = new Date(admin.password_changed_at).getTime() / 1000;
|
const passwordChangedSeconds = Math.floor(
|
||||||
if (decoded.iat < passwordChangedTime) {
|
new Date(admin.password_changed_at).getTime() / 1000
|
||||||
|
);
|
||||||
|
if (decoded.iat < passwordChangedSeconds) {
|
||||||
logger.warn('Token used after password change', { userId: decoded.id });
|
logger.warn('Token used after password change', { userId: decoded.id });
|
||||||
return res.status(401).json({
|
return res.status(401).json({
|
||||||
error: 'Token invalid due to password change',
|
error: 'Token invalid due to password change',
|
||||||
|
|||||||
Reference in New Issue
Block a user