Sessions and Cookies
Generated Auth uses short-lived access JWTs and opaque refresh secrets inside HttpOnly cookies, anchored to server-side session rows.
The browser carries credentials, but the database session remains authoritative.
Session Flow
flowchart LR login["login"] --> row["auth_sessions row"] row --> access["short-lived access cookie"] row --> refresh["opaque refresh cookie"] access --> request["protected request"] refresh --> recovery["access recovery"] recovery --> request
The access token contains user and session identity. It does not replace the persisted session check.
The refresh cookie contains sessionID.secret. Only a hash of the secret is stored.
Expiry Policy
Default policy:
| Setting | Default | Meaning |
|---|---|---|
AUTH_ACCESS_TOKEN_TTL | 15m | Access JWT lifetime. |
AUTH_SESSION_IDLE_TTL | 2h | Maximum session inactivity. |
AUTH_SESSION_TTL | 24h | Normal absolute session lifetime. |
AUTH_REMEMBER_SESSION_TTL | 720h | Remembered absolute session lifetime. |
The earliest applicable expiry wins. A valid access JWT cannot revive an expired, revoked, or idle session.
Refresh Behavior
Protected middleware can recover from a missing or expired access cookie using the current refresh secret. That recovery reissues access state without rotating the refresh secret.
Explicit POST /api/v1/auth/refresh rotates the refresh secret and updates refresh_rotated_at.
Keeping normal middleware recovery separate from explicit rotation prevents concurrent browser requests at the access-token boundary from repeatedly invalidating each other.
Revocation
Generated routes support:
- current-session logout
- logout from all sessions
- session listing
- revoking one owned session
- revoking other sessions after a password change
- revoking sessions after a password reset
Logout and current-session revoke own cookie clearing. An unrelated protected-request 401 does not clear cookies because it may race with newer valid browser state.
Cookie Policy
Generated auth cookies use:
HttpOnly: trueSameSite: LaxSecurefromAUTH_COOKIE_SECURE
Use AUTH_COOKIE_SECURE=true behind production HTTPS. auto is useful when the same App must support plain-HTTP local development and HTTPS deployment.
Generated auth cookies remain host-scoped. This keeps sibling hosts outside the authentication boundary.
CSRF Boundary
SameSite=Lax reduces common cross-site cookie submission, but it is not a complete substitute for request policy.
For browser-authenticated state-changing routes:
- use non-safe HTTP methods
- validate allowed origins where cross-origin traffic is possible
- add CSRF middleware when the deployment accepts cross-site forms or embeds
- keep CORS credentials and allowed origins explicit
- do not expose mutation behavior through
GET
Apply CSRF policy at route or router composition through webmiddleware; do not scatter token validation through business services.
Client Rules
Browser clients should:
- send requests with cookie credentials when crossing origins intentionally
- treat
401as an authentication result, not a reason to mutate cookies directly - avoid storing access or refresh values in local storage
- use session-list and revoke routes for user-visible session controls
Verify Session Policy
Generated Auth includes integration coverage for cookie flags, refresh rotation, replay rejection, expiry, logout, logout-all, session listing, and per-session revocation. Run the focused session and cookie tests after changing auth configuration or middleware:
go test -tags integration ./internal/auth -run \
'Test(LoginSetsSecureCookieDefaults|ControllerLogoutAllRevokesEverySession|ControllerRevokeSessionRevokesOnlyRequestedOwnedSession|RefreshRejectsReplayedRefreshToken)Integration$' \
-count=1Expected result: all four tests pass against the App's test database.
After deployment, use a non-privileged test account to verify login, one protected request, explicit refresh, session listing, and logout. Inspect the response cookies in browser developer tools: both auth cookies remain HttpOnly, production HTTPS cookies are Secure, and logout expires the current credentials. Confirm a request made with the revoked session receives 401; a 200 from the public health endpoint does not prove session revocation works.
Monitor authentication failures and session cleanup through bounded metrics, logs, and Inspects without recording JWTs, refresh secrets, cookie headers, or password material.
Common Mistakes
Common mistakes
- Do not trust a JWT after its session row is revoked or expired.
- Do not persist raw refresh secrets.
- Do not rotate refresh secrets from every concurrent protected request.
- Do not clear cookies from arbitrary middleware failures.
- Do not rely on CORS as CSRF protection.
Next Steps
- Auth describes the full generated component.
- OAuth explains provider-backed login and linking.
- Production Hardening covers deployment policy.
- Middleware explains HTTP middleware placement.