Task 0 · 8 tasks

Identity with Cognito

Get a machine-to-machine token so everything you deploy can prove who is calling.

15 minEasy
Alice’s ask

The “Enterprise Readiness” challenge

The local prototype won Alice over. Now she wants it in production for all 1,200 employees, and IT has one rule: nothing gets called without a verifiable identity.

In the original workshop this meant an hour of console clicking. Here the platform does it, and you spend the time understanding what a token actually carries.

Platform

What the platform provisions for you

terminal
uv run bootcamp.py up 0
  • A Cognito user pool for you, with a resource server and the scope datastream/mcp.access
  • An app client allowed to use the OAuth client credentials (M2M) flow
  • A Cognito domain that issues tokens (named ds-<10 hex chars>-<account>)
  • Nothing for model access: your laptop already reaches the LiteLLM gateway keylessly with your participant role

The very first up 0 pauses for about 5 minutes on purpose: a new Cognito domain needs time for DNS to propagate.

You

What you do as a developer

  1. Get a token

    terminal
    uv run bootcamp.py token

    That long string is a JWT. Every later stage (MCP runtime, Gateway, Agent) checks it.

  2. Read the token

    Challenge

    Decode your token and find the claim that lets you call MCP tools, and the claim that says which app client you are.

    Hint 1

    A JWT is three base64url parts separated by dots: header, payload, signature. The claims live in the payload; you don't need the signature to read them.

    Hint 2

    Split on ., take part 1, pad it to a multiple of 4 and base64.urlsafe_b64decode it. Look at scope and client_id.

    Solution
    terminal · macOS / Linux
    TOKEN=$(uv run bootcamp.py token)
    uv run python -c "import base64,json,sys; p=sys.argv[1].split('.')[1]; print(json.dumps(json.loads(base64.urlsafe_b64decode(p + '=' * (-len(p) % 4))), indent=2))" "$TOKEN"
    terminal · Windows PowerShell
    $TOKEN = uv run bootcamp.py token
    uv run python -c "import base64,json,sys; p=sys.argv[1].split('.')[1]; print(json.dumps(json.loads(base64.urlsafe_b64decode(p + '=' * (-len(p) % 4))), indent=2))" $TOKEN

    scope is datastream/mcp.access: the resource-server scope your runtimes and Gateway require. client_id identifies your M2M app client (the JWT authorizers allow only that client). exp is when it expires.

  3. See your ids

    terminal
    uv run bootcamp.py status

    Prints POOL_ID and friends. Later stages add more lines here.

Check your work

terminal
uv run bootcamp.py test --only 0

Three checks pass: Cognito issues a token for your client, litellm keyless identity (the gateway recognises your role) and no direct bedrock (a direct Bedrock call is refused with AccessDenied, as intended).

Under the hood

Amazon Cognito is AWS's identity provider. For service-to-service calls it uses the OAuth 2.0 client-credentials grant: your app client trades its id and secret for a short-lived access token scoped to datastream/mcp.access. AgentCore resources are configured with a JWT authorizer pointing at the pool's OIDC discovery URL, so they validate signatures and scopes without ever calling Cognito per request.

You work as the role bootcamp-participant-<name>, which the CLI assumes for you (BOOTCAMP_ROLE_ARN only overrides it). That role can only touch resources tagged Participant=<name> or named awsworkshop-<name>-*, and every role you create carries a permissions boundary that blocks direct Bedrock calls: LiteLLM is the only path to a model.