skip to content

questions

4

When an HTTP client follows a redirect, which parts of the original request does it send again, and why do clients strip the `Authorization` header when the redirect points to a different origin?

level: middleimportance: must knowfreq 55%

answer

  1. Redirect = brand-new request, not a continuation
  2. Host recomputed; ordinary headers copied
  3. Authorization dropped cross-origin (scheme/host/port change)
  4. Cookies re-derived from the jar, not copied
  5. Body only re-sent if the method is preserved; non-replayable bodies break

basics

~20 s

Most request headers are re-sent to the new URL, and the body is re-sent only when the redirect preserves the method. Host is recomputed. Credentials are the exception: clients drop Authorization (and proxy credentials) on a cross-origin redirect so a redirect cannot leak your token to another host.

solid answer

~60 s

On following a redirect the client builds a **new request** to the resolved `Location`: - **Ordinary headers** (`Accept`, `User-Agent`, custom headers) are carried over. - **`Host`** is recomputed for the new authority - never copied. - **The body** is re-sent only if the redirect preserves the method; when the client rewrites the request to a bodyless GET, it also drops `Content-Length`, `Content-Type` and any body. - **`Cookie`** is not copied. The cookie jar is re-consulted for the new URL, so cookies scoped to the new domain and path are attached and others are not. - **`Authorization`** is dropped when the redirect crosses to a different origin (scheme, host, or port change). The reason is credential leakage: a redirect target is chosen by the *server*, not the user. If a compromised or merely misconfigured endpoint returned `Location: https://attacker.example/`, and the client faithfully forwarded the bearer token or Basic credentials, the token would be handed to a third party in one hop. Stripping on cross-origin makes the credential's blast radius the origin it was issued for.

code

http · 11 lines
http
GET /files/1 HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOi...

HTTP/1.1 302 Found
Location: https://files.cdn.example/blob/1?sig=abc

(next request - no Authorization)
GET /blob/1?sig=abc HTTP/1.1
Host: files.cdn.example
Accept: */*

go deeper

for a junior

Know that following a redirect issues a new request, that most headers carry over, and that Authorization is not sent to a different host.

for a middle

Explain the full set: Host recomputed, cookies re-derived from the jar, body only when the method is preserved, and the credential-leak reason for stripping Authorization.

for a senior

Diagnose the resulting production symptoms - 401 after redirect, SameSite login loops, uploads that cannot be replayed - and design handoffs with signed URLs instead.

for a principal

Set the policy: authenticated endpoints should not redirect across origins at all; define how authority is delegated (signed URLs, token exchange) and audit client libraries for their credential-forwarding defaults.

## Following a redirect means issuing a new request A redirect is not a continuation of the original request - the client constructs a fresh request to the resolved `Location`. What it copies is a policy decision, and the policy is deliberately conservative about anything that carries authority. ## What is copied **Ordinary headers.** `Accept`, `Accept-Language`, `User-Agent`, `X-Request-Id` and application-specific headers are carried over. This is what makes redirects usable at all: an API client does not have to rebuild its request. **Method and body.** Whether the method survives depends on the status code used, which is the redirect codes topic's material. Mechanically, what matters here is the consequence: if the client rewrites to GET, it must also strip the body and its `Content-Length` / `Content-Type` headers, and any `Expect: 100-continue` negotiation is redone. If the method is preserved, the client must re-send the entire body - which is why a client streaming a large upload from a non-replayable source can fail to follow a redirect at all: it no longer has the bytes. Well-designed upload APIs therefore avoid redirecting POST/PUT, or redirect before the body is consumed. **Host.** Always recomputed from the new authority. Copying the old `Host` would send a request for the wrong virtual host. ## What is dropped, and why **Authorization.** RFC 9110 explicitly warns that credentials must not be forwarded to a different origin. Every mainstream client implements this: browsers, curl (which requires the explicit `--location-trusted` to override), and most language HTTP clients drop `Authorization` when the redirect changes scheme, host, or port. The threat model is simple. The client trusts the token to `api.example.com`; the redirect target is chosen by whatever answered that request. If that server is compromised, misconfigured, or accepts an attacker-controlled `?next=` parameter (an open redirect), forwarding the credential turns a redirect into credential exfiltration. The same reasoning applies to `Proxy-Authorization`, which is scoped to a specific proxy hop. A subtlety: some clients drop `Authorization` on *any* redirect, some only on cross-origin, and some (historically) leaked it on same-host scheme changes. Do not rely on a specific library's nuance; test it. **Cookie.** Cookies are not copied header-to-header at all in a cookie-aware client. The jar is re-evaluated against the new URL, so `Domain`/`Path`/`Secure`/`SameSite` attributes decide what is attached. A cross-site redirect can therefore drop session cookies for reasons unrelated to redirect policy - notably `SameSite=Lax`, where a cookie is sent on a top-level GET navigation but not on a cross-site POST. This is behind a lot of "login redirects in a loop only in Chrome" bug reports. **Referer.** Set to the redirecting URL (subject to referrer policy), not carried over. On a downgrade from https to http, browsers omit it entirely. ## The symptoms this produces - **401 after a redirect.** Your API call to `api.example.com` redirects to `cdn.example.com`; the token was stripped; the second host answers 401. The fix is to stop redirecting across origins for authenticated calls, or to use a credential the target accepts (typically a pre-signed URL with the authority in the query string - which is exactly why object stores use signed URLs). - **"It works with curl but not from the browser"** or vice versa - different default policies for credentials, cookies and redirect limits. - **Large upload fails on redirect** - non-replayable body. ## Designing around it For authenticated APIs, prefer stable URLs over redirects, and never redirect an authenticated POST to another origin. When you must hand off to another host, hand off authority explicitly: a short-lived signed URL, or a token exchange, rather than hoping the client forwards a header it is right not to forward. On the client side, if you genuinely need credentials to survive a cross-origin hop (curl's `--location-trusted`), restrict it to a pinned, trusted target - it is a deliberate weakening of a security default.

  • Cookies are not copied from the original request either. What decides whether a cookie is sent to the redirect target?
    The cookie jar is re-evaluated against the new URL, so the cookie's Domain, Path, Secure and SameSite attributes decide. A cookie scoped to api.example.com is simply not in scope for cdn.example.com. SameSite matters too: a Lax cookie is sent on a cross-site top-level GET navigation but not on a cross-site POST, which is a frequent cause of login redirect loops.
  • How would you design an authenticated API that must hand a client off to a different host for a file download?
    Do not rely on the client forwarding credentials - it should not. Issue a short-lived pre-signed URL that carries its own authority in the query string, and redirect to that. The target host validates the signature and expiry rather than a bearer token, so nothing sensitive and long-lived crosses the origin boundary, and the URL expires quickly if it leaks.
  • Why can a large streaming upload fail when the server responds with a method-preserving redirect?
    Following it requires re-sending the entire body, but a client streaming from a socket, a generator, or a consumed input stream may no longer have those bytes and cannot rewind. Clients then either fail the redirect or silently send nothing. The practical rules are to redirect before the body is consumed, to avoid redirecting uploads across origins, or to buffer/re-open a replayable body source.

Handing your building pass to a receptionist who says "go to the other company down the street". You walk over, but you do not hand the other company your pass - it was issued for this building only.

saying these in an interview costs you the question

  • Assuming the client forwards Authorization everywhere, then blaming the target for 401s
  • Thinking cookies are copied from the original request headers rather than re-derived from the cookie jar
  • Copying the original Host header to the redirect target
  • Assuming a POST body is always re-sent on any redirect
  • Recommending curl --location-trusted or disabling credential stripping as a general fix

context

open as a page

A redirect response arrives with the HTTP header `Location: /v2/users?page=2` instead of a full URL. How does the client work out the exact URL to request next, and what rules govern that resolution?

level: juniorimportance: should knowfreq 42%

basics

~20 s

The Location value may be a relative reference. The client resolves it against the URL of the request that produced the redirect, inheriting scheme, host and port, then applies normal URI resolution rules - so /v2/users?page=2 becomes https://api.example.com/v2/users?page=2.

open as a page

A page never loads and the logs show a long chain of 30x responses. How do HTTP clients detect and stop redirect loops, and what are the usual server-side causes?

level: seniorimportance: should knowfreq 38%

basics

~20 s

HTTP defines no loop limit, so clients impose a maximum hop count - typically 20 in browsers, 30 in curl, and configurable in libraries - and abort with a too-many-redirects error. Typical causes: https-redirect rules behind a TLS-terminating proxy, trailing-slash rewrites fighting each other, and login redirects where the session cookie never sticks.

open as a page

Your backend service calls third-party URLs with an HTTP client that automatically follows redirects. What controls would you place on that redirect-following behaviour before shipping it?

level: seniorimportance: should knowfreq 30%

basics

~20 s

Cap the number of hops, re-run your URL validation on every hop (a redirect bypasses the check you did on the first URL), refuse scheme downgrades and private or link-local addresses, verify credentials are dropped cross-origin, and apply a total time budget across the chain - or disable auto-follow and handle redirects yourself.

open as a page