Skip to content

Avoid exposing auth JWTs in OAuth URLs and browser-readable storage #4

Description

@Clouder0

Summary

The OAuth callback returns the master JWT in a URL query parameter, and the frontend stores the token in localStorage plus a JavaScript-written cookie. This increases token exposure through browser history, logs, referrers/telemetry, and XSS.

Evidence

  • OAuth login redirects to /oauth/success?token=...: internal/master/api/oauth/callback.go:147.
  • The success page reads the token from the URL and stores it in localStorage: web/src/app/(auth)/oauth/success/page.tsx:13 and web/src/app/(auth)/oauth/success/page.tsx:21.
  • The same page writes a JS-readable cookie without HttpOnly or Secure: web/src/app/(auth)/oauth/success/page.tsx:22.
  • Password login uses the same localStorage plus JS-readable cookie pattern: web/src/lib/auth.ts:33.
  • API requests read the bearer token from localStorage: web/src/lib/api/client.ts:21.

Risk

Bearer tokens are easier to exfiltrate or accidentally log. Cleaning the URL after the page loads helps, but it does not prevent exposure in the redirect itself or before the client script runs.

Proposed fix

  • Replace query-token delivery with a server-side session exchange, short-lived one-time code, or HttpOnly; Secure; SameSite cookie set by the server.
  • Avoid storing bearer tokens in localStorage.
  • If browser-side bearer tokens remain necessary, document the tradeoff and add strict CSP/XSS hardening.

Acceptance criteria

  • OAuth success redirects no longer include a JWT or long-lived bearer token in the URL.
  • Authentication works without reading the JWT from localStorage.
  • Cookies used for authentication are server-set with HttpOnly, Secure, and an explicit SameSite policy.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions