Cognito handles user authentication, authorization, and user management for web and mobile apps. Instead of building auth yourself (login, MFA, password reset, token management), you use Cognito.
Real-World: Your fitness app needs user login. Without Cognito: build registration, password hashing, session management, MFA, forgot password flow, OAuth integration... that's months of work. With Cognito: configure it, integrate in hours, done.
| Service | What it does |
|---|---|
| User Pools | Authentication — who are you? (username/password, social login, MFA) |
| Identity Pools | Authorization — what AWS resources can you access? (temporary AWS credentials) |
- User directory (username, email, phone, custom attributes)
- Sign-up, sign-in, forgot password flows
- MFA (TOTP, SMS)
- Social federation (Google, Facebook, Apple, SAML/OIDC)
- Returns JWT tokens (ID token + Access token + Refresh token)
| Token | Contains | Expiry | Use for |
|---|---|---|---|
| ID Token | User identity (email, name, custom attrs) | 1 hour | Identifying the user |
| Access Token | User's group memberships, scopes | 1 hour | API authorization |
| Refresh Token | Used to get new ID/Access tokens | 30 days (default) | Token renewal |
Mobile App → Cognito (login) → JWT Access Token
↓
Mobile App → API Gateway (Authorization: Bearer <JWT>)
→ API Gateway validates JWT against User Pool
→ Lambda (if valid)
No Lambda Authorizer needed — API Gateway natively validates Cognito JWT.
Cognito calls your Lambda at various points in the auth flow:
| Trigger | When | Use case |
|---|---|---|
| Pre Sign-up | Before user is created | Validate email domain |
| Post Confirmation | After user confirms email | Create DynamoDB user record |
| Pre Token Generation | Before token issued | Add custom claims to JWT |
| Post Authentication | After successful login | Log login events |
| Migrate User | When user not found | Migrate from legacy auth |
| Define Auth Challenge | Custom auth flow | Passwordless login |
Real-World: Post-Confirmation trigger creates a user profile in DynamoDB when a new user signs up.
Gives authenticated (or even unauthenticated) users temporary AWS credentials (via STS) to directly access AWS services.
User logs into User Pool → gets JWT
JWT → Identity Pool → calls STS AssumeRoleWithWebIdentity → temp credentials
Temp credentials → access S3, DynamoDB, etc. directly
Authenticated users → assume "AuthenticatedRole" (access their own S3 prefix)
Unauthenticated users → assume "UnauthenticatedRole" (read-only public content)
Real-World: A photo sharing app. Authenticated user's S3 IAM policy:
{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject"],
"Resource": "arn:aws:s3:::user-photos/${cognito-identity.amazonaws.com:sub}/*"
}${cognito-identity.amazonaws.com:sub} is the user's unique Cognito Identity ID — they can only access their own folder.
User Pool Group: "admins" → IAM Role: admin-role → full access
User Pool Group: "users" → IAM Role: user-role → read-only access
| Scenario | Use |
|---|---|
| User needs to login to your app | User Pool |
| User needs to call your API | User Pool (JWT) + API Gateway authorizer |
| User needs to directly access S3/DynamoDB | Identity Pool (temp AWS credentials) |
| User uses Google to login to your app | User Pool (federated identity) |
| Unknown/guest user needs limited S3 access | Identity Pool (unauthenticated role) |
Combined pattern (most common):
User Pool (login) → JWT → Identity Pool → AWS credentials → access AWS services
1. User clicks "Sign in with Google"
2. App redirects to Google OAuth
3. Google returns authorization code
4. App sends code to Cognito
5. Cognito exchanges with Google for tokens
6. Cognito issues its own JWT tokens
7. App uses Cognito JWT (consistent interface, regardless of provider)
Key: Cognito normalizes identity — your app always gets Cognito JWTs, not Google/Facebook tokens.
Enterprise users authenticate with Okta/ADFS/etc.:
User → Cognito → redirects to Okta (SAML IdP) → user logs in with corporate creds
→ Okta sends SAML assertion → Cognito validates → issues JWT
→ App gets Cognito JWT
Pre-built, customizable sign-in/up UI pages:
https://your-domain.auth.us-east-1.amazoncognito.com/login
- Supports all social providers
- Customizable with CSS
- Handles OAuth 2.0 flows (Authorization Code, Implicit)
- No UI to build — just redirect users to Cognito Hosted UI
- Adaptive Authentication: Cognito detects unusual sign-in behavior (new device, location) and triggers MFA or blocks
- Compromised Credential Detection: Checks if user's password appears in known breach datasets
- Risk-based authentication: Assign risk scores to login attempts
| Practice | Reason |
|---|---|
| Use Cognito User Pool for app auth | Managed, scalable, secure — don't build auth yourself |
| Use Identity Pools for direct AWS access | User gets scoped temp credentials, not shared AWS keys |
| Use Lambda triggers for custom logic | Post-confirmation → create DynamoDB record |
| Use groups for role-based access | Map groups to IAM roles via Identity Pool |
| Enable MFA for sensitive apps | Additional security layer |
| Use Cognito with API Gateway | Built-in JWT validation, no authorizer Lambda needed |
| Anti-Pattern | Impact | Fix |
|---|---|---|
| Giving Identity Pool role too many permissions | Users get excessive AWS access | Scope IAM role to minimum (use ${cognito-identity.amazonaws.com:sub}) |
| Sharing AWS credentials with mobile app | Credentials exposed in app/network | Use Identity Pool for temp credentials |
| Building custom auth when Cognito fits | Reinventing the wheel, security bugs | Use Cognito |
| Not validating JWT signatures | Token forgery attacks | Use AWS libraries that validate against Cognito JWKS endpoint |
- User Pool = authentication (sign in, JWT). Identity Pool = AWS access (temp credentials).
- API Gateway + Cognito: native integration, no Lambda authorizer needed.
- CUP triggers are Lambda functions — the most common integration exam pattern.
- Identity Pool supports unauthenticated users — can give guest users limited access.
- Cognito Sync / AppSync: Cognito Sync (legacy) or AppSync (modern) for syncing user data across devices.
- Token expiry: ID/Access = 1 hour, Refresh = 30 days (configurable up to 10 years).
- User Pool App Client: each app (mobile, web) has its own client ID. Client secret optional.
Q: Allow users to directly upload to their own S3 folder without using your server?
→ Cognito User Pool (login) → Identity Pool (temp AWS credentials with scoped S3 policy using ${cognito-identity.amazonaws.com:sub}).
Q: Add custom claim to JWT token (e.g., user's subscription tier)? → Use Pre Token Generation Lambda trigger.
Q: Migrate existing users from legacy auth without requiring password reset? → User Migration Lambda trigger in Cognito.
Q: Enforce MFA for all admin users? → Use Cognito User Pool Groups — assign admin group, enable MFA required for that group.
Q: Single-page app needs to call API Gateway with user auth? → Cognito User Pool + API Gateway Cognito Authorizer. User logs in → gets JWT → sends in Authorization header.