Last updated: 2025-11-15
Author: Dick Hardt Email: [email protected]
Redirect Headers move sensitive parameters from URLs to HTTP headers during browser redirects:
- Redirect-Query - Redirect parameters (replaces URL query string)
- Redirect-Origin - Browser-supplied origin (enables mutual authentication)
- Redirect-Path - Optional path validation (prevents redirect_uri manipulation)
Why: Authorization codes, tokens, and other sensitive data leak through URLs (browser history, Referer header, logs, analytics). Redirect Headers keep this data in headers that browsers control and don't expose to JavaScript or third parties.
Primary use case: Web server based OAuth/OIDC flows, but works for any protocol using browser redirects (SAML, proprietary auth flows).
SPA, inapp mobile browsers are out of scope of this proposal.
- Introduction
- Problems with Existing Redirect Mechanisms
- Redirect Headers
- 3.1 Redirect-Query
- 3.2 Redirect-Origin
- 3.3 Redirect-Path
- Use Cases
- OAuth Example: Before and After
- Security and Privacy Considerations
- Optimization: Omitting URL Parameters
- Implementation Status
- Related Documents
Authentication and authorization protocols (OAuth, OpenID Connect, SAML) use browser redirects to navigate users between applications and authorization servers. These redirects must carry protocol parameters, which historically appear in URLs or POSTed forms.
Problem: URLs leak sensitive data through browser history, Referer headers, server logs, analytics, and JavaScript access.
Solution: Redirect Headers move parameters into browser-controlled HTTP headers that aren't exposed in URLs or the DOM.
- Parameters appear in the URL
- URLs enter browser history
- URLs are visible to scripts and extensions
- URLs leak via the
Refererheader - URLs are logged in servers, proxies, analytics, crash reporting
- Parameters appear in DOM form fields
- Visible to JavaScript
- POST bodies may be logged or inspected
- Cross-site POST requires
SameSite=Nonecookies
- May be stripped, rewritten, or truncated
- May be removed by privacy tools and enterprise proxies
Redirect Headers solve these limitations.
Three headers work together during top-level 302/303 redirects:
| Header | Set by | Direction | Purpose |
|---|---|---|---|
| Redirect-Query | Server (client or AS) | Both directions | Carry parameters without URLs |
| Redirect-Origin | Browser | Both directions | Mutual origin authentication |
| Redirect-Path | Client | Client → AS | Validate redirect_uri path |
Browser behavior: Only processes these headers during top-level redirects. Ignores them for normal requests or embedded resources.
Carries redirect parameters using URL query string encoding.
Redirect-Query: "code=SplxlOBe&state=123"- Replaces URL query parameters
- Parsed using standard URL query string parsing
- Prevents exposure via browser history, Referer, logs, and analytics
- Set by server (client or AS)
Browser-supplied origin of the page initiating the redirect.
Redirect-Origin: "https://app.example"Properties:
- Set ONLY by the browser (cannot be spoofed by scripts)
- Enables AS to verify which client initiated the request
- Enables client to verify response came from correct AS
- Provides cryptographic mutual authentication (browser-mediated)
Optional path prefix for additional redirect_uri validation.
Client sets:
Redirect-Path: "/app1/"Browser validates:
- Checks current URL path begins with
/app1/ - If valid: includes Redirect-Path in request to AS
- If invalid: omits header (client cannot lie)
AS enforces:
- redirect_uri MUST begin with
Redirect-Origin+Redirect-Path
This prevents redirect_uri manipulation attacks within the same origin.
Primary: OAuth and OpenID Connect
- Authorization code flow
- Implicit flow (though deprecated)
- Hybrid flows
Other authentication protocols:
- SAML assertions
- Proprietary SSO flows
- Any protocol requiring browser-mediated parameter passing
When NOT to use:
- Public, non-sensitive parameters that can appear in URLs
- Server-to-server communication (no browser involved)
- Protocols that don't use browser redirects
Client Website returns to Browser:
HTTP/1.1 302 Found
Location: https://as.example/authorize?client_id=abc&state=123&redirect_uri=...Browser navigates, sends to AS:
GET /authorize?client_id=abc&state=123&redirect_uri=...
Host: as.example
Referer: https://app.example/login ← Unreliable, may be strippedAS returns code to Browser:
HTTP/1.1 302 Found
Location: https://app.example/cb?code=SplxlOBe&state=123 ← Leaked in URLBrowser sends code to Client Website:
GET /cb?code=SplxlOBe&state=123 ← In browser history, logs, analytics
Host: app.example
Referer: https://as.example/consent ← Third-party resources see code via RefererProblems:
- Authorization code appears in URL (history, logs, Referer, extensions)
- No cryptographic origin verification (Referer is optional and unreliable)
Client Website returns to Browser:
HTTP/1.1 302 Found
Location: https://as.example/authorize?client_id=abc&state=123
Redirect-Query: "client_id=abc&state=123"
Redirect-Path: "/app1/"Browser navigates, adds origin and forwards to AS:
GET /authorize?client_id=abc&state=123
Host: as.example
Redirect-Origin: "https://app.example" ← Browser-supplied, cannot be spoofed
Redirect-Path: "/app1/"
Redirect-Query: "client_id=abc&state=123"AS validates and returns to Browser:
HTTP/1.1 302 Found
Location: https://app.example/cb ← No parameters in URL!
Redirect-Query: "code=SplxlOBe&state=123"Browser forwards back to Client Website:
GET /cb ← Clean URL
Host: app.example
Redirect-Origin: "https://as.example" ← Client verifies this
Redirect-Query: "code=SplxlOBe&state=123" ← Not in URL, history, or RefererBenefits:
- Authorization code never appears in URLs
- Mutual origin authentication (browser-verified)
- Backward compatible (browsers/servers without support fall back to URL parameters)
Requirements:
- If Redirect-Query received in request: AS MUST use Redirect-Query for response
- Client MUST verify Redirect-Origin matches expected AS
- AS MUST verify Redirect-Origin matches expected client
- When Redirect-Query is present, client MUST ignore URL parameters and use only header parameters
Security:
- Redirect-Query contains sensitive data - servers MUST treat as confidential
- Browsers MUST prevent JavaScript from reading or setting redirect headers
- Redirect-Path supplements but does NOT replace redirect_uri validation
- Network middleboxes (proxies, load balancers) can still observe headers
- Defense assumes honest browser (cannot protect against browser compromise)
- Transition period: URLs still leak until clients stop sending URL parameters
Privacy:
- Authorization codes and tokens removed from browser history
- No Referer leakage to third-party resources
- No exposure to JavaScript, browser extensions, or DOM inspection
- Reduced logging in analytics, crash reports, and server logs
- User-visible URLs are clean and don't reveal sensitive parameters
For backward compatibility, clients initially send parameters in both URL and Redirect-Query.
Once both browser and AS support is confirmed, clients MAY send parameters only in Redirect-Query.
Detection using Client Hints:
Accept-CH: Redirect-SupportedBrowser responds:
Redirect-Supported: ?1This optimization reduces URL length but isn't required for security benefits.
Specification status: Exploratory draft Browser support: Not yet implemented (proposed specification) Server support: Reference implementations needed
This specification requires:
- Browser vendors to implement header handling
- Authorization servers to support Redirect-Query
- Client applications to adopt the pattern
Deployment strategy: Backward compatible - clients send both URL and headers during transition.