Last updated: 2025-12-03
Author: Dick Hardt Email: dick.hardt@hello.coop
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
- Use Cases
- OAuth Redirect Security Threats
- OAuth Example: Before and After
- OAuth Incremental Deployment
- Security and Privacy Considerations
- Feature Discovery
- Implementation Status
- Related Documents
- Acknowledgments
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
Scope: Redirect Headers specifically addresses OAuth and OIDC web-based redirect flows between websites where sensitive parameters are passed via URL query strings. This proposal does NOT address form_post mechanisms where data appears in the DOM, as that attack vector requires different mitigations.
The primary security weakness is in the authorization server's response containing the authorization code in the URL query string. When an AS redirects back to the client with ?code=...&state=..., the authorization code is exposed through multiple vectors:
Known attack vectors:
-
Browser history leakage - Authorization codes stored in browser history can be retrieved by attackers with device access
- Reference: OAuth 2.0 Security Best Current Practice
-
Server log exposure - Authorization codes visible in web server access logs, proxy logs, and load balancer logs
- Codes can be extracted in real-time or from archived logs
-
Referer header leakage - When the callback page loads third-party resources (images, scripts, analytics), the authorization code leaks via the Referer header
- Reference: OAuth 2.0 authentication vulnerabilities
-
Browser-swapping attacks - Attackers exploit scenarios where authorization codes leak through shared URLs or when users switch browsers during the flow
- Discussion: OAuth-WG Browser-Swapping thread
- The core issue: "no technology to reliably verify that the user controlling the client is the same user who logs in to the AS/IdP"
-
URL sharing - Users may inadvertently share URLs containing authorization codes after errors or confusion
-
Analytics and crash reporting - Authorization codes captured by analytics systems, error tracking, and monitoring tools
What Redirect Headers mitigates:
By moving the authorization code from the URL query string to the Redirect-Query header, all of these attack vectors are eliminated. The authorization code never appears in:
- URLs (no browser history exposure)
- Referer headers (no leakage to third parties)
- Server logs (when servers are configured to not log sensitive headers)
- User-visible locations (no accidental sharing)
Important clarification:
The security concern is specifically the authorization server's response with the authorization code. The client's authorization request to the AS (containing client_id, redirect_uri, state) does not have known security concerns from being in the URL, as these parameters are not sensitive credentials. However, moving them to headers provides consistency and reduces URL clutter.
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
Redirect Headers is designed for incremental adoption - each party (client, browser, authorization server) can independently add support, with functionality emerging when all parties support it.
Clients can start sending parameters in both locations:
- URL query string (for backward compatibility)
Redirect-Queryheader (signaling support)
Browsers forward Redirect- headers when present:
- No special detection needed
- Simply forward the headers during redirects
Authorization Servers detect support and respond accordingly:
- If request includes
Redirect-Query→ AS knows both client and browser support it - AS can then send response using only
Redirect-Queryheader (no URL parameters)
Each party adds support independently, in any order:
Clients add support
├─ Send params in URL + Redirect-Query
└─ Look for response in header, fall back to URL
Browsers add support
├─ Forward Redirect-* headers when present
└─ No configuration needed
Authorization Servers add support
├─ Detect support when Redirect-Query received
├─ Confirm: client + browser both support it
└─ Send response ONLY in Redirect-Query (omit URL params)
Result: Once all three support it → authorization code sent in header, not URL
No coordination required - each party adds support independently, and the system naturally converges to the secure behavior once all three support it. The client can immediately start sending both, browsers simply forward headers, and authorization servers detect support from incoming requests.
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
Some protocols may wish to explicitly discover browser support for Redirect Headers before relying on them. While not required for security (backward compatibility ensures graceful fallback), feature discovery can optimize behavior.
Servers can advertise support and request browser capabilities using Client Hints:
Server advertises support:
Accept-CH: Redirect-SupportedBrowser responds with capability:
Redirect-Supported: ?1Once both browser and AS support is confirmed through feature discovery, OAuth clients MAY send parameters only in Redirect-Query, omitting URL parameters entirely. This:
- Reduces URL length
- Prevents any possibility of parameter leakage via URLs
- Maintains backward compatibility (unsupported browsers fall back to URL parameters)
Note: Feature discovery is optional. The incremental deployment model (Section 7) works without explicit discovery - authorization servers detect support by receiving Redirect-Query headers in requests.
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.
- OAuth 2.0 Security Best Current Practice
- OAuth 2.0 Threat Model and Security Considerations (RFC 6819)
- OAuth-WG Browser-Swapping Discussion
- IETF 121 OAuth Meeting Minutes
- OAuth 2.0 authentication vulnerabilities
- Fetch Metadata Request Headers
- W3C Privacy Principles
- Client Hints Infrastructure
The author would like to thank early reviewers for their valuable feedback and insights that helped shape this proposal: Jonas Primbs, Sam Goto, Warren Parad.