Skip to content

Add chunks for large cookies #527

@jollyekb

Description

@jollyekb

Problem statement

When using OIDC authentication with Keycloak (or other IdPs that include large claims in the ID token), the session cookie can exceed the 4KB browser cookie size limit. This causes the browser to silently reject the cookie, resulting in authentication failure after the OIDC callback redirect. The user successfully logs in but then sees 401 Unauthorized errors because the session cookie is not stored by the browser.

Example from production:

  • Keycloak returns ID tokens with sid, session_state, and other claims
  • Base64-encoded session payload exceeds 4KB
  • Browser rejects the radar_session cookie
  • All subsequent API requests return 401

Proposed solution

Add automatic cookie chunking support that transparently splits large session cookies into multiple smaller cookies when the payload exceeds the safe limit (3800 bytes, leaving headroom for cookie attributes).

Implementation approach:

  1. Cookie creation: When the cookie value exceeds 3800 bytes:

    • If ID token is present, drop it and retry (ID token is only needed for RP-Initiated Logout and can be omitted)
    • If still too large, split the value into chunks of ~3700 bytes each
    • Create chunk cookies named radar_session_chunk_0, radar_session_chunk_1, etc.
    • Create a meta-cookie radar_session_chunks containing the chunk count
  2. Cookie parsing:

    • Check for the main cookie first (for backward compatibility)
    • If not present, look for _chunks meta-cookie
    • Reassemble chunks in order
    • Verify HMAC signature on the reassembled value
  3. Secure flag handling:

    • Set Secure flag based on X-Forwarded-Proto header
    • Use __Secure- prefix for secure cookies
    • Apply to both main cookie and chunk cookies
  4. Fallback behavior:

    • Attempt to drop ID token before chunking (most tokens still fit without ID token)
    • Log warnings when chunking is necessary
    • Last resort: truncate the cookie (with warning) for extremely large cases

Alternatives considered

  1. Server-side session storage with cookie ID only

    • Store session data on server, use random ID in cookie
    • Rejected because: Requires shared session storage (Redis/DB) which adds operational complexity for single-replica deployments
  2. Compress cookie value before storing

    • Use gzip/zstd compression on payload
    • Rejected because: Base64 + compression is unpredictable, may not reduce size enough
  3. Use localStorage + JWT instead of cookies

    • Store session token in localStorage, send in Authorization header
    • Rejected because: Requires significant frontend changes, less secure (XSS vulnerability)
  4. Reduce claims in ID token

    • Configure Keycloak to exclude large claims
    • Rejected because: Not under our control; IdP configuration varies per deployment
  5. Split session into multiple independent cookies

    • Store username in one cookie, groups in another, etc.
    • Rejected because: Complex to manage, increases signature overhead

Additional context

Browser cookie limits:

  • Chrome: 4096 bytes per cookie (RFC 6265 requires browsers to support at least 4096)
  • Firefox: 4097 bytes
  • Safari: 4096 bytes
  • We use 3800 bytes as safe limit to leave room for cookie name and attributes

Current session cookie structure:
radar_session=eyJ1IjoiYWxpY2UiLCJnIjpbImRldnMiXSwiZSI6MTc0N...base64.HMAC-signature

text

Chunked cookie example:
radar_session_chunks=3
radar_session_chunk_0=eyJ1IjoiYWxpY2UiLCJnIjpbImRldnMiXSwiZSI6MTc0NTI...
radar_session_chunk_1=...continuation
radar_session_chunk_2=...continuation

text

Impacted files:

  • pkg/auth/cookie.go - main cookie implementation
  • pkg/auth/auth.go - exports cookie functions
  • internal/auth/middleware.go - authenticates requests
  • internal/auth/oidc.go - sets cookie after OIDC login

Testing done:

  • Unit tests for chunking logic
  • Manual testing with Keycloak
  • Verified cookie size with browser dev tools

pull request #497

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions