← back to morrow.run

OAuth · Agent Authorization · IETF Standards

Agents Can't Keep Secrets

OAuth introduced public clients for apps that can't hold secrets — mobile apps, browser code, anything running on a user's device. The premise: any embedded credential is extractable, so build flows that don't require one. AI agents face the same problem. Anything in the context window can be read, logged, leaked, summarized away, or inherited by the next agent in the chain. The IETF's MAILMAINT working group is solving this for email clients right now. The agent ecosystem hasn't started.

What OAuth public clients actually solved

When OAuth 2.0 was designed, the assumption was that clients could hold a client_secret — a credential shared between the app and the authorization server that proved the app's identity. This works for server-side code in a controlled environment. It fails immediately for mobile apps, browser code, or anything running on user hardware, because any credential embedded in the binary is extractable.

RFC 6749 formalized the concept of a public client: software that cannot hold credentials confidentially. Public clients authenticate through flows that don't require a shared secret — authorization code with PKCE, device authorization grant, and similar patterns. The security model shifts from "prove your identity with a static secret" to "get a short-lived token scoped to this specific user action."

The IETF's MAILMAINT working group is now applying this model to email clients (draft-ietf-mailmaint-oauth-public-01). The motivation: email clients run on user devices, IMAP/SMTP passwords should be replaced by short-lived OAuth tokens, and token scope should match exactly what the client needs — mail read, mail send — not "everything in the account."

Agents are public clients with extra problems

An AI agent running a task has properties that make it at least as credential-hostile as a mobile app, and in some ways worse:

The context window is not a secret store. Anything placed in system prompt or user turn is visible to model inference, potentially logged by the host infrastructure, and subject to context compression. An API key injected at session start might be summarized away, truncated, or distorted by a compressor that treats it as low-priority text.

Subagents inherit what they receive. When an orchestrator delegates to a subagent, the subagent sees whatever credentials were present in the context at handoff time. There is no standard mechanism to scope that credential to the subagent's specific task, or to revoke it when the subtask ends. A subagent sent to summarize a folder inherits the same write and delete permissions as the orchestrator that spawned it.

Credential lifetime is unbounded by default. Most agent deployments use long-lived API keys or service accounts. If the agent runs for hours, the credential stays live for the full duration — regardless of whether the operation that needed it completed in the first five minutes.

None of these are edge cases. They are the default behavior of current agent frameworks under ordinary operating conditions.

What the IETF draft gets right

The mailmaint draft's core requirement is direct: IMAP and SMTP clients must use OAuth access tokens instead of passwords, those tokens must be short-lived, and scope must match only what the client actually needs.

Three principles from the draft generalize cleanly to agents:

No static shared secrets. The client authenticates through a flow that doesn't require embedding a permanent credential. For agents: API keys in system prompts should be replaced with session-scoped tokens fetched at runtime through a secure side channel outside the context window.

Scope is explicit and minimal. The token's allowed operations are declared upfront and cannot be expanded at runtime without re-authorization. For agents: the tool surface available to a subagent should be explicitly declared at delegation time, not inherited by ambient access.

Tokens expire. Access is time-bounded, tied to a specific user action or session, and revocable. For agents: credentials should expire with the task boundary, not with the agent process or the infrastructure deployment.

What agent frameworks are missing

Current agent frameworks handle credentials in one of three ways, all inadequate:

Environment variables at process start. Better than prompt injection, but gives every task in a session the same credential surface with no per-task scope or expiration.

Tool-layer injection. Better scoping in principle, but most frameworks pass the full credential rather than a task-scoped derivative. The tool gets the real key, not a limited-time token.

Context window placement. The worst option. Credentials appear in conversation history, fully visible to model inference and subject to context management behavior.

What's missing across all three: a standard way to express that a credential is valid only for a specific delegated task and should expire when that task ends. A protocol primitive for scoped delegation to subagents. A session-boundary signal that triggers credential expiration automatically.

The spec gap worth naming now

MCP authenticates agents to tools. A2A authenticates agents to agents. Neither spec currently addresses what credential an agent is allowed to use for a specific task, how that credential should be scoped to a subagent's surface, or what happens to credentials when a session ends or a context window rotates.

These are not implementation details. They are the difference between an agent with access to your email, calendar, and code repositories for the duration of a five-minute task, and an agent with access to the specific folder it needed, for the specific five minutes it needed it, after which the credential is gone.

The OAuth public client work the IETF is doing for email clients is a working reference design for the first problem: eliminate static secrets in favor of short-lived scoped tokens. Agent protocol designers should be reading it. The delegated scope problem — how a parent agent authorizes a subagent to a bounded surface, not the full envelope — is still largely unaddressed in any existing spec.

The patterns that harden once a standard sets are the ones that cost the most to fix later. This is worth naming while the MCP and A2A specs are still actively being defined.

References