Skip to content

Repository files navigation

agentcorefun — AgentCore Gateway × Okta auth patterns

Hands-on, Terraform-deployable demos of authenticating and authorizing a real MCP client (Claude) to Amazon Bedrock AgentCore Gateway, with Okta as the IdP — exploring two different downstream-auth models, plus the least-privilege provisioning pattern that stands them up.

Everything is verified working end to end (a user logs in via Okta from Claude and per-tool authorization is enforced), and documented with the AWS-isms / Okta-isms / lessons learned we hit along the way.

What's here

Folder / file Pattern In one line
pattern_token_exchange/ On-behalf-of (RFC 8693) The gateway exchanges the user's token for a new, per-audience downstream token that carries the user; per-tool authz via a gateway interceptor. Needs a small CLI shim (the TF provider can't express OBO yet).
pattern_service_account/ Service account + scopes No token exchange: one token (aud + scopes for the API), gateway reaches the Lambda over SigV4 as a service account and forwards the same claims. Scopes decide read/write. 100% native Terraform. Security-data-lake theme.
bootstrap/ Least-priv provisioning broker The one-time privileged Okta setup (API Services app, Private Key JWT, scoped *.manage only) that a repeatable low-priv run uses instead of a standing admin token. Local.
pattern_account_linking_okta/ Account linking / user-consent 3LO (USER_FEDERATION) Okta SSO (a real, verified login) proves who's asking; the agent then mints a GitHub consent URL, the user approves once, and AgentCore's token vault holds the delegated GitHub token — a join table linking two otherwise-unrelated identities, not claim-based OBO. CLI or a serverless web UI.
pattern_agent_token_exchange/ On-behalf-of (RFC 8693), agent-side The agent process itself — no gateway in front — exchanges the user's inbound Okta access token for a different-audience downstream Okta token that still carries the same sub: true claim-based identity propagation, minted by the agent instead of a gateway. Never leaves Okta.
production-architecture.html Topology How this looks in the real world: one MCP front door, privilege distributed across per-system scoped executors. Concentrate the interface, distribute the privilege.

Each folder is a self-contained Terraform root with its own README, a runnable end-to-end tester (login.py or agent.py, per the pattern's README), and terraform.tfvars.example.

Which pattern do I want?

  • The downstream API must authorize the individual user itself, via a gateway already in front of it (per-user data, fine-grained at the resource) → token exchange (pattern_token_exchange). The Lambda gets a token with the user's sub and its own audience.
  • One service account fronts the API and scope is the gate (read vs write, role-ish) → service account (pattern_service_account). Simpler infra; the gateway is a scoped robot and the token's scopes decide what's allowed.
  • There's no pre-existing enterprise IdP delegation at all, and the agent needs a user's interactive consent to an external SaaS (GitHub here, not Okta) → account linking (pattern_account_linking_okta). No silent exchange — a human clicks "Authorize" on the provider's own consent screen (fronted by a real, verified Okta SSO login), and AgentCore Identity's token vault holds the resulting delegated token as a join-table entry, not a claim.
  • The user's identity must reach your own downstream API directly from the agent — no gateway in front, no third-party consent screen, just the agent minting a downstream credential for itself → agent-side token exchange (pattern_agent_token_exchange). The agent calls AgentCore Identity directly and swaps the inbound Okta token for a different-audience Okta token carrying the same sub — true claim-based OBO, never leaving Okta.

The first two share the same front end (Claude → gateway → Okta login → gateway interceptor for per-tool authz); they differ only in how the downstream call is authorized.

Quick start

Pick a folder and follow its README. Minimum you need everywhere:

  • An IdP: a free Okta Integrator/developer org + an API token for pattern_token_exchange/pattern_service_account/pattern_account_linking_okta/ pattern_agent_token_exchange — plus a GitHub App for pattern_account_linking_okta's outbound consent leg (its inbound leg is Okta; GitHub is only the third-party being linked to).
  • AWS creds for us-east-1 / us-west-2, current aws-cli v2, jq.
  • Claude Code ≥ 2.1.30 to connect as an MCP client (static-client OAuth flags) — only relevant to the two gateway-fronted patterns (pattern_token_exchange/pattern_service_account); pattern_account_linking_okta and pattern_agent_token_exchange are CLI-driven demos that don't put Claude in the loop at all.
cd pattern_service_account      # or pattern_token_exchange
cp terraform.tfvars.example terraform.tfvars   # fill in Okta + demo_user_login
terraform init && terraform apply
python3 login.py                # log in via Okta and exercise the tools

pattern_account_linking_okta and pattern_agent_token_exchange follow the same shape (terraform.tfvars.exampleterraform apply) but each needs its own credentials up front and has its own phased quickstart in its README: pattern_account_linking_okta needs both an Okta org and a GitHub App (fill in tfvars, apply, then paste the AgentCore-minted callback URL into the GitHub App by hand); pattern_agent_token_exchange needs only an Okta org — no GitHub, no third party of any kind.

Security (these are demos)

  • Lambdas decode JWTs without verifying signatures; some targets are reachable directly — fine for tracing the flow, not production. Each README lists the hardening (JWKS verification, lock down URLs, scope IAM).
  • Secrets live only in terraform.tfvars + state, both gitignored. Provider lock files are committed for reproducibility.

Credits

Built iteratively with Claude Code — including the debugging journey documented in each pattern's README (the parts that weren't in any single doc).

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages