What you’ll be able to do
- Trace who is authenticated and whose permissions apply at each hop from user to agent to tool to downstream service
- Identify confused-deputy gaps where an agent’s broad credential lets a user exceed their own permissions
- Choose between delegated user credentials and service identities based on whose authority an action uses
- Place authorization checks in deterministic code at the resource, not in the model’s context
- Keep credentials out of prompts, tool parameters and logs, and limit their scope and lifetime
What you need to know
Authentication and authorization are separate questions at every hop
Authentication asks who is calling. Authorization asks whether that caller may do this specific thing to this specific resource. A Claude integration has several hops (user to application, application to model, model to tool, tool to downstream service, sometimes agent to agent) and both questions need an answer at each one. Most production gaps come from answering them once at the front door and assuming the answer carries through.
The model sits in the middle of this chain, but it isn't a security principal you can trust. It turns untrusted input (user text, retrieved documents, tool results) into tool calls. Treat every tool call as a request from a potentially manipulated intermediary and authorize it on that basis.
The confused deputy: the most-tested gap
The classic failure: a support agent serving thousands of users calls a CRM tool with one service account that can read every customer record. The user logged in, so the system "knows who they are", but the tool never uses that identity. Ask the agent about another customer's order, or slip an instruction into a document it retrieves, and the agent fetches data the user could never access directly. The agent is a deputy with more authority than the person it's acting for, and it can be talked into using it.
The fix is to carry the end user's identity to the point of enforcement:
- Delegated credentials. When the agent acts on a user's behalf, call the downstream service with a token representing that user and their consented scopes (OAuth-style delegation). The service applies its own permission model, so the agent can't exceed the user.
- Identity propagation with server-side checks. Where the service can't accept per-user tokens, the tool layer passes a verified user or tenant identifier (taken from the authenticated session, never from model-generated arguments) and enforces row- and tenant-level filters in code.
- Service identities for system actions. Scheduled jobs, batch pipelines and back-office automation act as the system itself. Give them dedicated, narrowly scoped service identities, not a developer's personal token or an all-powerful admin key.
Enforcement lives in code at the resource
"Only show users their own records" in the system prompt isn't access control. Neither is asking the model to check a permission field before answering. Authorization must be deterministic and must sit where the model can't route around it: the tool handler, an API gateway, the database's own row-level security, or the downstream service's permission model. The model can reason about permissions to give helpful explanations. It must never be what grants them.
A related point is where identifiers come from. If the model supplies customer_id as a tool argument and the handler trusts it, any user can ask for any customer. Bind identity-bearing parameters to the session server-side, or validate the model-supplied value against what the session is allowed to reach.
Retrieval needs authorization too
RAG pipelines are a common blind spot. If the index holds documents from many teams and permission filtering happens after retrieval, or worse, by telling the model to ignore documents the user can't see, restricted content has already entered the context and can leak into the answer. Apply access filters inside the retrieval query (metadata filters on ACLs or tenant, or separate indexes per tenant where isolation requirements demand it) so unauthorized chunks are never returned.
Credentials stay on the execution side
The model requests actions; it shouldn't hold the keys. Secrets belong in the tool's execution environment (a secret manager, workload identity, environment configuration), never in the system prompt, a tool parameter, or tool results the model can echo back. Scope every credential to what its tool needs and prefer short-lived tokens, so a leak through a log line or a dependency bug is a small incident rather than a breach. Scrub tokens from traces and logs as well. Observability pipelines are a common path for credentials to escape.
Networked MCP servers and multi-agent hops
A stdio MCP server runs as a local subprocess and inherits its launcher's identity. Once a server moves to an HTTP transport and is shared, it's a network service and needs real authentication and per-caller authorization. The MCP specification defines an OAuth-based authorization approach for HTTP transports. Whatever mechanism you use, the server has to know which user or client is calling and limit what each can do. In multi-agent systems, apply the same rule at every handoff: a subagent or remote agent should receive only the authority the task needs, not the orchestrator's full credential set.
Compliance implications
Regulated data raises the stakes rather than changing the principles. Frameworks such as HIPAA and GDPR care about who accessed which personal data and why. Per-user authorization, minimum-necessary access and audit logs that attribute each tool call to a real end user (not to "the agent service account") are what make that question answerable.
Key concept
Authorize every tool call as the end user (or a narrowly scoped service identity), enforced in deterministic code at the resource, with credentials the model never sees.
Questions describe an agent that leaks data across users, a prompt rule standing in for access control, or a shared admin credential behind a tool. The right answer moves enforcement downstream and makes the user's identity reach it. Distractors offer better prompts, output filtering, or more logging.
Practice scenario
Work it through, then open this
This is a confused deputy: the integration account’s authority is used no matter who is asking, and the only check is a prompt instruction the tester talked past. Rewording the prompt won’t close the gap. Take the requesting user’s identity from the authenticated session (never from the conversation), pass it to the tool layer, and enforce the reporting-line check in code before the HR API is called. Better still, use a delegated token or an HR API scope tied to that manager. Narrow the integration account to the fields the assistant needs, and log each lookup against the real requesting user so access is auditable.
Build exercise — Trace identity through one integration
Advanced · 45 min
What you’ll learn
- Mapping authentication and authorization at every hop of an agent integration
- Spotting where a broad credential or model-supplied identifier creates a confused deputy
- Moving a prompt-level access rule into an enforced check
-
Draw the request path for one user-facing agent action: user, front end, orchestrator, model, tool handler, downstream service. At each hop, write who is authenticated and whose permissions are applied.
- Why: Gaps show up where the answer to “whose permissions?” switches from the user to a service account without anyone deciding it should.
- You should see: At least one hop where the user’s identity is dropped or replaced by a broader credential.
-
For every tool, list identity-bearing parameters (user ID, tenant ID, account number) and note whether each comes from the session or from model-generated arguments.
- Why: Model-supplied identifiers that the handler trusts let any user act on any record.
- You should see: A short list of parameters to bind server-side or validate against the session’s entitlements.
-
Pick one access rule enforced only in the prompt, implement it in the tool handler or downstream query, and test it with a prompt-injection attempt and an impersonation attempt.
- Why: A control only counts if it holds when the model has been manipulated.
- You should see: Both attempts refused by code, with an audit record naming the real requesting user.
Exam traps
Assuming the user is authorized because they authenticated to the chat front end
Logging in establishes identity once. Each tool call still needs an authorization decision for that user on that resource.
Backing a multi-user agent with one shared service credential that can see every user’s data
That credential turns the agent into a confused deputy. Use delegated user credentials or propagate identity to a server-side check.
Enforcing data-access rules with system-prompt instructions to the model
Prompts can be argued with or injected. Access control has to be deterministic and live at the resource.
Passing tokens or API keys through the model’s context or as tool parameters
Anything in context can be echoed, logged or exfiltrated. Keep secrets in the execution environment, scoped and short-lived.
Filtering retrieved documents by permission after they have already been placed in context
By then the restricted content can already shape the answer. Filter inside the retrieval query.
Shipping a newly networked MCP server with no auth because the local version never needed it
A stdio server inherits a local identity. A shared HTTP server is a network service and needs authentication and per-caller authorization.
Sources
- Claude Developer Platform Docs
- Model Context Protocol
- Anthropic, Claude Certified Architect – Professional Exam Guide v1.0 (July 2026)