skip to content

HTTP defines both 401 Unauthorized with WWW-Authenticate and 407 Proxy Authentication Required with Proxy-Authenticate. What is the difference, and which request header answers each?

level: middleimportance: should knowfreq 40%

answer

  1. 401 origin, 407 proxy
  2. Authorization end-to-end
  3. Proxy-Authorization hop-by-hop, stripped
  4. reverse proxy issues 401 not 407
  5. CONNECT tunnel = proxy auth moment

basics

~20 s

401 plus WWW-Authenticate comes from the origin server (or a gateway acting as one) and is answered with Authorization, which travels end to end. 407 plus Proxy-Authenticate comes from the intermediary proxy you are talking to and is answered with Proxy-Authorization, which that proxy consumes and removes.

solid answer

~60 s

They are the same challenge-response mechanism applied at two different hops. - **401 + `WWW-Authenticate`** is the **origin server** saying "you have not authenticated to *me*". The client answers with **`Authorization`**, which is an end-to-end field: it passes through proxies untouched and is meant for the resource owner. - **407 + `Proxy-Authenticate`** is the **intermediary** — a forward proxy the client was configured to use — saying "you have not authenticated to *this hop*". The client answers with **`Proxy-Authorization`**, which is **hop-by-hop**: the proxy consumes it, strips it, and does not forward it upstream. Both use the identical grammar (scheme, optional realm and other params) and the identical IANA scheme registry. A client can be challenged by both at once and end up sending both headers on one request, with different credentials. Gotcha: a **reverse** proxy or API gateway sits in front of the origin and speaks *for* it, so it issues **401**, not 407. 407 is essentially a forward-proxy or corporate-egress phenomenon; `CONNECT` tunnels are its most common home.

code

http · 11 lines
http
CONNECT api.example.com:443 HTTP/1.1
Host: api.example.com:443

HTTP/1.1 407 Proxy Authentication Required
Proxy-Authenticate: Basic realm="corp-egress"

CONNECT api.example.com:443 HTTP/1.1
Host: api.example.com:443
Proxy-Authorization: Basic ZW1wOnNlY3JldA==

HTTP/1.1 200 Connection Established

go deeper

for a junior

Know which header pairs with which status and that one is for the server you are calling, the other for a proxy in between.

for a middle

Explain end-to-end versus hop-by-hop, that the proxy strips Proxy-Authorization, and that both share the same scheme grammar.

for a senior

Bring the operational split: reverse proxies must issue 401, forward proxies 407, CONNECT is where HTTPS proxy auth happens, and both credential headers need log redaction.

for a principal

Discuss where authentication should terminate in the topology — edge gateway versus service — and the blast radius of credentials that traverse intermediaries versus ones consumed at the hop.

## Two hops, one mechanism RFC 9110 splits authentication by *who is asking*. The framework, the grammar, and the scheme registry are shared; only the header names and the status code change. | Asking party | Status | Challenge header | Credential header | Scope | |---|---|---|---|---| | Origin server (or reverse proxy speaking for it) | 401 | `WWW-Authenticate` | `Authorization` | end-to-end | | Intermediary the client connects through | 407 | `Proxy-Authenticate` | `Proxy-Authorization` | hop-by-hop | ## Why 'hop-by-hop' is the whole point `Authorization` is addressed to the resource owner. Intermediaries forward it unchanged, which is exactly why a shared cache must not reuse such a response for a different user, and why leaking `Authorization` across a redirect to another host is a real credential-disclosure bug (well-behaved clients drop it on cross-origin redirects). `Proxy-Authorization` is addressed to the immediate next hop only. That proxy validates it and **removes it before forwarding**; if it passed it on, the corporate proxy password would arrive at the origin. Chained proxies each challenge for themselves. The same hop-by-hop rule is why these fields must never be cached or replayed upstream. ## Where you actually meet 407 - A laptop configured with a corporate forward proxy: the very first request returns `407 Proxy Authentication Required` with something like `Proxy-Authenticate: Negotiate` or `Basic realm="corp-proxy"`. - `CONNECT` tunnels for HTTPS: the client authenticates to the proxy on the CONNECT request itself, because once the TLS tunnel is up the proxy can no longer read or inject headers. This is why proxy auth for HTTPS is a `Proxy-Authorization` on CONNECT, and why a proxy that only supports 407 on plain HTTP breaks TLS traffic. - Tooling: `curl --proxy-user`, `HTTPS_PROXY` credentials, JVM `http.proxyUser` — all of these fill `Proxy-Authorization`, not `Authorization`. Mixing them up is a classic wasted afternoon. ## Reverse proxies do not use 407 A CDN, API gateway, ingress controller or load balancer in front of your service is a **reverse** proxy: to the client it *is* the origin. When it enforces auth it must return **401 with WWW-Authenticate**. Returning 407 there tells the client "go authenticate to your local proxy", which the client cannot act on and which some clients report as a network-configuration error. This distinction is the point of the question in most interviews. ## Both at once Nothing forbids being challenged by both: a request may carry `Proxy-Authorization: Basic ...` for the egress proxy and `Authorization: Bearer ...` for the API. The proxy strips the first and forwards the second. If your gateway logs headers, note that both are secrets and both belong on a redaction list. ## Diagnostics - Client reports 407 but you never deployed a proxy: the client environment has one (`HTTP_PROXY`, PAC file, corporate MDM). Nothing on your side can fix it. - Credentials sent as `Authorization` are ignored and the 407 repeats: wrong header — the proxy only reads `Proxy-Authorization`. - Auth works over HTTP but not HTTPS through the same proxy: the proxy is not handling authentication on `CONNECT`. - 407 responses that lack `Proxy-Authenticate` are as broken as 401s that lack `WWW-Authenticate`; the client cannot know which scheme to attempt. ## Status-code hygiene Both codes mean *unauthenticated at that hop*. Neither means "authenticated but not permitted" — that is 403 for the origin. And a proxy that refuses an authenticated client for policy reasons returns 403 too, not a repeated 407.

  • Your API gateway rejects unauthenticated calls with 407. Why is that wrong?
    The gateway is a reverse proxy: to the caller it is the origin server, so the correct refusal is 401 with WWW-Authenticate. 407 tells the client to authenticate to its own forward proxy, which the client either cannot do or will do against the wrong party. Clients and SDKs commonly surface 407 as a local network-configuration failure rather than an auth failure.
  • Why must Proxy-Authorization not be forwarded upstream?
    It is a hop-by-hop credential meant only for the proxy that issued the 407. Forwarding it would disclose the proxy password to the origin and to every later hop, and it would be meaningless there since the origin has its own protection space. Each proxy in a chain challenges and consumes its own credentials.

saying these in an interview costs you the question

  • Claiming Proxy-Authorization travels end to end like Authorization
  • Having a CDN, ingress or API gateway return 407 for a missing API token
  • Saying 407 means the user lacks permission — it means the hop is unauthenticated, permission failures are 403
  • Assuming the two use different credential grammars or a different scheme registry
  • Thinking proxy authentication for HTTPS happens on the inner request rather than on CONNECT

context