Skip to content

Instantly share code, notes, and snippets.

@amcginlay
Last active May 2, 2022 15:17
Show Gist options
  • Save amcginlay/b2ee81e8d2e603042f322528535480fd to your computer and use it in GitHub Desktop.
Save amcginlay/b2ee81e8d2e603042f322528535480fd to your computer and use it in GitHub Desktop.
Demo steps for Cognito User Pools and Identity Pools
<Cognito User Pool Demo with Chalice>
PART 1
- Create a new user pool (e.g. apm-demo-user-pool), click Review Defaults and create pool
- Show User and groups -> (empty)
- Show Policies -> deselect all password checkboxes (keep things simple) and save changes
- Show General settings / App clients ->
--- Add
--- set App client name (e.g. apm-demo-app-client)
--- Disable Generate client secret (so later call to "aws cognito-idp initiate-auth" doesn't barf)
--- Enable username based password authentication (the 3rd of 5 options - ALLOW_USER_PASSWORD_AUTH)
--- Client Create app client
--- Note App client ID (if necessary)
- Show App client settings ->
--- Locate your app client by ID (may only be one ATM)
--- Select Enabled Identity Providers -> Select All (includes Cognito User Pools)
--- Set callback URL (e.g. https://www.example.com - NOTE "http" not supported)
--- OAuth2 Flows -> Enable Implicit grant (without this we cannot launch a hosted UI)
--- OAuth2 Scope -> Enable email and openid (will error unless both selected)
--- Click Save changes (NOTE host UI unavailable until Domain Name specified)
- Go to Domain name ->
--- Set Domain prefix as appropriate (e.g. apm-demo)
--- Click Check availability
--- Click Save changes
- Go back to App client settings for your app client ID and click Launch hosted UI
- Click Sign up
- Generate and copy an email address from https://www.guerrillamail.com
- Fill in Sign Up form with User (please use "alan"), Email and Password
- ... DON'T wait for the Emailed Verification Code ...
- Show User and groups -> (no longer empty but one is Account status UNCONFIRMED)
- Select the UNCONFIRMED user and click "Confirm User" (if short on time)
- Once more, go back to App client settings again and click Launch hosted UI
- Sign in to see how Cognito decorates the URL as it navigates to https://www.example.com
- Use the following commands to extract the id_token from that URL ...
url="<URL>" # --- DON'T FORGET THE QUOTES!
echo ${url} | cut -d'#' -f2 | cut -d'&' -f1 | cut -d'=' -f2
- ... and enter it into https://jwt.io/ (note this displayes the username and email)
PART 2
- Grab the AWS resource IDs
user_pool_id=$(aws cognito-idp list-user-pools --max-results 5 --query 'UserPools[?Name==`apm-demo-user-pool`].Id' --output text)
user_pool_arn=$(aws cognito-idp describe-user-pool --user-pool-id ${user_pool_id} --query 'UserPool.Arn' --output text)
app_client_id=$(aws cognito-idp list-user-pool-clients --user-pool-id ${user_pool_id} --query 'UserPoolClients[0].ClientId' --output text)
- Use Chalice to build a serverless app behind API Gateway (perhaps SAM or CDK?)
--- run "pip install chalice"
--- run "chalice new-project apm-demo && cd apm-demo"
--- Open app.py for orientation purposes
--- run "chalice deploy"
--- update app.py as follows (note the use of user_pool_arn env var)
------
cat <<EOF > ~/environment/apm-demo/app.py
from chalice import Chalice
from chalice import CognitoUserPoolAuthorizer as cpa
app = Chalice(app_name='apm-demo')
auth = cpa(
'apm-demo-user-pool', provider_arns = ['${user_pool_arn}']
)
@app.route('/secret', authorizer = auth)
def secret():
return {'open': 'sesame'}
@app.route('/')
def index():
return {'hello': 'world'}
EOF
------
--- again, run "chalice deploy"
--- test endpoint (curl) -> "/" should be authorized but "secret" is unauthorized
- Click around in API Gateway, show authorizers
- Authenticate with user pool to generate tokens (note the use of app_client_id env var here)
--- aws cognito-idp initiate-auth --auth-flow USER_PASSWORD_AUTH --client-id ${app_client_id} --query 'AuthenticationResult.IdToken' --output text --auth-parameters USERNAME=alan,PASSWORD=<PASSWORD>
- NOTE you extract the <IdToken> JWT for API Gateway ... <AccessToken> is similar but more typically used for OAuth/OIDC
- Use Postman with "TYPE: No Auth" to call unsecured endpoint
--- / -> works!
- Use Postman with "TYPE: No Auth" to call secured endpoint
--- /secret -> "Unauthorized"
--- Change to "TYPE: Bearer Token" and paste in the <IdToken>
--- /secret -> works!
- Use Postman to hook out the curl syntax so you can reproduce the /secret demo in your terminal
- Go to https://jwt.io and paste in the <IdToken> (or <AccessToken> for comparison)
- [Consider extending this to federate in with Okta]
<Cognito Identity Pool Demo>
- Identity pool return AWS credentials
- authenticated (e.g. S3-Full) OR unauthenticated (e.g. S3-Read)
- Identity pool has no user directory
- Create a new Identity Pool (e.g. apm-demo-identity-pool)
- Set authenticated and unauthenticated roles
- Show Unauthenticated identities
--- Set Enable access to unauthenticated identities
- Show Authentication providers ... use: echo ${user_pool_id} && echo ${app_client_id}
--- Set Cognito User Pool ID
--- Set Cognito App client Id
- Grab the Identity Pool ID
--- identity_pool_id=$(aws cognito-identity list-identity-pools --max-results 5 --query 'IdentityPools[?IdentityPoolName==`apm-demo-identity-pool`].IdentityPoolId' --output text)
- [ USING UNAUTHENTICATED ROLE ]
- Generate an temp user (IdentityId) and associated credentials
--- unauth_id=$(aws cognito-identity get-id --identity-pool-id ${identity_pool_id} --query 'IdentityId' --output text)
--- creds=($(aws cognito-identity get-credentials-for-identity --identity-id ${unauth_id} --query 'Credentials.[AccessKeyId,SecretKey,SessionToken]' --output text))
--- echo ${creds[*]} # just to see what we have
--- AWS_ACCESS_KEY_ID=${creds[0]} AWS_SECRET_ACCESS_KEY=${creds[1]} AWS_SESSION_TOKEN=${creds[2]} aws sts get-caller-identity
- ************ NOT WORKING !!!!! ***************
- [ USING AUTHENTICATED ROLE - NOT WORKING!!!, I've tried swapping out AuthenticationResult.IdToken for AuthenticationResult.AccessToken but to no avail ?!?!?!? ]
--- alan_password=<PASSWORD>
--- auth_token=$(aws cognito-idp initiate-auth --auth-flow USER_PASSWORD_AUTH --client-id ${app_client_id} --query 'AuthenticationResult.IdToken' --output text --auth-parameters USERNAME=alan,PASSWORD=${alan_password})
--- auth_id=$(aws cognito-identity get-id --identity-pool-id ${identity_pool_id} --logins cognito-idp.us-west-2.amazonaws.com/${user_pool_id}=${auth_token} --query 'IdentityId' --output text)
[NOTE the rest is the same as UNAUTH]
--- creds=($(aws cognito-identity get-credentials-for-identity --identity-id ${auth_id} --query 'Credentials.[AccessKeyId,SecretKey,SessionToken]' --output text))
--- AWS_ACCESS_KEY_ID=${creds[0]} AWS_SECRET_ACCESS_KEY=${creds[1]} AWS_SESSION_TOKEN=${creds[2]} aws sts get-caller-identity
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment