OAuth redirect_uri Lab: Steal a Login Code With a Loose Check

✨ AI Summary
AuthHub decides where to send your OAuth login code by checking that the 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.
Lab at a glance: Intermediate · 90 XP · about 15 minutes · runs in your browser, no signup or setup. Try it yourself first; the full solution is behind a spoiler below.

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
  1. 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).
  2. Start the OAuth flow with that redirect_uri. The substring check passes.
  3. Approve the login. AuthHub sends the authorization code to your crafted URL instead of the real app.
  4. 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.

Core principleMatch redirect_uri exactly against a pre-registered value. Substring, 'starts-with' and unanchored checks are all bypassable.

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.
Mr Elite tip: When testing OAuth you are authorised to assess, probe the redirect_uri check with your own domain carrying the trusted string as a subdomain or path. If the provider accepts it, the matching is too loose.

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.

❓ Frequently asked questions

What does redirect_uri do in OAuth?
It is the URL the provider sends the authorization code to after you approve a login. Whoever receives that code can exchange it for access to the account.
Why is a substring check unsafe?
Because many attacker-controlled URLs can still contain the trusted domain — as a subdomain, path or query — so the code gets delivered to the attacker.
What is the correct validation?
Exact matching against a pre-registered redirect_uri, anchored to the full scheme, host and path. The OAuth spec requires this.
Does PKCE fix this?
PKCE reduces the damage of a stolen code but does not replace exact redirect_uri matching. Use both.
⚡
Join free to earn XP for reading this article Track your progress, build streaks and compete on the leaderboard.
Join Free
Lokesh N. Singh aka Mr Elite
Lokesh N. Singh aka Mr Elite
Founder, Securityelites · AI Red Team Educator
Founder of Securityelites and creator of the SE-ARTCP credential. Working penetration tester focused on AI red team, prompt injection research, and LLM security education.
About Lokesh ->

Leave a Comment

Your email address will not be published. Required fields are marked *