Before submitting
Bug summary
The authentication middleware contains a silent-refresh flow that issues a new access token using only JWT signature validation of the refresh token. Unlike the /api/auth/refresh endpoint, this path does not verify the refresh token against the stored security.refreshTokenHash. As a result, refresh tokens that have been revoked through logout or invalidated through token rotation can continue to be used to obtain new access tokens until the refresh token JWT itself expires.
Steps to reproduce
Log in and obtain an access token and refresh token.
Call POST /api/auth/refresh to rotate tokens.
The original refresh token should now be invalid because a new hash is stored in the database.
Allow the access token to expire.
Send an authenticated request using:
expired access token
original refresh token cookie
Observe that the middleware silently generates a new access token and the request succeeds.
The same behavior occurs after logout if the old refresh token cookie is preserved.
Expected behavior
Refresh-token revocation and rotation should be enforced consistently across all authentication flows.
A refresh token that has been revoked through logout or superseded through rotation should not be able to obtain a new access token, regardless of whether the request uses the explicit refresh endpoint or the middleware's silent-refresh mechanism.
Actual behavior
The explicit refresh endpoint validates refresh-token state against persisted session data, while the middleware silent-refresh flow appears to rely solely on JWT verification.
As a result, revoked or rotated refresh tokens may continue to be accepted until their JWT expiration time is reached.
Screenshots or recordings
No response
Browser and device information
Browser:
Browser version:
Operating system:
Device:
Screen size/resolution:
Additional context
No response
Before submitting
Bug summary
The authentication middleware contains a silent-refresh flow that issues a new access token using only JWT signature validation of the refresh token. Unlike the /api/auth/refresh endpoint, this path does not verify the refresh token against the stored security.refreshTokenHash. As a result, refresh tokens that have been revoked through logout or invalidated through token rotation can continue to be used to obtain new access tokens until the refresh token JWT itself expires.
Steps to reproduce
Log in and obtain an access token and refresh token.
Call POST /api/auth/refresh to rotate tokens.
The original refresh token should now be invalid because a new hash is stored in the database.
Allow the access token to expire.
Send an authenticated request using:
expired access token
original refresh token cookie
Observe that the middleware silently generates a new access token and the request succeeds.
The same behavior occurs after logout if the old refresh token cookie is preserved.
Expected behavior
Refresh-token revocation and rotation should be enforced consistently across all authentication flows.
A refresh token that has been revoked through logout or superseded through rotation should not be able to obtain a new access token, regardless of whether the request uses the explicit refresh endpoint or the middleware's silent-refresh mechanism.
Actual behavior
The explicit refresh endpoint validates refresh-token state against persisted session data, while the middleware silent-refresh flow appears to rely solely on JWT verification.
As a result, revoked or rotated refresh tokens may continue to be accepted until their JWT expiration time is reached.
Screenshots or recordings
No response
Browser and device information
Browser:
Browser version:
Operating system:
Device:
Screen size/resolution:
Additional context
No response