Lion Cipher Lab
Build an OAuth 2.0 redirect_uri validator that survives a bypass gauntlet
- Identity & Access Management
- Intermediate
- ~45 min
- Free · no account required
Why it matters
In the OAuth authorization-code flow, the redirect_uri is the address the authorization server sends the browser back to WITH the authorization code attached -- the code that is then traded for the user's access token. If the server will send that code to an address the real client never registered, an attacker can craft a link that pops the normal consent screen and then bounces the code to a server they control, taking over the account. The only defence the specs trust is dead simple to state and surprisingly hard to get right by hand: compare the redirect_uri to a pre-registered value by…
What you'll learn
- what the redirect_uri actually controls in an OAuth 2.0 authorization-code flow, and why it is where the authorization code lands
- why the spec (RFC 6749 section 3.1.2, RFC 9700 section 4.1.3) demands EXACT string matching against a pre-registered allow-list, not pattern matching
- writing the four naive matchers people actually ship (startsWith, substring, 'host contains the domain', un-anchored regex) and a spec-correct exact matcher
- running a bypass gauntlet and reading, with real counts, exactly how many malicious redirect_uris each naive matcher lets through
- using urllib.parse.urlsplit to see why https://good.com@evil.com and https://good.com.evil.com point at evil.com
- the honest tradeoff: exact match forbids the dynamic loopback ports native apps need (RFC 8252) and any query-string variation, and what to do instead
Steps in this lab
- The one idea: redirect_uri is where the authorization code lands
- Set up: one folder, Python, and nothing else
- Register an allow-list and build the bypass gauntlet
- Write the four naive matchers people actually ship
- Write the exact matcher and a runner that scores the gauntlet
- BEFORE: run it and read the scoreboard
- Look inside urlsplit to see why each bypass works
- AFTER: the exact matcher blocks all 12 and keeps the 1
- The honest negative: exact match forbids things some legit clients need
- The judgment: when to reach for this, and the pro way to do it