- OAuth 2.1 (draft-ietf-oauth-v2-1-16)Hardt, Parecki, Lodderstedt - work in progress; §10 is the draft's non-normative list of differences from 2.0
- RFC 9700: Best Current Practice for OAuth 2.0 Securitythe BCP that already carries most of the 2.1 restrictions - build against this
- RFC 8693: OAuth 2.0 Token ExchangeJones, Nadalin, Campbell, Bradley, Mortimore (IETF, January 2020)
- RFC 9449: DPoPFett, Campbell, Bradley, Lodderstedt, Jones, Waite (IETF, September 2023)
- RFC 9126: Pushed Authorization RequestsLodderstedt, Campbell, Sakimura, Tonge, Skokan (IETF, September 2021)
- RFC 10017: OAuth 2.0 for Browser-Based ApplicationsParecki, De Ryck, Waite (IETF, August 2026)
Not a new protocol. OAuth 2.1 is a consolidation: one Standards Track document that folds in the decade of corrections - RFC 8252, RFC 9700, the browser-apps BCP - and "removes features that have been found to be insecure". Its own compatibility statement (draft §1.8): "OAuth 2.1 is compatible with OAuth 2.0 with the extensions and restrictions from known best current practices applied." If you have been building to RFC 9700, you are already building to 2.1.
Status, stated precisely: as of October 2026 the document is draft-ietf-oauth-v2-1-16, published September 3, 2026, expiring March 7, 2027, by Hardt, Parecki, and Lodderstedt - a work in progress that cannot be cited as a standard. Its abstract announces the destination anyway: it "replaces and obsoletes" RFC 6749 and RFC 6750. The practical reading: treat the draft as the shape of the future and the underlying RFCs as what you implement against today.
| Topic | OAuth 2.0 (RFC 6749, 2012) | OAuth 2.1 (draft-16, 2026) |
|---|---|---|
| Grant types | Four: authorization code, implicit, resource-owner password, client credentials (§1.3) | Three: "authorization code, refresh token, and client credentials" (§1.3) - implicit and password are removed |
| PKCE | Not in the core; a separate RFC for public clients | Mandatory with the code grant: "clients MUST use code_challenge and code_verifier and authorization servers MUST enforce their use" (§4.1.1), with one narrow exception where the AS has reasonable assurance that a confidential client implements the OpenID Connect nonce mechanism properly (§7.5.1.1) |
| PKCE methods | S256 and plain coexist | "The plain code challenge method... is explicitly forbidden" (§7.5.2) |
| Redirect matching | Exact string comparison only when the full URI was registered (§3.1.2.3); partial registration allowed component matching | Strict string matching required, everywhere except the native-app loopback port rule inherited from RFC 8252 §7.3 |
| Scope | Bearer token usage lives in a separate RFC | Bearer token usage folded in (RFC 6750 consolidated), with 9700's rules applied |
| Client auth | Basic MUST be supported; body parameters NOT RECOMMENDED (§2.3.1) | Flipped: body parameters are the MUST-support method, Basic demoted to MAY (§2.4.1) |
| Native + browser apps | Section 9 sketches native apps in four paragraphs | RFC 8252 incorporated as section 8; the browser-apps BCP is cited but its normative text is still a placeholder in draft-16 - external user agents and loopback redirects land, the BFF patterns wait for the final BCP |
RFC 6749 was designed to be extended, and the extensions are where modern OAuth actually lives. Eighteen documents, grouped by the question they answer.
| Spec | What it adds | You meet it in |
|---|---|---|
| RFC 6749The OAuth 2.0 Authorization Framework · 2012 | The vocabulary: roles, grants, endpoints, tokens | Everything; being consolidated by 2.1 |
| RFC 6750Bearer Token Usage · 2012 | How tokens are presented, and the error contract | Every resource server |
| RFC 7636PKCE · 2015 | Per-request proof keys; stolen codes become worthless | Every public client - SPAs, native apps, CLIs |
| RFC 8252OAuth 2.0 for Native Apps (BCP 212) · 2017 | External user agents, loopback and URI-scheme redirects | Mobile and desktop apps |
| RFC 8628Device Authorization Grant · 2019 | The two-screen flow for input-constrained devices | TVs, consoles, CLIs |
| RFC 10017OAuth 2.0 for Browser-Based Apps (BCP 212) · 2026 | SPA architectures ranked: BFF, token-mediating backend, pure client | Every JavaScript app doing OAuth |
| RFC 7009Token Revocation · 2013 | A revocation endpoint; killing refresh tokens on logout | Logout, account removal |
| RFC 7662Token Introspection · 2015 | A live lookup: is this opaque token active, and what is in it | Resource servers validating opaque tokens |
| RFC 8707Resource Indicators · 2020 | The resource parameter: ask for tokens scoped to a specific audience | Multi-service deployments; audience discipline at the AS |
| RFC 9068JWT Profile for Access Tokens · 2021 | One claim layout for JWT access tokens, typed at+jwt | Offline validation at any API gateway |
| RFC 8705mTLS Client Auth & Certificate-Bound Tokens · 2020 | Certificates as client credentials; tokens bound to a key | Open banking, PSD2, enterprise APIs |
| RFC 9449DPoP · 2023 | Sender-constrained tokens without TLS certs - per-request signed proofs | SPAs and native apps in financial-grade deployments |
| RFC 9126Pushed Authorization Requests (PAR) · 2021 | Authorization parameters pushed to the AS, referenced by request_uri | FAPI 2.0, UK Open Banking - integrity for the authorize call |
| RFC 9207Authorization Server Issuer Identification · 2022 | The iss parameter on authorization responses | Any client talking to more than one AS (mix-up defense) |
| RFC 8693Token Exchange · 2020 | A Security Token Service: trade one token for another, with delegation semantics | Service-to-service chains, cloud IAM-style on-behalf-of |
| RFC 9728Protected Resource Metadata · 2025 | How a resource server publishes its requirements: scopes, issuers, signing keys | Agent-facing APIs; the anchor of MCP authorization |
| RFC 9700Best Current Practice for OAuth 2.0 Security (BCP 240) · 2025 | The security floor: PKCE rules, exact redirects, refresh rotation, deprecations | Every deployment, today |
| OIDC CoreOpenID Connect Core 1.0 · 2014 | The identity layer: ID tokens, openid scope, UserInfo | Every "Sign in with..." flow |
Grouped: Core (6749, 6750) · Flows & clients (7636, 8252, 8628, 9126, 9207, 10017) · Tokens (7009, 7662, 8707, 9068, 8705, 9449) · Integration (8693, 9728) · Security (9700) · Identity (OIDC). The agent-era stack now has its first published piece: RFC 9728 (Proposed Standard, April 2025) is the metadata spec MCP's authorization layer builds on. Cross-app access (the ID-JAG draft) and client-id metadata documents are still active IETF drafts - the honest tracking surface is the datatracker, not any of the tables above.
RFC 8693 (January 2020) answers the question the framework dodged: what does a resource server do when it needs to call another service on the user's behalf? It cannot forward the token it received - that token names a different audience. It mints a new one, by trading the old: an extension grant, grant_type=urn:ietf:params:oauth:grant-type:token-exchange, with subject_token (who is being acted for) and optionallyactor_token (who is acting). No actor token means impersonation semantics; both present means delegation - and the issued token carries the chain in nested act claims (§4.1), the outermost being the current actor.
The semantics are the conceptual ancestor of AWS STS AssumeRole, Azure's on-behalf-of flow, and GCP service-account impersonation; the actchain shows up wherever zero-trust architectures need to say who acted for whom. Two details bite in production: over-broad requests earn invalid_target (§2.2.2), and revocation does not automatically propagate from input token to output token (§2.1).
RFC 9449 (September 2023) is bearer's answer for clients that cannot do mTLS - which is every browser app and phone. The client generates its own key pair and proves possession on every call with a signed JWT in a DPoP header: jti (unique, for replay detection),htm and htu (the exact method and URI being signed for), iat, plus ath - the hash of the access token - once there is one. The authorization server binds the token to the proof's public key via a cnf claim; the resource server demands a fresh proof per request and rejects the scheme Beareroutright for DPoP-bound tokens (§7.2).
The honest limits, from the RFC itself (§2): an attacker executing code inside the client can sign with the client's own key - DPoP deliberately does not defend that execution context; and without the server-nonce mechanism, proofs exfiltrated today can be pre-computed for tomorrow. What it does buy: exfiltrated token strings alone - the classic breach - become unusable. Confidential-client refresh tokens are deliberately not DPoP-bound (§5): client authentication already constrains them, and skipping the binding lets credentials rotate without killing sessions.
PAR (RFC 9126). The authorization request's weak point was always that its parameters - scope, redirect, transaction context - travel through the browser where anyone can tamper. PAR pushes them to the AS first, authenticated like a token request, and the browser carries only an opaque, single-use request_uri. Integrity, confidentiality, and no more kilometre-long URLs; mandatory in FAPI 2.0 and UK Open Banking.
JWT access tokens (RFC 9068). A single interop layout for self-contained access tokens: typed at+jwt, required claims (iss, exp, aud, sub,client_id, iat, jti), and a validation checklist for resource servers. The explicit typing is the defense against ID-token/access-token confusion attacks. Corollary the spec insists on: "the client MUST NOT inspect the content of the access token" (§6) - it is still cargo.
iss on authorization responses (RFC 9207). One parameter closes the mix-up attack class for multi-AS clients: the response names its issuer, and the client MUST reject on mismatch (§2.4).
Browser-based apps (RFC 10017, August 2026). The SPAs' BCP, and the freshest document in the suite. It ranks the architectures by what survives a malicious-JavaScript attack: Backend-for-Frontend (tokens never touch the browser - most secure), token-mediating backend, then the pure browser client (viable, weakest). It also retires the implicit grant with a history section that doubles as the best short explanation of why the flow existed at all.
- PKCE with S256 on every authorization-code client - public ones MUST already (RFC 9700 §2.1.1), all of them under 2.1 (§4.1.1)
- Exact-string redirect matching; loopback ports are the only variable component (§2.1, RFC 8252 §7.3)
- Refresh tokens for public clients: rotation with reuse detection, or sender-constrain them (§2.2.2)
- Verify
isson authorization responses if you talk to more than one AS (RFC 9207) - Prefer asymmetric client authentication - private_key_jwt or mTLS (§2.5)
- Never in URLs: access tokens MUST NOT ride in query parameters (§4.3.2)
- Audience-restrict tokens; resource servers check
audon every request (§2.3)