Redesign auth: Auth0-managed sessions replace self-minted JWTs#257
Draft
baely wants to merge 6 commits into
Draft
Redesign auth: Auth0-managed sessions replace self-minted JWTs#257baely wants to merge 6 commits into
baely wants to merge 6 commits into
Conversation
Previously Auth0 was only consulted at the moment of login; the app then minted its own 30-day HS256 JWT with a static SIGNING_KEY. Nothing could revoke or refresh a login once issued. Auth0 now manages the login token lifecycle: - Login requests the offline_access scope, so Auth0 issues a rotating refresh token alongside the ID token. - The cookie holds only an opaque session ID; the Auth0 token set lives server-side in Redis (30-day absolute lifetime, matching Auth0's default refresh-token expiry). - When the token expires, the session is refreshed against Auth0 -- so revoking a user's grant at Auth0 ends their session at the next refresh. Concurrent refreshes single-flight through a Redis lock so rotation isn't burned. - Logout revokes the refresh token at Auth0's revocation endpoint and deletes the session, rather than just dropping the cookie. - The HS256 JWT machinery, SIGNING_KEY config and golang-jwt dependency are removed. Session cookies are now Secure on https and SameSite=Lax. The local OIDC mock now allows offline access so the dev login flow can exercise refresh and revocation. Existing logins are invalidated on deploy (old JWT cookies no longer resolve); users log in once to get a session. The Auth0 application must have the Refresh Token grant enabled, with rotation recommended. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Re-expresses the cookie rename (#263) in session terms: sessions are issued under the env-specific 'user' name, legacy __session cookies are still accepted for lookup, and MigrateLegacyCookie re-issues the same session ID under the current name instead of minting a JWT. Logout resolves the session from either cookie name before revoking at Auth0. The JWT machinery main still carried stays deleted, along with the golang-jwt dependency. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The GitHub update-branch merge resolved the same conflicts by keeping the __session-only cookie name and the golang-jwt dependency, which would regress the #263 rename on merge to main. This keeps the resolution that preserves #263: env-specific 'user' cookie, legacy __session accepted and migrated, JWT machinery and dependency removed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * origin/auth0-token-redesign:
Refresh failures are now classified: a definitive rejection (4xx, e.g. invalid_grant for a revoked grant) still ends the session immediately, but timeouts, connection failures and 5xx responses serve the stale session within a 24-hour grace window, retrying the refresh at most once a minute so an outage doesn't add the Auth0 timeout to every request. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Beta runs at debug level so per-request auth timings are visible: auth resolution in the middleware (total added latency per request), session store get/set, and the Auth0 refresh call. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
What
Auth0 was only consulted at the moment of login — the callback verified the ID token, then minted a home-grown 30-day HS256 JWT signed with a static
SIGNING_KEY. Nothing could refresh or revoke a login, and logout just dropped the cookie.Auth0 now manages the login token lifecycle:
offline_accessscope, so Auth0 issues a rotating refresh token alongside the ID token.internal/auth/session.go) with a 30-day absolute lifetime, matching Auth0's default refresh-token expiry./logoutand/auth/logout.SIGNING_KEYconfig andgolang-jwtdependency are removed. Session cookies are nowSecureon https andSameSite=Lax. API secrets and the mobile native exchange are unchanged.Deployment notes
AllowOfflineAccess: true.SIGNING_KEYis no longer read. The deploy workflows still inject it (harmless); left for a later clean-up since fix: stats-collector secret names + render last-updated in Melbourne time #246 has pending workflow changes.Verification
go build,go vet, fullgo test ./...green; new unit tests cover session round-trip, refresh + rotation, refused refresh, concurrent-refresh coordination and logout revocation against a fake Auth0 tenant.🤖 Generated with Claude Code