OAuth 2.1 is best understood as:
OAuth 2.0, plus a decade of security lessons turned into defaults.
It’s less about “new shiny features” and more about removing insecure options and standardizing modern guidance.
What OAuth 2.1 changes (conceptually)
OAuth 2.1 consolidates best practices that most serious OAuth deployments already follow:
- Deprecates Implicit (use Authorization Code instead)
- Makes PKCE a first-class requirement for public clients
- Reinforces strict redirect URI rules and safer client patterns
Even if your vendor still labels things “OAuth 2.0,” the practical target state is “OAuth 2.1 posture.”
Diagram: Authorization Code + PKCE (public client)
Diagram
PKCE prevents code interception from being enough to steal tokens.
Threat model: what you’re defending against
Common OAuth attack paths:
- Authorization code interception (PKCE helps)
- Redirect URI manipulation (strict allowlists help)
- Token replay (short-lived tokens, DPoP/mTLS help)
- Refresh token theft (rotation + reuse detection help)
- Consent phishing / over-scoped apps (govern app approvals + scopes)
Best practices checklist (practical)
Redirect URIs
- Exact match allowlist (no wildcards unless you really know why)
- Avoid open redirects in your app
- Separate dev/stage/prod client registrations
PKCE everywhere
- Use S256
- Never log the verifier
- Treat the verifier as a secret for the duration of the login transaction
Refresh tokens: rotation and theft detection
- Prefer refresh token rotation (one-time use)
- If a rotated refresh token is used again → revoke the whole session/token family
Short-lived access tokens
- Make access tokens short enough that theft has limited value
- Combine with continuous evaluation where supported
Sender-constrained tokens (when you can)
- DPoP (bind token to a client-held key)
- mTLS (bind token to a TLS channel)
Related: /topic/specifications/dpop-and-sender-constrained-tokens
Operational reality (what breaks)
- Clock skew →
exp/nbfvalidation failures - Mobile deep-link redirect URI mismatches
- Multiple IdPs/tenants → wrong issuer/JWK set
- Refresh token rotation implemented in the IdP, but apps don’t handle reuse detection properly
