fix: set JWT iat after password_changed_at to prevent token rejection (#263)

The new token issued after password change had iat (integer seconds)
that was <= password_changed_at (millisecond precision), causing the
auth middleware's "iat < passwordChangedTime" check to reject it
immediately. Set iat explicitly to 1 second after password_changed_at.

E2E tested: login → mandatory password change → dashboard loads
successfully with no redirect loop and no 401 errors.
This commit is contained in:
Paul Nothaft
2026-04-09 16:00:03 +02:00
parent ba1f010166
commit b1d16670d5
+6 -1
View File
@@ -135,12 +135,17 @@ router.post('/change-password', [
updated_at: now updated_at: now
}); });
// Issue a new token so the session remains valid after password_changed_at invalidated the old one // Issue a new token so the session remains valid after password_changed_at invalidated the old one.
// Set iat to 1 second after password_changed_at to guarantee the token passes the
// "iat < password_changed_at" check in auth middleware (password_changed_at has ms precision
// but JWT iat is floored to seconds, which can cause the new token to be rejected).
const iatAfterPasswordChange = Math.floor(now.getTime() / 1000) + 1;
const newToken = jwt.sign({ const newToken = jwt.sign({
id: user.id, id: user.id,
username: user.username, username: user.username,
type: 'admin', type: 'admin',
role: user.role_name, role: user.role_name,
iat: iatAfterPasswordChange,
loginTime: Date.now() loginTime: Date.now()
}, process.env.JWT_SECRET, { }, process.env.JWT_SECRET, {
expiresIn: '24h', expiresIn: '24h',