OAuth 2.0 Attacks in 2026: Code Injection, PKCE Downgrade, JWT Issues

Manish Garg
Manish Garg Associate of (ISC)² · RingSafe
Apr 25, 2026
4 min read

Last updated: April 26, 2026

OAuth 2.0 is the de-facto authorisation framework for modern web and mobile applications. Implemented well, it provides delegated access without exposing credentials. Implemented carelessly — and most implementations are careless on at least one detail — OAuth turns into account-takeover primitives. This article covers the modern OAuth attack surface in 2026: redirect URI manipulation, authorisation code injection, state parameter abuse, PKCE downgrade, JWT-as-access-token issues, and the proven defences.

The OAuth flow recap

Standard authorisation code flow:

  1. Client redirects user to authorisation server (Google, GitHub, Auth0, Okta).
  2. User authenticates and consents.
  3. Authorisation server redirects back to client with an authorisation code.
  4. Client exchanges the code (server-to-server) for an access token.
  5. Access token used to call protected APIs.

Each step has attack surface.

Attack 1: Redirect URI manipulation

The authorisation server returns the code by redirecting to a URI. Most implementations accept a list of registered redirect URIs and require an exact match. Common errors:

  • Wildcard or partial-match validationhttps://*.example.com/cb registered, attacker uses https://attacker.example.com/cb
  • Path traversal in URIhttps://example.com/../attacker/cb bypasses path validation
  • Open redirect chained — registered URI is a page with open-redirect parameter; attacker chains
  • Subdomain takeover — registered URI is on a subdomain that has been abandoned

If the attacker can redirect the code to their server, they exchange it for the token = full account takeover.

Attack 2: Authorization code injection

Recent class of attack (CVE-2023-X disclosures): the attacker initiates an OAuth flow, captures the code, then injects it into the victim’s session — victim’s client exchanges the code, gets a token bound to attacker’s identity, and the victim is now logged into attacker’s account (or vice-versa, depending on flow direction).

Mitigation: PKCE (Proof Key for Code Exchange) — client generates a code_verifier, sends code_challenge with auth request, then sends code_verifier with token exchange. Without the original code_verifier, the code is useless to anyone else.

Attack 3: State parameter omission / replay

The state parameter is the OAuth CSRF token. If the client doesn’t generate or verify it, an attacker can:

  1. Initiate an OAuth flow against the target client
  2. Get the code redirected to victim’s session via crafted link
  3. Victim’s client accepts the code, exchanges, logs victim into attacker’s account

Also called Login CSRF. Mitigation: cryptographically-random state parameter, bound to user’s session, verified on callback.

Attack 4: PKCE downgrade

PKCE was originally for public clients (mobile apps); confidential clients (server-side) historically didn’t use it. If the auth server supports both PKCE and non-PKCE for the same client, an attacker can force the non-PKCE path and bypass code-injection protection.

Mitigation: enforce PKCE for all clients, even confidential ones (RFC 9700 recommendation).

Attack 5: Token leakage via referrer / logs

If access tokens are placed in URL fragments (implicit flow) or query strings, they leak through:

  • Referrer headers when the page loads external resources
  • Browser history / bookmarks
  • Server access logs
  • Mobile app logs

Mitigation: avoid implicit flow (deprecated since OAuth 2.1); use authorisation code flow with PKCE; tokens in HTTP headers, not URLs.

Attack 6: JWT access token weaknesses

If access tokens are JWTs (common with Auth0, Cognito), every JWT attack applies — alg:none, RS256-to-HS256, weak HMAC, JWKS injection. Covered separately in our JWT article.

Attack 7: Scope escalation

Some authorisation servers honour scope changes during refresh-token flows. Attacker requests a refreshed token with broader scope; if not validated, scope creeps up.

Attack 8: Cross-site WebSocket hijacking via OAuth state

If the OAuth callback page initiates a WebSocket connection without origin validation, attacker can establish a WebSocket from their site that inherits the just-completed OAuth session.

Practical workflow

  1. Identify OAuth in scope. Look for redirects to auth.target.com, login.target.com, or third-party OAuth providers.
  2. Capture the auth flow with Burp.
  3. Test redirect URI: try wildcards, path traversal, subdomain swap, append fragments.
  4. Test state: omit it; replay it; check if the client validates.
  5. Test PKCE: omit code_verifier; check if client allows.
  6. Test code reuse: exchange the same code twice; should fail.
  7. Test scope: request additional scopes during refresh.
  8. If JWT access token, run JWT attack chain.

Detection — what works

  • Authorisation server logs — multiple failed code exchanges, unusual redirect URI patterns, scope-mismatch refresh attempts.
  • Anomalous OAuth flow — same code attempted multiple times, code-exchange from unexpected IP after redirect.
  • Strict redirect URI validation at the authorisation server.

The fix

  • Use OAuth 2.1 (the consolidated, hardened version of OAuth 2.0).
  • Authorisation code flow with PKCE for all clients.
  • Exact-match redirect URI validation. No wildcards, no path traversal.
  • Cryptographically-random state parameter, bound to session.
  • Short access token lifetimes (5-15 min); refresh tokens with rotation.
  • JWT access tokens validated correctly (algorithm pinned, signature verified).
  • Scope validation on every refresh.

Compliance angle

  • OWASP API Top 10 API2 (Broken Authentication) — OAuth implementation flaws are common findings.
  • RFC 9700 — OAuth 2.0 Security Best Current Practice; the modern bar.
  • DPDP §8(5) — OAuth bypass leading to account takeover is a defensible-security failure.

The takeaway

OAuth done correctly is fine. OAuth done with a 2017 implementation guide is broken. Audit your OAuth flows against OAuth 2.1 and RFC 9700. The fix is mostly configuration — PKCE, exact redirect match, state validation. The cost of skipping it is account takeover at scale.

Need a real pentest?

Get a VAPT scoping call

Senior practitioner-led VAPT — not a checklist run by juniors. CVSS-scored findings, free retest, attestation letter. India's SMBs and SaaS teams.

Book VAPT scoping call Replies in 4 working hrs · India-only · Senior consultants