ReleaseInsight · On RadarAWS Machine Learning Blog→ original

Okta and AgentCore Bring AI Agents Under Control: Access Revocation in 1 Second

When an AI agent acts on behalf of a person, shared service accounts and per-application OAuth consent do not answer the central question: which agent may act for which user, and where. AWS demonstrated an integration between Okta Cross App Access and Amazon Bedrock AgentCore: Okta evaluates policy on every request, while AgentCore Identity exchanges the decision for a short-lived token, keeping secrets out of the agent's code.

AI-processed from AWS Machine Learning Blog; edited by Hamidun News
Okta and AgentCore Bring AI Agents Under Control: Access Revocation in 1 Second
Source: AWS Machine Learning Blog. Collage: Hamidun News.
Listen to article
Article Fact Sheet & Key Figures
ParameterDetails
Primary sourceAWS Machine Learning Blog ↗
Editor-in-Chief
Assignment revocationOkta rejects new requests in approximately 1 second
Key metric #2Issued tokens remain valid for no more than 5 minutes after revocation
Key metric #3AgentCore Identity adds about 0.6 seconds to a 30-second request

An agent that updates a ticket or reads a customer record operates on behalf of a person and inside applications that person can access. This raises an awkward question for security teams: exactly which agent is entitled to act for which user in which application, and how can it be stopped? Per-application OAuth consent and shared service accounts do not answer that question. In the first part of its walkthrough, AWS proposes an answer based on Okta Cross App Access (XAA) and Amazon Bedrock AgentCore.

Who Is Responsible for What

The division is straightforward. Okta is the control plane: it decides which agent may act for which user and on which resource. AgentCore Identity is the execution plane: it stores the agent's credentials, converts Okta's decision into a token accepted by the resource, and preserves both identities in that token—the user and the agent.

Three tokens participate in every request. The ID token identifies the user. The ID-JAG is Okta's decision itself: it is single-use and valid for 5 minutes. The access token is what the target resource accepts; it is also valid for 5 minutes, identifies both the user and the agent, and carries the user's groups.

The chain works as follows. The user signs in to the frontend (BFF) through OpenID Connect. The BFF exchanges the user's ID token for an ID-JAG in Okta under RFC 8693, authenticating itself as the agent.

Okta verifies that the agent is active, that the user is assigned to it, and that an administrator connected the agent to the correct authorization server with the required scopes. The BFF then invokes the agent in the AgentCore runtime, passing the ID-JAG as a bearer token. The runtime's JWT authorizer accepts only ID-JAGs issued by Okta specifically for that agent.

AgentCore Identity then exchanges the ID-JAG for an access token under RFC 7523, which the agent uses to access MCP servers. The task manager checks that the token was obtained by a registered agent and that the user's group and scope permit the specific tool.

Where It Is Easy to Trip Up

The authors candidly list the pitfalls they encountered themselves.

First, Okta rejects an ID-JAG request if it contains OpenID Connect scopes such as openid or profile, returning an invalid_scope error. At least one custom scope—and no standard scopes—is required.

Second, the ID token must come from the same application associated with the agent. A token from another application breaks the exchange with an error saying that the client is not registered for delegation.

Third, each agent needs its own Okta credential provider. Attempting to redeem one agent's ID-JAG on behalf of another is rejected because the client_id values do not match.

Fourth, the SDK stores the workload access token in BedrockAgentCoreContext, not in the request headers. The authors' first implementation looked for it in the headers, failed to find it, and sent all 21 tested requests down a fallback path using a second workload identity. The token must be read from the context.

Finally, the ARN segment in the IAM policy is written as oauth2credentialprovider, without a hyphen; with a hyphen, every call failed with AccessDeniedException. The agent role needs only two statements: GetResourceOauth2Token and permission to read the provider secret.

Numbers and Limitations

After an administrator removed the user's assignment to the agent, Okta began rejecting new requests in approximately 1 second, while previously issued tokens expired within 5 minutes. The first call, including ID-JAG redemption, took about half a second, and AgentCore Identity added roughly 0.6 seconds overall to a request lasting around 30 seconds. A second call to another MCP server returned the same token from storage in an average of 58 ms, without redeeming the single-use ID-JAG again. A new ID-JAG for the same user produces a new token, so every request reflects Okta's current decision.

Caveats: the code is an educational, non-production example; the snippets illustrate the pattern, not a ready-made solution. Tests ran on the free Okta Integrator tier in a single AWS region (Oregon). The walkthrough takes about an hour. Production requires MFA, secret rotation—or Private Key JWT instead of a shared secret—and reviews by security and legal teams.

What to Do

If your agents access internal systems through a shared service account, it is time to reconsider the architecture. Register the agent as a separate entity in the IdP, restrict its scopes, keep tokens short-lived, and verify user permissions within the tools themselves, not only at entry. Part two promises the same treatment for AgentCore Gateway, Cedar policies, an agent on EKS, and auditing in CloudWatch.

Story

Key Questions Answered

Who Is Responsible for What?

The division is straightforward. Okta is the control plane: it decides which agent may act for which user and on which resource. AgentCore Identity is the execution plane: it stores the agent's credentials, converts Okta's decision into a token accepted by the resource, and preserves both identities in that token—the user and the agent. Three tokens participate in every request. The ID token identifies the user. The ID-JAG is Okta's decision itself: it is single-use and valid for 5 minutes.

Where It Is Easy to Trip Up?

The authors candidly list the pitfalls they encountered themselves. First, Okta rejects an ID-JAG request if it contains OpenID Connect scopes such as openid or profile, returning an invalid_scope error. At least one custom scope—and no standard scopes—is required. Second, the ID token must come from the same application associated with the agent. A token from another application breaks the exchange with an error saying that the client is not registered for delegation.

What are the key details on Numbers and Limitations?

After an administrator removed the user's assignment to the agent, Okta began rejecting new requests in approximately 1 second, while previously issued tokens expired within 5 minutes. The first call, including ID-JAG redemption, took about half a second, and AgentCore Identity added roughly 0.6 seconds overall to a request lasting around 30 seconds. A second call to another MCP server returned the same token from storage in an average of 58 ms, without redeeming the single-use ID-JAG again.

ZK
Zhemal Khamidun — CPO at Alpina Digital, product manager of AlpinaGPT. Building AI products since 2019. Hamidun News is a pet project that grew into a production aggregator with 6,000+ readers.
✦ Unified AI Workspace · Nomad

Test Frontier LLMs & Autonomous Agents in One Workspace

Run Claude Opus 5.5, GPT-6, Gemini 3.1, and DeepSeek side-by-side in Nomad AI (nomadnet.ai) — unified model routing, deep research, and multimodal workflows under one subscription.

Try Nomad AI →Launch Nomad Agent
What do you think?
Loading comments…