AI agent access control works best as a series of distinct checks: Okta issues a delegated identity grant, Amazon Bedrock AgentCore Gateway validates it, Cedar decides which tools the agent may use, and the MCP server checks the user’s own permissions. AWS described this design and its test results in a tutorial published November 6, 2026. A separate practitioner hypothetical raises another question: what an agent might infer by combining results that were each allowed on their own.
What each layer checks
AWS’s design separates the agent’s delegated authority from the user’s permission to perform an action. The agent’s back-end service passes it an Okta-issued Identity Assertion JWT Authorization Grant, or ID-JAG. The agent forwards that grant to its Gateway, which validates the issuer, audience, permitted client and scopes before redeeming it for access to a target. The target’s configured scopes must match the ID-JAG’s scopes. AWS’s tutorial describes the flow.
Cedar, the policy language used in the example, then evaluates whether that agent and its delegated scope may list or call a particular tool. The example uses permit-only policies with default-deny behavior: an action without a matching permit is not allowed. The MCP server performs a separate check of the user’s groups and scope. Passing the Gateway and Cedar checks therefore does not itself satisfy the target-side user check.
AWS’s design gives each agent its own Gateway and credential provider. In its second-agent example, the agent running on Amazon EKS has a separate Okta registration and a resource connection limited to xaa:read. The agent’s execution role no longer needs token-exchange or provider-secret permissions in this design.
Set the boundary around both who the agent acts for and what the user may do through it.
XAA and per-user OAuth consent
The target application’s authorization server determines which access path fits AWS’s examples. Cross App Access (XAA) applies when the target accepts ID-JAGs; an Okta administrator decides which agent may act for which users, and users see no consent prompt. For a target with its own authorization server, such as the GitHub example, AWS describes a per-user OAuth consent flow instead.
| Access model | Who authorizes? | User consent | Behavior AWS reported in its test |
| XAA | An Okta administrator sets which agent may act for which users; Okta evaluates policy when a token is requested. | No consent prompt in the described flow. | Okta controls stop the next ID-JAG from being issued. Issued XAA ID-JAGs expire within about five minutes. |
| Per-user OAuth consent | The user grants consent to the target application. | The user must connect and consent. | In the GitHub test, suspending Alice did not invalidate an existing one-hour inbound token or stored grant; a new sign-in was refused. Unsuspending her restored access without new consent. Disconnecting the grant made the target report the connection as unavailable. |
These are outcomes from AWS’s described test lanes, not a single revocation rule for every target. The practical decision depends on whether the target accepts ID-JAGs or uses its own authorization server.
What AWS reported in its test
In AWS’s test, Agent A listed six tools. Alice and Carol could not create tasks, while Bob could. Agent B listed four tools because Cedar hid its write tools; it had no write tool for Bob. These outcomes illustrate how the agent/tool policy and the MCP server’s user check operate as separate gates.
AWS also reported p50 and p90 spans from 24 hours of Gateway A observations. The median, or p50, is the midpoint of the observed spans; p90 is the point at or below which 90% of those spans fell.
| Span | p50 | p90 |
Gateway.InboundAuth | 34 ms | 69 ms |
Identity.Authorize | 25 ms | 60 ms |
Identity.GetWorkloadAccessToken | 48 ms | 94 ms |
Identity.GetResourceOauth2Token | 70 ms | 439 ms |
Policy.AuthorizeAction per call | 47 ms | 56 ms |
Policy.PartiallyAuthorizeActions per tool listing | 65 ms | 75 ms |
Gateway.TargetInvocation | 5,565 ms | 6,273 ms |
AWS says the identity and policy spans for one tool call added up to about 0.2 seconds at their medians; the MCP server’s authz.check span took under 1 ms. Those figures describe this test deployment, not a general performance guarantee. AWS also reported that Okta log events reached its CloudWatch stream about one second after publication in its test, allowing identity events to be correlated with AgentCore traces.
When individually allowed results can reveal more together
A practitioner’s hypothetical illustrates a risk that per-call authorization alone may not address: one tool returns payroll totals by team, another returns headcount by team, and a team with one member makes that person’s salary inferable from the combined results. The example is not a reported incident or a measured result.
The design question is whether policy should govern only each tool call or also the combined question and information exposed by multiple outputs. The practitioner suggests keeping the combined query inside a policy-controlled tool or preventing separate outputs from being combined. That is a proposed approach, not a demonstrated guarantee.
Implementation details that can affect the checks
AWS identifies several conditions that matter when adapting its example. Policies that name individual tools did not attach to dynamically listed targets in its tests, so the example relies on static tool schemas. Because the Gateway paginates tools/list by target, a client must follow the returned cursor to see later targets’ tools. Policies also need to be ACTIVE before attaching the policy engine.
For the EKS example, AWS says its Auto Mode general-purpose node pool runs amd64 and recommends building multi-architecture images. Its AgentCore Python SDK binds to localhost unless DOCKER_CONTAINER=true is set in the described container setup. For tracing, AWS says botocore may need to be added for ADOT exports, and the BFF configuration must preserve HTTP client instrumentation so trace context reaches the agent.
AWS describes the snippets as conceptual rather than a complete deployable solution and says the sample code is for non-production use.