Repository navigation
fix(backend:auth): enforce link expiration on token refresh - #315
Conversation
|
@tynianov1, thanks for the fix. We already have
The same boundary should be preserved during refresh. The refresh flow already keeps the refresh token’s absolute The CSRF cookie should use the same maximum session boundary for consistency. For links without an expiration date, the existing configured lifetimes would remain unchanged. This approach removes the additional database query on every refresh and makes the expiration established at authentication time an immutable security boundary. Extending the link later would not extend already-issued sessions; the link user would need to authenticate again. |
…d of a refresh DB check Cap every token and cookie of a link session to the link expiration at authentication, so the whole session is bounded by the link itself with no database read on refresh. The refresh token then carries that boundary, and refreshing can never extend a session past it. Also cap the access token and the CSRF cookie to the remaining refresh lifetime on refresh for all users, so a refreshed access token never outlives its session.
|
hi @johaven At link authentication I pass link.expiresAt to setCookies and cap every token and cookie to min(configured lifetime, expiresAt - now), using the same instant the existing check uses (new Date() >= expiresAt), so the refresh token carries the boundary and refresh needs no DB read. Access and CSRF are now also capped to the remaining refresh lifetime on refresh for all users. |
|
Thanks for the update! Let's handle WebSocket disconnection in a separate PR 😊 The CLA is back up and running, and I'll take a look at your PR soon! |
|
@johaven CLA website is still doesn't work for me. Is there anything else needed from my side for this PR? |
|
@tynianov1 Could you retry with CLA website, it seems ok now. |
|
@johaven should be done now |
|
@tynianov1, I grouped the link expiration fixes into one commit. Expiration is now checked atomically when consuming an access, and no session is created once the expiration boundary has been reached. I also added coverage for expiration race conditions and updated the related documentation. If this looks good to you, we can merge. |
Preserve link session expiration bounds while incorporating the API token restrictions for link accounts.
|
@johaven in my opinion it's looking good, we can merge it |

What was happening
A public link has an optional expiration date (
expiresAt). That date is only checked incheckLinkon the/links/*entry points. When a visitor opens a link, a dedicated link user (USER_ROLE.LINK) is created and receives access and refresh cookies. After that, requests go through the normal authenticated API and the link is never checked again.So once a link expired, an already open session kept working. The refresh token re-issues access tokens while keeping its original expiration (an absolute cap of 4h by default, measured from session creation), so the expired link kept access for up to that cap plus one access token lifetime (about 15m).
What changed
On token refresh, when the authenticated user is a link user (
USER_ROLE.LINK), the refresh now loads that link and rejects the refresh if the link has expired. The check lives inAuthTokenRefreshStrategy, the single validation point shared by both refresh endpoints:POST /auth/refresh(web client) andPOST /auth/token/refresh(desktop client).The expiration comparison is the exact one already used by
checkLink. It has been extracted into a small helper (isLinkExpired) so both paths use the same logic and cannot drift.Effect: an expired link session stops being refreshed, so it ends within one access token lifetime (about 15m) instead of lasting until the refresh token cap.
What was intentionally not changed
limitAccesswas left as is (one access equals one session), as agreed.SpaceGuardwere not touched.Notes
How it was tested
nest build, tsc) reports no issues.This was discussed and agreed with the maintainer beforehand.