Quick answer
An HTTP client that follows redirects automatically can carry your credentials to a host you never intended to trust. When a 302 or 307 points at a different domain, a client that blindly re-attaches the same Authorization header leaks a bearer token to that host, and the behavior differs between redirect types because only some preserve the original method and body. Do not rely on the default redirect policy for authenticated requests. Pin which hosts are allowed to receive credentials, strip the authorization header on cross-origin redirects, and understand the difference between 302 and 307 so you are not surprised by a method change or a dropped body.
What the credential leak looks like
A request to your API is redirected to a file store or a partner host to complete the operation.
The redirect is often legitimate, but the token scoped to your API is not meant for the partner host. If the client applies the same headers to every hop without checking the destination, the secret is exposed in the other service's logs and trust boundary.
Why redirect statuses confuse the behavior
Not all redirects are equal, and clients historically diverge on how they handle them. A 302 commonly causes a POST to be reissued as a GET, which can drop the body, while a 307 and 308 are defined to preserve the method and body. A 301 and 302 may be cached and rewritten by intermediaries. If you assume a redirect simply re-sends the identical request, you will be wrong about the method, the body, or the headers depending on the status and the client.
| Redirect status | Typical method handling | Credential concern |
|---|---|---|
| 301 / 302 | POST often becomes GET | Body may be dropped; headers may follow |
| 307 / 308 | Method and body preserved | Same request shape, headers may follow |
| Meta or script redirect | New request constructed by the client | Headers usually not inherited |
Controlling redirects for authenticated calls
Disable automatic redirects for sensitive requests, or configure a policy that evaluates each hop's destination before deciding what headers to send. Credentials should only be attached to an allow-listed set of hosts; a cross-origin redirect either gets a host-specific credential or no authorization header at all.
Handling the redirect explicitly makes the trust decision visible in code rather than buried in a default. It also gives you a place to assert the method and body are preserved when using 307, rather than discovering a 302 turned a POST into a GET.
Beyond the Authorization header
Bearer tokens are the obvious target, but they are not the only sensitive data a client can carry across a redirect. Session cookies are attached automatically based on the cookie's domain and scope, so a redirect to a host in the same registrable domain can still inherit a cookie the developer did not think about. Custom headers such as X-API-Key, signed request signatures, and headers carrying personally identifiable information have the same problem and need the same allow-list treatment. Also consider the reverse direction: a page that issues a cross-origin request may leak the originating URL, including query parameters, through the Referer header, so a strict referrer policy complements the redirect rules. The general principle is to treat every header and cookie as scoped to a trust boundary, and to re-evaluate what belongs on each hop rather than copying the entire header set by default.
Server-side responsibility
Clients are not the only place to fix this. The server should avoid redirecting authenticated clients to untrusted hosts while expecting the same token, and prefer short-lived, scoped credentials for the destination resource rather than forwarding the user's primary token. If a redirect genuinely crosses an organization boundary, issue a purpose-limited token for that host. Document the redirect contract, including which status is used and whether the client should follow it, so the behavior is designed rather than accidental.
Testing the redirect path
Add tests that return a redirect to a different host and assert the outgoing follow-up request does not contain the original bearer token, and a separate test for same-host redirects confirming the credential is retained. Verify the method and body handling for both 302 and 307 so the distinction is explicit. These tests catch a regression where a client upgrade restores default automatic redirects and silently re-attaches credentials.
FAQ
Is it always wrong to send credentials on a redirect?
Not always. A same-host redirect to a trusted endpoint can legitimately keep the credential. The problem is cross-origin forwarding. Use an allow-list so trusted hosts keep appropriate credentials and unknown hosts never receive the primary token.
What is the safest way to let a client reach a partner host?
Issue a short-lived, scoped token intended for that specific resource rather than forwarding the user's main bearer token. That limits the blast radius if the partner-side credential leaks.
Why did my POST become a GET after the redirect?
That is the common historical behavior for 301 and 302 responses. If you need the method and body preserved, use 307 or 308, and configure the client to confirm the request shape rather than assuming.
Should I just disable redirects globally?
That can break ordinary benign redirects and push manual handling everywhere. Better to keep automatic redirects for anonymous requests and apply explicit, host-aware policies specifically for authenticated calls.
This is part of the Powerduck vs Insomnia: API Client and Contract Testing — start there for the full picture of keeping an API client safe and predictable.
