ndovuoauth2

SPEC PRIMER · OAUTH 2.1 DRAFT-16 & THE EXTENSIONS

OAuth 2.1 and the modern suite

Where OAuth2 is heading: the OAuth 2.1 consolidation, the delta from RFC 6749, and the extension RFCs carrying modern workloads - token exchange, DPoP, PAR, JWT access tokens, and the browser-apps BCP.

October 26, 20262.1 is a draft - build to it via the RFCsThe 2012 baseline
01 · What OAuth 2.1 actually is

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.

02 · The delta from 2.0
TopicOAuth 2.0 (RFC 6749, 2012)OAuth 2.1 (draft-16, 2026)
Grant typesFour: 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
PKCENot in the core; a separate RFC for public clientsMandatory 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 methodsS256 and plain coexist"The plain code challenge method... is explicitly forbidden" (§7.5.2)
Redirect matchingExact string comparison only when the full URI was registered (§3.1.2.3); partial registration allowed component matchingStrict string matching required, everywhere except the native-app loopback port rule inherited from RFC 8252 §7.3
ScopeBearer token usage lives in a separate RFCBearer token usage folded in (RFC 6750 consolidated), with 9700's rules applied
Client authBasic 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 appsSection 9 sketches native apps in four paragraphsRFC 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
03 · The suite map

RFC 6749 was designed to be extended, and the extensions are where modern OAuth actually lives. Eighteen documents, grouped by the question they answer.

SpecWhat it addsYou meet it in
RFC 6749The OAuth 2.0 Authorization Framework · 2012The vocabulary: roles, grants, endpoints, tokensEverything; being consolidated by 2.1
RFC 6750Bearer Token Usage · 2012How tokens are presented, and the error contractEvery resource server
RFC 7636PKCE · 2015Per-request proof keys; stolen codes become worthlessEvery public client - SPAs, native apps, CLIs
RFC 8252OAuth 2.0 for Native Apps (BCP 212) · 2017External user agents, loopback and URI-scheme redirectsMobile and desktop apps
RFC 8628Device Authorization Grant · 2019The two-screen flow for input-constrained devicesTVs, consoles, CLIs
RFC 10017OAuth 2.0 for Browser-Based Apps (BCP 212) · 2026SPA architectures ranked: BFF, token-mediating backend, pure clientEvery JavaScript app doing OAuth
RFC 7009Token Revocation · 2013A revocation endpoint; killing refresh tokens on logoutLogout, account removal
RFC 7662Token Introspection · 2015A live lookup: is this opaque token active, and what is in itResource servers validating opaque tokens
RFC 8707Resource Indicators · 2020The resource parameter: ask for tokens scoped to a specific audienceMulti-service deployments; audience discipline at the AS
RFC 9068JWT Profile for Access Tokens · 2021One claim layout for JWT access tokens, typed at+jwtOffline validation at any API gateway
RFC 8705mTLS Client Auth & Certificate-Bound Tokens · 2020Certificates as client credentials; tokens bound to a keyOpen banking, PSD2, enterprise APIs
RFC 9449DPoP · 2023Sender-constrained tokens without TLS certs - per-request signed proofsSPAs and native apps in financial-grade deployments
RFC 9126Pushed Authorization Requests (PAR) · 2021Authorization parameters pushed to the AS, referenced by request_uriFAPI 2.0, UK Open Banking - integrity for the authorize call
RFC 9207Authorization Server Issuer Identification · 2022The iss parameter on authorization responsesAny client talking to more than one AS (mix-up defense)
RFC 8693Token Exchange · 2020A Security Token Service: trade one token for another, with delegation semanticsService-to-service chains, cloud IAM-style on-behalf-of
RFC 9728Protected Resource Metadata · 2025How a resource server publishes its requirements: scopes, issuers, signing keysAgent-facing APIs; the anchor of MCP authorization
RFC 9700Best Current Practice for OAuth 2.0 Security (BCP 240) · 2025The security floor: PKCE rules, exact redirects, refresh rotation, deprecationsEvery deployment, today
OIDC CoreOpenID Connect Core 1.0 · 2014The identity layer: ID tokens, openid scope, UserInfoEvery "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.

04 · Spotlight: token exchange

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.

Token exchange: an API trading the incoming token for one scoped to a backend callAppAPI (RS)Auth serverBackend1. call with token A (aud: API)2. exchange: subject_token=A, audience=backend3. token B (aud: backend, act: API for user)4. call backend with token Bthe backend sees exactly who is acting (the API) on whose behalf (the user) - no shared secrets, no over-broad tokensone caveat the spec states plainly: exchange is a one-time event - renewing A does not renew B (section 2.1)

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).

05 · Spotlight: DPoP

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.

06 · The rest of the new work

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.

07 · Build to 2.1 today
  • 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 iss on 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 aud on every request (§2.3)
08 · Primary sources