Provision an AWS Cognito User Pool
Provision an AWS Cognito User Pool
The following parameters are needed when following these steps to provision a user pool for use with the aws-cognito guard.
- User pool name:
my-user-pool - Hosted UI domain prefix:
my-app - Resource server identifier:
my-api - Resource server scope:
stream - App client name (one per external client):
my-client
Check your selected region
Make sure you have selected the desired region, ex: US East (N. Virginia) us-east-1.
Create the User Pool
aws cognito-idp create-user-pool \
--region us-east-1 \
--pool-name my-user-pool \
--query 'UserPool.Id' --output textNote the returned pool id (e.g. us-east-1_ABC123XYZ) — the aws-cognito guard's options.pool accepts this id directly, the full ARN, or just its suffix.
Create a Hosted UI Domain
The OAuth token endpoint that app clients use to request tokens lives under the pool's Hosted UI domain.
aws cognito-idp create-user-pool-domain \
--region us-east-1 \
--domain my-app \
--user-pool-id <pool-id>The token endpoint is then https://<domain>.auth.<region>.amazoncognito.com/oauth2/token.
Create a Resource Server
A resource server defines the custom scope app clients request when authenticating.
aws cognito-idp create-resource-server \
--region us-east-1 \
--user-pool-id <pool-id> \
--identifier my-api \
--name my-api \
--scopes "ScopeName=stream,ScopeDescription=Stream messages"Create an App Client per External Client
Each external client that authenticates through external.authorization needs its own app client, using the client_credentials OAuth flow (no end user involved):
aws cognito-idp create-user-pool-client \
--region us-east-1 \
--user-pool-id <pool-id> \
--client-name my-client \
--generate-secret \
--allowed-o-auth-flows client_credentials \
--allowed-o-auth-flows-user-pool-client \
--allowed-o-auth-scopes "my-api/stream" \
--supported-identity-providers COGNITONote the returned ClientId and ClientSecret — these are the credentials each client uses to fetch its access token.
Access tokens carry no aud claim
Tokens from the client_credentials grant have token_use: access and no aud claim, so the aws-cognito guard's options.client-id (not options.audience) is what validates them, matched against the token's client_id claim.
Fetch and Inspect a Token
To confirm a client's token has the expected shape (token_use: access, client_id set, no aud):
curl -s -X POST "https://my-app.auth.us-east-1.amazoncognito.com/oauth2/token" \
-u "<client-id>:<client-secret>" \
-d "grant_type=client_credentials&scope=my-api/stream" \
| jq -r .access_token | cut -d. -f2 | tr '_-' '/+' \
| { p=$(cat); case $(( ${#p} % 4 )) in 2) p="${p}==" ;; 3) p="${p}=" ;; esac; printf '%s' "$p"; } \
| base64 -d | jq .Clean Up
Removing everything created above, in reverse order:
aws cognito-idp delete-user-pool-client --region us-east-1 --user-pool-id <pool-id> --client-id <client-id>
aws cognito-idp delete-resource-server --region us-east-1 --user-pool-id <pool-id> --identifier my-api
aws cognito-idp delete-user-pool-domain --region us-east-1 --domain my-app --user-pool-id <pool-id>
aws cognito-idp delete-user-pool --region us-east-1 --user-pool-id <pool-id>Caution
Deleting the user pool removes every user, group, and app client in it — only delete a pool if nothing else depends on it.

