Skip to content
By AI Security

Your AI Agent Has No Idea Who Authorized It

Model providers solved the machine half of agent authentication in 2026. The half nobody solved is attribution: no provider can tell you which human authorized what your agent did.

Your AI Agent Has No Idea Who Authorized It, by Deepak Gupta on guptadeepak.com

An agent in your product just deleted a customer record. Your audit log says the call came from a service account. It does not say which human asked for it, and there is no provider feature you can turn on that would have told you.

That is the actual gap in AI agent security right now, and it is not the one the industry spent the last year fixing.

I built identity infrastructure at LoginRadius from 2013 and scaled it past a billion identities, so I have watched this exact problem arrive before. It arrived for service accounts in the 2010s, and the answer the industry converged on was delegation: a token that carries both the machine acting and the human it acts for. I wrote up what that architecture looks like for agents in the three-token delegation model. This post is about how much of it actually exists.

The short version: agent authentication in 2026 solved the machine half convincingly and has barely started on the human half.

Verified as of 8 September 2026 against each provider's own authentication documentation, linked inline.

The easy half got solved, quietly and fast

If you last looked at this in 2025, your mental model is out of date. The received wisdom was that model providers ship static API keys with no expiry and no rotation story, and that anyone wanting real credential hygiene had to go through a cloud.

That is no longer true for the two largest direct APIs.

Anthropic ships Workload Identity Federation. You bring an OIDC identity from AWS, GCP, Azure, GitHub Actions, Kubernetes, SPIFFE, or Okta, exchange the JWT under RFC 7523, and receive a short-lived token. Lifetime is configurable from 60 seconds to 24 hours, defaulting to an hour, capped at twice the remaining lifetime of the upstream token. Federation rules match on subject prefix, on claims, or on a CEL expression. Replayed token IDs are rejected and the rejection is visible in the console.

Anthropic also lets you set an expiry when you create a static key, from three hours to thirty days to never, and the choice is immutable afterward. An organization can enforce a maximum. That is a materially better key lifecycle than most internal platforms I have seen.

OpenAI ships the same primitive, covering a similar set of issuers, plus restricted keys with per-endpoint read and write permissions and an organization-level spend ceiling.

So the honest scoreboard on the easy half: scoping exists, expiry exists, and short-lived credentials exist without going anywhere near a cloud provider. Anyone still saying model APIs only offer permanent static keys is describing last year.

The catch is real but narrower than the old claim. Static keys remain the default path in both providers' quickstarts, and the federation route requires deliberate setup that nobody does by accident. The capability exists. The default behavior has not moved.

The half nobody solved

Every mechanism above authenticates a workload. A Kubernetes service account, a CI job, a cloud role. None of them authenticate the person on whose behalf the workload is acting.

That distinction sounds academic until you need it. When your agent takes a consequential action, four questions matter: what happened, what identity called the API, what the agent was permitted to do, and who authorized it. Providers answer the first three well now. The fourth has no first-party answer at the inference layer.

I looked for an on-behalf-of token, something shaped like RFC 8693 token exchange with an actor claim, across OpenAI, Anthropic, Google, AWS Bedrock, and Azure OpenAI. None of the five documents one for its own inference API. Anthropic's federation maps a workload to a service account. OpenAI's does the same. Google's newer Gemini auth keys bind to a service account, which identifies a service, not a person.

Three things come closest, and their limits are instructive.

AWS gets nearest, and it is not an AI feature. STS SourceIdentity persists through chained role assumptions, so a gateway can assume a role on behalf of an end user and keep that user's identity in the CloudTrail record. It genuinely answers "which human." It also predates the agent era entirely, applies to AWS API calls rather than to a model's reasoning, and only works if your integrator wired it up deliberately.

Microsoft built the most agent-native identity object. Entra Agent ID gives an agent a first-class identity, distinct from a human account and from a generic service principal, governable with the same tooling as a human identity, with an agent user account concept maintaining a link back. Azure OpenAI's diagnostic logs record the Entra object ID of the calling principal per request, though only for Entra-authenticated calls and not for API-key calls.

MCP inherits the question rather than answering it. The authorization specification is a subset of OAuth 2.1: the server is a resource server, the client makes requests "on behalf of a resource owner," and there is a separate authorization server. It mandates RFC 8707 resource indicators so a token bound to one server cannot be replayed at another, which is a genuine confused-deputy protection. But authorization is explicitly optional in the spec, and STDIO-transport implementations are told to take credentials from the environment and skip it. MCP adds no delegation primitive beyond whatever OAuth server you point it at.

Why the missing piece is the expensive one

Scoping and expiry limit blast radius. They are containment controls, and containment is worth having.

Attribution is what makes an incident investigable and a decision defensible. When a regulator, an auditor, or an angry customer asks why an automated system did something to them, "a service account did it" is not an answer. It is a description of the mechanism that failed to record the answer.

This gets sharper as agents get more autonomy. An agent that summarizes a ticket is low-stakes. An agent that issues a refund, changes an entitlement, escalates a permission, or sends an email as your company is taking an action a person is accountable for. The accountability exists whether or not the log captured it.

The pattern is familiar to anyone who worked on service accounts. The reason shared service accounts became a governance problem was never that they were insecure in themselves. It was that they collapsed many actors into one identity, and once that happened, no amount of logging could tell you who did what. Agents running on workload credentials reproduce that collapse, with the added complication that the agent's action was not deterministic.

What to do, given that nobody ships the answer

You have to construct attribution yourself, above the provider. Four things, roughly in order of payoff.

Carry the human principal through your own call chain. When a user triggers an agent, attach their identity to the request context and log it alongside every downstream model and tool call your system makes. The provider will not do it for you, and no provider will reject you for keeping your own record.

Give each agent its own credential, not a shared one. One key per agent per environment, at minimum. If you are on Azure, Entra Agent ID is the closest thing to a purpose-built version of this. Shared credentials across agents put you back in the service-account hole before you start.

Use the federation primitives that now exist. If you run on Kubernetes or CI, Anthropic and OpenAI will both accept your existing workload identity and hand back a short-lived token. That removes a stored secret, and a secret that does not exist cannot leak.

Wire SourceIdentity if you are on AWS. It is the only widely available primitive that preserves a human identity across a delegation chain, and it is sitting unused in most deployments.

None of this is provider-specific cleverness. It is ordinary identity engineering, applied to a workload type that arrived faster than the identity layer under it.

The question worth asking your own team

Pick the most consequential thing an agent can do in your product without a human clicking approve. A refund, a permission change, an outbound message, a data deletion.

Now ask whether your logs can name the person who authorized it, or only the credential that executed it.

If the answer is the credential, you have the same gap every provider has. The difference is that you can close yours this quarter, and they have not closed theirs.

Every page on guptadeepak.com is hand-curated by Deepak Gupta. Pick a thread:

Get the newsletter

New writing on identity, AI security, and building software, delivered when it ships. No tracking pixels, no funnels, unsubscribe with one click.