RFC 9700 / START HERE
OAuth security, before the details
OAuth 2.0 security guidance
OAuth lets an app use a service with your permission, without receiving your password. This RFC explains how to make that arrangement safer.
The idea in one picture
You grant access
The app receives a token
The service checks permission
A simplified picture of the idea; the chapters explain the actual mechanisms.
Why it exists
Early OAuth deployments exposed ways to steal codes, replay tokens, or confuse the parties. This guide covers the safeguards against those mistakes.
A familiar example
You let a photo-printing app read selected photos. The app should get only the access you granted, and a stolen credential should be harder to misuse.
Helpful background
You can start here without reading another RFC. If these ideas are unfamiliar, these short introductions may help.
What you’ll learn next
Begin with chapter one, or choose a topic.
- OAuth overviewOAuth lets an app access your data with permission, without receiving your password.→
- Authorization code + PKCEProof Key for Code Exchange (PKCE) lets an app prove that it started the request. A stolen authorization code alone is not enough.→
- Retire unsafe grantsAvoid tokens in the front-channel response. Never collect the resource owner’s password through the password grant.→
- Prevent token replayA copied credential should not automatically grant a second caller the same access.→
- Limit token privilegesA token should carry only the audience, resources, and actions the app actually needs.→
- Authenticate the clientWhen credentials can be issued and kept confidential, require the app to prove its own identity.→
- Metadata, TLS & CORSDiscover the right endpoints, protect the channel, and distinguish browser redirects from cross-origin API calls.→
- The attacker modelAttackers can run their own services, control a network, observe OAuth messages, or obtain a token. They can also collaborate.→
- Redirect URI validationA permissive redirect pattern can send a code or token straight to an attacker-controlled address.→
- Referer header leakageExternal resources or links on OAuth pages can disclose sensitive URL contents through the Referer header.→
- Browser history leakageCodes and tokens in visited URLs can remain in history, where someone with device access may find them.→
- Authorization server mix-upA client using several authorization servers can be tricked into redeeming an honest server’s code at a malicious token endpoint.→
- Authorization code injectionAn attacker injects a stolen code into their own app session so the legitimate app connects that session to the victim’s resources.→
- Access token injectionA thief can substitute a stolen access token into an implicit response while retaining the client’s valid state.→
- Cross-site request forgeryAn attacker sends an unsolicited callback to a victim’s browser, causing the client to connect to resources chosen by the attacker.→
- PKCE downgradeA server that silently accepts an unbound code can undo a client’s reliance on PKCE for CSRF protection.→
- Leakage at resource serversA counterfeit endpoint or compromised resource server can collect access tokens and attempt to use them elsewhere.→
- Misuse of stolen tokensCombine proof of possession with audience checks so a stolen token cannot travel freely between callers and APIs.→
- Open redirectionA URL on a trusted client or authorization server can bounce the browser to an arbitrary phishing or exfiltration endpoint.→
- 307 credential forwardingAfter a login POST, a 307 redirect preserves the method and body, potentially sending user credentials to the client.→
- TLS termination & proxiesA TLS-terminating proxy becomes part of the security boundary. Forwarded headers and the internal hop need protection too.→
- Refresh token protectionRefresh tokens can mint future access. Rotation makes reuse visible; sender constraints make possession alone insufficient.→
- Client as resource ownerAn API can confuse a client identity with a user identity when both occupy the same identifier namespace.→
- ClickjackingA hidden frame or deceptive overlay can turn an innocent click into consent, or capture a password intended for the real login page.→
- In-browser messagingBrowser messaging changes the transport, not the trust rules. A wildcard recipient or unchecked sender can leak or inject a response.→
This introduction explains RFC 9700 (2025). Read the original RFC ↗