OAuth

OAuth is a gift to bug bounty hunters. The spec is complex, implementations vary wildly, and developers frequently misunderstand what they're supposed to be protecting. Every app with "Login with Google/GitHub/Facebook" is worth testing here.

OAuth Flow with Attack Points

flowchart TD
    A["User clicks Login with Provider"] --> B["Redirect to Auth Server"]
    B --> C["GET /authorize"]
    C --> D["User authenticates + consents"]
    D --> E["Redirect to redirect_uri with auth code"]
    E --> F["Client exchanges code for token"]
    F --> G["access_token + refresh_token"]

    B -.- X1["ATTACK: redirect_uri validated?"]
    B -.- X2["ATTACK: state param present?"]
    E -.- X3["ATTACK: code leaks via Referer?"]
    F -.- X4["ATTACK: state validated? CSRF if not"]
    G -.- X5["ATTACK: token storage secure?"]

redirect_uri Manipulation

This is the big one. If the redirect_uri isn't strictly validated, you can steal auth codes.

Open redirect chaining - if the app allows redirect_uri=https://target.com/callback and there's an open redirect at https://target.com/redirect?to=, try:

redirect_uri=https://target.com/redirect?to=https://evil.com

Path traversal - if the app validates the domain but not the path:

# Registered: https://target.com/callback
# Try:
redirect_uri=https://target.com/callback/../../../attacker-controlled-path
redirect_uri=https://target.com/callback%2F..%2F..%2Fevil

Subdomain/path confusion:

redirect_uri=https://target.com.evil.com/callback
redirect_uri=https://target.com/callback?x=https://evil.com
redirect_uri=https://target.com/callback#https://evil.com

State Parameter - CSRF on OAuth

If there's no state parameter, or it's not validated on return, the entire OAuth flow is vulnerable to CSRF. You can force a victim to link your account to theirs.

PoC:

  1. Start an OAuth flow, capture the authorization URL
  2. Don't complete it - grab the URL up to the redirect
  3. Send that URL to a victim (logged in to the target app)
  4. If the app doesn't validate state, victim's account gets linked to your OAuth identity

Token Leakage via Referer

Same issue as Password Reset - if the redirect lands on a page with third-party scripts and the access token appears in the URL fragment or query string, it leaks.

https://target.com/callback?code=AUTH_CODE - that code ends up in Referer headers.

PKCE Bypass

PKCE (Proof Key for Code Exchange) is supposed to prevent code interception. Common implementation bugs:

  • code_verifier accepted without code_challenge being checked
  • Server accepts any code_verifier value regardless of what was sent during authorization
  • PKCE entirely optional when it should be required

Test by starting a PKCE flow, intercepting the token exchange, and removing or altering the code_verifier:

POST /oauth/token HTTP/1.1
Host: auth.target.com
Content-Type: application/x-www-form-urlencoded
 
grant_type=authorization_code&code=AUTH_CODE&redirect_uri=https://target.com/callback
# No code_verifier  -  does the server reject this?

Scope Escalation

Request scopes beyond what the app normally requests. Sometimes the auth server approves anything the client asks for without checking against what was registered.

# Normal request
scope=read:profile email
 
# Try escalating
scope=read:profile email admin write:all repo

Also look for scope confusion - if the app uses offline_access to get a refresh token but the refresh token has broader permissions than intended.

Account Takeover via Unlinked Email

Classic chain: target app allows sign-up with email and also supports OAuth. You register victim@gmail.com with a password. Victim later logs in via "Login with Google" using the same email. If the app merges these accounts automatically without email verification - you have the victim's account.

Implicit Flow

If the app is using the implicit flow (token returned directly in the URL fragment, not via code exchange), that's worth noting. Tokens in URL fragments can leak via:

  • Browser history
  • Server logs if the fragment gets accidentally server-side
  • JavaScript on the page reading window.location.hash

Public Reports

Real-world OAuth findings across bug bounty programs:

  • Open redirect on cs.money chained with OAuth for account takeover - HackerOne #905607
  • Account takeover via Pornhub OAuth flow using unverified email - HackerOne #192648
  • Account takeover via Google OneTap on Priceline without email verification - HackerOne #671406
  • GitLab OAuth email verification bypass leading to third-party account takeover - HackerOne #922456
  • SSO - SAML-based SSO has overlapping attack patterns
  • Session Management - where OAuth tokens end up and how they're stored
  • Password Reset - apps with OAuth sometimes have a broken legacy password reset too