Skip to content

Conversation

@maxdinech
Copy link

What kind of change does this PR introduce?

Bug fix - Security hardening

What is the current behavior?

Token endpoints (password grant, refresh token, PKCE, MFA, etc.) do not set Cache-Control headers in their responses. This allows browsers to cache JWT token responses containing sensitive credentials.

Security Impact:

  • Browsers like Firefox cache token responses in about:cache
  • Attackers with physical access to a machine can extract cached JWT tokens
  • Violates OAuth 2.0 RFC 6749 Section 5.1 which requires Cache-Control: no-store

Issue discovered during professional security audit (OWASP OTG-AUTHN-006)

Affected endpoints:

  • /token?grant_type=password (password login)
  • /token?grant_type=refresh_token (token refresh)
  • /token?grant_type=pkce (OAuth PKCE flow)
  • /token?grant_type=id_token (OIDC)
  • /token?grant_type=web3 (Web3 authentication)
  • /verify (email/phone verification)
  • /signup (user registration)
  • MFA endpoints (TOTP, phone, WebAuthn)
  • Anonymous signup

What is the new behavior?

All token endpoints now return proper cache control headers:

Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache

Implementation:

  • Added sendTokenJSON helper function in internal/api/helpers.go
  • Updated all 12 token-returning endpoints to use sendTokenJSON instead of sendJSON
  • Follows existing pattern (JWKS and SAML endpoints already set custom Cache-Control headers)

Browsers will no longer cache token responses, preventing exposure of JWT tokens through browser cache inspection.

Additional context

Testing performed:

  • make format passed
  • make vet passed
  • ✅ All existing tests pass
  • Verified headers are correctly set on token responses

References:

This change affects all authentication flows but is backward compatible - it only adds headers, doesn't modify response bodies or behavior.

…caching

Token endpoints (password grant, refresh token, PKCE, MFA, etc.) were
missing Cache-Control headers, allowing browsers to cache JWT tokens
in memory. This violates RFC 6749 Section 5.1 which requires token
responses to include 'Cache-Control: no-store'.

Security Impact:
- Browsers like Firefox cache token responses in about:cache
- Attackers with physical access can extract cached JWT tokens
- Leads to potential session hijacking

Changes:
- Add sendTokenJSON helper function with no-store cache headers
- Update all token-returning endpoints to use sendTokenJSON
- Covers password, refresh, PKCE, MFA, OIDC, Web3, anonymous, signup, and verify flows

Fixes discovered during professional security audit (OWASP OTG-AUTHN-006).
@maxdinech maxdinech requested a review from a team as a code owner October 18, 2025 14:03
Comment on lines +23 to +24
w.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate")
w.Header().Set("Pragma", "no-cache")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These apply just in general to all Auth requests, so maybe it can be added as middleware?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants