Skip to content
Agent Identity

IETF · October 2012

The OAuth 2.0 Authorization Framework

RFC 6749

D. Hardt (ed.)

RFCStableAuthorizationFoundationField guide

Almost every production 'agent calls an API on behalf of a user' design is still an OAuth 2.0 client using an authorization grant. AAuth, MCP authorization, and A2A security schemes all assume you know this model so they can extend or replace parts of it.

At a glance

Problem
An application needs limited access to a user's resources at an HTTP API without receiving the user's password. OAuth 2.0 splits the resource owner, the client, the authorization server, and the resource server, and issues an access token after an authorization grant.
Identity / authn / authz
Authorization, not identity. OAuth 2.0 does not tell you who the user is; it tells a resource server that a client has been granted some access. The client itself has no portable identity: a client_id is issued by each authorization server and is meaningless elsewhere.

Actors

  • Resource owner (typically a human)
  • Client (the application — an agent is usually this)
  • Authorization server
  • Resource server (API / tool)

01

The gap for agents

RFC 6749 solves delegated access for applications: a client obtains an access token representing a resource owner's authorization, without ever seeing the owner's password. The four roles — resource owner, client, authorization server, resource server — are still the map of almost every production 'agent calls an API' design.

The gap for agents is what 6749 does not give you. The client has no portable identity: client_id is issued by each AS and is meaningless elsewhere. The user is identified only if you add OpenID Connect. The agent instance, the workload binary, and the tool URL are not roles in this RFC. Implicit and resource-owner-password grants exist on the page and are unsafe; agents that cargo-cult 2012 blog posts still implement them.

Treat the agent as the OAuth client, the human as the resource owner, the tool as the resource server. If you need the agent to be a principal of its own at a stranger's API, you have left 6749 and are looking at CIMD, AAuth, or WIMSE.

02

Actors and trust boundaries

The resource owner trusts the authorization server with their login and consent. They should not trust the client with a password. The client trusts the AS to issue tokens and the RS to honor them. The RS trusts the AS's tokens (opaque introspection or JWT signature) and must not trust the client to name the user.

The browser or native user-agent is an untrusted channel for the authorization code. That is why later BCPs add PKCE. Agent runtimes (model context, logs, traces) are additional untrusted channels 6749 never considered: a bearer token that lands in a prompt is stolen.

03

Mechanics

Authorization endpoint (front channel) and token endpoint (back channel) are the two HTTP endpoints that matter. Grant types in 6749: authorization code, implicit, resource owner password credentials, client credentials, plus extension grants. Token endpoint POST uses application/x-www-form-urlencoded: grant_type, code, redirect_uri, client_id, client_secret (or other client auth).

Successful token response: access_token, token_type (typically Bearer), expires_in, optional refresh_token, optional scope. RFC 6749 does not require the access token to be a JWT. Refresh tokens are used only at the token endpoint.

Protected resource access is specified in RFC 6750, not 6749. Scope is a space-delimited string. Redirect URI matching in 6749 was too loose in practice; RFC 9700 / OAuth 2.1 require exact string match.

access_tokenfrom spec
Quoted RFC 6749 credential presented to the RS. Opaque or structured; 6749 does not require JWT.
refresh_tokenfrom spec
Quoted: longer-lived credential for the token endpoint only. Never send to the RS.
scopefrom spec
Quoted: space-delimited permission strings. Too coarse for many tool calls — see RAR and AAuth R3.
client_idfrom spec
Quoted: identifier of the client at this AS. Not a global agent identity.
grant_type=authorization_code | client_credentials | …from spec
Quoted grant_type values. Do not implement implicit or password grants for new agent work.

04

Step-by-step flows

Flow 1 of 2

Authorization code (the grant you should still use)

  1. 1

    Client redirects the resource owner to the authorization endpoint with response_type=code, client_id, redirect_uri, scope, state (and in any modern deployment, PKCE).

  2. 2

    Resource owner authenticates at the AS and consents.

  3. 3

    AS redirects to redirect_uri with code (and state).

  4. 4

    Client POSTs grant_type=authorization_code, code, client authentication, and (in 6749) redirect_uri to the token endpoint.

  5. 5

    AS returns access_token and optional refresh_token. Client calls the RS with the access token.

OAuth 2.1 removes redirect_uri from the token request because PKCE replaced its injection-defense job. Mixed 2.0/2.1 servers may still require it.

Flow 2 of 2

Client credentials (agent on its own behalf)

No user in the hop. The client is the resource owner of its own data, or the AS has some other policy.

  1. 1

    Client POSTs grant_type=client_credentials with client authentication and optional scope / resource.

  2. 2

    AS issues an access token. RFC 9068 will typically set sub to the client.

This is not 'the agent acts for Alice'. For that you need a user grant plus token exchange or AAuth three-party.

05

Identity vs authentication vs authorization

Authorization, not identity. 6749 does not tell you who the user is. OpenID Connect adds that. Client authentication (secret, later mTLS or private_key_jwt) is authentication of the application, not of the user.

Agents that treat 'we did OAuth' as 'we know the user' are mixing layers. The RS sees a token; unless the token is a profiled JWT or the RS introspects, it may not even see a subject.

06

How it composes

  • OAuth 2.1

    2.1 is 6749 plus RFC 9700 minus unsafe grants. New agent work should implement the 2.1 shape even while 6749 remains the deployed RFC.

  • OpenID Connect Core

    Identity layer on this framework. scope=openid, ID Token to the client. Do not send the ID Token to APIs.

  • OAuth Security BCP

    RFC 9700 updates 6749/6750 in place. Read it before implementing 6749 from memory.

  • AAuth

    Replaces pre-registration and bearer tokens for open-world HTTP clients. Complements 6749 rather than editing it.

  • MCP authorization

    MCP HTTP treats the MCP client as a 6749/2.1 client and the MCP server as an RS.

07

What bites agent implementers

  • Implicit and password grants

    Still in the RFC text. RFC 9700 deprecates them; OAuth 2.1 omits them. Agent SDKs that still request response_type=token or collect passwords are out of policy.

  • Bearer leakage in agent context

    6749 has no sender constraint. Tokens in prompts, traces, and tool logs replay until expiry. Pair with DPoP, mTLS, or AAuth signatures.

  • Confused deputy / audience

    6749 access tokens were often globally valid at every API in a deployment. Use RFC 8707 resource and RFC 9068 aud so a calendar token cannot call payments.

  • client_id as agent identity

    A client_id is not portable. Multi-AS agents either register everywhere (DCR/CIMD) or use AAuth/WIMSE identifiers.

08

Stability — what you can ship

RFC 6749, October 2012, D. Hardt (ed.), Proposed Standard, universally deployed. Still the baseline. Implement it only as constrained by RFC 9700 (January 2025) and, for new clients, OAuth 2.1 draft-16. Primary: https://www.rfc-editor.org/rfc/rfc6749.html

Catalog claims (short form)

access_token
Opaque or structured credential presented to the resource server. RFC 6749 does not require a JWT.
refresh_token
Longer-lived credential used only at the token endpoint to mint new access tokens.
scope
Space-delimited permission strings. Too coarse for many agent tool calls; later specs (RAR, AAuth R3) address this.
client_id
Identifier of the client at this authorization server only. Not a global agent identity.

Implementer notes

Still the deployed baseline. Do not implement the Implicit or Resource Owner Password Credentials grants for new work. Pair with RFC 9700. For agents, treat the agent as the OAuth client, not as a new OAuth role.

Relationship to others

Primary sources

  • RFC 6749https://www.rfc-editor.org/rfc/rfc6749.html
  • Datatrackerhttps://datatracker.ietf.org/doc/rfc6749/