Abusing OAuth 2.0 PKCE Downgrade in Native Clients

A subtle authorization-code injection path emerging when public clients silently fall back from S256 to plain PKCE.

· updated · 12 min read
#oauth#web#auth#cve

Background

OAuth 2.0 PKCE (RFC 7636) was designed to neutralize authorization-code interception against public clients. In practice, several SDKs still accept the legacy plain transformation when S256 negotiation fails — and a meaningful subset of identity providers will quietly honor it.

This post documents a chain that turns that fallback into an account takeover on a production native client.

The downgrade

When the client emits two simultaneous authorization requests — one with code_challenge_method=S256 and one omitted — the provider's session binding collapses to the most recent request. The recovered code is then exchangeable with a verifier the attacker controls.

GET /authorize?response_type=code
  &client_id=app
  &code_challenge=abc
  &code_challenge_method=plain

Impact

Single-tap account takeover from a malicious app holding the universal link entitlement.

Mitigation

Reject any token exchange where the original code_challenge_method is absent or plain for a client that previously advertised S256. Bind the method to the session, not the request.


sharelinkedinx / twitter