OAuth 2.1 consolidates OAuth 2.0 and its security best practices: mandatory PKCE, no implicit grant, exact redirect matching. Plus what it means for AI agents.
The Model Context Protocol requires it. Every authorization server that wants to serve an AI agent over HTTP has to implement it. And it is still a draft.
OAuth 2.1 is the consolidation of OAuth 2.0 and the decade of security guidance that followed it into a single specification, with the flows that proved unsafe removed and the strongest protections made mandatory instead of optional. It is not a new protocol. If you know OAuth 2.0, you already know most of OAuth 2.1. What you may not know is which of your current habits it just made non-compliant.
This page covers what OAuth 2.1 actually changes, which grant types survive and how to choose between them, and the part the changelogs skip. OAuth was designed around a human sitting at a browser who can be redirected and can click approve. An autonomous agent is neither of those things. That gap is where most agent access goes wrong.
OAuth 2.1 is an in-progress IETF specification that consolidates OAuth 2.0 and its accompanying security best practices into one document, removes the grant types that proved unsafe in practice, and makes the strongest protections mandatory. It keeps the same roles, the same endpoints, and the same tokens as OAuth 2.0. What it changes is which of them you are allowed to use, and how. The OAuth 2.1 draft specification says so in its own words: it consolidates the earlier documents and removes the features that were found to be insecure.
The roles are unchanged, and worth restating because the agent discussion later depends on them:
It is just as useful to be clear about what OAuth 2.1 is not. It is not a new token format, so your JWTs and opaque tokens are unaffected. It is not a replacement for OpenID Connect, which still sits on top of it for authentication. And it is not a clean break: almost every OAuth 2.0 deployment that already followed the security best practices is close to compliant already.
This is the question most people actually arrive with, and most articles answer it badly or not at all. OAuth 2.1 is not an RFC. It is an active IETF Internet-Draft produced by the OAuth working group. The current revision is draft-ietf-oauth-v2-1-16, published on 3 September 2026, and the working group milestone for submitting it to the IESG is December 2026. The IETF datatracker record for the draft carries the revision history and those milestones.
Draft status has not slowed adoption, because 2.1 is mostly a restatement of guidance that was already binding in practice. Its value is that it puts five documents into one:
| Document | What it contributed |
|---|---|
| RFC 6749 | The OAuth 2.0 authorization framework itself: roles, endpoints, grant types. |
| RFC 6750 | How to use bearer tokens when calling a protected resource. |
| RFC 8252 | OAuth for native apps, which is where the external-user-agent and PKCE guidance originated. |
| RFC 9700 | The OAuth 2.0 Security Best Current Practice, the source of nearly every removal in 2.1. |
| OAuth 2.0 for Browser-Based Apps | The single-page-app guidance that made the implicit grant indefensible. |
Read that table as the real story of OAuth 2.1. Nothing in it is new thinking. It is a decade of hard-won corrections, finally written down as the default instead of as an appendix people did not read. Nearly every removal traces back to the OAuth 2.0 Security Best Current Practice, which catalogued the attacks that made them necessary.
Seven changes matter. Each one closes a specific, documented attack rather than tightening things for its own sake.
| Area | OAuth 2.0 | OAuth 2.1 | What it closes |
|---|---|---|---|
| PKCE | Optional, recommended for public clients | Required for all authorization code clients | Authorization code interception and injection |
| Implicit grant | Available | Removed | Access tokens leaking through URL fragments, browser history, and referrer headers |
| Password grant | Available | Removed | Applications collecting, storing, and replaying user passwords |
| Redirect URI matching | Partial and wildcard matching tolerated in practice | Exact string comparison | Open redirects and authorization code theft |
| Tokens in URLs | Permitted as a query parameter | Forbidden | Tokens landing in proxy logs, server access logs, and analytics |
| Refresh tokens (public clients) | Long-lived and reusable | Must be sender-constrained or rotated on every use | Replay of a stolen refresh token |
| Client types | Mixed criteria | Defined solely by whether the client holds credentials | Ambiguity about which rules apply to whom |
PKCE (Proof Key for Code Exchange, pronounced "pixy") is a small addition to the authorization code flow. The client generates a random secret, sends a hash of it with the authorization request, and sends the original secret with the token request. The authorization server will only exchange the code if the two match. The mechanism is defined in RFC 7636, the specification for Proof Key for Code Exchange, which was written specifically to stop authorization code interception.
Without it, an authorization code is a bearer value in transit. Anything that can see it can spend it: a malicious app registered on the same custom URL scheme, a misconfigured redirect, a logging proxy. PKCE turns the code into something only the original requester can redeem.
OAuth 2.0 scoped this to public clients, on the reasoning that a confidential client already proves itself with a client secret at the token endpoint. The working group changed its mind for a good reason: a client secret protects against an attacker who lacks the secret, not against code injection where the attacker gets the legitimate client to redeem a code the attacker obtained. So in OAuth 2.1, PKCE applies to everyone.
The implicit grant returned an access token directly in the redirect URL fragment, with no code exchange. It existed because browsers once had no other way to get a token into a single-page app. That reason expired years ago, and the cost never did: fragments end up in browser history, in referrer headers when the page links outward, and in anything reading the address bar. Single-page apps now use the authorization code flow with PKCE instead.
The resource owner password credentials grant had the client collect the user's actual username and password and trade them for a token. It was always a migration shim for legacy apps, and it defeats the entire purpose of OAuth, which is to let a user grant access without handing over their password. It also makes multi-factor authentication and federation structurally impossible. It is gone.
OAuth 2.1 requires the authorization server to compare the registered redirect URI to the requested one by exact string comparison. No prefix matching, no wildcard subdomains, no ignoring the query string.
This sounds pedantic until you consider what partial matching allows. If https://app.example.com/callback is registered as a prefix, then https://app.example.com/callback/../../open-redirect?to=attacker may still match. Anywhere a redirect can be bent, an authorization code can be delivered to the wrong party. Exact matching is the only comparison with no interpretation in it.
Bearer tokens are no longer permitted in URI query strings. URLs are the least private part of an HTTP request: they are written to server access logs, cached by intermediaries, kept in browser history, and forwarded in referrer headers. Tokens belong in the Authorization header or a request body, neither of which is logged by default.
Refresh tokens get a parallel treatment. For public clients, which by definition cannot keep a secret, a refresh token must either be sender-constrained (cryptographically bound to the client that received it, so a copy is useless elsewhere) or rotated on every use, so that a stolen token is invalidated the moment either party redeems it. Rotation also gives the authorization server a detection signal: if the same refresh token is presented twice, one of the two presenters is an attacker, and the whole token family can be revoked.
Three grant types survive, plus refresh. Choosing between them comes down to one question: on whose behalf is the call being made?
| Grant | Acting on behalf of | Human present? | Use it when | Do not use it when |
|---|---|---|---|---|
| Authorization code + PKCE | A user | Yes, at grant time | Any app accessing a user's data, including web, mobile, single-page, and agent onboarding | There is no user and no user data involved |
| Client credentials | The application itself | No | Service-to-service calls on the application's own resources | The call touches a specific user's data |
| Device authorization | A user | Yes, on a second device | Input-constrained clients: TVs, CLIs, headless installs | A normal browser redirect is available |
| Refresh token | Whoever the original grant was for | No | Extending an existing grant without re-prompting | You need a new or broader permission |
This is the default and, for anything touching user data, effectively the only correct answer. The user authenticates at the authorization server, approves a specific scope, and the client receives a code it redeems for a token. The token carries the user's identity and the approved scope, which means the resource server can enforce per-user permissions and the audit trail names a person.
The client credentials flow is the simplest grant in OAuth 2.1. The client sends its own credentials to the token endpoint and gets back an access token. There is no user, no redirect, no consent screen, and no browser. It survives 2.1 unchanged because it is genuinely useful and its risk profile is well understood.
It is the right choice when the caller really is acting as itself: a nightly batch job reconciling its own records, one internal service calling another, a build system publishing an artifact. The token represents the application, the scope is fixed at configuration time, and the audit trail correctly names the service.
It becomes the wrong choice the moment the call touches a specific person's data, and that distinction turns out to be the central problem in agent deployments. More on that below.
When the client has no browser and no keyboard worth typing a password on, the device authorization grant lets it display a short code the user enters on a separate device. Useful for CLIs and headless installs, and worth knowing about because it is the closest thing OAuth has to a flow for a client that cannot host a redirect. It still requires a present human, so it does not solve the agent problem either.
A refresh token extends a grant the user already gave. It is not a way to obtain new permissions, and treating it as a long-lived credential is exactly the habit OAuth 2.1 tightened. Keep them confidential in transit and at rest, rotate them, and expect the authorization server to be free to not issue one at all.
If you are wiring an AI agent into real systems, OAuth 2.1 stops being background reading. It is the specification your agent's access is measured against, and the Model Context Protocol has made it a hard requirement for HTTP-based servers. That sits one layer below the broader question of agent authorization, which is about deciding what an agent may do at all. OAuth 2.1 is about how the resulting permission gets carried and proven.
MCP does not invent its own authorization. It selects a subset of existing OAuth specifications and makes them normative, and the MCP authorization specification sets out exactly which.
| Requirement | Who | Level | Why it exists |
|---|---|---|---|
| Implement OAuth 2.1, for both confidential and public clients | Authorization servers | MUST | One consistent security floor for every MCP deployment |
| Implement OAuth 2.0 Protected Resource Metadata (RFC 9728) | MCP servers | MUST | So a client can discover which authorization server to talk to |
Send the resource parameter from Resource Indicators for OAuth 2.0 (RFC 8707) on authorization and token requests | MCP clients | MUST | So the issued token names the specific server it is for |
| Validate that a token's audience is this server | MCP servers | MUST | A token minted for somewhere else must not work here |
| Never accept or forward a token issued for a different resource | MCP servers | MUST NOT | Stops token passthrough, where a server replays your token to third parties |
| Keep access tokens out of the query string | MCP clients | MUST NOT | Inherited directly from OAuth 2.1 |
| Support authorization server metadata discovery (RFC 8414 or OIDC Discovery) | Both | MUST | Removes hard-coded endpoint configuration |
The audience rules deserve emphasis. Token passthrough, where a gateway or server takes the token you gave it and reuses it against some other API, is the confused-deputy problem in its purest form, and MCP forbids it outright. That single rule is why audience-restricted tokens matter so much in agent architectures. For the wider picture of how this fits together, see how MCP authentication works end to end and the caller-identity questions covered in MCP identity.
One practical wrinkle worth knowing: the published MCP specification text still references an earlier OAuth 2.1 draft revision than the one the IETF has current. The 2025-06-18 authorization specification cites draft revision 13, three revisions behind the current draft. Downstream specifications pin to a snapshot and catch up later. Read both, and expect the pinned revision to move.
Here is the trap. An agent has no browser and no human watching it at three in the morning, so the client credentials flow looks like the obvious fit. It is not, and the reason is worth being blunt about.
When an agent authenticates with client credentials, it acts as itself. Its token carries the agent's identity and whatever standing scopes were configured, not the identity of the person it is working for. Three things break at once:
The other tempting shortcut, handing the agent a long-lived copy of a user's token, fails differently and worse. It gives a non-human actor the full standing scope of a person, with no expiry pressure and no way to distinguish an agent action from a human one in the logs. Treating the agent as its own non-human identity is a precondition for getting any of this right, but identity alone is not delegation. Frontegg makes the same argument in its guidance on identity management for AI agents: the agent needs an identity of its own that stays tied to the person it serves.
The workable pattern keeps the human in the picture at the one moment they are genuinely available, then narrows relentlessly from there.
Notice that only step one is plain OAuth 2.1. The specification gives you safe primitives: an exactly-matched redirect, a PKCE-protected code, an audience-restricted token, a rotating refresh token. It does not give you the chain. That you build, and research on authenticated delegation makes the same point from the academic side: a third party needs to be able to verify that an agent is an agent, that it acts for a specific person, and that it holds specific permissions. That framing comes from published research on authenticated delegation for AI agents.
Most teams are closer than they expect. Work through these in order, because the early items surface the ones that follow.
resource and start validating audience at your resource servers. If you are exposing anything over MCP, this is mandatory rather than advisable.An honest read of the specification includes its boundaries, because assuming it covers more than it does is how teams end up surprised.
read and write are compliant and nearly useless for the per-request, least-privilege posture that NIST's zero trust architecture guidance describes.No. OAuth 2.1 is an active IETF Internet-Draft, currently at revision 16, published in September 2026. The OAuth working group has milestoned it for submission to the IESG in December 2026, which is the step before RFC publication. Draft status has not prevented adoption, since most of its content restates guidance that was already best practice.
OAuth 2.1 keeps OAuth 2.0's roles, endpoints, and tokens, then makes PKCE mandatory for all authorization code clients, removes the implicit and password grants, requires exact redirect URI matching, forbids bearer tokens in URL query strings, and requires refresh tokens for public clients to be sender-constrained or rotated on use.
Yes, for every client using the authorization code flow, including confidential clients that also authenticate with a client secret. OAuth 2.0 recommended PKCE mainly for public clients. OAuth 2.1 extends it to all of them, because a client secret does not defend against authorization code injection attacks.
Largely, yes. If your deployment already follows the OAuth 2.0 security best practices, you are close to compliant. The genuinely breaking changes are narrow: clients using the implicit grant or the resource owner password credentials grant must move, and redirect URIs registered with wildcards must be made exact.
Use the client credentials flow when the caller is acting as itself and no user's data is involved: service-to-service calls, scheduled jobs, or a build system touching its own resources. Avoid it whenever the call reaches a specific person's data, because the resulting token carries the application's identity rather than that user's.
The implicit grant returned an access token directly in the redirect URL fragment, where it could leak through browser history, referrer headers, and anything reading the address bar. It existed only because early single-page apps had no alternative. The authorization code flow with PKCE now does the same job without exposing the token.
Yes, for HTTP-based transports that implement authorization. The Model Context Protocol specification requires authorization servers to implement OAuth 2.1, MCP servers to publish protected resource metadata and validate token audience, and MCP clients to send resource indicators. Servers using STDIO transport take credentials from the environment instead.
OAuth 2.1 is the base layer. These pages cover what gets built on top of it:
The specification tells you how to issue a safe token. It does not tell you how to keep an autonomous agent accountable to the person it works for. That part is architecture, and it is what Agen is built to handle: an identity foundation for AI agents that issues scoped, short-lived credentials per action and keeps every one of them traceable back to a human. Start with agent authorization if you are still deciding what your agents are allowed to do at all.
Keep reading
Workload identity federation lets services and AI agents get short-lived cloud credentials from a configured trust relationship, not a stored secret.
Written by
Agen.co
OAuth token exchange (RFC 8693) swaps a broad token for a narrow, audience-bound one. How delegation, impersonation, and the act claim work for AI agents.