← Course Home
Module 2

Identity & Access Control for AI Agents

The agent identity problem, Token Vault and credential management, the Amazon Bedrock AgentCore IAM condition keys, and preventing confused-deputy attacks.

⏱ ~30 min · Identity
SURFACE · IDENTITY

The Agent Identity Problem

Traditional IAM answers "which principal is making this call?" Agents break that model in three ways, and each one needs a purpose-built answer.

Agents act on behalf of users

A single agent serves many users. Its permissions must narrow to the specific user of the current session — not the union of everyone it ever serves.

Agents access third-party tools

Slack, GitHub, market-data APIs. Each needs credentials the agent must hold securely and use only when authorized.

Agents need delegated permissions

The agent needs a way to prove "I'm acting for user X" downstream, without becoming a universal super-principal.

Amazon Bedrock AgentCore Identity architecture

Amazon Bedrock AgentCore Identity — which is powered by Amazon Cognito — provides a centralized agent identity directory plus a Token Vault. Every agent gets a unique identifier (an ARN), and it works with your existing identity provider, so there's no user migration or rebuilt auth flow. It supports the protocols agents actually need:

SigV4
AWS-native

Signed requests to AWS services.

OAuth 2.0
Third-party

Delegated access to external tools.

API keys
Simple services

For services without OAuth.

Secrets
Secrets Manager

Managed storage & rotation.

Token Vault & Credential Management

The Token Vault stores and rotates OAuth tokens so agents can reach third-party tools without ever seeing raw long-lived secrets.

Store & rotate

The Vault holds OAuth tokens and refreshes them, keeping credentials out of agent code and prompts.

JWT authorizers

Agent-to-service auth uses JWT authorizer patterns so each call carries a verifiable, scoped token.

OAuth for MCP

Agents authenticate to MCP servers through the Vault, so tool access is brokered, not embedded.

Anti-pattern Never embed credentials in agent prompts or memory. Anything in the prompt can be echoed back by prompt injection, and anything in memory persists as a durable secret leak. Credentials belong in the Token Vault or Secrets Manager — nowhere else.

Think of the Token Vault as a valet: the agent hands over a claim ticket (its identity), and the Vault produces the right credential for the right tool at the right moment — the agent never holds the keys directly.

Two ways to say "I'm acting for user X" — only one is verified

When an agent needs a token on a user's behalf, there are two paths, and they are not equivalent in security terms.

JWT path — use this in production

  • GetWorkloadAccessTokenForJWT
  • Validates the token's issuer, signature, and expiry
  • Agent identity is bound to the user's verified identity

UserId path — development only

  • GetWorkloadAccessTokenForUserId / the X-Amzn-Bedrock-AgentCore-Runtime-User-Id header
  • Treats the user identifier as an opaque string — no IdP verification
  • Fine for quickstarts, or when identity is resolved upstream
If you do use the header Derive its value from the authenticated principal's context, never from a client-supplied field. Otherwise any authenticated user can impersonate any other user by changing one header. Better still: for workloads that always have a JWT, explicitly deny bedrock-agentcore:GetWorkloadAccessTokenForUserId and bedrock-agentcore:InvokeAgentRuntimeForUser in IAM, so every identification must go through the cryptographically verified path.
Configure JWT authorizers completely A JWT authorizer is only as strong as the fields you fill in. Set the discovery URL, allowed audiences, allowed clients, allowed scopes, and any required custom claims. A runtime supports one auth method at a time — create separate versions for different types.

IAM Policies with Amazon Bedrock AgentCore Condition Keys

Amazon Bedrock AgentCore ships eight service-specific IAM condition keys. They let you scope permissions to a specific key, network, namespace, strategy, session, actor, or user — the building blocks of least privilege for agents.

KmsKeyArn

bedrock-agentcore:KmsKeyArn — require a specific CMK.

subnets

bedrock-agentcore:subnets — pin to approved subnets.

securityGroups

bedrock-agentcore:securityGroups — pin to SGs.

namespace

bedrock-agentcore:namespace — scope memory namespace.

strategyId

bedrock-agentcore:strategyId — scope memory strategy.

sessionId

bedrock-agentcore:sessionId — scope to a session.

actorId

bedrock-agentcore:actorId — scope per acting user.

userid

bedrock-agentcore:userid — scope to a user id.

Example — scope an agent's actions to the acting user

# Only allow reading events for the actor bound to this session { "Effect": "Allow", "Action": "bedrock-agentcore:GetEvent", "Resource": "*", "Condition": { "StringEquals": { "bedrock-agentcore:actorId": "${aws:PrincipalTag/actorId}" } } }
This is how you honor M1's warning The actorId and sessionId keys are how you enforce the session-to-user binding that the Runtime does not do for you. Scope memory and tool access per actor and you close the gap.

Preventing Confused-Deputy Attacks

A confused deputy is a service tricked into using its privileges on an attacker's behalf. Cross-service agent calls are a classic setup for it. AWS gives you two global condition keys to shut it down.

aws:SourceArn

  • Restrict which specific resource may induce the call
  • Ties the trust to one known ARN, not "any caller"

aws:SourceAccount

  • Restrict which account may induce the call
  • Blocks cross-account confused-deputy paths

For cross-account agent deployments, pair these with resource-based policies so the resource itself states who may use it — defense that holds even if an identity policy is misconfigured.

Rule of thumb: any time an Amazon Bedrock AgentCore resource can be invoked by another service, add aws:SourceArn and aws:SourceAccount conditions. It's cheap, and it removes an entire attack class.

Sources