This article describes a critical OAuth vulnerability where loose redirect_uri validation allows attackers to intercept login authorization codes. The lab demonstrates how substring-based checks—validating that a redirect_uri merely contains a trusted domain rather than matching it exactly—can be bypassed by crafting URLs under attacker control that still pass the weak validation. This matters because the authorization code can be exchanged for full account access, making redirect_uri validation a fundamental security boundary in OAuth flows.
- Substring validation fails completelyAuthHub accepts any redirect_uri containing the string 'trustedclient.com' anywhere within it, without anchoring to the host start or comparing against an exact pre-registered value. This allows URLs like 'trustedclient.com.attacker.example' or paths on attacker hosts to pass validation, because the substring match succeeds even though the actual destination is attacker-controlled.
- How the attack works in practiceAn attacker constructs a URL containing the trusted domain as a subdomain label or in the path, then initiates the OAuth flow with this malicious redirect_uri. The weak substring check passes, the user approves login, and the authorization code is sent to the attacker's destination instead of the legitimate app, where it can be intercepted and exchanged for account access.
- Authorization code becomes account takeover vectorBecause the authorization code can be exchanged for access to the user's account, controlling where it is delivered is equivalent to controlling account access. The redirect_uri is the final step ensuring the code reaches only the real application, making loose validation a direct path to account compromise.
- Correct validation requires exact matchingThe OAuth specification mandates exact string matching of the redirect_uri against a pre-registered value, anchored to the full scheme, host, and path. Substring checks, unanchored 'starts-with' checks, and other partial matching strategies are all bypassable and must be rejected entirely.
- Real-world prevalence and impact mappingLoose redirect_uri validation is documented as a recurring source of OAuth account-takeover reports because developers often choose the shortcut of substring validation. The OWASP Top 10 (2021) maps this vulnerability to Broken Access Control (A01) and Security Misconfiguration (A05), reflecting its significance in production systems.
- PKCE provides defense-in-depth but not primary fixThe article notes that PKCE (Proof Key for Code Exchange) reduces the damage of a stolen code but does not replace exact redirect_uri matching. Both controls must be implemented together; PKCE alone is insufficient to prevent redirect_uri bypass attacks.
- Testing approach for security assessmentWhen authorized to test OAuth systems, probe the redirect_uri validation by using your own domain while carrying the trusted string as a subdomain or path element. If the provider accepts such a URL, the matching logic is too loose and requires remediation.
Bottom line: OAuth redirect_uri validation must perform exact string matching against a pre-registered value anchored to the full scheme, host, and path; any substring, prefix, or partial matching approach enables attackers to redirect authorization codes to attacker-controlled destinations and compromise user accounts. Defenders must reject loose validation patterns entirely and treat exact matching as a non-negotiable requirement, not a nice-to-have optimization.
redirect_uri merely contains the string trustedclient.com. A substring check feels close enough — but 'contains' is not 'is', and that gap is enough to ship the login code to an attacker.📋 In this walkthrough
What this lab teaches
In OAuth, after you approve a login the provider sends an authorization code to the app's redirect_uri. That code can be exchanged for access to your account, so the provider must send it only to the real app. If it validates the redirect_uri with a loose check, an attacker can craft a URL that passes the check but points somewhere they control.
The lesson: redirect_uri must be matched exactly against a pre-registered value. Substring and unanchored prefix checks are bypassable.
How AuthHub validates redirect_uri
AuthHub accepts a redirect_uri as long as the string trustedclient.com appears somewhere in it. It never anchors the check to the start of the host or compares against an exact registered URI, so a URL that merely includes those characters as a prefix, subdomain or path is accepted.
The attack approach
- Notice the redirect_uri is accepted on a substring match for trustedclient.com.
- Construct a URL you control that still contains that string somewhere the check is happy with.
- Point the real destination at an attacker host so the code lands there.
- Complete the flow and capture the authorization code that AuthHub delivers.
Full walkthrough (spoiler)
If the provider rejects your redirect_uri, the string is not in a spot the check accepts — adjust and open the steps.
Show the step-by-step solution
- Build a redirect_uri whose host is attacker-controlled but which still contains trustedclient.com where the naive check looks (for example as a subdomain label or in the path).
- Start the OAuth flow with that redirect_uri. The substring check passes.
- Approve the login. AuthHub sends the authorization code to your crafted URL instead of the real app.
- Read the code from where it landed. The lab detects the code reaching the attacker destination and marks you solved.
Why it works
The provider's only guard is 'does this string contain trustedclient.com?', which is true for many URLs an attacker fully controls — a subdomain like trustedclient.com.attacker.example, or a path on another host. The authorization code is sensitive, but the provider happily delivers it to any URL that slips past the weak check.
Where this happens in the real world
Loose redirect_uri validation is a recurring source of OAuth account-takeover reports, because 'just check it contains our domain' is a tempting shortcut. The OAuth specification requires exact matching for exactly this reason. It maps to Broken Access Control (A01) and Security Misconfiguration (A05) in the OWASP Top 10 (2021).
How to defend against it
- Register redirect URIs up front and match incoming ones exactly, string for string.
- Never validate with contains or unanchored starts-with — anchor to the full scheme, host and path.
- Prefer the authorization-code flow with PKCE, which limits what a stolen code is worth.
- Treat the Origin and Referer as hints only, never as the authorisation decision.
Try it, then go further
Reading about it is the easy part. Open the lab, try your own approach before peeking at the spoiler, and see how many attempts it takes.
