View a markdown version of this page

Getting started with Amazon Cognito user pools - AWS SDK Code Examples

There are more AWS SDK examples available in the AWS Doc SDK Examples GitHub repo.

Getting started with Amazon Cognito user pools

The following code example shows how to:

  • Create a user pool

  • Create an app client

  • Set up a domain for your user pool

  • Create a user as an administrator

  • Enable self-registration

  • List users in the user pool

  • Clean up resources

Bash
AWS CLI with Bash script
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the Sample developer tutorials repository.

#!/bin/bash # Amazon Cognito User Pools Getting Started Script # This script creates and configures an Amazon Cognito user pool with an app client set -euo pipefail # Security: Set restrictive umask umask 0077 # Set up logging with secure permissions LOG_FILE="cognito-user-pool-setup.log" touch "$LOG_FILE" chmod 600 "$LOG_FILE" exec > >(tee -a "$LOG_FILE") 2>&1 echo "Starting Amazon Cognito User Pool setup script at $(date)" echo "All commands and outputs will be logged to $LOG_FILE" # Function to check for errors in command output check_error() { local output=$1 local cmd=$2 if echo "$output" | grep -qi "error\|failed"; then echo "ERROR: Command failed: $cmd" >&2 echo "Output: $output" >&2 cleanup_on_error exit 1 fi } # Function to check AWS CLI return code check_aws_error() { local exit_code=$? local cmd=$1 if [ $exit_code -ne 0 ]; then echo "ERROR: AWS CLI command failed with exit code $exit_code: $cmd" >&2 cleanup_on_error exit "$exit_code" fi } # Function to clean up resources on error cleanup_on_error() { echo "Error encountered. Attempting to clean up resources..." >&2 if [ -n "${DOMAIN_NAME:-}" ] && [ -n "${USER_POOL_ID:-}" ]; then echo "Deleting user pool domain: $DOMAIN_NAME" >&2 aws cognito-idp delete-user-pool-domain \ --user-pool-id "$USER_POOL_ID" \ --domain "$DOMAIN_NAME" 2>/dev/null || true fi if [ -n "${USER_POOL_ID:-}" ]; then echo "Deleting user pool: $USER_POOL_ID" >&2 aws cognito-idp delete-user-pool \ --user-pool-id "$USER_POOL_ID" 2>/dev/null || true fi } # Set trap for cleanup on exit trap cleanup_on_error EXIT ERR # Validate AWS CLI is installed and configured if ! command -v aws &> /dev/null; then echo "ERROR: AWS CLI is not installed" >&2 exit 1 fi # Validate jq is installed if ! command -v jq &> /dev/null; then echo "ERROR: jq is not installed" >&2 exit 1 fi # Validate openssl is installed if ! command -v openssl &> /dev/null; then echo "ERROR: openssl is not installed" >&2 exit 1 fi if ! aws sts get-caller-identity &> /dev/null; then echo "ERROR: AWS CLI is not configured or credentials are invalid" >&2 exit 1 fi # Get the current AWS region AWS_REGION=$(aws configure get region) if [ -z "$AWS_REGION" ]; then AWS_REGION="us-east-1" # Default region if not configured fi echo "Using AWS Region: $AWS_REGION" # Validate region format if ! [[ "$AWS_REGION" =~ ^[a-z]{2}-[a-z]+-[0-9]{1}$ ]]; then echo "ERROR: Invalid AWS region format: $AWS_REGION" >&2 exit 1 fi # Generate random identifier for resource names using secure method RANDOM_ID=$(openssl rand -hex 6) if [ -z "$RANDOM_ID" ]; then echo "ERROR: Failed to generate random identifier" >&2 exit 1 fi USER_POOL_NAME="MyUserPool-${RANDOM_ID}" APP_CLIENT_NAME="MyAppClient-${RANDOM_ID}" DOMAIN_NAME="my-auth-domain-${RANDOM_ID}" # Validate resource names don't exceed limits if [ ${#USER_POOL_NAME} -gt 128 ]; then echo "ERROR: User pool name exceeds maximum length of 128 characters" >&2 exit 1 fi if [ ${#APP_CLIENT_NAME} -gt 128 ]; then echo "ERROR: App client name exceeds maximum length of 128 characters" >&2 exit 1 fi echo "Using random identifier: $RANDOM_ID" echo "User pool name: $USER_POOL_NAME" echo "App client name: $APP_CLIENT_NAME" echo "Domain name: $DOMAIN_NAME" # Step 1: Create a User Pool echo "Creating user pool..." USER_POOL_OUTPUT=$(aws cognito-idp create-user-pool \ --pool-name "$USER_POOL_NAME" \ --auto-verified-attributes email \ --username-attributes email \ --policies '{"PasswordPolicy":{"MinimumLength":12,"RequireUppercase":true,"RequireLowercase":true,"RequireNumbers":true,"RequireSymbols":true}}' \ --schema '[{"Name":"email","Required":true,"Mutable":true}]' \ --mfa-configuration OFF \ --user-attribute-update-settings '{"AttributesRequireVerificationBeforeUpdate":["email"]}' \ --account-recovery-setting 'RecoveryMechanisms=[{Name=verified_email,Priority=1}]' \ --deletion-protection INACTIVE \ --region "$AWS_REGION" \ 2>&1) check_aws_error "create-user-pool" # Extract the User Pool ID using jq for safety USER_POOL_ID=$(echo "$USER_POOL_OUTPUT" | jq -r '.UserPool.Id // empty') if [ -z "$USER_POOL_ID" ]; then echo "ERROR: Failed to extract User Pool ID" >&2 exit 1 fi # Validate User Pool ID format if ! [[ "$USER_POOL_ID" =~ ^[a-z]{2}-[a-z]+-[0-9]+_[a-zA-Z0-9]+$ ]]; then echo "ERROR: Invalid User Pool ID format: $USER_POOL_ID" >&2 exit 1 fi echo "User Pool created with ID: $USER_POOL_ID" # Wait for user pool to be ready echo "Waiting for user pool to be ready..." sleep 5 # Step 2: Create an App Client with enhanced security echo "Creating app client..." APP_CLIENT_OUTPUT=$(aws cognito-idp create-user-pool-client \ --user-pool-id "$USER_POOL_ID" \ --client-name "$APP_CLIENT_NAME" \ --no-generate-secret \ --explicit-auth-flows ALLOW_REFRESH_TOKEN_AUTH ALLOW_USER_PASSWORD_AUTH \ --callback-urls '["https://localhost:3000/callback"]' \ --allowed-o-auth-flows 'code' \ --allowed-o-auth-scopes 'openid' 'email' 'profile' \ --allowed-o-auth-flows-user-pool-client \ --prevent-user-existence-errors ENABLED \ --enable-token-revocation \ --access-token-validity 1 \ --id-token-validity 1 \ --refresh-token-validity 30 \ --token-validity-units 'AccessToken=hours,IdToken=hours,RefreshToken=days' \ --region "$AWS_REGION" \ 2>&1) check_aws_error "create-user-pool-client" # Extract the Client ID using jq for safety CLIENT_ID=$(echo "$APP_CLIENT_OUTPUT" | jq -r '.UserPoolClient.ClientId // empty') if [ -z "$CLIENT_ID" ]; then echo "ERROR: Failed to extract Client ID" >&2 cleanup_on_error exit 1 fi # Validate Client ID format if ! [[ "$CLIENT_ID" =~ ^[a-z0-9]{26}$ ]]; then echo "ERROR: Invalid Client ID format: $CLIENT_ID" >&2 cleanup_on_error exit 1 fi echo "App Client created with ID: $CLIENT_ID" # Step 3: Set Up a Domain for Your User Pool echo "Setting up user pool domain..." DOMAIN_OUTPUT=$(aws cognito-idp create-user-pool-domain \ --user-pool-id "$USER_POOL_ID" \ --domain "$DOMAIN_NAME" \ --region "$AWS_REGION" \ 2>&1) check_aws_error "create-user-pool-domain" echo "Domain created: $DOMAIN_NAME.auth.$AWS_REGION.amazoncognito.com" # Step 4: View User Pool Details echo "Retrieving user pool details..." USER_POOL_DETAILS=$(aws cognito-idp describe-user-pool \ --user-pool-id "$USER_POOL_ID" \ --region "$AWS_REGION" \ 2>&1) check_aws_error "describe-user-pool" echo "User Pool details retrieved successfully" # Step 5: View App Client Details echo "Retrieving app client details..." APP_CLIENT_DETAILS=$(aws cognito-idp describe-user-pool-client \ --user-pool-id "$USER_POOL_ID" \ --client-id "$CLIENT_ID" \ --region "$AWS_REGION" \ 2>&1) check_aws_error "describe-user-pool-client" echo "App Client details retrieved successfully" # Step 6: Create a User (Admin) echo "Creating admin user..." ADMIN_USER_EMAIL="admin@example.com" TEMP_PASSWORD="$(openssl rand -base64 12 | tr -d '\n')!@#" if [ -z "$TEMP_PASSWORD" ]; then echo "ERROR: Failed to generate temporary password" >&2 cleanup_on_error exit 1 fi ADMIN_USER_OUTPUT=$(aws cognito-idp admin-create-user \ --user-pool-id "$USER_POOL_ID" \ --username "$ADMIN_USER_EMAIL" \ --user-attributes Name=email,Value="$ADMIN_USER_EMAIL" Name=email_verified,Value=true \ --temporary-password "$TEMP_PASSWORD" \ --message-action SUPPRESS \ --region "$AWS_REGION" \ 2>&1) check_aws_error "admin-create-user" echo "Admin user created: $ADMIN_USER_EMAIL" # Securely clear temporary password from memory unset TEMP_PASSWORD # Step 7: Self-Registration echo "Demonstrating self-registration..." USER_EMAIL="user@example.com" USER_PASSWORD="SecurePassword123!" SIGNUP_OUTPUT=$(aws cognito-idp sign-up \ --client-id "$CLIENT_ID" \ --username "$USER_EMAIL" \ --password "$USER_PASSWORD" \ --user-attributes Name=email,Value="$USER_EMAIL" \ --region "$AWS_REGION" \ 2>&1) check_aws_error "sign-up" echo "User signed up: $USER_EMAIL" echo "A confirmation code would be sent to the user's email in a real scenario" # Securely clear password from memory unset USER_PASSWORD echo "" echo "===================================================" echo "IMPORTANT: In a real scenario, the user would receive" echo "a confirmation code via email. For this demo, we'll" echo "use admin-confirm-sign-up instead." echo "===================================================" echo "" # Step 8: Confirm User Registration (using admin privileges for demo) echo "Confirming user registration (admin method)..." CONFIRM_OUTPUT=$(aws cognito-idp admin-confirm-sign-up \ --user-pool-id "$USER_POOL_ID" \ --username "$USER_EMAIL" \ --region "$AWS_REGION" \ 2>&1) check_aws_error "admin-confirm-sign-up" echo "User confirmed: $USER_EMAIL" # Step 9: Set permanent password for user echo "Setting permanent password for user..." SET_PASSWORD="SecureUserPassword123!" SET_PASS_OUTPUT=$(aws cognito-idp admin-set-user-password \ --user-pool-id "$USER_POOL_ID" \ --username "$USER_EMAIL" \ --password "$SET_PASSWORD" \ --permanent \ --region "$AWS_REGION" \ 2>&1) check_aws_error "admin-set-user-password" echo "Permanent password set for user" unset SET_PASSWORD # Step 10: Authenticate a User echo "Authenticating user..." AUTH_PASSWORD="SecureUserPassword123!" AUTH_OUTPUT=$(aws cognito-idp initiate-auth \ --client-id "$CLIENT_ID" \ --auth-flow USER_PASSWORD_AUTH \ --auth-parameters "USERNAME=$USER_EMAIL,PASSWORD=$AUTH_PASSWORD" \ --region "$AWS_REGION" \ 2>&1) check_aws_error "initiate-auth" echo "User authenticated successfully" unset AUTH_PASSWORD # Extract auth tokens securely ID_TOKEN=$(echo "$AUTH_OUTPUT" | jq -r '.AuthenticationResult.IdToken // empty') ACCESS_TOKEN=$(echo "$AUTH_OUTPUT" | jq -r '.AuthenticationResult.AccessToken // empty') # Validate tokens exist if [ -z "$ID_TOKEN" ] || [ -z "$ACCESS_TOKEN" ]; then echo "WARNING: Failed to extract authentication tokens" >&2 else echo "Authentication tokens obtained successfully" fi # Securely clear tokens from memory unset ID_TOKEN unset ACCESS_TOKEN # Step 11: List Users in the User Pool echo "Listing users in the user pool..." USERS_OUTPUT=$(aws cognito-idp list-users \ --user-pool-id "$USER_POOL_ID" \ --region "$AWS_REGION" \ 2>&1) check_aws_error "list-users" echo "Users listed successfully" # Display summary of created resources echo "" echo "===================================================" echo "RESOURCE SUMMARY" echo "===================================================" echo "User Pool ID: $USER_POOL_ID" echo "User Pool Name: $USER_POOL_NAME" echo "App Client ID: $CLIENT_ID" echo "App Client Name: $APP_CLIENT_NAME" echo "Domain: $DOMAIN_NAME.auth.$AWS_REGION.amazoncognito.com" echo "Admin User: $ADMIN_USER_EMAIL" echo "Regular User: $USER_EMAIL" echo "===================================================" echo "" # Auto-confirm cleanup echo "" echo "===========================================" echo "CLEANUP" echo "===========================================" echo "Starting cleanup process..." # Step 12: Clean Up Resources echo "Deleting user pool domain..." DELETE_DOMAIN_OUTPUT=$(aws cognito-idp delete-user-pool-domain \ --user-pool-id "$USER_POOL_ID" \ --domain "$DOMAIN_NAME" \ --region "$AWS_REGION" \ 2>&1) check_aws_error "delete-user-pool-domain" echo "Domain deleted successfully" # Wait for domain deletion to complete echo "Waiting for domain deletion to complete..." sleep 5 echo "Deleting user pool (this will also delete the app client)..." DELETE_POOL_OUTPUT=$(aws cognito-idp delete-user-pool \ --user-pool-id "$USER_POOL_ID" \ --region "$AWS_REGION" \ 2>&1) check_aws_error "delete-user-pool" echo "User pool deleted successfully" echo "All resources have been cleaned up" echo "Script completed at $(date)" # Remove trap to prevent cleanup on successful exit trap - EXIT ERR