This chapter covers Amazon Cognito Hosted UI and OAuth Flows, a critical topic for the DVA-C02 exam under Domain 2: Security (Objective 2.2). You will learn how Cognito provides a ready-made, customizable authentication interface, the different OAuth 2.0 and OIDC flows it supports, and how to configure and secure these flows. Approximately 5-10% of exam questions touch on Cognito authentication, often testing your ability to select the correct flow for a given scenario or to troubleshoot token exchange. Mastering this content will help you answer scenario-based questions about user authentication, token management, and identity federation.
Jump to a section
Imagine a busy airport with multiple airlines, each requiring passengers to check in before boarding. The airport provides a central check-in desk (the Cognito Hosted UI) that any airline (your application) can use. When a passenger wants to fly, they go to the check-in desk and present their passport (identity provider credentials like Google or Facebook). The desk verifies the passport, then issues a boarding pass (ID token) and a luggage tag (access token) that allows the passenger to board the plane and access certain areas. The passenger can also get a separate baggage claim stub (refresh token) to retrieve their luggage later without re-checking in. The check-in desk offers different processes: a simple self-service kiosk (Implicit grant) for passengers who just need a boarding pass quickly, a full-service counter (Authorization Code grant) that exchanges a boarding pass stub for the actual pass after verification, and a premium lounge (Client Credentials grant) for airline staff who already have internal badges. The airport's security ensures that only authorized airlines can use the check-in desk (app client configuration), and the desk can be customized with the airport's branding (custom domain and UI customization). If a passenger loses their boarding pass, they can use the baggage claim stub (refresh token) at a kiosk to get a new one without going through the full check-in again. This mirror shows how Cognito Hosted UI centralizes authentication, supports multiple OAuth flows, and issues tokens for secure access to your app's resources.
What is Cognito Hosted UI and Why It Exists
Amazon Cognito Hosted UI is a pre-built, customizable web page that handles user sign-up and sign-in for your applications. Instead of building your own login forms and managing authentication logic, you can offload that to Cognito. The Hosted UI is the front end; behind it, Cognito uses OAuth 2.0 and OpenID Connect (OIDC) protocols to issue tokens (ID, access, and refresh tokens) that your application uses to authorize API calls.
Why does this matter for DVA-C02? The exam tests your understanding of when to use the Hosted UI versus building a custom UI, how to configure OAuth flows, and how tokens are exchanged. You need to know the specifics of each OAuth grant type and the parameters used in the authorization request.
How Cognito Hosted UI Works Internally
When a user clicks "Sign In" on your app, they are redirected to a Cognito domain (e.g., https://your-domain.auth.us-east-1.amazoncognito.com/login). The URL includes query parameters that specify the OAuth flow, client ID, redirect URI, response type, and scope. Cognito authenticates the user (via username/password, social IdP, or SAML), then redirects back to your app with tokens or an authorization code, depending on the flow.
OAuth 2.0 and OIDC Flows Supported
Cognito Hosted UI supports three main OAuth 2.0 grant types, each suited for different application types:
Authorization Code Grant: Used by server-side applications (e.g., Java, Python, .NET) where the client secret can be kept confidential. The flow: user authenticates, Cognito returns an authorization code to the redirect URI; your app then exchanges that code (plus client secret) for tokens via a back-channel POST to Cognito's token endpoint. This is the most secure flow because the tokens never touch the user's browser.
Implicit Grant: Used by client-side applications (e.g., JavaScript SPA) where the client secret cannot be stored securely. Cognito returns tokens directly in the URL fragment after authentication. This flow is simpler but less secure because tokens are exposed in the browser history. The exam expects you to know that the Implicit grant is deprecated by OAuth 2.0 Security Best Current Practice (BCP) and that Authorization Code Grant with PKCE is recommended.
Client Credentials Grant: Used for machine-to-machine communication (e.g., backend services calling APIs). No user involvement; the app authenticates itself using its client ID and secret to obtain an access token. This is not typically used with Hosted UI because there is no user to log in.
Cognito also supports OIDC, which adds an ID token (a JWT containing user identity claims) to the OAuth flows. The ID token is obtained alongside the access token in the Authorization Code and Implicit grants.
Key Components, Values, Defaults, and Timers
Cognito User Pool: The user directory. You must have a user pool to use Hosted UI.
App Client: Represents your application. Each app client has a client ID (public) and optionally a client secret (confidential). For Hosted UI, you must enable the OAuth 2.0 grant types allowed (Authorization Code, Implicit, or both).
Domain: Cognito provides a domain like https://<domain-prefix>.auth.<region>.amazoncognito.com. You can also use a custom domain (e.g., auth.yourdomain.com) with an ACM certificate.
Redirect URIs: Must be HTTPS (except for localhost in development). Up to 100 per app client.
Scopes: Define what access is requested. Standard OIDC scopes: openid, email, profile, aws.cognito.signin.user.admin (for user info). Custom scopes can be defined.
Token Expiration: Access token: 1 hour (default, configurable 5 min to 24 hours). ID token: 1 hour (default, configurable 5 min to 24 hours). Refresh token: 30 days (default, configurable 1 hour to 10 years).
Authorization Code Expiration: The code is valid for 5 minutes (not configurable).
State Parameter: A random string you generate to prevent CSRF attacks. Cognito returns it unchanged in the redirect.
PKCE (Proof Key for Code Exchange): An extension to the Authorization Code grant to prevent authorization code interception attacks. The app creates a code verifier (random string) and a code challenge (SHA-256 hash of the verifier). The challenge is sent in the initial request; the verifier is sent when exchanging the code. Cognito verifies they match.
Configuration and Verification Commands
To configure Hosted UI, you can use the AWS Management Console, AWS CLI, or SDK. Below are CLI examples:
Create a user pool (if not existing):
aws cognito-idp create-user-pool --pool-name MyPoolCreate an app client with Hosted UI enabled:
aws cognito-idp create-user-pool-client --user-pool-id us-east-1_xxxxx --client-name MyApp --generate-secret --explicit-auth-flows ALLOW_REFRESH_TOKEN_AUTH --allowed-o-auth-flows code --allowed-o-auth-scopes openid email --callback-urls https://yourapp.com/callback --logout-urls https://yourapp.com/logout --supported-identity-providers COGNITOCreate a domain:
aws cognito-idp create-user-pool-domain --domain mydomain --user-pool-id us-east-1_xxxxxVerify configuration:
aws cognito-idp describe-user-pool-client --user-pool-id us-east-1_xxxxx --client-id xxxxxHow Hosted UI Interacts with Related Technologies
API Gateway: You can use Cognito as an authorizer for API Gateway. The access token (or ID token) is passed in the Authorization header. API Gateway validates the JWT signature and expiration.
ALB (Application Load Balancer): ALB can authenticate users via Cognito Hosted UI before routing requests to your application. This is useful for microservices where you don't want each service to handle authentication.
Lambda: You can use Cognito triggers (pre sign-up, post authentication, etc.) to customize the auth flow. For example, a pre sign-up Lambda can validate user attributes before registration.
CloudFront: You can use Lambda@Edge with Cognito to enforce authentication at the CDN edge.
OAuth Flows in Detail
Authorization Code Grant with PKCE (Recommended for SPAs):
1. App generates a code verifier (random 43-128 characters) and code challenge (SHA-256 hash, base64url-encoded).
2. App redirects user to Cognito Hosted UI with response_type=code, code_challenge_method=S256, code_challenge=<hash>.
3. User authenticates. Cognito redirects to callback URL with code=authorization_code.
4. App sends POST to token endpoint with grant_type=authorization_code, code, redirect_uri, client_id, and code_verifier.
5. Cognito verifies the code verifier against the challenge, then returns ID token, access token, and refresh token.
Implicit Grant (Deprecated):
1. App redirects user to Cognito Hosted UI with response_type=token (or id_token for ID token only).
2. User authenticates. Cognito redirects to callback URL with tokens in the URL fragment (e.g., #access_token=...&id_token=...).
3. App extracts tokens from fragment. No back-channel call.
Client Credentials Grant:
1. App (backend service) sends POST to token endpoint with grant_type=client_credentials, client_id, client_secret.
2. Cognito returns an access token (no user context).
Security Considerations
Always use HTTPS for redirect URIs and the Hosted UI domain.
Use the state parameter to prevent CSRF.
Use PKCE for public clients (SPAs, mobile apps).
Store client secrets securely (e.g., AWS Secrets Manager).
For server-side apps, use the Authorization Code grant (not Implicit).
Set appropriate token expiration times per your security policy.
Exam Tips
The exam often asks which OAuth flow to use for a given scenario: e.g., "A server-side web app needs to authenticate users. Which flow?" Answer: Authorization Code Grant.
Know the difference between ID token (user identity) and access token (authorization).
Remember that the Implicit grant is deprecated and PKCE should be used instead.
Understand that the Client Credentials grant is for machine-to-machine, not for user login.
Custom domains require an ACM certificate in the same region as the user pool.
The Hosted UI can be customized with a custom CSS, but you cannot change the HTML structure.
Troubleshooting Common Issues
Redirect URI mismatch: Ensure the redirect URI in the app client configuration exactly matches the one in the request (including protocol, case, and trailing slashes).
Invalid grant type: Make sure the allowed OAuth flows in the app client include the one you are using.
Token expiration: If tokens expire unexpectedly, check the refresh token expiration and ensure your app uses the refresh token to get new tokens.
CORS errors: If your SPA is calling Cognito endpoints from a different domain, configure CORS headers in the app client.
Summary of Key Values
Authorization code lifetime: 5 minutes
Access token default: 1 hour (configurable 5 min - 24 hours)
ID token default: 1 hour (configurable 5 min - 24 hours)
Refresh token default: 30 days (configurable 1 hour - 10 years)
PKCE code verifier length: 43-128 characters
PKCE code challenge method: S256 (recommended) or plain
Maximum redirect URIs per app client: 100
Custom domain requires ACM certificate in same region
Conclusion
Cognito Hosted UI simplifies authentication by providing a secure, customizable login page that implements OAuth 2.0 and OIDC. Understanding the different flows and their appropriate use cases is essential for the DVA-C02 exam. Focus on the Authorization Code grant with PKCE as the modern standard, and be aware of the security implications of each flow.
Configure User Pool and App Client
First, create a Cognito user pool. This is the user directory that will store user attributes and handle authentication. Then, create an app client that represents your application. In the app client settings, you must enable the Hosted UI by specifying the allowed OAuth flows (e.g., Authorization Code, Implicit), allowed OAuth scopes (e.g., openid, email), and callback URLs. You can also generate a client secret for confidential clients. The app client ID and secret will be used in the OAuth flow. Ensure that the callback URLs are HTTPS (except localhost). This step is foundational; without a properly configured app client, the Hosted UI will not work.
Set Up Cognito Domain
Cognito provides a default domain like `https://<domain-prefix>.auth.<region>.amazoncognito.com`. You can create this via the AWS Console or CLI. Optionally, you can configure a custom domain (e.g., `auth.yourdomain.com`) by adding an ACM certificate in the same region and updating DNS records. The domain is used as the base URL for the Hosted UI endpoints (login, logout, token, etc.). Without a domain, the Hosted UI cannot be accessed.
User Initiates Login via Hosted UI
Your application redirects the user's browser to the Cognito Hosted UI login endpoint. The URL includes query parameters: `client_id`, `response_type` (e.g., code for Authorization Code, token for Implicit), `redirect_uri`, `scope`, and `state` (for CSRF protection). For PKCE, also include `code_challenge_method` and `code_challenge`. The user sees Cognito's login page, which can be customized with your logo and CSS. The user enters credentials (or uses social login).
Cognito Authenticates and Redirects
Cognito validates the user's credentials against the user pool. If successful, it generates an authorization code (for Authorization Code grant) or tokens (for Implicit grant) and redirects the browser to the callback URL specified in the request. The authorization code is appended as a query parameter (`?code=...`), while tokens are appended as a URL fragment (`#access_token=...`). The redirect also includes the `state` parameter unchanged. The user's browser now lands on your application's callback endpoint.
Exchange Code for Tokens (Authorization Code Grant)
If using the Authorization Code grant, your server-side application receives the authorization code from the callback URL. It then makes a server-to-server POST request to Cognito's token endpoint (`/oauth2/token`) with the following parameters: `grant_type=authorization_code`, `code` (the received code), `redirect_uri` (must match the original), `client_id`, and `client_secret` (if app client has one). For PKCE, also include `code_verifier`. Cognito validates the code (expires in 5 minutes), verifies the PKCE if used, and returns a JSON response containing `access_token`, `id_token`, `refresh_token`, and `token_type`. Your server stores these tokens securely and uses the access token to call protected APIs.
Use Tokens to Access Resources
Your application now has tokens. The access token is used as a bearer token in the Authorization header of API calls (e.g., to API Gateway or your backend). The ID token can be used to get user profile information. The refresh token can be used to obtain new access and ID tokens when they expire, without requiring the user to log in again. To refresh, your app sends a POST to the token endpoint with `grant_type=refresh_token`, `refresh_token`, `client_id`, and optionally `client_secret`. Cognito returns a new set of tokens (the refresh token may also be rotated). Token expiration times are configurable in the user pool.
Enterprise Scenario 1: SaaS Application with Social Login
A SaaS company provides a project management tool used by multiple organizations. They want to allow users to sign in with their existing Google or Microsoft accounts to reduce friction. They configure a Cognito user pool with Google and Microsoft as social identity providers. They use the Hosted UI with the Authorization Code grant (with PKCE) for their React SPA. The Hosted UI shows buttons for Google and Microsoft login. When a user chooses Google, Cognito redirects to Google's OAuth endpoint, then back to Cognito, then to the app with an authorization code. The SPA exchanges the code for tokens using PKCE. The access token is used to call the backend API, which validates the token using the Cognito JWT public keys. The ID token contains user claims like email and name. Refresh tokens are stored in localStorage (with caution) to maintain sessions. The company customizes the Hosted UI with their logo and colors. They also set up a custom domain auth.projectmanager.com with an ACM certificate. One common issue: if the redirect URI in the app client does not match exactly (e.g., trailing slash), users get an error. They also had to configure CORS for the SPA to call the token endpoint from a different domain.
Enterprise Scenario 2: Server-Side Web App with Enterprise SSO (SAML)
A large enterprise uses an internal SAML 2.0 identity provider (e.g., Okta) for employee authentication. They build a .NET MVC application that needs to authenticate employees. They configure Cognito as a SAML service provider by adding the SAML IdP metadata. They use the Hosted UI with the Authorization Code grant. The user clicks 'Sign in with SSO', which redirects to the Hosted UI, which then redirects to the enterprise IdP. After SAML assertion, Cognito issues an authorization code to the app. The server-side app exchanges the code for tokens using its client secret. The access token is used to call internal APIs. The ID token contains claims mapped from SAML attributes (e.g., employee ID). They configure refresh token expiration to 8 hours to match the workday. They also enable token revocation via Cognito's RevokeToken endpoint for logout. A challenge they faced: the SAML assertion included group membership that exceeded the token size limit (4096 bytes for Cognito tokens). They resolved by limiting claims to essential ones.
Enterprise Scenario 3: Mobile App with Offline Access
A mobile app for a delivery service needs to authenticate users and allow them to stay logged in for weeks. They use Cognito Hosted UI with the Authorization Code grant (with PKCE). The mobile app opens the Hosted UI in a web view (using ASWebAuthenticationSession on iOS or Chrome Custom Tabs on Android). After successful login, the app receives an authorization code via a custom URL scheme. The app exchanges the code for tokens, including a refresh token. The refresh token is stored securely in the device's keychain/keystore. When the access token expires, the app uses the refresh token to get a new one without user interaction. They set the refresh token expiration to 30 days. If the user logs out, the app calls the Cognito logout endpoint to revoke the refresh token. They also handle token refresh failures by prompting the user to log in again. A common issue: if the device's time is off by more than 5 minutes, token validation fails because Cognito checks the iat (issued at) claim. They implemented NTP sync to prevent this.
DVA-C02 Focus on Cognito Hosted UI and OAuth Flows
The DVA-C02 exam (Objective 2.2: Implement authentication and authorization for applications) tests your ability to select and configure the appropriate OAuth flow for different application architectures. Expect scenario-based questions where you must choose between Authorization Code, Implicit, and Client Credentials grants. The exam also tests your understanding of PKCE, token types, and security best practices.
Common Wrong Answers and Why Candidates Choose Them
Choosing Implicit Grant for a server-side app: Candidates think it's simpler, but the exam expects Authorization Code because the client secret can be kept confidential. Implicit is only for public clients (SPAs) and is deprecated.
Confusing ID token with access token: The ID token is for user identity (claims like name, email), while the access token is for authorization (API access). The exam might ask which token to use to authorize API calls — answer: access token.
Thinking Client Credentials grant is for user login: It's for machine-to-machine. Candidates may choose it for a backend service calling another service, but for user authentication, you need Authorization Code or Implicit.
Not using PKCE for SPAs: The exam emphasizes that the Implicit grant is deprecated and PKCE should be used with Authorization Code for SPAs. Candidates may suggest Implicit because it's simpler, but the correct answer is Authorization Code with PKCE.
Specific Numbers and Terms That Appear on the Exam
Authorization code lifetime: 5 minutes
Access token default: 1 hour (configurable 5 min - 24 hours)
Refresh token default: 30 days (configurable 1 hour - 10 years)
PKCE code challenge method: S256 (recommended) or plain
Maximum redirect URIs per app client: 100
Custom domain requires ACM certificate in same region
The state parameter is used for CSRF protection
Edge Cases and Exceptions
If the user pool has a domain prefix that is already taken, you must choose another.
Custom domains cannot be used with some Cognito features like the Hosted UI in the Asia Pacific (Mumbai) region initially (check documentation).
Token size limit: Cognito tokens cannot exceed 4096 bytes (4 KB). If you add many custom claims, you may hit this limit.
Refresh token rotation: By default, Cognito rotates refresh tokens (issues a new one) when you use a refresh token to get new tokens. The old refresh token becomes invalid. This is important for security but can cause issues if not handled.
Logout endpoint: To log out, you must redirect the user to https://<domain>/logout?client_id=<client_id>&logout_uri=<encoded_uri>. The logout URI must be one of the allowed logout URLs in the app client.
How to Eliminate Wrong Answers Using the Underlying Mechanism
When you see a question about choosing an OAuth flow, think about where the client secret can be stored: - Server-side app: Can store secret securely → Authorization Code grant. - SPA or mobile app: Cannot store secret securely → Authorization Code grant with PKCE (not Implicit). - Machine-to-machine: No user → Client Credentials grant.
If the question mentions "public client" or "no client secret", eliminate any answer that requires a client secret. If it mentions "server-side" or "confidential client", eliminate Implicit and Client Credentials. If it mentions "user authentication", eliminate Client Credentials. If it mentions "deprecated", eliminate Implicit.
Also, remember that the Hosted UI is used for user-facing login. If the scenario involves an application that needs to authenticate users via a browser, the Hosted UI is appropriate. If it's a backend service calling another service, you don't need the Hosted UI.
Finally, pay attention to token types: if the question asks for a token that contains user claims, it's the ID token. If it asks for a token to authorize API calls, it's the access token. If it asks for a token to get new tokens, it's the refresh token.
Cognito Hosted UI provides a pre-built login page that implements OAuth 2.0 and OIDC flows.
The Authorization Code grant is the most secure flow for server-side apps; use PKCE for SPAs.
The Implicit grant is deprecated; do not use it for new applications.
The Client Credentials grant is for machine-to-machine, not user authentication.
Authorization codes expire in 5 minutes; access tokens default to 1 hour; refresh tokens default to 30 days.
Always use the `state` parameter to prevent CSRF attacks.
Custom domains require an ACM certificate in the same region as the user pool.
Cognito rotates refresh tokens by default; handle token refresh failures.
These come up on the exam all the time. Here's how to tell them apart.
Authorization Code Grant
Requires a back-channel token exchange (server-to-server), so tokens are never exposed to the browser.
Allows use of refresh tokens for long-lived sessions.
Supports PKCE for additional security in public clients.
Recommended for confidential clients (server-side apps) and public clients with PKCE.
More secure because the authorization code is short-lived (5 minutes) and exchanged over a secure server channel.
Implicit Grant
Tokens are returned directly in the URL fragment, visible in browser history.
Cannot use refresh tokens (tokens must be short-lived).
No PKCE support (deprecated flow).
Only suitable for public clients (SPAs) but deprecated in favor of Authorization Code + PKCE.
Less secure due to token exposure and lack of code exchange.
Mistake
The Implicit grant is the best choice for SPAs because it is simpler.
Correct
The Implicit grant is deprecated by OAuth 2.0 Security Best Current Practice (BCP) due to security vulnerabilities (e.g., tokens exposed in browser history). The recommended approach for SPAs is the Authorization Code grant with PKCE, which provides better security without needing a client secret.
Mistake
The ID token and access token are interchangeable.
Correct
They have different purposes. The ID token (JWT) contains user identity claims (e.g., name, email) and is used to identify the user. The access token (opaque or JWT) is used to authorize access to resources (e.g., API calls). They have different scopes and should not be used interchangeably.
Mistake
Cognito Hosted UI can be fully customized with custom HTML.
Correct
Cognito Hosted UI only allows customization via CSS (custom styles) and the ability to add a logo. You cannot change the underlying HTML structure or add custom JavaScript. For full control, you must build a custom UI using the Cognito SDKs.
Mistake
The refresh token never expires if you keep using it.
Correct
Refresh tokens have a configurable expiration time (default 30 days). Even if you use it to get new tokens, the refresh token itself expires after the configured duration. Additionally, Cognito rotates refresh tokens by default, meaning the old one becomes invalid when you use it. You must handle token refresh failures gracefully.
Mistake
You can use the Client Credentials grant to authenticate users.
Correct
The Client Credentials grant is for machine-to-machine communication where no user is involved. It uses the app's credentials (client ID and secret) to get an access token for the app itself, not for a user. For user authentication, you need the Authorization Code or Implicit grant.
Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.
The ID token is a JWT that contains claims about the authenticated user, such as name, email, and phone number. It is used to identify the user to your application. The access token is also a JWT (or opaque) that is used to authorize access to protected resources, like your backend API. The access token contains claims about the allowed scopes and the client. Always use the access token in the Authorization header of API calls, not the ID token.
The Implicit grant is deprecated because it exposes tokens in the URL fragment, making them vulnerable to interception via browser history, referrer headers, and other attacks. The recommended alternative is the Authorization Code grant with PKCE (Proof Key for Code Exchange). PKCE adds a cryptographic challenge that prevents interception of the authorization code, making it secure for public clients like SPAs and mobile apps.
To use a custom domain (e.g., auth.yourdomain.com), you need an AWS Certificate Manager (ACM) SSL/TLS certificate in the same AWS region as your Cognito user pool. Then, in the Cognito console, under 'App integration' -> 'Domain name', choose 'Use your own domain' and enter your domain name. Cognito will provide a CloudFront distribution URL that you need to point your DNS CNAME record to. The domain must be unique across all AWS accounts.
Yes, mobile apps can use Cognito Hosted UI by opening the login URL in a secure web view (e.g., ASWebAuthenticationSession on iOS, Chrome Custom Tabs on Android). After authentication, Cognito redirects to a custom URL scheme (e.g., myapp://callback) that the mobile app handles. The app then exchanges the authorization code for tokens using PKCE. This approach is recommended over embedding the Hosted UI in a WebView because it uses the device's browser for better security.
When the refresh token expires, your application can no longer obtain new access tokens without user interaction. The user must log in again. To handle this gracefully, your app should detect when a token refresh fails (e.g., HTTP 400 Bad Request with 'Invalid refresh token') and redirect the user to the Hosted UI for re-authentication. You can also set a longer refresh token expiration (up to 10 years) in the user pool settings, but this is a security trade-off.
To log out, redirect the user's browser to the Cognito logout endpoint: `https://<your-domain>/logout?client_id=<client_id>&logout_uri=<encoded_redirect_uri>`. The logout URI must be one of the allowed logout URLs configured in the app client. Cognito will clear the user's session and redirect to the logout URI. Additionally, you should revoke the refresh token by calling the RevokeToken endpoint to invalidate it.
The `state` parameter is a random string generated by your application that is included in the initial authorization request. Cognito returns it unchanged in the redirect back to your app. Your app then verifies that the returned state matches the one it sent. This prevents Cross-Site Request Forgery (CSRF) attacks by ensuring that the response corresponds to the request your app initiated.
You've just covered Cognito Hosted UI and OAuth Flows — now see how well it sticks with free DVA-C02 practice questions. Full explanations included, no account needed.
Done with this chapter?