Skip to main content

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โ€‹

FeatureUser PoolIdentity Pool (Federated Identities)
PurposeAuthenticate users (sign up/sign in)Grant temporary AWS credentials
ReturnsJWT tokens (ID, Access, Refresh)AWS credentials (via STS)
Use caseLog into your appCall AWS services (S3, DynamoDB) directly from client
Think of it asOAuth 2.0 / OIDC serverAWS 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โ€‹

FeatureDescription
Sign-up/Sign-inEmail, phone, username, or social login
Hosted UIPre-built login page (customizable)
MFATOTP (authenticator app) or SMS
Password policiesMin length, special chars, etc.
Email/phone verificationAutomatic confirmation workflow
Lambda triggersCustomize auth flow at every step
Social federationGoogle, Facebook, Apple, Amazon
Corporate federationSAML 2.0, OIDC
User groupsGroup-based access control
Custom attributesAdd custom user fields

JWT Token Typesโ€‹

TokenExpiryContentUse
ID Token5 min โ€“ 1 day (default 1h)User identity claims (email, sub, custom attributes)Identify the user
Access Token5 min โ€“ 1 day (default 1h)Scopes, groups, client_idAuthorize API calls
Refresh Token60 min โ€“ 10 years (default 30 days)Opaque tokenGet new ID/Access tokens

Lambda Triggers (Exam Favorite!)โ€‹

TriggerWhen FiredCommon Use
Pre Sign-upBefore user is createdBlock disposable email domains
Post ConfirmationAfter email/phone verificationAdd user to DynamoDB, send welcome email
Pre AuthenticationBefore sign-inCustom validation, rate limiting
Post AuthenticationAfter successful sign-inAudit logging, update last-login
Pre Token GenerationBefore issuing JWTAdd/modify custom claims
Custom MessageBefore sending verification email/SMSBrand the message
User MigrationWhen user doesn't exist in poolMigrate from legacy auth system
Define Auth ChallengeCustom auth flowImplement CAPTCHA, magic links
Create Auth ChallengeGenerate challengeSend OTP, CAPTCHA
Verify Auth ChallengeVerify challenge responseCheck 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โ€‹

RolePurpose
AuthenticatedPermissions for logged-in users
UnauthenticatedPermissions 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(
"USERNAME", "[email protected]",
"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")
.username("[email protected]")
.password("StrongPass123!")
.userAttributes(
AttributeType.builder().name("email").value("[email protected]").build(),
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โ€‹

  1. Use Identity Pool for direct AWS service access from mobile/browser
  2. Use User Pool Authorizer with API Gateway โ€” simplest auth setup
  3. Pre Token Generation trigger โ€” add custom claims for authorization logic
  4. Short token TTL (15-60 min) for sensitive apps
  5. Use groups for role-based access control
  6. Enable MFA for sensitive operations
  7. User Migration trigger for seamless migration from legacy auth

๐ŸŽฏ DVA-C02 Exam Tipsโ€‹

Cognito Exam Cheat Sheet
  1. User Pool = authentication (JWT tokens). Identity Pool = AWS credentials
  2. Pre Token Generation trigger = add custom claims to JWT
  3. User Migration trigger = migrate from legacy auth on first login
  4. Identity Pool can work with User Pool, Google, Facebook, SAML, OIDC
  5. Unauthenticated identities = guest access with limited IAM role
  6. Fine-grained access = use ${cognito-identity.amazonaws.com:sub} in policies
  7. Access Token for API authorization. ID Token for user identity
  8. Refresh Token can last up to 10 years
  9. Hosted UI provides login page without building your own
  10. 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.


๐Ÿ”— Resourcesโ€‹