Amazon Cognito Identity Pools: Federate Coding-Agent Tool Callers Without Long-Lived Keys

2 views

Your coding-agent console needs to list S3 artifacts, start a Batch review job, or invoke an API Gateway tool endpoint. Baking AKIA… into the SPA is how you get a GuardDuty finding and a bad week. Amazon Cognito Identity Pools (federated identities) trade a proven user/IdP token for temporary STS credentials bound to IAM roles — humans and UI-driven agent callers get least privilege that expires. Distinct from IAM Roles Anywhere (X.509 for on-prem/machine runners), AppSync subscriptions auth (Cognito user pools as GraphQL authorizer), and VPC Lattice service auth (service-to-service): here we mint AWS creds for tool callers via Identity Pools.

⚡ TL;DR: Authenticate humans with a Cognito User Pool (or OIDC IdP), attach an Identity Pool that maps authenticated role vs guest deny, scope IAM to specific tool APIs/S3 prefixes, and refresh via the Amplify/AWS SDK credential chain. Related: IAM Roles Anywhere, VPC Lattice service auth, API Gateway + WAF rate limits, Verified Permissions.

Identity Pools vs User Pools (stop mixing the terms)

Piece Job
User Pool Sign-up/sign-in, JWT for your app APIs
Identity Pool Exchange JWT (or public provider token) → AWS credentials
IAM role (authenticated) What those creds may call
IAM role (unauthenticated) Usually deny-all for coding-agent consoles

❌ Using only a User Pool access token against AWS APIs that require SigV4 — you need Identity Pool (or a backend that proxies).

Browser
  → User Pool Hosted UI / OIDC
  → JWT
  → Identity Pool GetId + GetCredentialsForIdentity
  → temporary AWS keys
  → SigV4 to API Gateway / S3 / execute-api

Wire an Identity Pool for the coding-agent console

bash
# ✅ identity pool with Cognito User Pool authentication providers
aws cognito-identity create-identity-pool \
  --identity-pool-name coding_agent_console \
  --allow-unauthenticated-identities \
  --cognito-identity-providers \
    ProviderName=cognito-idp.us-east-1.amazonaws.com/us-east-1_ABC,ClientId=clientid123,ServerSideTokenCheck=true

# Prefer allow-unauthenticated-identities=false for agent consoles

Map roles:

bash
aws cognito-identity set-identity-pool-roles \
  --identity-pool-id us-east-1:guid \
  --roles authenticated=arn:aws:iam::111122223333:role/CodingAgentConsoleAuth,unauthenticated=arn:aws:iam::111122223333:role/CodingAgentConsoleDeny
json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "InvokeToolApi",
      "Effect": "Allow",
      "Action": ["execute-api:Invoke"],
      "Resource": [
        "arn:aws:execute-api:us-east-1:111122223333:apiid/*/POST/tools/*",
        "arn:aws:execute-api:us-east-1:111122223333:apiid/*/GET/sessions/*"
      ]
    },
    {
      "Sid": "ReadOwnArtifacts",
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:ListBucket"],
      "Resource": [
        "arn:aws:s3:::coding-agent-artifacts-prod",
        "arn:aws:s3:::coding-agent-artifacts-prod/tenant/${cognito-identity.amazonaws.com:claims.tenant}/*"
      ],
      "Condition": {
        "StringEquals": {
          "s3:ExistingObjectTag/tenant": "${cognito-identity.amazonaws.com:claims.tenant}"
        }
      }
    },
    {
      "Sid": "DenyBedrockDirect",
      "Effect": "Deny",
      "Action": ["bedrock:*"],
      "Resource": "*"
    }
  ]
}

Force tool calls through your API (Cedar/Verified Permissions) instead of letting the browser hit Bedrock directly — Identity Pool creds should be narrow.

Browser / gateway credential provider

typescript
// ✅ Amplify v6 / fromCognitoIdentityPool pattern (illustrative)
import { fromCognitoIdentityPool } from "@aws-sdk/credential-providers";
import { SignatureV4 } from "@smithy/signature-v4";

const credentials = fromCognitoIdentityPool({
  clientConfig: { region: "us-east-1" },
  identityPoolId: "us-east-1:guid",
  logins: {
    "cognito-idp.us-east-1.amazonaws.com/us-east-1_ABC": idTokenJwt,
  },
});

// Use credentials with API Gateway SigV4 or AWS SDK clients
// ❌ process.env.AWS_SECRET_ACCESS_KEY in Vite bundle

For server-side agent gateways calling on behalf of a user, prefer backend assumes a role with the user’s identity in context (or Identity Pool on the server with the user’s JWT) — never forward long-lived keys to the model context.

Principal tags and tenant isolation

Pass tenant claims into the Identity Pool role session with principal tags so IAM conditions work:

bash
# role trust policy fragment — allow Cognito identity to assume with tags
{
  "Effect": "Allow",
  "Principal": { "Federated": "cognito-identity.amazonaws.com" },
  "Action": ["sts:AssumeRoleWithWebIdentity", "sts:TagSession"],
  "Condition": {
    "StringEquals": {
      "cognito-identity.amazonaws.com:aud": "us-east-1:guid"
    },
    "ForAnyValue:StringLike": {
      "cognito-identity.amazonaws.com:amr": "authenticated"
    }
  }
}

Map custom attributes (custom:tenant_id) via rules. Combine with Access Analyzer reviews so the authenticated role does not slowly accrete * powers.

When not to use Identity Pools

Caller Prefer
On-prem / CI machine runner IAM Roles Anywhere
Service → service inside VPC VPC Lattice auth / IAM SigV4 mesh
GraphQL subscriptions only AppSync + User Pool JWT (AppSync progress)
Overnight Batch jobs Job role on the Batch job definition — no Cognito

Rate-limit public execute-api with WAF. Watch for stolen JWTs with GuardDuty.

Failure modes

Issue Symptom Mitigation
Unauthenticated enabled Anonymous AWS calls Disable unauth; deny role
Overbroad authenticated role Browser can bedrock:InvokeModel Deny Bedrock; proxy via API
Missing TagSession Tenant conditions fail open/closed Require sts:TagSession; test
Token in localStorage XSS Session theft HttpOnly patterns / short TTL / CSP
Confused IdP Wrong user pool client ServerSideTokenCheck=true

Production checklist

  • [ ] User Pool (or enterprise OIDC) for humans; Identity Pool for AWS creds
  • [ ] Unauthenticated identities disabled for agent consoles
  • [ ] Authenticated role least privilege; explicit Deny on Bedrock if proxied
  • [ ] Tenant principal tags + S3/API conditions tested
  • [ ] No long-lived keys in frontend bundles or agent prompts
  • [ ] WAF rate limits on tool APIs; Cognito advanced security optional
  • [ ] Distinct from Roles Anywhere / Lattice / AppSync user-pool-only auth
  • [ ] Access Analyzer + periodic role review
  • [ ] Document token TTL / refresh UX

FAQ

Q: Identity Pool or just exchange code for API Gateway JWT authorizer?
A: If every AWS call is behind your HTTP API, a JWT authorizer may be enough — no AWS creds in the browser. Use Identity Pools when the client must SigV4 to AWS (S3 direct, execute-api IAM, AppSync IAM mode).

Q: Can agents themselves use Identity Pools?
A: UI-driven and user-delegated callers yes. Headless Batch/ECS workers should use task/job roles. Don’t put Cognito user passwords in agent tool configs.

Q: Guest access for demos?
A: Separate demo pool with tiny quotas and kill-switch — never the prod authenticated role with a “temporary” Allow.

Related reading

Federate the human. Mint temporary creds. Keep AKIA out of the SPA — and out of the model’s mouth.

Last updated on October 4, 2026

Deep-dive PDF

Get the expanded guide for this post — extra diagrams-style checklists, failure modes, and a production walkthrough. Free when you subscribe to CheatCoders.

Already subscribed? or open the subscribe page.


Discover more from CheatCoders

Subscribe to get the latest posts sent to your email.

Comments

No comments yet. Why don’t you start the discussion?

Leave a comment

No account needed. Name and email are optional.