skip to content

How does an open redirector on an OAuth 2.0 client or authorization server expose the authorization response?

level: seniorimportance: should knowfreq 45%

answer

  1. an endpoint that forwards where you say
  2. the registered value is itself the redirector
  3. validation passes, then the browser moves again
  4. never take a forward target from the request
  5. an error page, never a redirect

basics

~20 s

An open redirector forwards a browser to a target named in the request. On a client, a perfectly registered redirection endpoint then lands the browser at an attacker's site; on an authorization server, it lends the attacker a trusted hostname.

solid answer

~50 s

RFC 9700 section 4.11 describes two shapes. In the first, the **client** exposes a redirector: a registered redirection endpoint, or a path it hands off to, that forwards the browser to a location named in the request. Validating the registered `redirect_uri` does not help, because the value is registered - it is the endpoint itself that carries the browser onward. If the forward preserves the query, the authorization response goes with it; if it does not, the attacker still gets a hop from a trusted host and a referring URL. In the second, the **authorization server** becomes the redirector by sending the browser to a `redirect_uri` that failed its validation instead of stopping and telling the resource owner. That gives an attacker redirects under the authorization server's own hostname, which is what makes a phishing link credible. The defences are symmetrical: never forward to a target taken from the request, and never redirect when validation fails.

code

http · 5 lines
http
GET /go?next=https%3A%2F%2Fattacker.example%2Fc HTTP/1.1
Host: claims.example.rail

HTTP/1.1 302 Found
Location: https://attacker.example/c

go deeper

for a junior

Know what an open redirector is: an endpoint that sends the browser to a location named in the request, and that such an endpoint on an OAuth client's host is a security defect.

for a middle

Explain why registering the redirect URI does not help - the registered host is the one doing the forwarding - and what the attacker gains even when the query is not copied.

for a senior

Demonstrate both shapes, including the authorization server that redirects on a failed validation, and show the server-side-state fix for a legitimate return-to-page feature.

for a principal

Treat it as a class rather than a bug: define where registrations may live, and make 'no request-supplied redirect targets on a registered host' a standing rule with a recurring test.

## Two open redirectors, one consequence An **open redirector** is any endpoint that takes a destination from the request and sends the browser there. It is a small, common, apparently harmless feature - "return to where you were" after login, a click-tracking hop, a language switcher that preserves the page. In an OAuth 2.0 deployment it stops being harmless, because the browser it is asked to forward is carrying an authorization response. RFC 9700 section 4.11 treats this as its own item precisely because the flaw lives outside the OAuth code entirely. ## Shape one: the client is the redirector The rail operator's delay-repay claim service registers `https://claims.example.rail/oauth/callback` with the ticket retailer's authorization server. Elsewhere on the same host it has a small forwarder used after sign-in: ```http GET /go?next=https%3A%2F%2Fattacker.example%2Fc HTTP/1.1 Host: claims.example.rail HTTP/1.1 302 Found Location: https://attacker.example/c ``` The attacker's leverage is that **redirect-URI validation cannot see this**. Whatever rule the authorization server applies to the registered value, the value is genuinely the client's; the browser arrives where it was supposed to and is then sent on. What the attacker gains depends on how the forward is built: - if the forwarder copies the incoming query onto the target, the authorization response travels with the browser to the attacker's host; - if it does not, the attacker still receives a request whose **referring URL** may be the callback URL, subject to the referrer policy in force; - either way the attacker gets a redirect originating from a hostname users and filters trust, which is the raw material of a convincing phishing chain and of longer attack chains against the same client. The fix is not to sanitise the target. It is to stop taking the target from the request: 1. Resolve the post-login destination from **server-side state** keyed by the session, set before the flow started. 2. Where a parameter is unavoidable, accept only a **relative path** within the application, rejecting anything with a scheme, an authority or a protocol-relative prefix. 3. Keep the redirection endpoint minimal - redeem, establish the local session, redirect to a fixed path. 4. Search the whole registered host for forwarders, not just the OAuth code; the flaw is usually in a page nobody associates with authentication. ## Shape two: the authorization server is the redirector The mirror image is an authorization server that receives a `redirect_uri` it cannot validate - unregistered, malformed, belonging to nobody - and redirects to it anyway, perhaps with an error in the query. That turns the authorization endpoint into a general-purpose redirector under the authorization server's own hostname, and the authorization server's hostname is the one the user has been taught to look for. The rule is the one RFC 6749 already gives for this case: when the redirection URI is missing, malformed or fails validation, the authorization server **must not** automatically redirect. It informs the resource owner directly, on its own page, that something is wrong with the request. An error page is duller than a redirect and it is the correct behaviour. | Shape | Who forwards | What validation misses | Defence | |---|---|---|---| | Client redirector | The client's own host, after the response arrives | The registered value is genuine, so it passes | Never take a forward target from the request | | Authorization server redirector | The authorization endpoint, on a failed request | The failure happens before any check would run | Render an error to the resource owner, never redirect | ## Why this keeps recurring Three properties make it durable. It is **not in the OAuth code**, so an integration review misses it. It **looks like a product feature**, so it is added back after being removed. And it **fails open**: nothing breaks, no error is logged, the flow completes for every legitimate user. So make it a standing check rather than a one-off audit. On any host that holds a registration with an authorization server, treat "takes a URL and sends the browser to it" as a defect class of its own, and test for it with the same regularity you test the login flow itself.

  • If the registered redirect URI is validated strictly, why does a client-side redirector still matter?
    Because validation only decides where the authorization server sends the browser first. The registered endpoint is genuinely the client's, so the check passes; what happens after arrival is the client's own business, and a forward from that host takes the browser - and possibly the response with it - somewhere the authorization server never saw.
  • What should an authorization server do when the `redirect_uri` on a request fails validation?
    Stop and tell the resource owner on its own page. It must not send the browser to the unvalidated location, even to deliver an error, because doing so makes the authorization endpoint a redirector under a hostname users trust.
  • A product team needs a genuine 'return to the page you were on' after linking an account. How do you build it safely?
    Record the destination in server-side state keyed by the session before the flow starts, and look it up after the callback. If a parameter is unavoidable, accept only a relative path with no scheme, no authority and no protocol-relative prefix, and fall back to a fixed page on anything else.
  • Where do these redirectors usually turn up in practice?
    Rarely in the authentication code. They appear in click tracking, language and region switchers, marketing landing pages, help-centre links and legacy paths kept alive for old bookmarks - anywhere on the registered host, which is the scope that matters, not the OAuth module.

saying these in an interview costs you the question

  • Believes registering the redirect URI bounds where the browser ends up
  • Sanitises the forward target instead of not taking one
  • Accepts a protocol-relative target because it has no scheme
  • Thinks an authorization server may redirect to an invalid redirect URI to report the error
  • Looks only in the OAuth code, not across the whole registered host
  • Assumes no harm unless the forward copies the query string