AI Engineer World's Fair 2025
How to Secure Agents using OAuth
Read the talk
How to Secure Agents Using OAuth
Connecting agents through static API keys expands their reach and their risk. OAuth separates access decisions from APIs, but securing agents also requires identity, delegation and control over downstream actions.
From a talk by Jared Hanson
Before you start: Familiarity with HTTP APIs, API keys and the basic purpose of an MCP server is helpful; OAuth concepts are introduced as they appear.
The cost of connecting more systems
What happens when the API key pasted into one MCP server’s configuration becomes the access pattern for hundreds or thousands of agents? Jared Hanson, Keycard co-founder and Passport.js creator, approaches that question after building identity infrastructure at Auth0 and working at Okta. More connected agents can automate more work, but their usefulness creates an access-control problem: grant broad access and accept the exposure, or restrict access and lose capabilities.
The configuration pattern makes the problem concrete. Developers obtain long-lived, broadly scoped API keys, paste them into configuration files or environment variables, and let agents use them. Repeating that setup multiplies the credentials and permissions that need protection. The alternative is dynamic access: use OAuth to obtain authorization through a controlled process instead of treating possession of a static secret as the enduring basis for access.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Follow a calendar connection
OAuth has many extensions, but its basic division of responsibilities is straightforward. An application, called the client, requests access to an API, called the resource server. An authorization server mediates that request. Connecting Calendly to Google Calendar is a familiar example: Calendly wants permission to access a particular person’s calendar.
The browser-based authorization code flow proceeds through these steps:
- Calendly directs the user to Google with a request for calendar access.
- Google establishes that the user is logged in and asks for consent.
- If the user approves, the browser returns an authorization code to Calendly, which exchanges it for an access token.
- Calendly presents that access token to the calendar API.
An optional refresh token lets Calendly obtain replacement access tokens without making the user repeat the entire consent process. This permits short-lived access tokens while maintaining the authorized connection; the actual lifetime is a server policy choice.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Why sign-in appears in an authorization protocol
Sign in with Google or Facebook can make OAuth’s purpose confusing. If OAuth delegates access, why does it also appear to log people in? Hanson starts with the API being accessed: replace the calendar API with a UserInfo endpoint that returns the user’s identifier, name and email address. Access to that information gives the application a basis for identifying the user. OpenID Connect formalizes the identity layer over OAuth, including authentication, identity claims and the UserInfo response.
OpenID Connect adds terminology: the authorization server acts as an identity provider, and the application is a relying party. It also introduces the ID token, a signed JSON Web Token containing claims about the authentication and the user. The application can validate it without making a separate UserInfo request. That makes it useful beyond simply retrieving profile information: it provides an authentication statement intended for the client and also participates in session-related behavior.
In a real application, authentication and authorization commonly run together. The application learns who signed in and obtains access to the user’s calendar through the same overall interaction. The two results still serve different purposes: the ID token informs the client about authentication, while the access token authorizes requests to an API.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Separate token issuance from token verification
The architectural benefit comes from separating three software roles. OAuth formally also includes the resource owner, usually the person granting access, but Hanson’s diagram concentrates on the cooperating systems:
| Software role | Responsibility |
|---|---|
| Client | Obtain, hold and present tokens |
| Authorization server | Mediate access and issue tokens |
| Resource server | Verify tokens and enforce access to resources |
The authorization server issues a token to the client; the client carries it to the resource server. That indirection is what allows the API to rely on a separate system for the authorization process.
Password checks, step-up authentication and consent screens no longer need to be implemented inside each API. The authorization server handles those interactions, and the token communicates the resulting authorization in a form the API can validate. Centralizing that work also gives a collection of applications and APIs a common place to apply policy. An API can enforce access without becoming a login and token-issuance service.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
How MCP lost—and recovered—the third software role
Applying this architecture to agents should be a small conceptual step. A chatbot or agent such as Claude becomes the application connecting through an MCP client; the MCP server provides the resources or tools; an authorization server mediates access. But MCP’s authorization design did not begin there. Hanson describes a protocol only about seven months old at the time of the talk. Its first version focused on local servers and included no authorization mechanism, even though remote servers were already contemplated.
The March 26, 2025 authorization specification was the first OAuth attempt Hanson critiques. Clients implemented the client side of OAuth, but MCP servers were also expected to handle authentication and token issuance. The resource-server and authorization-server responsibilities had effectively collapsed into one component. His warning against learning OAuth from that section concerns this historical revision.
Christian Posta’s The MCP Authorization Spec Is... a Mess for Enterprise appeared five days after the March specification release. It challenged the treatment of the MCP server as both resource server and authorization server. Aaron Parecki followed with Let’s fix OAuth in MCP, pointing to the diagram that made the MCP server itself responsible for authorization. Hanson describes both posts as widely circulated.
The proposed repair was to model the MCP server as an OAuth resource server. Hanson recalls roughly 400 comments on one correction PR, illustrating how much discussion the separation generated. He also recalls recommending that same resource-server model in a January specification review. The lesson is architectural: preserving OAuth’s separate responsibilities keeps every tool provider from inheriting an identity platform’s job.
In the revised draft shown in the talk, the authorization server is separate again. The MCP server validates tokens arriving over HTTP and delegates the authentication and token-issuance machinery to OAuth infrastructure. The subsequent June 18, 2025 specification formalized this separation, including requirements to validate that tokens were issued for the receiving server and to reject token passthrough. Verification still leaves the resource server responsible for enforcing the permissions on each operation. This repairs the client-to-MCP-server connection; it does not yet secure every interaction an agent can initiate.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Whose authority does an agent use?
User delegation is only one reason an agent needs access. An agent may also call another agent or an MCP server on its own behalf. OAuth distinguishes these cases through different flows:
| Situation | OAuth flow | Basis of access |
|---|---|---|
| Agent acts for a user | Authorization code | User delegation |
| Agent acts for itself | Client credentials | Client’s own authorization |
The client credentials grant is for confidential clients that can authenticate appropriately to the authorization server. Running autonomously does not, by itself, make a desktop or mobile agent a confidential client.
That distinction leads to a second question: how does an agent obtain a client identity? The familiar developer workflow is manual—visit a portal, create an application, obtain a client ID and secret, and configure them in the application. MCP aims to connect tools and agents that may have no prior knowledge of one another, so requiring that setup for every pairing introduces substantial friction.
Dynamic Client Registration moves registration to runtime. A client submits its metadata and receives a client identifier and, where applicable, credentials before continuing its OAuth flow. Hanson describes the specification as about ten years old and judges its adoption to have been limited. His central objection is about trust: if registration accepts an uncredentialed assertion of identity, issuing a new credential does not establish who the agent really is.
Registration and verified identity are different properties. Hanson doubts the viability of anonymous registration as the foundation for trusted agents. That criticism applies to open registration; RFC 7591 also allows protected registration, initial access tokens and software statements. The choice is therefore not simply whether to automate registration, but what evidence the authorization server requires before trusting the resulting client.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Public clients and authenticated agents need different identities
For public clients whose identity does not need to be authenticated, Hanson points to Pushed Client Registration. The emerging proposal uses a shared, well-known client identifier and can carry client metadata in the request. It avoids creating and retaining a durable registration record for every client. The April 2025 proposal is an individual Internet-Draft, and its pushed authorization request still involves an exchange and transaction state; the simplification is eliminating persistent per-client registration.
For agents whose identities must be authenticated, Hanson proposes using URLs and public-key infrastructure. His example is an agent identified by agent.com: reuse an identifier people already associate with the application, then connect it to cryptographic keys. The agent signs a JWT assertion or an HTTP message; the recipient verifies the signature with the corresponding public key from a key set. The identity is then backed by proof of possession of a key rather than merely a name supplied during registration.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Access to data is also a question about where it goes
An authorized agent can retrieve data and immediately send it to an LLM. Authorizing the retrieval does not answer the question of which model or software environment receives that data. In a controlled deployment, treating the LLM as another API gives the system a place to apply access policy. That approach becomes less complete when agents run on desktops or mobile devices whose software environment the service operator does not control.
Hanson points toward IETF work on remote attestation and software supply-chain security: obtain evidence about the device and the software running on it, evaluate that evidence, and incorporate the result into an OAuth authorization decision. The goal is to make access sensitive to the environment that will process the data, including the intended LLM destination. Attestation supplies evidence for a trust decision; identifying a client alone cannot provide that environmental assurance.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Ask for permission after the user leaves
Browser-based authorization assumes a user is present to respond. Background agents disrupt that assumption: the user starts a task, walks away, and the agent later discovers that it needs additional access. Hanson asks how permission requests could reach the user through SMS or push notifications instead of requiring the whole interaction to remain in a browser. The security problem includes both obtaining the additional authorization and presenting a request the user can understand in its new context.
Voice, video and fully background operation extend the same question to other interfaces. Hanson points to real-time communication communities and protocols such as SIP, XMPP and WebRTC as sources of prior art. The next authorization interaction may occur while speaking to an assistant or responding to a notification, rather than while looking at a conventional consent page.
This is the product direction Hanson describes for Keycard: identity and access management connecting copilots, custom agents and third-party agents to applications, services and infrastructure through standards-compliant A2A, MCP and OAuth protocols. He closes by inviting both people interested in building that infrastructure and partners building agents to work with the company. The destination is an agent ecosystem in which useful access can expand without making static, broadly privileged credentials its foundation.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Resources
From the talk
The identity layer defining ID Tokens, authentication claims and the UserInfo endpoint.
The historical authorization design discussed in the talk's critique.
Christian Posta explains the enterprise costs of combining resource-server and authorization-server responsibilities.
Aaron Parecki explains separate OAuth roles, protected-resource discovery and token validation.
RFC 7591 defines runtime client registration, including open and protected registration models.
An April 2025 draft for ephemeral clients using a shared identifier and optional metadata in pushed authorization requests.
RFC 9396 represents fine-grained permissions with structured authorization details, including payment requests.
RFC 8693 defines token exchanges supporting delegation and impersonation across service calls.
Further reading
- OAuth 2.0 Authorization FrameworkDocumentation
The foundational definitions of OAuth roles, authorization-code flow, refresh tokens and client credentials.
- Remote Attestation ArchitectureDocumentation
The IETF architecture for evaluating evidence about a system and using attestation results in trust decisions.
Updates since the talk
- MCP's June 2025 authorization specificationDocumentation
The subsequent specification formalizes resource discovery and audience-bound token validation.
- Identity and Authorization Chaining Across DomainsDocumentation
The evolving OAuth draft for carrying identity and authorization across trust boundaries.
- Identity Assertion JWT Authorization GrantDocumentation
A later draft describing how identity assertions support authorization grants for access across domains.
Read the transcript and explore slides
Loading transcript and slides…