fix(auth): don't expire sessions with the Google ID token - #65
Open
rigwig wants to merge 1 commit into
Open
Conversation
The session cookie stores the Google ID token, and `authenticated` re-verified it on every request and rejected the session once the token's `exp` passed. Google issues ID tokens for about an hour, and nothing refreshed them, so every client — app.jetkvm.com included — was signed out roughly an hour after login regardless of activity, even though the cookie's maxAge is 24h. The token was already verified (signature, issuer, audience) by openid-client in the OIDC callback, and the cookie is signed with COOKIE_SECRET, so the per-request JWKS verification only served to enforce a lifetime that was never meant to be a session lifetime. Replace it with a real session policy: - idle timeout: the cookie's existing 24h maxAge, now actually rolling — `authenticated` touches `lastActiveAt` (at most every 5 minutes) so cookie-session re-issues the cookie while the session is in use; - absolute lifetime: 30 days from `authenticatedAt`, set at sign-in. Sessions issued before this change fall back to the token's `iat`. The client WebSocket upgrade path now applies the same check via getActiveSession() instead of accepting any cookie that carries a token. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related: jetkvm/kvm#1530
Summary
Cloud sessions currently die about an hour after sign-in, regardless of activity, because
authenticatedre-verifies the Google ID token stored in the session cookie on every request and rejects it once the token'sexppasses. Google issues ID tokens for ~1h and nothing refreshes them, so the cookie'smaxAge: 24hnever actually applies — every client (app.jetkvm.com included) is signed out hourly. This PR replaces the token-expiry check with a real session policy.What changed
authenticatedno longer callsjwtVerifyagainst Google's JWKS. The token was already verified (signature, issuer, audience) by openid-client in/oidc/callback, and the cookie is signed withCOOKIE_SECRET— so the per-request verification only served to enforce a lifetime that was never meant to be a session lifetime (and cost a JWKS fetch per process).maxAge, now actually rolling:authenticatedtouchessession.lastActiveAt(at most every 5 minutes) so cookie-session re-issues the cookie while the session is in use.session.authenticatedAt, set in the OIDC callback. Sessions issued before this change fall back to the token'siat, so nobody is logged out by the deploy.authenticateClientRequest) now goes through the samegetActiveSession()check instead of accepting any cookie that carries a token.ALLOWED_IDENTITIES) is unchanged.How to verify
id_tokento one with a pastexp), callGET /me— 200 instead of 401.Set-Cookie: session=…at most once per 5 minutes.authenticatedAtolder than 30 days gets 401.Checklist
npm run buildandnpm testpass locally (61 tests, 8 new intest/auth.test.tscovering the middleware andgetActiveSession)Context: I maintain JetPilot, an iOS client for JetKVM that talks to this API, and the hourly sign-out is the top complaint from users. Happy to adjust the lifetimes or make them configurable if you'd prefer.