OAuth Misconfiguration Pentest: From redirect_uri to PKCE
Cybersecurity
OAuth flaws keep producing critical bugs because the spec leaves dangerous flexibility to implementers. Here's the redirect_uri, state, and code-handling pentest playbook plus the configuration that closes each gap.
By Arjun Raghavan, Security & Systems Lead, BIPI · January 11, 2025 · 8 min read
OAuth 2.0 is a delegation framework with optional security features. Authorization servers and clients regularly skip those options, which is why account takeover via OAuth is one of the most-paid bug classes on HackerOne in 2026.
How to test for it
Capture the full authorization request and response in Burp. Log every parameter: client_id, redirect_uri, state, scope, response_type, code_challenge, response_mode. Then mutate each one and observe behavior.
- redirect_uri tampering: try evil.com, victim.com.evil.com, victim.com@evil.com, victim.com#@evil.com, victim.com/.evil.com, and Unicode lookalikes.
- redirect_uri path traversal: registered as https://victim.com/cb, try /cb/../redirect or /cb#@evil.com.
- Missing state parameter: drop state from the request and check whether the callback still completes, then test CSRF on the callback.
- Authorization code reuse: capture a code, send it twice within seconds, see if both return tokens.
- Implicit flow leakage: switch response_type=token and check whether the token lands in the URL fragment, exposed to Referer leak and browser history.
- Cross-client confusion: use one client's authorization code against another client's token endpoint, or pass an access token issued for one audience to an API expecting a different audience.
- Open redirect chain: find an open redirect on the registered redirect_uri host, then chain the OAuth code through it to attacker.com.
For mobile OAuth, test custom URL schemes for hijacking by another app. For SPA flows, confirm the client uses PKCE with S256 and not plain. Caido's OAuth Hunter extension automates redirect_uri permutations.
Common provider bugs
Some providers do prefix matching on redirect_uri instead of exact match, allowing victim.com.evil.com to match victim.com. Others normalize URL fragments before comparison, allowing fragment-based bypasses. Custom IdP implementations frequently skip state validation when the client claims to use PKCE, conflating two unrelated controls.
Detection
Log every authorization request with client_id, redirect_uri, and source IP. Alert on redirect_uri values that have never been seen before for that client_id, on authorization codes redeemed from IPs different from the IP that requested them within a short window, and on tokens redeemed without a corresponding code_verifier when PKCE is required.
Remediation
- Enforce exact-string redirect_uri matching at the authorization server. No prefix, no regex, no normalization beyond RFC 3986.
- Require PKCE with S256 for all clients, public and confidential. Reject plain. Reject missing code_verifier on token exchange.
- Require state on every authorization request, validate it on callback, and reject if missing or mismatched.
- Make authorization codes single-use and short-lived (under 60 seconds). Invalidate the code on first use even if the redemption fails.
- Bind tokens to the audience: include an aud claim and reject tokens at resource servers that do not match.
- Disable the implicit flow. Use authorization code with PKCE for SPAs.
- Rotate client secrets and use mTLS or JWT client assertion for confidential clients.
Real chain example
On a recent engagement we chained an open redirect on the legitimate /redirect?to= endpoint with a registered redirect_uri of https://app.victim.com/auth/callback. The authorization server accepted the redirect_uri, the code arrived at /auth/callback, but a forced 302 in the rendering layer leaked the code to attacker.com via Referer. Fix: strict redirect_uri match plus Referrer-Policy of no-referrer on auth callback pages.
Validation
Re-run the mutation matrix on every redirect_uri and confirm all variants except the exact registered URI are rejected with invalid_redirect_uri. Confirm code reuse returns invalid_grant on the second attempt. Add a Burp Active Scan extension or a custom nuclei template to your CI pipeline.
Read more field notes, explore our services, or get in touch at info@bipi.in. Privacy Policy · Terms.