OAuth 2.1: What's New and How It Differs from OAuth 2.0
Security teams keep asking the same question in slightly different words: is OAuth 2.0 still safe to build on, or should new work target OAuth 2.1? OAuth 2.1 is less a new protocol than a cleanup. It folds more than a decade of separately published OAuth security fixes into one specification, removes the options that turned out to be traps, and sets a stricter baseline for anyone issuing or accepting access tokens.
That baseline is also the one the Model Context Protocol (MCP) authorization spec builds directly on, which is why the question now turns up in far more backlogs than it used to.
What Is OAuth 2.1?
OAuth 2.1 is an IETF Internet-Draft, currently at revision 16 (published 3 September 2026). It consolidates the original OAuth 2.0 Authorization Framework (RFC 6749) with the security best-practice documents published since 2012, including OAuth 2.0 for Native Apps (RFC 8252), the OAuth Security Best Current Practice (RFC 9700), and OAuth 2.0 for Browser-Based Apps, which is itself still a separate Internet-Draft rather than a published RFC.
The draft says it's intended to replace and obsolete RFC 6749 and the Bearer Token Usage spec (RFC 6750) once it's published; it hasn't done so yet. As of this writing (September 2026), it's still a working draft under active revision by the OAuth Working Group, not a ratified RFC.
The four roles are unchanged from OAuth 2.0: resource owner, client, authorization server, and resource server. What has changed is which options each of them is still allowed to use.
Why OAuth 2.1? The Problem It Solves
RFC 6749 shipped in 2012 with a wide menu of grant types and few hard requirements. That flexibility let implementers choose the easiest option rather than the safest one. Over the following decade, security researchers documented exactly which choices were being exploited in practice: bearer tokens leaking through browser history, redirect URIs validated by prefix instead of exact match, and public clients issued tokens with no proof that they were the client that asked for them.
The OAuth Security Best Current Practice (RFC 9700) turned those findings into concrete recommendations. But it sat alongside the OAuth 2.0 specification rather than replacing it, so an implementer who read only the core spec had no signal that anything had changed.
OAuth 2.1 closes that gap by removing the insecure options from the specification itself, instead of leaving them technically legal but discouraged in a companion document. An authorization server built against OAuth 2.1 doesn't need a separate best-practices checklist, because the checklist is now the spec.
That's also why "OAuth 2.1 vs 2.0" is usually the wrong way for teams to frame their next step. The two aren't competing designs with different trade-offs. OAuth 2.1 is what OAuth 2.0 looks like once you apply everything the working group has learned since 2012. Most of that learning was already published; OAuth 2.1 simply makes it mandatory rather than optional.
Key Changes from OAuth 2.0 to OAuth 2.1
Six changes account for most of the migration work. Four remove or restrict something OAuth 2.0 allowed, and two make something that used to be optional mandatory.
| Change | OAuth 2.0 behavior | OAuth 2.1 behavior |
|---|---|---|
| PKCE (authorization code flow) | Optional extension (RFC 7636); both S256 and plain challenge methods allowed | Mandatory for every client using the authorization code flow, public or confidential; plain is removed and explicitly prohibited, and S256 is the only method defined |
| Implicit grant | Defined and widely implemented for single-page apps | Removed from the specification |
| Resource Owner Password Credentials | Defined for first-party, high-trust clients | Removed from the specification |
| Redirect URI matching | Prefix or pattern matching permitted by many implementations | Exact string match required, with a narrow loopback exception |
| Bearer tokens in query strings | Discouraged, but listed as a valid transport option | Not carried forward as a method for resource requests |
| Refresh tokens | Rotation and sender-constraining optional | Sender-constrained or rotated when the client can't be authenticated |
PKCE is now mandatory for every authorization code flow client
Proof Key for Code Exchange started as an OAuth 2.0 extension for public clients that can't hold a secret, such as mobile and single-page apps. OAuth 2.1 requires it for every client that uses the authorization code flow, public or confidential. The client generates a code_verifier and derives a code_challenge from it, and the authorization server must reject any token exchange whose code_verifier doesn't match.
This applies only to the authorization code grant. The client credentials and refresh token grants have no redirect step and define no code_challenge parameter, so PKCE isn't something you add to those requests.
As of draft revision 16, S256 is no longer merely the mandatory-to-implement method: plain has been removed and is explicitly prohibited. That closes a downgrade path where an attacker able to intercept a request could otherwise swap plain in for S256.
The challenge is derived like this:
code_verifier = high-entropy random string, 43-128 characters
code_challenge = BASE64URL-ENCODE(SHA256(code_verifier))
Example matching pair (RFC 7636's own test vector):
code_verifier: dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
code_challenge: E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
The authorization request carries the challenge:
GET /authorize?response_type=code&client_id=s6BhdRkqt3
&redirect_uri=https%3A%2F%2Fclient.example.com%2Fcb
&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
&code_challenge_method=S256
And the token request carries the verifier. The code_verifier must hash to the code_challenge above, and the redirect_uri must match the one used in the authorization request:
POST /token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient.example.com%2Fcb
&code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
Implicit grant is removed
The implicit grant returned an access token directly in the fragment of a browser redirect. A URL fragment isn't sent to the server in an ordinary HTTP request, and user agents are required to strip it before generating a Referer header, so the token doesn't end up in server access logs or referrer headers by default, the way a query-string token would.
The real exposure is narrower but still serious. The fragment persists in browser history, and any script running on the page can read it through location.hash. The OAuth Security BCP also documents a specific attack: user agents reattach a redirect's original fragment when a later Location header omits one, which an attacker can combine with an open redirector on the client to steal the token.
OAuth 2.0 offered the implicit grant as a shortcut for JavaScript apps that couldn't perform a server-side code exchange. OAuth 2.1 doesn't define it at all. Browser-based clients now use the authorization code flow with PKCE instead, typically through a backend-for-frontend pattern.
Resource Owner Password Credentials (ROPC) grant is removed
ROPC let a client collect a user's username and password directly and exchange them for a token, which essentially reintroduced the credential-sharing problem OAuth was created to avoid. It's no longer specified in OAuth 2.1. Anything still using it should move to the authorization code flow, or to client credentials if the "user" is actually another service.
Redirect URIs require exact string matching
OAuth 2.0 implementations often matched redirect URIs by prefix, which let attackers append their own path segments and send authorization responses somewhere they controlled. OAuth 2.1 requires the authorization server to reject any redirect URI that isn't an exact string match for what the client registered. There's one exception: loopback redirects, where only the port number may vary.
No bearer tokens in the query string
OAuth 2.0's bearer token spec listed three ways to present a token: the Authorization header, a form-encoded body parameter, and a URI query parameter. The query-string option was marked as a last resort, because URLs get logged by proxies, browsers, and servers. OAuth 2.1's resource-request section defines only the header and form-encoded methods; the query-string option isn't carried forward. If a token appears in a URL, something upstream will write it to a log file.
Refresh tokens must be sender-constrained or rotated
A stolen refresh token that never expires and never rotates is a standing liability. OAuth 2.1 requires the authorization server to verify the binding between a refresh token and its client whenever it can authenticate that client. Where it can't, the server must either issue sender-constrained refresh tokens or rotate them on each use.
Rotation is the more common choice in practice. Each refresh exchange returns a new refresh token and invalidates the old one, so if a leaked token is used by both the legitimate client and an attacker, the reuse can be detected.
What Stays the Same in OAuth 2.1
Most of the protocol is untouched. The authorization code, client credentials, and refresh token grants are still the three grant types the spec defines, and extension grants are still supported for cases those three don't cover. The four-role model, the token and authorization endpoints, scopes, and bearer tokens as the default access token type all carry over unchanged. If your mental model of OAuth 2.0 was already built around the authorization code flow with a confidential client, OAuth 2.1 mostly formalizes habits you probably already had.
That continuity helps with migration planning, but it doesn't mean resource servers are unaffected. Two of the six changes reach beyond the authorization and token endpoints. A resource server that still accepts a bearer token as a query parameter has to stop. And one that adopts sender-constrained access tokens (DPoP or mutual TLS) needs to validate the proof on every request, not just check that a token is present.
The practical exercise is an audit rather than a redesign. Confirm which token transports your resource servers actually accept, which token format they validate against (the JWT Profile for Access Tokens and the JWT security BCP are the relevant references for structured tokens), and whether sender-constraint proofs are checked wherever you've enabled them.
Is OAuth 2.0 Obsolete? Can You Adopt OAuth 2.1 Today?
OAuth 2.0 isn't obsolete, and strictly speaking it can't be, because OAuth 2.1 is still a draft rather than a published RFC. What has changed is the practical baseline. Most identity providers and API gateways that describe themselves as "OAuth 2.1-compliant" today are running OAuth 2.0 implementations that already enforce PKCE, exact redirect matching, and the other consolidated security requirements, not a separate protocol version. Adopting OAuth 2.1 in practice means configuring an existing OAuth 2.0 stack to stop allowing the removed options, not migrating to new infrastructure.
A short migration checklist covers most of the work:
- Confirm that PKCE with
S256is enforced for every authorization code flow client, not just public ones, and thatplainis disabled. - Turn off the implicit and ROPC grants if either is still enabled.
- Switch redirect URI validation from prefix or wildcard matching to exact string comparison.
- Confirm that no endpoint accepts a bearer token as a query parameter.
- Enable refresh token rotation, or sender-constrain refresh tokens with DPoP or mTLS, for any client that can't authenticate itself.
Because the underlying IETF draft is still changing, revisit this checklist against the current revision from time to time rather than treating it as a one-off project.
OAuth 2.1 and AI Agent Authorization (MCP)
MCP's authorization specification is optional, and where it applies, it's limited to HTTP-based transports. Implementations using STDIO are explicitly told to skip it and take credentials from the environment instead. Where an MCP deployment does use it, MCP authorization implementations must implement OAuth 2.1, which is why OAuth 2.1 comes up in agentic AI security conversations even among teams that haven't touched the rest of the spec.
One detail for anyone tracking version drift: the security considerations in that version of MCP's spec tie its PKCE requirement to a specific OAuth 2.1 draft revision (13), rather than to whichever revision is current. So "MCP requires OAuth 2.1" refers to a particular snapshot of the draft, not a promise to adopt every later change discussed above automatically.
An MCP server acts as an OAuth 2.1 resource server, and an MCP client acts as an OAuth 2.1 client making protected resource requests on behalf of whoever, or whatever, started the connection.
That "whoever, or whatever" is where MCP adds a wrinkle that OAuth 2.1 alone doesn't solve. An AI agent isn't quite the resource owner, and it isn't quite a standard confidential client either. It often needs to act under its own identity in some situations (calling a tool on a schedule, with no user present) and under a user's delegated authority in others (a user asking the agent to fetch their own data). Getting PKCE and exact redirect matching right, as described above, secures the mechanics of the token exchange. It doesn't by itself tell a resource server which of those two situations a given request represents, and MCP deployments generally need that distinction for audit and least-privilege reasons. WSO2 has written about this in the context of OWASP's MCP security guidance.
MCP's spec also adds its own scoping rules on top of OAuth 2.1. Clients must use the resource parameter (RFC 8707) to state which server a token is for, and servers must reject any token that doesn't name them as its audience. If an MCP server itself calls an upstream API, it has to obtain its own separate token there instead of forwarding the one it received from the client. Forwarding it would be exactly the kind of confused-deputy pattern that audience validation exists to prevent.
Token lifecycle is the other area where agent workloads push harder than typical OAuth 2.0 clients did. An agent holding a long-lived access token and calling dozens of tools autonomously has a much bigger blast radius than a browser tab holding a short session token. That's part of why sender-constraining mechanisms like DPoP matter more here than they did for most OAuth 2.0 deployments. DPoP binds a token to a proof-of-possession key the client holds, so a copied or intercepted token is useless without that key.
WSO2's own PKCE-for-MCP walkthrough covers the token exchange mechanics for a resource server and an authorization server deployed as separate components, which is the common case for enterprise MCP deployments.
How WSO2 API Platform Applies OAuth 2.1 to MCP Traffic
In WSO2 API Platform, the AI Gateway's MCP Proxy is where the resource-server half of MCP authorization is enforced.
Its MCP Authentication policy makes the gateway act as the OAuth resource server for an MCP server. It validates JWT access tokens against the configured issuers, and serves the OAuth 2.0 Protected Resource Metadata document at /.well-known/oauth-protected-resource so MCP clients can discover the authorization server. When a token is missing or invalid, it returns a WWW-Authenticate header pointing to that metadata. By default, it also withholds the client's token from the upstream MCP server, in line with the MCP spec's ban on token passthrough described above.
Authorization decisions come from the MCP Authorization policy, which evaluates the validated token's claims and scopes for each tool, resource, prompt, or JSON-RPC method, so decisions can be made per tool rather than per connection. The MCP Rate Limit policy applies separate limits to each capability.
The authorization server itself, including how it enforces PKCE, redirect matching, and refresh token rotation, is whichever identity provider you connect, so the OAuth 2.1 checklist above still applies there. None of this replaces an implementation-specific security review: validating audiences, checking token formats, and confirming that sender constraints are enforced remain the deploying team's responsibility.
Conclusion
OAuth 2.1 isn't a rewrite. It's OAuth 2.0 with the guesswork removed: PKCE, exact redirect matching, and constrained refresh tokens go from recommended to required, and the grant types that kept causing incidents are gone. For most teams already running a well-configured OAuth 2.0 deployment, adoption is a configuration audit rather than a migration project. And for anyone building or securing MCP-based agent access, it's the baseline the rest of the stack now assumes.
If agent authorization is the part of that stack you're working through right now, WSO2 API Platform's AI Gateway handles the resource-server side for MCP servers, from token validation and protected resource metadata to the tool-level access control that OAuth 2.1 alone doesn't specify.
Frequently Asked Questions
Is OAuth 2.0 obsolete?
No. OAuth 2.1 is still an IETF draft, not a published RFC, and OAuth 2.0 remains the formally standardized version. Most "2.1-ready" deployments today are OAuth 2.0 implementations configured to the stricter, consolidated rules.
What is the current version of OAuth?
OAuth 2.0 (RFC 6749) is the current published standard. OAuth 2.1 is the draft in progress, currently at revision 16 (published 3 September 2026), and it will eventually replace OAuth 2.0 once the IETF finalizes it and publishes it as an RFC.
Are OAuth and OAuth 2.0 the same?
Not exactly. OAuth 1.0 and OAuth 2.0 are different, incompatible protocols. "OAuth" without a version number almost always means OAuth 2.0 today, because OAuth 1.0 has been largely retired.
What does OAuth 2.0 do?
It lets a user grant a third-party application limited access to their data on another service without handing over their password. Instead, an authorization server issues the application a scoped, time-limited access token.