Amazon Cognito
Core concept: Cognito handles AuthN (who are you?) via User Pools and AuthZ (what AWS resources can you access?) via Identity Pools.
๐ฐ What Is Cognito?โ
Cognito provides authentication, authorization, and user management for web/mobile apps without building your own identity system.
Analogy:
- User Pool = hotel front desk that checks your ID and gives you a room key (JWT token)
- Identity Pool = the hotel concierge who gives you a VIP pass (AWS credentials) to access the gym, pool, and spa (S3, DynamoDB, etc.)
User Pools vs Identity Poolsโ
| Feature | User Pool | Identity Pool (Federated Identities) |
|---|---|---|
| Purpose | Authenticate users (sign up/sign in) | Grant temporary AWS credentials |
| Returns | JWT tokens (ID, Access, Refresh) | AWS credentials (via STS) |
| Use case | Log into your app | Call AWS services (S3, DynamoDB) directly from client |
| Think of it as | OAuth 2.0 / OIDC server | AWS IAM role vending machine |
| Can work alone | โ Yes | โ Yes (with external IdP) |
| Can work together | โ User Pool โ Identity Pool | โ Identity Pool validates User Pool JWT |
Combined Flow (Most Common)โ
1. User โ Cognito User Pool โ Sign In โ JWT Tokens (ID, Access, Refresh)
2. App โ Cognito Identity Pool โ Exchange JWT for AWS Credentials
3. App โ Call S3/DynamoDB directly with temporary AWS credentials
User Pool Deep Diveโ
Featuresโ
| Feature | Description |
|---|---|
| Sign-up/Sign-in | Email, phone, username, or social login |
| Hosted UI | Pre-built login page (customizable) |
| MFA | TOTP (authenticator app) or SMS |
| Password policies | Min length, special chars, etc. |
| Email/phone verification | Automatic confirmation workflow |
| Lambda triggers | Customize auth flow at every step |
| Social federation | Google, Facebook, Apple, Amazon |
| Corporate federation | SAML 2.0, OIDC |
| User groups | Group-based access control |
| Custom attributes | Add custom user fields |
JWT Token Typesโ
| Token | Expiry | Content | Use |
|---|---|---|---|
| ID Token | 5 min โ 1 day (default 1h) | User identity claims (email, sub, custom attributes) | Identify the user |
| Access Token | 5 min โ 1 day (default 1h) | Scopes, groups, client_id | Authorize API calls |
| Refresh Token | 60 min โ 10 years (default 30 days) | Opaque token | Get new ID/Access tokens |
Lambda Triggers (Exam Favorite!)โ
| Trigger | When Fired | Common Use |
|---|---|---|
Pre Sign-up | Before user is created | Block disposable email domains |
Post Confirmation | After email/phone verification | Add user to DynamoDB, send welcome email |
Pre Authentication | Before sign-in | Custom validation, rate limiting |
Post Authentication | After successful sign-in | Audit logging, update last-login |
Pre Token Generation | Before issuing JWT | Add/modify custom claims |
Custom Message | Before sending verification email/SMS | Brand the message |
User Migration | When user doesn't exist in pool | Migrate from legacy auth system |
Define Auth Challenge | Custom auth flow | Implement CAPTCHA, magic links |
Create Auth Challenge | Generate challenge | Send OTP, CAPTCHA |
Verify Auth Challenge | Verify challenge response | Check OTP, CAPTCHA |
Custom Auth Flowsโ
Standard: USERNAME_PASSWORD_AUTH โ Cognito validates โ tokens
Custom: CUSTOM_AUTH โ Define Auth Challenge โ Create Challenge
โ User responds โ Verify Challenge โ tokens
Use cases: Magic link login, CAPTCHA, biometrics, passwordless
Identity Pool Deep Diveโ
Flowโ
User authenticates (User Pool / Google / Facebook / SAML)
โ JWT Token
Cognito Identity Pool
โ GetId โ GetCredentialsForIdentity (or AssumeRoleWithWebIdentity)
Temporary AWS Credentials (AccessKey + SecretKey + SessionToken)
โ
Client calls AWS APIs directly (S3, DynamoDB, etc.)
IAM Roles in Identity Poolsโ
| Role | Purpose |
|---|---|
| Authenticated | Permissions for logged-in users |
| Unauthenticated | Permissions for guest/anonymous users |
Role Mappingโ
Assign different IAM roles based on user attributes:
// User in "admins" group โ AdminRole
// User in "users" group โ UserRole
// Default โ BasicRole
{
"Type": "Token",
"AmbiguousRoleResolution": "AuthenticatedRole",
"RulesConfiguration": {
"Rules": [{
"Claim": "cognito:groups",
"MatchType": "Contains",
"Value": "admins",
"RoleARN": "arn:aws:iam::123:role/AdminRole"
}]
}
}
Fine-Grained Access with Policy Variablesโ
// Each user can only access THEIR OWN S3 prefix
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject"],
"Resource": "arn:aws:s3:::user-data/${cognito-identity.amazonaws.com:sub}/*"
}
${cognito-identity.amazonaws.com:sub} = unique Cognito identity ID for each user.
API Gateway + Cognitoโ
Cognito User Pool Authorizer (REST API)โ
Client โ Authorization: Bearer <Access Token>
โ API Gateway โ Cognito Authorizer โ Validates JWT
โ โ
Valid โ Forward to Lambda
โ โ Invalid โ 401 Unauthorized
- Built-in, no Lambda needed
- Validates JWT signature against User Pool's JWKS
- Can check scopes:
aws.cognito.signin.user.admin
JWT Authorizer (HTTP API)โ
# HTTP API with Cognito JWT authorizer
Authorizer:
Type: JWT
IdentitySource: "$request.header.Authorization"
JwtConfiguration:
Issuer: "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_abc123"
Audience: ["your-app-client-id"]
Java SDK Examplesโ
Authenticate Userโ
CognitoIdentityProviderClient client = CognitoIdentityProviderClient.create();
InitiateAuthResponse authResult = client.initiateAuth(InitiateAuthRequest.builder()
.authFlow(AuthFlowType.USER_PASSWORD_AUTH)
.clientId("your-app-client-id")
.authParameters(Map.of(
"PASSWORD", "SecretPass123!"))
.build());
String idToken = authResult.authenticationResult().idToken();
String accessToken = authResult.authenticationResult().accessToken();
String refreshToken = authResult.authenticationResult().refreshToken();
Refresh Tokensโ
InitiateAuthResponse refreshResult = client.initiateAuth(InitiateAuthRequest.builder()
.authFlow(AuthFlowType.REFRESH_TOKEN_AUTH)
.clientId("your-app-client-id")
.authParameters(Map.of("REFRESH_TOKEN", refreshToken))
.build());
String newAccessToken = refreshResult.authenticationResult().accessToken();
Sign Up Userโ
client.signUp(SignUpRequest.builder()
.clientId("your-app-client-id")
.password("StrongPass123!")
.userAttributes(
AttributeType.builder().name("custom:tenant_id").value("TENANT-001").build())
.build());
Hosted UIโ
Cognito provides a pre-built, customizable login page:
https://<your-domain>.auth.<region>.amazoncognito.com/login?
response_type=code&
client_id=<app-client-id>&
redirect_uri=https://myapp.com/callback
Customization: Logo, CSS, custom domain (requires ACM certificate in us-east-1)
๐ Best Practicesโ
- Use Identity Pool for direct AWS service access from mobile/browser
- Use User Pool Authorizer with API Gateway โ simplest auth setup
- Pre Token Generation trigger โ add custom claims for authorization logic
- Short token TTL (15-60 min) for sensitive apps
- Use groups for role-based access control
- Enable MFA for sensitive operations
- User Migration trigger for seamless migration from legacy auth
๐ฏ DVA-C02 Exam Tipsโ
- User Pool = authentication (JWT tokens). Identity Pool = AWS credentials
- Pre Token Generation trigger = add custom claims to JWT
- User Migration trigger = migrate from legacy auth on first login
- Identity Pool can work with User Pool, Google, Facebook, SAML, OIDC
- Unauthenticated identities = guest access with limited IAM role
- Fine-grained access = use
${cognito-identity.amazonaws.com:sub}in policies - Access Token for API authorization. ID Token for user identity
- Refresh Token can last up to 10 years
- Hosted UI provides login page without building your own
- Custom Auth Flow = CUSTOM_AUTH for passwordless, CAPTCHA, magic links
๐งช Practice Questionsโ
Q1. Mobile app uploads photos to S3. Users authenticate with Google. Which provides temporary AWS credentials?
A) User Pool
B) Identity Pool
C) Cognito Sync
D) Lambda Trigger
โ Answer & Explanation
B โ Identity Pool federates the Google JWT and returns temporary AWS credentials via STS.
Q2. Add custom tenant_id to JWT tokens. Which trigger?
A) Post Confirmation
B) Pre Authentication
C) Pre Token Generation
D) Custom Message
โ Answer & Explanation
C โ Pre Token Generation fires before token issuance, allowing custom claim injection.
Q3. Each user should only access their own S3 prefix. How?
A) Separate bucket per user
B) IAM policy with ${cognito-identity.amazonaws.com:sub} variable
C) Lambda@Edge to filter requests
D) S3 access points per user
โ Answer & Explanation
B โ Use the Cognito identity ID as a policy variable to scope S3 access to user-specific prefixes.
Q4. Guest users need read-only access to public content. Which feature?
A) User Pool Guest Mode
B) Identity Pool Unauthenticated Identities
C) S3 Public Access
D) CloudFront signed URLs
โ Answer & Explanation
B โ Enable Unauthenticated Identities in Identity Pool with a limited IAM role.
Q5. Company migrating from legacy auth to Cognito. Users should log in without re-registering. Which trigger?
A) Pre Sign-up
B) Post Confirmation
C) User Migration
D) Define Auth Challenge
โ Answer & Explanation
C โ User Migration trigger fires when a user doesn't exist in the User Pool. It validates credentials against the legacy system and creates the user transparently.