Amazon Cognito is the AWS identity service for customer-facing applications — the mobile apps, single-page web apps, and business-to-consumer portals where the end users are not your employees but your customers. It solves two distinct problems that developers keep confusing: (1) signing users into your application (is this user [email protected], and can she prove it?) and (2) handing AWS credentials to an app so it can call AWS APIs directly (can this signed-in user write to a specific Amazon S3 prefix from the browser?). The first problem is what Amazon Cognito user pools solve. The second is what Amazon Cognito identity pools solve. Confusing the two is the single most-tested trap in the DVA-C02 Security domain.
On the DVA-C02 exam, Task 2.1 ("Implement authentication and/or authorization for applications and AWS services") expects you to design Amazon Cognito into serverless architectures: pick user pools vs identity pools correctly, choose the right OAuth 2.0 flow, wire up a Cognito Authorizer on Amazon API Gateway, decode JWT tokens, trigger Lambda functions on sign-up and sign-in, federate with SAML 2.0 and social identity providers, and exchange tokens for temporary AWS credentials via AssumeRoleWithWebIdentity. This guide walks through every piece, highlights the highest-frequency traps, and uses plain-language analogies so the vocabulary sticks on exam day.
What is Amazon Cognito?
Amazon Cognito is a managed AWS service that provides authentication, authorization, and user management for web and mobile applications. It is regional (each Amazon Cognito user pool and Amazon Cognito identity pool lives in one AWS Region) and scales automatically to millions of users. Amazon Cognito has two independent building blocks that share a brand but solve different problems:
- Amazon Cognito user pool — a fully managed user directory. Handles sign-up, sign-in, password reset, MFA, account recovery, and issues OpenID Connect (OIDC) compliant JWT tokens (ID token, access token, refresh token). Think of a user pool as "your app's login database, managed by AWS."
- Amazon Cognito identity pool — a federated identity broker. Takes a proof-of-identity token (from an Amazon Cognito user pool, from Facebook, Google, Apple, SAML, OIDC, or even an unauthenticated guest) and hands back temporary AWS credentials via AWS STS
AssumeRoleWithWebIdentity. Think of an identity pool as "the bouncer that exchanges a stamped hand for AWS keys."
You can use Amazon Cognito user pools alone (most common — you just need sign-in for your app), identity pools alone (rare — only when you federate from non-Cognito IdPs directly to AWS), or both together (typical for mobile apps that call AWS APIs from the client).
- User pool: an Amazon Cognito user directory that authenticates users and issues JWT tokens.
- Identity pool: an Amazon Cognito federated identity broker that exchanges tokens for temporary AWS credentials.
- ID token: OIDC JWT containing user identity claims (sub, email, cognito:groups). Used to prove who the user is.
- Access token: OAuth 2.0 JWT containing scopes and cognito:groups. Used to authorize API calls.
- Refresh token: long-lived opaque token used to obtain new ID and access tokens without re-authenticating.
- Hosted UI: the AWS-hosted sign-in and sign-up pages provided by Amazon Cognito user pools.
- App client: a configuration inside a user pool that represents one application (mobile, SPA, server) and holds OAuth settings.
- Federation: accepting identities from external identity providers (SAML 2.0, OIDC, Google, Facebook, Apple, Amazon).
- Reference: https://docs.aws.amazon.com/cognito/latest/developerguide/what-is-amazon-cognito.html
Why Amazon Cognito matters for DVA-C02
DVA-C02 Domain 2 (Security) carries 26% exam weight, and Amazon Cognito is one of its two heaviest topics (alongside IAM roles and policies). The exam repeatedly tests four decisions: user pool vs identity pool, ID token vs access token, which OAuth 2.0 flow matches a given client type, and API Gateway Cognito Authorizer vs Lambda Authorizer. Nail those four decisions and Amazon Cognito stops being a trap on exam day.
白話文解釋 Amazon Cognito
Amazon Cognito blends two concepts that are easy to tangle. These analogies pull them apart.
Analogy 1: The Nightclub with Two Bouncers
Picture a trendy nightclub. The first bouncer at the front door checks your ID and your invitation list — that is the Amazon Cognito user pool. Once approved, they stamp the back of your hand and give you a wristband with a barcode (the JWT tokens: ID token plus access token plus refresh token). The wristband proves "this person has been verified and belongs to the Gold tier group."
Inside the club, there is a second bouncer standing in front of the VIP lounge — that is the Amazon Cognito identity pool. The second bouncer does not re-verify your ID. They just scan the barcode on your wristband, confirm it is authentic, and hand you a VIP access card that works for the next hour (the temporary AWS credentials returned by AssumeRoleWithWebIdentity). The VIP card only opens certain doors inside (matching IAM role permissions) and expires on its own, so even if you lose it, nobody can wear it forever.
Getting the two bouncers mixed up is exactly the DVA-C02 trap: a user pool verifies identity and issues wristbands (JWT). An identity pool trades a wristband for AWS credentials. You do not "sign in" to an identity pool directly — you always arrive with a wristband from somewhere (Amazon Cognito user pool, Google, Facebook, SAML), and the identity pool decides which VIP card your wristband deserves.
Analogy 2: The Passport Office and the Car Rental Counter
Your country's passport office is the Amazon Cognito user pool. It verifies who you are (birth certificate, biometrics, MFA), issues you a passport (the signed JWT ID token) and a travel authorization (the access token with scopes). The passport office does not rent you a car; it only establishes identity.
The car rental counter at the airport is the Amazon Cognito identity pool. It does not re-verify your birth certificate. It looks at your passport, confirms it is from a trusted country (a trusted identity provider), checks what class of car your status allows (role mapping: premium members get a premium role, basic members get a basic role, unauthenticated guests get a public role), and hands you temporary car keys (temporary AWS credentials) that stop working after a few hours.
The trap: a passport on its own does not drive a car, and car keys on their own cannot re-enter the passport office. User pool JWT authenticates your app; identity pool credentials authorize AWS API calls. They are sequential, not interchangeable.
Analogy 3: The Hotel Check-In With a Key Concierge
Finally, picture a big hotel. The check-in desk (Amazon Cognito user pool) verifies your reservation — email confirmation, MFA via text message, government ID, and even a custom pre-check-in Lambda trigger that inspects your guest record (a pre-signup or pre-authentication Lambda trigger). They print you a room keycard with the group tag "Gold-Floor" (the ID token carrying your cognito:groups claim).
Need anything from the hotel's external partners — a tee-time at the affiliated golf course, a table at the partnered restaurant? You walk over to the concierge (Amazon Cognito identity pool). The concierge inspects your Gold-Floor keycard (your user pool JWT), maps "Gold-Floor" to the partner's VIP tier (role mapping), and hands you a temporary partner voucher (temporary AWS credentials) valid only for the next hour. If you arrive instead with a different partner's card — say your Facebook login — the concierge can still issue a voucher, because the concierge trusts multiple issuers (federated identity providers), not only the hotel front desk.
On exam day, when you see "Amazon Cognito user pool" mentally picture the front-door bouncer stamping your hand; when you see "Amazon Cognito identity pool" picture the VIP-lounge bouncer scanning the stamp and handing out temporary VIP cards. That split alone will pull you out of 80% of the trap questions. Reference: https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html
Amazon Cognito User Pools — Sign-Up, Sign-In, and JWT Issuance
An Amazon Cognito user pool is a regional user directory. One user pool can back one or many applications in your AWS account. Each application is represented by an app client inside the user pool, and each app client has its own OAuth 2.0 settings, callback URLs, and identity provider list.
What a user pool does for you
- Stores user records (username, email, phone number, and any custom attributes you define such as
custom:tenant_id). - Handles sign-up — email and/or phone verification, custom attribute capture, opt-in MFA.
- Handles sign-in — SRP password flow, admin-auth flow, user-password flow, custom auth challenge flow, and federation.
- Handles account recovery — forgotten password, forgotten username.
- Issues three JWT tokens on successful authentication: ID token, access token, refresh token.
- Provides the Hosted UI — AWS-hosted sign-in, sign-up, and password-reset pages — so you do not have to build those screens yourself.
Password policies and MFA
Each Amazon Cognito user pool has a password policy that you configure at pool creation (and can update). You set minimum length (6–99 characters), and which character classes are required (uppercase, lowercase, number, symbol). You also configure temporary password expiration for passwords issued during admin-created accounts.
Multi-factor authentication (MFA) can be Off, Optional, or Required at the pool level. Supported factors include:
- SMS text message — a one-time code sent to the user's phone number (the phone number must be verified).
- Time-based one-time password (TOTP) — Google Authenticator, Authy, 1Password, etc.
- Email MFA — a one-time code sent to the verified email (newer addition).
If MFA is set to Required, every sign-in must present a second factor. If Optional, users choose per-account whether to enable MFA.
The three JWT tokens — ID, access, refresh
When a user signs in successfully, the Amazon Cognito user pool returns three tokens. Knowing what each token is for is a direct DVA-C02 exam item.
- ID token — a JWT signed by the user pool. Contains identity claims:
sub(user unique id),email,phone_number,cognito:username,cognito:groups, and any custom attributes. The ID token is meant for your application to know who the user is. Default lifetime: 1 hour (configurable 5 minutes to 24 hours). - Access token — a JWT signed by the user pool. Contains OAuth 2.0 scopes (for example
openid,email,profile,aws.cognito.signin.user.admin, or custom resource-server scopes) andcognito:groups. The access token is meant for APIs you protect to authorize the call. Default lifetime: 1 hour (configurable 5 minutes to 24 hours). - Refresh token — an opaque token (not a JWT you can inspect). Used to request a new ID token and access token without requiring the user to re-authenticate. Default lifetime: 30 days (configurable 1 hour to 10 years).
- ID token = "who is the user" — identity claims; default 1 hour.
- Access token = "what can the user do" — OAuth scopes + cognito:groups; default 1 hour.
- Refresh token = "let me get fresh tokens without re-login" — opaque; default 30 days.
- All three tokens are issued together on successful sign-in.
- Amazon API Gateway Cognito Authorizer can validate either the ID token or the access token — the access token is the OAuth-native choice when you use scopes.
- Reference: https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html
Token revocation
Refresh tokens can be revoked with the RevokeToken API. Once revoked, that refresh token can no longer mint new ID and access tokens. Revoking a refresh token also invalidates any access tokens issued from it for the purposes of the aws.cognito.signin.user.admin scope, but already-issued JWT access tokens remain valid for their natural lifetime in third-party APIs that validate tokens locally (they only check signature and exp claim). This is why short access-token lifetimes matter — revocation does not retroactively kill JWTs in flight; time expiration does.
Hosted UI, Custom Domains, and OAuth 2.0 Flows
The Hosted UI is the sign-in and sign-up web experience that Amazon Cognito hosts for you. You configure it by enabling an app client with a domain prefix and a set of allowed callback URLs; from your app, you redirect the user's browser to the Hosted UI URL, they sign in, and Amazon Cognito redirects back with a code or token in the URL fragment or query string.
The three Cognito domain options
- Amazon Cognito prefix domain — free, format
https://<your-prefix>.auth.<region>.amazoncognito.com. Fast to set up; domain is obviously AWS-branded. - Custom domain — your own domain (
https://auth.example.com). Requires an ACM certificate inus-east-1(for Amazon CloudFront, which fronts the Hosted UI) and a DNS record pointing at the Cognito CloudFront distribution. Used when you want sign-in to look like part of your brand. - Managed login (newer) — the refreshed Hosted UI, supporting richer branding and multi-language assets.
OAuth 2.0 flows supported by Cognito
Amazon Cognito user pool app clients speak OAuth 2.0 and OIDC. The DVA-C02 exam expects you to match a client type to the right flow.
- Authorization code grant (
code) — the app receives a short-livedcodein the redirect URL, then its backend POSTs the code to Cognito's/oauth2/tokenendpoint (with the app client secret) in exchange for ID, access, and refresh tokens. Recommended for server-rendered web apps and mobile apps (using PKCE when the client is public). This is the most secure flow because tokens never appear in the browser URL. - Implicit grant (
token) — the app receives the tokens directly in the URL fragment. Legacy OAuth 2.0 flow; considered less secure because tokens can leak via browser history or referrer headers. Historically used for single-page apps but now discouraged — PKCE with authorization code is preferred. - Client credentials grant (
client_credentials) — a machine-to-machine flow. The caller presents the app client ID and secret directly and gets back only an access token (no user — there is no end user in this flow). Used for server-to-server API access where a backend needs to call a protected resource. Requires a resource server with custom scopes configured in the user pool.
DVA-C02 tests OAuth flow selection directly. Map client type to flow: web/mobile with end user → authorization code (with PKCE for public clients). Server-to-server with no end user → client credentials. Implicit grant is legacy and should not be selected unless the question is explicitly about a legacy SPA — modern SPAs should also use authorization code + PKCE. Reference: https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-app-idp-settings.html
OAuth scopes and resource servers
Beyond the built-in OIDC scopes (openid, email, profile, phone), you can define a resource server inside a user pool and declare custom scopes like api.example.com/orders.read or api.example.com/orders.write. Your app client is configured with the scopes it may request; the access token JWT's scope claim lists what was granted. Your API (behind Amazon API Gateway or your own server) validates the scope claim before serving the request.
Cognito Lambda Triggers — Customizing the User Flow
An Amazon Cognito user pool lets you inject Lambda functions at specific lifecycle points. Triggers are synchronous: your Lambda receives the trigger event, returns a modified event object, and Amazon Cognito continues (or aborts) the flow based on your response. This is Amazon Cognito's main extensibility mechanism and is regularly tested on DVA-C02.
The main triggers you should know by name:
- Pre sign-up — fires before a new user is written to the directory. Use cases: validate email domain against an allowlist, automatically confirm trusted users (skip email verification), reject disposable email services.
- Post confirmation — fires after a user confirms their email or phone. Use cases: add the user to a default Amazon DynamoDB record, enqueue a welcome email via Amazon SES, subscribe them to a mailing list.
- Pre authentication — fires before sign-in is processed. Use cases: geographic IP allowlist, deny sign-in from known compromised accounts, enforce account-level lockout logic beyond the standard Cognito protection.
- Post authentication — fires after a successful sign-in. Use cases: log sign-in events to Amazon CloudWatch, update a "last login" timestamp, refresh a user's cached session in Amazon DynamoDB.
- Custom message — fires when Amazon Cognito is about to send an SMS or email (verification code, forgot-password code, admin-created invitation). Use cases: customize the subject and body, localize into the user's language.
- Pre token generation — fires just before the ID and access tokens are signed. Use cases: add custom claims (for example, tenant id, role, feature flags) into the ID token so downstream APIs can authorize without extra database lookups.
- User migration — fires when a user signs in that does not yet exist in the Amazon Cognito user pool. Use cases: migrate users from a legacy auth system the first time they sign in (Cognito calls your Lambda, your Lambda checks the old system, returns the attributes, Cognito creates the record). Powerful pattern for phased migration without a bulk user import.
- Define auth challenge / Create auth challenge / Verify auth challenge response — the trio that powers custom authentication flows (passwordless SMS OTP, magic links, CAPTCHA, passkeys) by letting you script a challenge-response state machine.
On the exam, if the scenario says "automatically approve users from our corporate email domain without email verification", the answer is a pre sign-up Lambda trigger that sets autoConfirmUser: true. If the scenario says "add the user's tenant id to the JWT so APIs can authorize directly", the answer is a pre token generation Lambda trigger. Reference: https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html
Federated Identity Providers — SAML, OIDC, and Social
Amazon Cognito user pools can be configured to federate with external identity providers. Instead of (or in addition to) local username/password accounts inside the pool, users click "Sign in with Google" or "Sign in with my corporate IdP" and return with a validated identity that Amazon Cognito then wraps in its own JWT tokens.
Supported federated identity providers
- SAML 2.0 — Microsoft Entra ID, Active Directory Federation Services, Okta, Ping Identity, or any SAML IdP. You upload the IdP's metadata XML (or URL) and configure attribute mapping from SAML assertion to user pool attributes.
- OIDC — any OpenID Connect-compliant IdP. You provide issuer URL, client id, client secret, and attribute mapping.
- Social identity providers — pre-built integrations for Google, Facebook, Login with Amazon, and Sign in with Apple. You register your app with the social provider, paste in the app id and app secret, and Amazon Cognito handles the OAuth dance.
How federation actually flows
- User clicks "Sign in with Google" on your app.
- Browser redirects to Amazon Cognito's
/oauth2/authorizeendpoint with the identity provider name in the query string. - Amazon Cognito redirects to Google.
- User signs in at Google; Google redirects back to Amazon Cognito with a Google token.
- Amazon Cognito validates the Google token, creates or updates a matching user in the user pool (with attributes mapped per your configuration), and redirects back to your app with a code (authorization code flow).
- Your app exchanges the code for Amazon Cognito JWT tokens.
From your application's point of view, the result is identical to a native user-pool sign-in: you get Cognito-issued ID, access, and refresh tokens. The identities claim inside the ID token tells you which external IdP the user came from.
Migration from user pool to social IdP
A common scenario on DVA-C02: a pool originally used local username/password is extended to offer "Sign in with Google" for the same user. Two patterns matter:
- Account linking via the
identitiesattribute — when a federated user signs in and their email matches an existing user-pool record, Amazon Cognito can be configured to link the accounts (so the user has one identity with both local and federated sign-in paths). - User migration Lambda trigger — for moving off a legacy auth system entirely: the first time a user signs in with their legacy password, the migration trigger validates the password against the old system, pulls their attributes, and Amazon Cognito creates the user pool record on the fly.
The single highest-frequency DVA-C02 Cognito trap: the question describes a mobile app that needs to upload user-generated photos directly from the device to Amazon S3, and offers the candidate a choice between "configure an Amazon Cognito user pool" and "configure an Amazon Cognito identity pool." The correct answer is both — the user pool authenticates the user (issuing JWT), and the identity pool exchanges the JWT for temporary AWS credentials that the mobile SDK uses to sign the S3 PutObject request. If the question only allows one, pay attention to the verb: "sign in / authenticate / issue JWT" → user pool; "get AWS credentials / call AWS API from client / AssumeRoleWithWebIdentity" → identity pool. Reference: https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html
Advanced Security Features (ASF)
Amazon Cognito user pools offer a paid tier called Advanced Security Features (ASF) that adds risk-based adaptive authentication and compromised-credential detection. It is DVA-C02 content at awareness level — you should recognize the capability names and when to enable them.
- Adaptive authentication — Amazon Cognito assigns each sign-in attempt a risk score (Low, Medium, High) based on device, location, and behavior patterns. You configure actions per risk level: allow, require MFA, block, notify user. Classic scenario: block sign-ins from unusual countries, require MFA on medium risk, log all high-risk attempts.
- Compromised credentials detection — Amazon Cognito checks usernames and passwords against a database of known-leaked credential pairs (from public breaches). You can configure the pool to block sign-up and sign-in with credentials that appear in that database, or require a password change.
- Risk-based event logging — every sign-in attempt is scored and logged for auditing, visible in the Amazon Cognito console and delivered to Amazon CloudWatch.
ASF is pool-wide and priced per monthly active user (MAU) in addition to the base Amazon Cognito user pool price.
ASF is not enabled by default and is priced per monthly active user on top of the standard Amazon Cognito user pool pricing. When the DVA-C02 exam asks for "risk-based adaptive authentication" or "detecting the use of breached passwords in a user pool", the answer is Advanced Security Features in Amazon Cognito user pools. Reference: https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-managing-security.html
Amazon Cognito Identity Pools — Temporary AWS Credentials
An Amazon Cognito identity pool (the AWS service was formerly called "Cognito Federated Identities") is a separate resource from an Amazon Cognito user pool. It does one specific job: take a token proving some identity, map that identity to an IAM role, call AWS STS AssumeRoleWithWebIdentity on the caller's behalf, and return short-term AWS credentials (access key id, secret access key, session token, expiration).
Why identity pools exist
Mobile and browser apps often want to call AWS APIs directly — upload to Amazon S3, read from Amazon DynamoDB, publish to Amazon SNS — without going through your own server tier. The AWS SDK in the mobile/web client needs AWS credentials to sign requests. You cannot ship long-term IAM user access keys in a mobile app (that is a catastrophic anti-pattern; anyone who decompiles the app has permanent AWS keys). Instead, the app signs in with Amazon Cognito (or Google, Facebook, SAML, etc.), then exchanges the resulting token at an identity pool for short-term credentials good for one hour by default.
Authenticated vs unauthenticated identities
Every Amazon Cognito identity pool supports two kinds of identity:
- Authenticated identities — the caller arrived with a valid token from a trusted identity provider (Amazon Cognito user pool, Google, Facebook, Apple, Amazon, a SAML IdP, or any OIDC IdP). The identity pool maps this identity to the authenticated IAM role.
- Unauthenticated (guest) identities — the caller did not present a token. If the identity pool is configured to allow unauthenticated identities, the caller is mapped to the unauthenticated IAM role. Typical use case: a public read-only Amazon S3 gallery that anyone (logged in or not) can browse from the browser.
Both roles are regular IAM roles with trust policies that permit the identity pool to assume them. The difference is only in what permissions each role carries — unauthenticated roles are typically extremely narrow (read-only, specific prefixes).
Role mapping — basic and rules-based
Amazon Cognito identity pools let you assign different authenticated roles based on the identity's attributes. Two mapping modes exist:
- Default role resolution — all authenticated identities get the single authenticated role. Simple and enough for most apps.
- Rules-based role mapping — inspect claims on the incoming token (for example, a Cognito user pool ID token's
cognito:groupsor a SAML assertion attribute) and pick from multiple roles. Classic pattern:cognito:groups contains "Admin"→ admin role with broad permissions; otherwise → standard role with read-only permissions.
Additionally, role-based access with token claims lets you let the token itself name the role to assume (via a cognito:preferred_role claim), as long as it is in the allowed list.
AssumeRoleWithWebIdentity under the hood
When your app calls GetCredentialsForIdentity on the identity pool (directly or via the AWS SDK's CognitoIdentityCredentials provider), the identity pool internally calls AWS STS AssumeRoleWithWebIdentity with the mapped IAM role ARN and the OIDC token. AWS STS validates the token signature against the IdP's public keys, checks the role's trust policy permits this web identity, and returns temporary credentials. The identity pool passes those credentials back to your app. Default session duration is 1 hour; the role's MaxSessionDuration can extend it up to 12 hours for some flows.
- Authenticate via an IdP (user pool, Google, Facebook, SAML, OIDC, Apple, Amazon) → get OIDC/SAML token.
- Call
GetIdon the identity pool with the token → receive a Cognito identity id. - Call
GetCredentialsForIdentitywith the identity id + token. - Identity pool internally calls AWS STS
AssumeRoleWithWebIdentity. - Your app receives short-term AWS credentials (access key, secret key, session token, expiration). Reference: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html
User Pool vs Identity Pool — The Classic Trap, Fully Resolved
This distinction is tested on every DVA-C02 attempt. Memorize the table.
| Aspect | Amazon Cognito user pool | Amazon Cognito identity pool |
|---|---|---|
| Primary job | Authenticate users; manage user directory | Exchange identity tokens for temporary AWS credentials |
| What it returns | JWT tokens (ID, access, refresh) | Temporary AWS credentials via AssumeRoleWithWebIdentity |
| Who trusts it | Your application code; Amazon API Gateway; AWS AppSync | AWS services via IAM role trust policies |
| Integrates with | Hosted UI, OAuth 2.0, SAML, OIDC, social IdPs | User pools, Google, Facebook, Apple, Amazon, SAML, OIDC, unauthenticated |
| Output consumed by | Your app's session; API authorizers | AWS SDK for direct AWS API calls from client |
| Think of it as | "Login database + OIDC IdP" | "Token-to-IAM-role bouncer" |
| Mandatory for direct AWS API calls from browser/mobile? | No | Yes |
The cleanest mental test: if the app is calling my own API (behind Amazon API Gateway), I need a user pool only — the API Gateway Cognito Authorizer will validate the JWT. If the app is calling an AWS API directly from the client (Amazon S3 upload from browser, Amazon DynamoDB read from mobile), I need an identity pool — it is the only thing that issues AWS credentials. If the app does both, I use both, chained.
Amazon Cognito with Amazon API Gateway — The Cognito Authorizer
Amazon API Gateway has a native authorizer type called the Cognito User Pool Authorizer. You wire a REST API method or an HTTP API route to a specific Amazon Cognito user pool, and API Gateway will automatically validate the JWT on every request before forwarding to the integration.
How the Cognito Authorizer works
- The client puts the JWT (typically the ID token for REST APIs, or the access token for HTTP APIs that check scopes) in the
Authorizationheader (or a custom header you configure). - Amazon API Gateway fetches the user pool's JSON Web Key Set (JWKS), caches the public keys, and validates the JWT's signature locally — no call to Amazon Cognito is required per request, making the authorizer fast.
- API Gateway verifies the token's
issmatches the user pool URL, thetoken_useclaim matches what the authorizer is configured for (idoraccess), theclient_id/audclaim matches an allowed app client, and theexpis in the future. - If validation passes, API Gateway forwards the request and puts the token claims into the integration context (
$context.authorizer.claims.sub,$context.authorizer.claims.email,$context.authorizer.claims['cognito:groups']). - If validation fails, API Gateway returns 401 immediately.
Scope-based authorization (HTTP APIs)
Amazon API Gateway HTTP APIs (the newer API Gateway type) support OAuth 2.0 scope checking: you declare which scopes each route requires, and the authorizer rejects the request if the access token's scope claim does not include them. This is the clean OAuth pattern for API protection and aligns with client-credentials-grant M2M calls (where there is only an access token, not an ID token).
Cognito Authorizer vs Lambda Authorizer
Amazon API Gateway supports two authorizer types. On DVA-C02 you must know when to pick each.
- Cognito User Pool Authorizer — use when your tokens come from an Amazon Cognito user pool. Zero code, fully managed, fast (local JWT validation). Best default.
- Lambda Authorizer (formerly custom authorizer) — use when authentication comes from a non-Cognito IdP (Auth0, Firebase, a home-grown JWT issuer), when you need to inspect custom claims beyond what Cognito offers, or when authorization logic depends on external lookups (database, third-party API). Two sub-types: token authorizer (passes the raw token) and request authorizer (passes the full request context — headers, path, source IP).
Both authorizers support a policy-document response that returns an IAM-style policy (Allow/Deny specific API Gateway methods). Lambda authorizer results can be cached per identity (default TTL 300 seconds) to reduce Lambda invocations.
If the scenario says "protect my API Gateway endpoint with an Amazon Cognito user pool", the answer is Cognito User Pool Authorizer — not a Lambda Authorizer. Reach for a Lambda Authorizer only when (a) the IdP is not Amazon Cognito, or (b) you need custom authorization logic the built-in authorizer cannot express. Reference: https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html
Amazon Cognito with AWS AppSync
AWS AppSync is the managed GraphQL service. It supports five authorization modes, and Amazon Cognito user pools is the most common:
- Amazon Cognito User Pools — pass the JWT in the
Authorizationheader; AWS AppSync validates it and exposes claims to resolvers. You can enforcecognito:groupsmembership on specific fields using@aws_authdirectives. - AWS IAM — sign the request with SigV4 using AWS credentials (typically obtained from an Amazon Cognito identity pool for client-side apps).
- API keys — only for development or truly public endpoints; not for production user data.
- OpenID Connect (OIDC) — any OIDC IdP, not necessarily Amazon Cognito.
- Lambda authorizer — same pattern as Amazon API Gateway Lambda authorizers.
A typical mobile app setup uses Cognito user pools as the primary authorization mode for authenticated operations, and the user-pool JWT flows from sign-in directly to GraphQL queries.
Putting It All Together — Two Canonical Architectures
Architecture 1: Serverless web app protected by API Gateway
A single-page app (React, Vue, Svelte) calls a REST API behind Amazon API Gateway that routes to AWS Lambda.
- User signs in via the Amazon Cognito Hosted UI (authorization code flow with PKCE, custom domain
auth.example.com). - Hosted UI redirects back with an authorization code; the SPA exchanges the code for ID, access, and refresh tokens.
- SPA stores tokens (access + refresh in memory or secure storage; never localStorage for long-lived tokens in production) and includes the ID token in the
Authorizationheader on every API call. - Amazon API Gateway's Cognito User Pool Authorizer validates the JWT locally using the user pool's JWKS. On success, forwards the request to AWS Lambda with claims in the event context.
- AWS Lambda reads
event.requestContext.authorizer.claims.subto know which user is calling and applies business-level authorization.
No identity pool needed — the app never calls AWS APIs directly from the client.
Architecture 2: Mobile app uploading photos directly to Amazon S3
A mobile app (iOS/Android) wants users to upload photos straight to Amazon S3 without going through a server.
- User signs in via the Amazon Cognito user pool from inside the app (SDK native flow or Hosted UI).
- App receives the ID token (JWT).
- App passes the ID token to an Amazon Cognito identity pool via
GetId+GetCredentialsForIdentity. - Identity pool calls AWS STS
AssumeRoleWithWebIdentityand returns temporary AWS credentials (access key, secret key, session token) tied to an IAM role withs3:PutObjectonarn:aws:s3:::photo-bucket/${cognito-identity.amazonaws.com:sub}/*. - App's AWS SDK for Amazon S3 uses those credentials to upload directly to the bucket. The
${cognito-identity.amazonaws.com:sub}IAM policy variable scopes each user's prefix to their own identity id — classic multi-tenant isolation.
Both a user pool and an identity pool are required here, and they work together sequentially.
Key Numbers and Must-Memorize Facts for Amazon Cognito
- User pool issues JWT; identity pool issues AWS credentials via
AssumeRoleWithWebIdentity. - ID token, access token: default 1 hour, configurable 5 minutes to 24 hours.
- Refresh token: default 30 days, configurable 1 hour to 10 years.
- Temporary AWS credentials from identity pool: default 1 hour; role
MaxSessionDurationup to 12 hours. - OAuth 2.0 flows: authorization code (best for web/mobile), implicit (legacy), client credentials (server-to-server).
- MFA: SMS, TOTP, Email. Options: Off / Optional / Required.
- Federation: SAML 2.0, OIDC, Google, Facebook, Apple, Amazon.
- API Gateway Cognito Authorizer validates JWT locally using JWKS — no per-request Cognito API call.
- Advanced Security Features (ASF): adaptive authentication + compromised credential detection; paid per MAU.
- Token revocation:
RevokeTokeninvalidates the refresh token; issued JWTs remain valid untilexp. - Reference: https://docs.aws.amazon.com/cognito/latest/developerguide/what-is-amazon-cognito.html
Common Exam Traps — Amazon Cognito on DVA-C02
Trap 1: User pool vs identity pool confusion
The most-tested Cognito trap. Any scenario that says "sign in / authenticate / manage user accounts / MFA / password reset" wants a user pool. Any scenario that says "the mobile/web app needs to call AWS APIs directly / upload to Amazon S3 from the browser / get AWS credentials from a social login" wants an identity pool (often paired with a user pool). "Temporary AWS credentials" + "client-side" almost always points to an identity pool.
Trap 2: ID token vs access token for API authorization
Both are JWTs. Amazon API Gateway REST API Cognito authorizers historically check ID tokens by default but can be configured for access tokens. HTTP API JWT authorizers default to access tokens (the OAuth-correct choice) and support scope validation. When the scenario mentions OAuth scopes, the right token is the access token. When the scenario only needs to know who the user is, the ID token is fine.
Trap 3: OAuth 2.0 flow selection
"Server-to-server / M2M / backend service calling an API" = client credentials grant, returns only an access token. "SPA / mobile / any end-user app" = authorization code grant with PKCE (do not pick implicit grant). If a question explicitly describes a legacy browser-only app with no backend and no PKCE support, implicit grant is the historical answer — but modern best practice is authorization code + PKCE everywhere.
Trap 4: Cognito Authorizer vs Lambda Authorizer on API Gateway
If the IdP is Amazon Cognito user pool, the default answer is Cognito User Pool Authorizer. Lambda Authorizer is correct only when the scenario mentions a non-Cognito IdP (Auth0, Firebase, custom JWT issuer), a need for custom authorization logic (cross-tenant checks, external database lookups), or non-JWT tokens (API keys validated against an external directory).
Trap 5: "Guest access" means unauthenticated identity pool identities
If the exam scenario says "allow anyone, even unauthenticated users, to read from this Amazon S3 bucket through my mobile app", that is the unauthenticated identity feature of an Amazon Cognito identity pool — not a bucket policy with Principal: "*", and not an IAM user embedded in the app. Enable "allow unauthenticated identities" on the identity pool and scope the unauthenticated IAM role tightly.
Trap 6: Amazon Cognito is regional, AWS IAM is global
Amazon Cognito user pools and identity pools are regional AWS resources. If you need users to sign in from multiple regions with disaster recovery, you must plan for regional replication yourself (or use a global database layer and a region-specific pool strategy). Contrast with AWS IAM, which is global and does not require region planning.
Trap 7: Lambda trigger vs custom auth flow
"Add a custom claim to the JWT" = pre token generation Lambda trigger. "Migrate users from a legacy system lazily on first sign-in" = user migration Lambda trigger. "Implement passwordless SMS OTP sign-in or magic links or passkeys" = the custom authentication challenge trio (define / create / verify auth challenge), not a single trigger.
Practice Question Links — DVA-C02 Task 2.1 Cognito Scenarios
- "A mobile app needs to upload files directly to Amazon S3 for each signed-in user." → Amazon Cognito user pool (sign-in) + Amazon Cognito identity pool (temporary AWS credentials), with an IAM role that scopes S3 prefix by
${cognito-identity.amazonaws.com:sub}. - "Protect an Amazon API Gateway REST API so only signed-in users of our web app can call it." → Amazon Cognito user pool + Cognito User Pool Authorizer on API Gateway.
- "A backend microservice needs to call an internal API Gateway endpoint. There is no human user." → OAuth 2.0 client credentials grant with a resource server and custom scopes in the user pool; API Gateway HTTP API JWT authorizer validates the access token's scope claim.
- "Customers should be able to sign in with Google or Facebook, and we want one user record per person." → User pool with Google and Facebook as federated identity providers, with account linking by email.
- "Auto-confirm users whose email ends with
@corp.example.comand reject everyone else." → Pre sign-up Lambda trigger that checks the email domain, setsautoConfirmUser: truefor trusted domains, and throws for others. - "Inject the user's tenant id into the JWT so downstream APIs can authorize without a database lookup." → Pre token generation Lambda trigger.
- "Block sign-ins from IP addresses known to have breached credentials." → Enable Advanced Security Features on the user pool and configure adaptive authentication + compromised credentials detection.
- "Migrate users from a legacy MySQL auth table lazily on first sign-in without forcing a password reset." → User migration Lambda trigger.
FAQ — Amazon Cognito Top Questions
Q1: When should I use an Amazon Cognito user pool vs an identity pool?
Use an Amazon Cognito user pool whenever you need to sign users in, manage their accounts, issue JWT tokens, or protect your own APIs behind Amazon API Gateway's Cognito Authorizer. Use an Amazon Cognito identity pool only when a client-side app (mobile or browser) needs to call AWS APIs directly and therefore needs temporary AWS credentials. Most applications use both together — the user pool authenticates, the identity pool converts the JWT into AWS credentials via AssumeRoleWithWebIdentity. If your app talks only to your own API (not directly to AWS services), you probably do not need an identity pool at all.
Q2: What is the difference between the ID token, access token, and refresh token?
The ID token is an OIDC JWT containing identity claims (sub, email, cognito:groups, custom attributes); use it to know who the user is in your application. The access token is an OAuth 2.0 JWT containing scopes and cognito:groups; use it to authorize API calls — especially when you use OAuth resource-server scopes. The refresh token is an opaque long-lived token used to request new ID and access tokens without forcing the user to sign in again. Default lifetimes: 1 hour / 1 hour / 30 days, all configurable.
Q3: Which OAuth 2.0 flow should my app use?
Server-rendered web apps and native mobile apps should use the authorization code grant (with PKCE for public clients where you cannot safely store a client secret). Single-page apps should also use authorization code + PKCE in 2026 — implicit grant is legacy and should be avoided. Client credentials grant is the right flow for backend-to-backend service calls where there is no human user; it returns only an access token and requires a resource server with custom scopes configured in the user pool. Do not confuse client credentials with authorization code — client credentials has no redirect and no end user.
Q4: How do I protect an Amazon API Gateway endpoint with Amazon Cognito?
Create an Amazon Cognito user pool and an app client. On the API Gateway method (REST) or route (HTTP API), attach a Cognito User Pool Authorizer pointing at the user pool. The client sends the JWT in the Authorization header; API Gateway validates the signature locally against the user pool's JWKS (no Cognito API call per request), checks iss, aud/client_id, token_use, and exp, and forwards the claims to your integration. For HTTP APIs, also configure required OAuth scopes per route to check the access token's scope claim. Use a Lambda Authorizer instead only if the IdP is not Cognito or you need custom logic.
Q5: How do I add custom claims to the JWT issued by my user pool?
Implement a pre token generation Lambda trigger. The trigger receives the default claims, can add/override claims in claimsToAddOrOverride, and returns the modified event. Amazon Cognito signs the final token. Typical custom claims: tenant id, feature flags, internal user id, role — anything that downstream APIs need for authorization without an extra database lookup per request.
Q6: What happens when a refresh token is revoked?
Calling RevokeToken on a refresh token prevents that refresh token from minting new ID and access tokens. However, JWT access tokens already issued from that refresh token remain valid until their exp claim because third-party APIs validate JWTs locally against the user pool's public keys — they do not call Amazon Cognito on every request. For this reason, keep access token lifetimes short (5–60 minutes) if revocation propagation matters. The aws.cognito.signin.user.admin scope is special: Cognito will reject its use after revocation even within the token's natural lifetime.
Q7: How do I migrate users from a legacy auth system to Amazon Cognito?
The user migration Lambda trigger is the main pattern. When a user signs in with a username that does not exist in the Amazon Cognito user pool, the trigger fires with the submitted username and password; your Lambda validates against the legacy system, returns the user's attributes on success, and Amazon Cognito creates the user pool record transparently. This lets users migrate gradually as they sign in, without a password reset or a bulk import. For bulk imports, Cognito also supports CSV-based user imports with AdminCreateUser variants, but those require users to reset their password on first sign-in.
Q8: How does Amazon Cognito integrate with AWS AppSync?
AWS AppSync supports Amazon Cognito user pools as one of five authorization modes. The client includes the JWT in the Authorization header; AppSync validates it and exposes claims to your resolvers (direct Amazon DynamoDB resolvers, Lambda resolvers, etc.). You can restrict specific GraphQL fields or mutations to specific cognito:groups using the @aws_auth schema directive. For fine-grained per-record authorization, combine the user pool JWT mode with VTL resolver logic that checks the calling user's sub against item attributes like ownerId. For direct AWS API calls, AppSync also supports AWS IAM auth — typically paired with an Amazon Cognito identity pool that issues the IAM credentials.
Further Reading
- Amazon Cognito Developer Guide
- Amazon Cognito User Pools
- Amazon Cognito Identity Pools (Federated Identities)
- Using Tokens with User Pools
- Configuring OAuth 2.0 Flows in User Pools
- Lambda Triggers for Amazon Cognito User Pools
- Amazon Cognito Advanced Security Features
- Control Access to a REST API with Amazon Cognito User Pools
- AWS AppSync Authorization and Authentication
- AWS STS AssumeRoleWithWebIdentity API
- AWS DVA-C02 Exam Guide (PDF)