Cognito User Pools
Cognito User Pools
Cognito User Pools are user directories that provide sign-up and sign-in functionality.
Create User Pool
# Create user pool
aws cognito-idp create-user-pool \
--pool-name my-user-pool \
--policies '{
"PasswordPolicy": {
"MinimumLength": 12,
"RequireUppercase": true,
"RequireLowercase": true,
"RequireNumbers": true,
"RequireSymbols": true
}
}' \
--auto-verified-attributes email \
--username-attributes email \
--mfa-configuration ON \
--enabled-mfas SOFTWARE_TOKEN_MFA
# Create app client
aws cognito-idp create-user-pool-client \
--user-pool-id us-east-1_xxxxx \
--client-name my-app \
--explicit-auth-flows ALLOW_USER_PASSWORD_AUTH ALLOW_REFRESH_TOKEN_AUTH \
--generate-secret
User Pool Features
| Feature | Description |
|---|---|
| Sign-up | Self-registration with verification |
| Sign-in | Username/email/phone authentication |
| MFA | SMS or TOTP multi-factor authentication |
| Password Policy | Configurable complexity requirements |
| Social Login | Google, Facebook, Apple integration |
| SAML/OIDC | Enterprise federation |
User Pool Schema
# Add custom attributes
aws cognito-idp create-user-pool \
--pool-name my-pool \
--schema '[{
"Name": "custom:department",
"AttributeDataType": "String",
"Mutable": true,
"Required": false
}, {
"Name": "custom:role",
"AttributeDataType": "String",
"Mutable": true,
"Required": false
}]'
Authentication Flows
Authentication Flows
Sign-Up
import boto3
client = boto3.client('cognito-idp')
# Sign up
response = client.sign_up(
ClientId='your-client-id',
Username='user@example.com',
Password='SecurePass123!',
UserAttributes=[
{'Name': 'email', 'Value': 'user@example.com'},
{'Name': 'name', 'Value': 'John Doe'}
]
)
# Confirm sign up
client.confirm_sign_up(
ClientId='your-client-id',
Username='user@example.com',
ConfirmationCode='123456'
)
Sign-In
# User password authentication
response = client.initiate_auth(
ClientId='your-client-id',
AuthFlow='USER_PASSWORD_AUTH',
AuthParameters={
'USERNAME': 'user@example.com',
'PASSWORD': 'SecurePass123!'
}
)
# Get tokens
id_token = response['AuthenticationResult']['IdToken']
access_token = response['AuthenticationResult']['AccessToken']
refresh_token = response['AuthenticationResult']['RefreshToken']
# Refresh tokens
response = client.initiate_auth(
ClientId='your-client-id',
AuthFlow='REFRESH_TOKEN_AUTH',
AuthParameters={
'REFRESH_TOKEN': refresh_token
}
)
Password Recovery
# Forgot password
response = client.forgot_password(
ClientId='your-client-id',
Username='user@example.com'
)
# Confirm forgot password
client.confirm_forgot_password(
ClientId='your-client-id',
Username='user@example.com',
ConfirmationCode='123456',
Password='NewSecurePass123!'
)
Cognito Identity Pools
Cognito Identity Pools
Identity pools provide temporary AWS credentials for accessing AWS services.
Create Identity Pool
# Create identity pool
aws cognito-identity create-identity-pool \
--identity-pool-name my-identity-pool \
--allow-unauthenticated-identities false \
--cognito-identity-providers '[{
"ProviderName": "cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxxx",
"ClientId": "your-client-id",
"ServerSideTokenCheck": true
}]'
# Set IAM roles for authenticated users
aws cognito-identity set-identity-pool-roles \
--identity-pool-id us-east-1:xxxxx \
--roles '{
"authenticated": "arn:aws:iam::xxx:role/CognitoAuthenticatedRole",
"unauthenticated": "arn:aws:iam::xxx:role/CognitoUnauthenticatedRole"
}'
IAM Role for Authenticated Users
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "cognito-identity.amazonaws.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"cognito-identity.amazonaws.com:aud": "us-east-1:xxxxx"
},
"ForAnyValue:StringLike": {
"cognito-identity.amazonaws.com:amr": "authenticated"
}
}
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-bucket/${cognito-identity.amazonaws.com:sub}/*"
}
]
}
Cognito Triggers
Cognito Triggers
Lambda triggers customize authentication flows.
Pre Sign-Up Trigger
# Validate email domain before sign-up
def lambda_handler(event, context):
email = event['request']['userAttributes']['email']
domain = email.split('@')[1]
allowed_domains = ['company.com', 'partner.com']
if domain not in allowed_domains:
raise Exception('Email domain not allowed')
return event
Post Confirmation Trigger
# Create user profile after confirmation
def lambda_handler(event, context):
user_id = event['userName']
email = event['request']['userAttributes']['email']
# Create user in DynamoDB
dynamodb = boto3.client('dynamodb')
dynamodb.put_item(
TableName='Users',
Item={
'UserId': {'S': user_id},
'Email': {'S': email},
'CreatedAt': {'S': datetime.now().isoformat()}
}
)
return event
Available Triggers
| Trigger | When |
|---|---|
| Pre Sign-Up | Before user registration |
| Post Confirmation | After email confirmation |
| Pre Authentication | Before login |
| Post Authentication | After login |
| Custom Message | Customizing messages |
| Define Auth Challenge | Custom authentication |
| Verify Auth Challenge | Custom challenge verification |
| Token Generation | After token creation |
Cognito Security and Best Practices
Cognito Security and Best Practices
Security Configuration
# Enable advanced security
aws cognito-idp update-user-pool \
--user-pool-id us-east-1_xxxxx \
--user-pool-add-ons '{
"AdvancedSecurityMode": "ENFORCED"
}'
# Enable compromised credentials check
aws cognito-idp update-user-pool \
--user-pool-id us-east-1_xxxxx \
--user-pool-add-ons '{
"AdvancedSecurityMode": "ENFORCED"
}'
# Configure account takeover protection
aws cognito-idp update-user-pool \
--user-pool-id us-east-1_xxxxx \
--user-pool-add-ons '{
"AdvancedSecurityMode": "ENFORCED"
}'
Integration with API Gateway
# Configure Cognito authorizer
aws apigateway create-authorizer \
--rest-api-id abc123 \
--name CognitoAuthorizer \
--type COGNITO_USER_POOLS \
--provider-arns arn:aws:cognito-idp:us-east-1:xxx:userpool/us-east-1_xxxxx \
--identity-source method.request.header.Authorization
# Protect API methods
aws apigateway update-method \
--rest-api-id abc123 \
--resource-id xyz789 \
--http-method GET \
--patch-operations 'op=replace,path=/authorizationType,value=COGNITO_USER_POOLS' 'op=replace,path=/authorizerId,value=xxx'
Best Practices
- Enable MFA for all users
- Use strong password policies
- Enable advanced security features
- Use Lambda triggers for custom validation
- Monitor with CloudWatch
- Use token validation on protected endpoints
- Implement refresh token rotation
- Use attribute-based access control (ABAC)
Pricing
| Feature | Cost |
|---|---|
| Monthly Active Users (MAU) | First 50K free, then $0.0055/MAU |
| Advanced Security | $0.05/MAU |
| SMS | Standard SMS rates |
| Federated Identities | First 50K free |