This chapter covers Amazon Cognito Lambda triggers for pre- and post-authentication events, a key topic in the DVA-C02 Security domain (Objective 2.2). These triggers allow developers to inject custom logic into the authentication flow without modifying the client or managing separate identity providers. Approximately 5-10% of exam questions touch on Cognito triggers, often testing your understanding of when each trigger fires, what you can modify, and common use cases. Mastering this topic ensures you can design secure, custom authentication workflows and confidently answer scenario-based questions.
Jump to a section
Imagine a hotel where guests use key cards to access rooms, gym, and pool. Before issuing a card, the front desk checks your reservation (pre-authentication). But the hotel also uses a custom system: when you swipe into the gym, a trigger checks if your membership is active (post-authentication). Think of Amazon Cognito's pre-authentication Lambda trigger as the front desk checking your ID before giving the key. The post-authentication trigger is like the gym door logging your entry and updating your access count. If the pre-check fails (e.g., reservation expired), no key is issued. If the post-check fails (e.g., gym membership lapsed), you still have your room key but can't enter the gym. In Cognito, pre-authentication triggers run before Cognito issues tokens, allowing you to block sign-in based on custom logic. Post-authentication triggers run after tokens are issued, enabling logging, analytics, or custom claims without affecting the authentication outcome. The hotel's central system logs every swipe and can trigger alerts—just like CloudWatch Logs capturing Lambda execution results.
What Are Cognito Lambda Triggers?
Amazon Cognito User Pools provide a fully managed identity and access management service for web and mobile applications. Lambda triggers are AWS Lambda functions that Cognito invokes at specific points during the authentication lifecycle. These triggers allow you to execute custom code to modify authentication behavior, enrich tokens, or perform side effects like logging. The two triggers covered here are:
- Pre-authentication trigger: Invoked after Cognito validates the user's credentials (password or one-time code) but before it issues tokens. This trigger can block sign-in by throwing an exception or returning a specific error message.
- Post-authentication trigger: Invoked after Cognito successfully authenticates the user and issues tokens. This trigger cannot block sign-in; it is used for logging, analytics, or adding custom claims to the ID token (via the claimsOverrideDetails response parameter).
Why They Exist
Standard Cognito authentication is binary: either the user's credentials are valid and tokens are issued, or they are not. But real-world applications often need additional checks: is the user's account suspended? Did they sign in from a suspicious IP? Should we record every login attempt? Pre- and post-authentication triggers fill this gap. The pre-authentication trigger acts as a gatekeeper: you can reject authentication even if the password is correct. The post-authentication trigger acts as an observer: you can log, update a database, or enrich tokens after successful login.
How They Work Internally
When a user signs in (e.g., via AdminInitiateAuth or InitiateAuth), Cognito performs these steps:
1. Credential validation: Cognito verifies the username/password or one-time password against its internal directory.
2. Pre-authentication trigger invocation: If a Lambda trigger is configured for the pre-authentication event, Cognito invokes the function asynchronously? No, it's synchronous. The Lambda function receives an event with user attributes and authentication details. The function can throw an exception to abort authentication, or return a response that Cognito uses to continue. The Lambda function must complete within a timeout (default 3 seconds, max 900 seconds for custom authorizers, but Cognito triggers have a 5-second timeout). If the Lambda fails (throws an error or times out), authentication fails.
3. Token generation: If the pre-authentication trigger succeeds (or is not configured), Cognito generates the ID token, access token, and refresh token.
4. Post-authentication trigger invocation: After tokens are generated, Cognito invokes the post-authentication trigger. This trigger cannot abort authentication. It receives the same event structure plus the tokens. The function can modify the ID token's claims by returning claimsOverrideDetails in the response. The Lambda timeout is again 5 seconds; if it fails, the authentication still succeeds but the error is logged.
Key Components, Values, Defaults, and Timers
Trigger source: PreAuthentication_Authentication for pre-authentication, PostAuthentication_Authentication for post-authentication.
Event structure: Both triggers receive a JSON event with fields: version, triggerSource, region, userPoolId, userName, callerContext, and request containing userAttributes (map of user attributes) and validationData (from the client). For post-authentication, request also includes newDeviceUsed (boolean). The response for pre-authentication is empty (just {}); for post-authentication, you can return claimsOverrideDetails to override ID token claims.
Timeout: Lambda function timeout must be ≤ 5 seconds. Cognito will timeout and fail authentication if the function exceeds this.
Error handling: If the pre-authentication Lambda throws an exception (or returns an error object), Cognito returns an NotAuthorizedException to the client. The error message from the Lambda is surfaced in the client response.
IAM permissions: The Lambda function's resource policy must allow Cognito to invoke it. The trust policy is automatically managed when you configure the trigger via the console or API.
Multiple triggers: You can have multiple triggers per user pool, but only one Lambda per trigger type. For example, you cannot have two pre-authentication Lambdas; you must combine logic into one function.
Configuration and Verification
To configure a trigger, you can use the AWS Management Console, AWS CLI, or AWS SDK. The CLI command to update a user pool with a pre-authentication trigger:
aws cognito-idp update-user-pool --user-pool-id us-east-1_example --lambda-config "PreAuthentication=arn:aws:lambda:us-east-1:123456789012:function:myPreAuthFunc"To verify the trigger is working, trigger a sign-in and check CloudWatch Logs for the Lambda function. You can also use the describe-user-pool CLI command:
aws cognito-idp describe-user-pool --user-pool-id us-east-1_example --query 'UserPool.LambdaConfig'This returns the Lambda ARNs for each trigger.
Interaction with Related Technologies
Amazon DynamoDB: Common pattern: store user status (e.g., suspended) in DynamoDB. Pre-authentication Lambda reads DynamoDB and throws if suspended. Post-authentication Lambda updates last login timestamp.
AWS CloudTrail: Cognito authentication events are logged in CloudTrail, but Lambda invocations are separate. You can enable detailed billing and monitoring.
Amazon Pinpoint: Post-authentication triggers can send analytics events to Pinpoint for user engagement tracking.
AWS WAF: Pre-authentication triggers can check IP reputation by calling external APIs, but Cognito also supports WAF integration for CAPTCHA and rate limiting.
Amazon Cognito Sync: Not directly related, but post-authentication triggers can sync user data to Cognito Sync datasets.
Common Pitfalls
Assuming post-authentication can block sign-in: It cannot. The authentication has already succeeded. Use pre-authentication for blocking.
Timeout misconfiguration: If your Lambda takes longer than 5 seconds, Cognito fails authentication. Ensure your function completes quickly, especially if calling external APIs.
Not handling errors gracefully: If pre-authentication Lambda throws an unhandled exception, the user gets a generic error. Always catch errors and return a meaningful error message.
Claim override limitations: The claimsOverrideDetails only allows adding or overriding claims in the ID token, not the access token. Also, you cannot remove standard claims (e.g., sub, iss).
Trigger source confusion: Pre-authentication trigger is invoked after password validation but before token generation. Post-authentication is after token generation. There is also a pre-sign-up trigger (for registration) and a post-confirmation trigger (for account confirmation). Exam questions often mix these up.
User submits credentials
The client application calls `InitiateAuth` or `AdminInitiateAuth` with the user's username and password (or SRP parameters). Cognito receives the request and begins the authentication flow. The client sends the authentication parameters in the request body. Cognito validates the request format and checks if the user pool exists and is enabled.
Cognito validates credentials
Cognito checks the provided credentials against its user directory. For password-based authentication, it verifies the password hash. For SRP (Secure Remote Password), it performs the cryptographic exchange. If the credentials are invalid, Cognito returns an `NotAuthorizedException` immediately, and no Lambda trigger is invoked. If valid, Cognito proceeds to the next step.
Pre-authentication Lambda invoked
Cognito checks if a Lambda function is configured for the `PreAuthentication_Authentication` trigger. If so, it invokes the function synchronously with an event containing the user's attributes and `validationData` from the client. The Lambda must complete within 5 seconds. If the Lambda throws an exception or returns an error, Cognito aborts authentication and returns an error to the client. If the Lambda returns successfully (even an empty response), Cognito continues.
Cognito generates tokens
After the pre-authentication trigger succeeds, Cognito generates the ID token, access token, and refresh token. These are JSON Web Tokens (JWTs) signed by Cognito. The ID token contains user attributes and standard claims. The access token is used for API authorization. The tokens are returned to the client in the `AuthenticationResult`.
Post-authentication Lambda invoked
After tokens are generated, Cognito invokes the post-authentication Lambda (if configured). This trigger receives the same event as pre-authentication plus `request.newDeviceUsed`. The Lambda can modify the ID token by returning `claimsOverrideDetails` in the response. If the Lambda fails or times out, authentication still succeeds, but the error is logged. The client receives the tokens regardless.
Client receives tokens
The client receives the `AuthenticationResult` containing the ID token, access token, and refresh token. The client can now use these tokens to access AWS resources or application APIs. If the post-authentication Lambda overrode claims, the ID token will include those custom claims. The client is unaware of the Lambda executions.
Enterprise Scenario 1: Multi-Tenant SaaS Application
A SaaS company hosts a multi-tenant application where each tenant has its own user pool. They use a pre-authentication Lambda to check if the user's tenant subscription is active. The Lambda reads from a DynamoDB table that maps user IDs to subscription status. If the subscription is expired, the Lambda throws an error with a custom message like "Your subscription has expired. Please renew." This prevents users from accessing the application even if they have valid credentials. The post-authentication Lambda logs each sign-in to CloudWatch Logs with tenant ID and timestamp for auditing. At scale, the DynamoDB table is provisioned with auto-scaling to handle thousands of sign-ins per second. The Lambda function is optimized to complete in under 100ms to avoid timeout. Misconfiguration: If the Lambda cannot connect to DynamoDB (e.g., VPC misconfiguration), authentication fails for all users, causing an outage.
Enterprise Scenario 2: Financial Services with Risk Scoring
A bank uses Cognito for customer login. They implement a pre-authentication Lambda that calls an external risk scoring API (e.g., based on IP address, device fingerprint, and time of day). If the risk score exceeds a threshold, the Lambda throws an error, blocking the login. The bank also uses a post-authentication Lambda to update a customer activity table in DynamoDB with the login timestamp and risk score. This data feeds a dashboard for fraud analysis. The Lambda functions are deployed in a VPC with a NAT gateway to access the external API. Performance considerations: The external API call must complete within 3 seconds to stay within the 5-second Lambda timeout. The bank uses CloudWatch metrics to monitor Lambda duration and error rates. Common issue: If the external API is slow or down, users are unable to log in. They implement a fallback to allow login if the API times out, but with reduced functionality.
Enterprise Scenario 3: Healthcare Application with Custom Claims
A healthcare app uses Cognito for patient authentication. They need to include the patient's primary care physician ID in the ID token for downstream authorization. They use a post-authentication Lambda that queries a relational database (e.g., Amazon RDS) to fetch the physician ID and returns it as a custom claim via claimsOverrideDetails. This avoids a separate API call from the client. The Lambda is configured with a 3-second timeout. The database query is indexed on user_id to ensure fast lookups. Misconfiguration: If the Lambda returns an incorrect claim name, the client may not recognize the claim, causing authorization failures. They use a consistent naming convention like custom:physicianId.
What DVA-C02 Tests
Exam questions under Objective 2.2 (Security) focus on your ability to choose the correct Lambda trigger for a given scenario. Key distinctions:
- Pre-authentication: Use when you need to block sign-in based on custom logic (e.g., account suspended, IP blacklist, multi-factor required).
- Post-authentication: Use when you need to log sign-ins, update user activity, or add custom claims to the ID token (but cannot block sign-in).
- Trigger source names: You must know the exact trigger source strings: PreAuthentication_Authentication and PostAuthentication_Authentication. The exam may present similar-sounding names like PreSignUp_SignUp or PostConfirmation_ConfirmSignUp.
Common Wrong Answers and Why
Using post-authentication to block sign-in: Candidates assume any Lambda can block authentication. Wrong. Post-authentication fires after tokens are issued; you cannot block. Pre-authentication is the only trigger that can abort authentication.
Thinking you can modify access token claims: The claimsOverrideDetails only affects the ID token. Access token claims are immutable. Candidates often confuse ID token and access token.
Choosing pre-authentication for logging: While you can log in pre-authentication, the exam expects you to use post-authentication for logging because it doesn't affect the user experience. Pre-authentication should be reserved for blocking decisions.
Assuming triggers are asynchronous: All Cognito Lambda triggers are synchronous. The authentication flow waits for the Lambda to complete. Candidates may think they are asynchronous for performance, but they are not.
Specific Numbers and Terms
Lambda timeout: 5 seconds (maximum for Cognito triggers).
Trigger source: PreAuthentication_Authentication and PostAuthentication_Authentication.
Response parameter for custom claims: claimsOverrideDetails.
Error thrown by pre-authentication: Cognito returns NotAuthorizedException.
The request object contains userAttributes (map) and validationData.
Edge Cases and Exceptions
If the pre-authentication Lambda returns successfully but with an empty response, authentication proceeds. If it throws an error, authentication fails. The error message from the Lambda is passed to the client.
If the post-authentication Lambda fails, authentication still succeeds. The failure is logged in CloudWatch Logs, but the client is unaffected.
You cannot have two Lambdas for the same trigger type. You must combine logic into one function.
Custom claims override only works for the ID token; the access token cannot be modified.
How to Eliminate Wrong Answers
If the scenario says "block sign-in if..." → choose pre-authentication.
If the scenario says "log sign-in" or "add custom claims" → choose post-authentication.
If the scenario mentions modifying the access token → it's impossible; eliminate all options that claim to modify access token.
If the scenario says "asynchronous" → it's wrong; all triggers are synchronous.
Look for trigger source names carefully; don't confuse with pre-sign-up or post-confirmation.
Pre-authentication trigger can block sign-in; post-authentication cannot.
Post-authentication trigger can add custom claims to ID token via claimsOverrideDetails.
All Cognito Lambda triggers are synchronous with a 5-second timeout.
Only one Lambda per trigger type per user pool is allowed.
Trigger source names: PreAuthentication_Authentication and PostAuthentication_Authentication.
Custom claims override does not affect the access token.
Pre-authentication fires after password validation; if password is wrong, trigger is not invoked.
These come up on the exam all the time. Here's how to tell them apart.
Pre-authentication Trigger
Fires after credential validation, before token generation.
Can block sign-in by throwing an exception.
Use for conditional access checks (e.g., account suspended, IP blacklist).
Response is empty; cannot modify tokens.
If Lambda fails, authentication fails with NotAuthorizedException.
Post-authentication Trigger
Fires after token generation.
Cannot block sign-in; authentication already succeeded.
Use for logging, analytics, or adding custom claims to ID token.
Can return claimsOverrideDetails to modify ID token claims.
If Lambda fails, authentication still succeeds; error is logged.
Mistake
Post-authentication Lambda can block sign-in by throwing an exception.
Correct
Post-authentication Lambda fires after tokens are already issued. Throwing an exception logs an error but the authentication still succeeds. Only pre-authentication Lambda can block sign-in.
Mistake
You can override claims in both ID token and access token using claimsOverrideDetails.
Correct
claimsOverrideDetails only overrides claims in the ID token. The access token is immutable and cannot be modified by Lambda triggers.
Mistake
Cognito Lambda triggers are invoked asynchronously to improve performance.
Correct
All Cognito Lambda triggers are synchronous. The authentication flow waits for the Lambda to complete (up to 5 seconds) before proceeding.
Mistake
Pre-authentication trigger fires before password validation.
Correct
Pre-authentication trigger fires after Cognito validates the password but before token generation. If the password is invalid, the trigger is not called.
Mistake
You can configure multiple Lambdas for the same trigger type in a user pool.
Correct
Cognito allows only one Lambda function per trigger type. To execute multiple actions, you must combine logic into a single Lambda function.
Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.
No, the pre-authentication Lambda cannot modify tokens. It can only block or allow authentication. To add custom claims, you must use the post-authentication Lambda and return `claimsOverrideDetails` in the response. The pre-authentication response is ignored for token modifications.
If the post-authentication Lambda exceeds the 5-second timeout, Cognito logs the error but the authentication still succeeds. The client receives the tokens normally. The Lambda execution is terminated, and the error is recorded in CloudWatch Logs. For production, ensure your Lambda completes quickly.
No, MFA enforcement is a built-in Cognito feature configured via the user pool's MFA settings. Pre-authentication triggers cannot force MFA. However, you can use a pre-authentication trigger to check if the user has MFA enabled and reject if not, but that's not the intended use. Better to use Cognito's MFA configuration.
You can simulate the event using the AWS SAM CLI or by invoking the Lambda with a test event that mimics the Cognito event structure. For pre-authentication, use a sample event from the AWS documentation. For post-authentication, include the `newDeviceUsed` field. Test the Lambda response and error handling before configuring it in the user pool.
No, access tokens are immutable. Only the ID token can be modified via the `claimsOverrideDetails` parameter in the post-authentication trigger. The access token is used for API authorization and its claims cannot be changed by Lambda triggers.
Pre-authentication fires during sign-in, after credential validation. Pre-sign-up fires during user registration, before the user is created. Pre-authentication is for login blocking; pre-sign-up is for custom validation during sign-up (e.g., checking if email domain is allowed). They serve different purposes.
The post-authentication Lambda event does not include the tokens themselves. It includes user attributes and metadata. To access tokens, you would need to capture them from the client side or use a different mechanism. The trigger is meant for side effects like logging or claim override.
You've just covered Cognito Lambda Triggers: Pre/Post Authentication — now see how well it sticks with free DVA-C02 practice questions. Full explanations included, no account needed.
Done with this chapter?