Pre token generation Lambda trigger - Amazon Cognito

Pre token generation Lambda trigger

Because Amazon Cognito invokes this trigger before token generation, you can customize the claims in user pool tokens. With the Basic features of the version one or V1_0 pre token generation trigger event, you can customize the identity (ID) token. In user pools with advanced security features active, you can generate the version 2 or V2_0 trigger event with access token customization.

Amazon Cognito sends a V1_0 event as a request to your function with data that it would write to the ID token. A V2_0 event is a single request with the data that Amazon Cognito would write to both the identity and access tokens. To customize both tokens, you must update your function to use the most recent trigger version, and send data for both tokens in the same response.

This Lambda trigger can add, remove, and modify some claims in identity and access tokens before Amazon Cognito issues them to your app. To use this feature, associate a Lambda function from the Amazon Cognito user pools console or update your user pool LambdaConfig through the AWS Command Line Interface (AWS CLI).

Event versions

Your user pool can deliver different versions of a pre token generation trigger event to your Lambda function. A V1_0 trigger delivers the parameters for modification of ID tokens. A V2_0 trigger delivers parameters for the following.

  1. The functions of a V1_0 trigger.

  2. The ability to customize access tokens.

  3. The ability to pass complex datatypes to ID and access token claim values:

    • String

    • Number

    • Boolean

    • Array of strings, numbers, booleans, or a combination of any of these

    • JSON

Note

In the ID token, you can populate complex objects to the values of claims except for phone_number_verified, email_verified, updated_at, and address.

User pools deliver V1_0 events by default. To configure your user pool to send a V2_0 event, choose a Trigger event version of Basic features + access token customization when you configure your trigger in the Amazon Cognito console. You can also set the value of LambdaVersion in the LambdaConfig parameters in an UpdateUserPool or CreateUserPool API request. Additional costs apply to access token customization with V2_0 events. For more information, see Amazon Cognito Pricing.

Excluded claims and scopes

Amazon Cognito limits the claims and scopes that you can add, modify, or suppress in access and identity tokens. If your Lambda function attempts to set a value for any of these claims, Amazon Cognito issues a token with the original claim value, if one was present in the request.

Shared claims
  • acr

  • amr

  • at_hash

  • auth_time

  • azp

  • exp

  • iat

  • iss

  • jti

  • nbf

  • nonce

  • origin_jti

  • sub

  • token_use

ID token claims
  • identities

  • aud

  • cognito:username

Access token claims
  • username

  • client_id

  • scope

    Note

    You can change the scopes in an access token with scopesToAdd and scopesToSuppress response values, but you can't modify the scope claim directly. You can't add scopes that begin with aws.cognito, including the user pools reserved scope aws.cognito.signin.user.admin.

  • device_key

  • event_id

  • version

You can’t add or override claims with the following prefixes but you can suppress them, or prevent them from appearing in the token.

  • dev:

  • cognito:

You can add an aud claim to access tokens, but its value must match the app client ID of the current session. You can derive the client ID in the request event from event.callerContext.clientId.

Customizing the identity token

With the pre token generation Lambda trigger, you can customize the content of an identity (ID) token from your user pool. The ID token provides user attributes from a trusted identity source for sign-in to a web or mobile app. For more information about ID tokens, see Using the ID token.

The uses of the pre token generation Lambda trigger with an ID token include the following.

  • Make a change at runtime to the IAM role that your user requests from an identity pool.

  • Add user attributes from an external source.

  • Add or replace existing user attribute values.

  • Suppress disclosure of user attributes that, because of your user's authorized scopes and the read access to attributes that you granted to your app client, would otherwise be passed to your app.

Customizing the access token

With the pre token generation Lambda trigger, you can customize the content of an access token from your user pool. The access token authorizes users to retrieve information from access-protected resources like Amazon Cognito token-authorized API operations and third-party APIs. Although you can generate access tokens for machine-to-machine (M2M) authorization with Amazon Cognito with a client credentials grant, M2M requests don’t invoke the pre token generation trigger function and can't issue customized access tokens. For more information about access tokens, see Using the access token.

The uses of the pre token generation Lambda trigger with an access token include the following.

  • Add or suppress OAuth 2.0 scopes in the scope claim. For example, you can add scopes to an access token that resulted from Amazon Cognito user pools API authentication, which only assigns the scope aws.cognito.signin.user.admin.

  • Change a user's membership in user pool groups.

  • Add claims that aren't already present in an Amazon Cognito access token.

  • Suppress disclosure of claims that would otherwise be passed to your app.

To support access customization in your user pool, you must configure the user pool to generate an updated version of the trigger request. Update your user pool as shown in the following procedure.

AWS Management Console
To support access token customization in a pre token generation Lambda trigger
  1. Go to the Amazon Cognito console, and then choose User Pools.

  2. Choose an existing user pool from the list, or create a user pool.

  3. If you haven't already, activate advanced security features from the App integration tab.

  4. Choose the User pool properties tab and locate Lambda triggers.

  5. Add or edit a Pre token generation trigger.

  6. Choose a Lambda function under Assign Lambda function.

  7. Choose a Trigger event version of Basic features + access token customization. This setting updates the request parameters that Amazon Cognito sends to your function to include fields for access token customization.

User pools API

To support access token customization in a pre token generation Lambda trigger

Generate a CreateUserPool or UpdateUserPool API request. You must specify a value for all parameters that you don't want set to a default value. For more information, see Updating user pool configuration.

Include the following content in the LambdaVersion parameter of your request. A LambdaVersion value of V2_0 causes your user pool to add parameters for access token customization. To invoke a specific function version, use a Lambda function ARN with a function version as the value of LambdaArn.

"PreTokenGenerationConfig": { "LambdaArn": "arn:aws:lambda:us-west-2:123456789012:function:MyFunction", "LambdaVersion": "V2_0" },

Pre token generation Lambda trigger sources

triggerSource value Event
TokenGeneration_HostedAuth Called during authentication from the Amazon Cognito hosted UI sign-in page.
TokenGeneration_Authentication Called after user authentication flows have completed.
TokenGeneration_NewPasswordChallenge Called after the user is created by an admin. This flow is invoked when the user has to change a temporary password.
TokenGeneration_AuthenticateDevice Called at the end of the authentication of a user device.
TokenGeneration_RefreshTokens Called when a user tries to refresh the identity and access tokens.

Pre token generation Lambda trigger parameters

The request that Amazon Cognito passes to this Lambda function is a combination of the parameters below and the common parameters that Amazon Cognito adds to all requests. When you add a pre token generation Lambda trigger to your user pool, you can choose a trigger version. This version determines whether Amazon Cognito passes a request to your Lambda function with additional parameters for access-token customization.

Version 1

The version 1 token can set group membership, IAM roles, and new claims in ID tokens.

{ "request": { "userAttributes": {"string": "string"}, "groupConfiguration": { "groupsToOverride": [ "string", "string" ], "iamRolesToOverride": [ "string", "string" ], "preferredRole": "string" }, "clientMetadata": {"string": "string"} }, "response": { "claimsOverrideDetails": { "claimsToAddOrOverride": {"string": "string"}, "claimsToSuppress": [ "string", "string" ], "groupOverrideDetails": { "groupsToOverride": [ "string", "string" ], "iamRolesToOverride": [ "string", "string" ], "preferredRole": "string" } } } }
Version 2

The version 2 request event adds fields that customize the access token. It also adds support for complex claimsToOverride data types in the response object. Your Lambda function can return the following types of data in the value of claimsToOverride:

  • String

  • Number

  • Boolean

  • Array of strings, numbers, booleans, or a combination of any of these

  • JSON

{ "request": { "userAttributes": { "string": "string" }, "scopes": ["string", "string"], "groupConfiguration": { "groupsToOverride": ["string", "string"], "iamRolesToOverride": ["string", "string"], "preferredRole": "string" }, "clientMetadata": { "string": "string" } }, "response": { "claimsAndScopeOverrideDetails": { "idTokenGeneration": { "claimsToAddOrOverride": { "string": [accepted datatype] }, "claimsToSuppress": ["string", "string"] }, "accessTokenGeneration": { "claimsToAddOrOverride": { "string": [accepted datatype] }, "claimsToSuppress": ["string", "string"], "scopesToAdd": ["string", "string"], "scopesToSuppress": ["string", "string"] }, "groupOverrideDetails": { "groupsToOverride": ["string", "string"], "iamRolesToOverride": ["string", "string"], "preferredRole": "string" } } } }

Pre token generation request parameters

Name Description Minimum trigger event version
userAttributes

The attributes of your user's profile in your user pool.

1
groupConfiguration

The input object that contains the current group configuration. The object includes groupsToOverride, iamRolesToOverride, and preferredRole.

1
groupsToOverride

The user pool groups that your user is a member of.

1
iamRolesToOverride

You can associate a user pool group with an AWS Identity and Access Management (IAM) role. This element is a list of all IAM roles from the groups that your user is a member of.

1
preferredRole

You can set a precedence for user pool groups. This element contains the name of the IAM role from the group with the highest precendence in the groupsToOverride element.

1
clientMetadata

One or more key-value pairs that you can specify and provide as custom input to the Lambda function for the pre token generation trigger.

To pass this data to your Lambda function, use the ClientMetadata parameter in the AdminRespondToAuthChallenge and RespondToAuthChallenge API operations. Amazon Cognito doesn't include data from the ClientMetadata parameter in AdminInitiateAuth and InitiateAuth API operations in the request that it passes to the pre token generation function.

1
scopes

Your user's OAuth 2.0 scopes. The scopes that are present in an access token are the user pool standard and custom scopes that your user requested, and that you authorized your app client to issue.

2

Pre token generation response parameters

Name Description Minimum trigger event version
claimsOverrideDetails A container for all elements in a V1_0 trigger event. 1
claimsAndScopeOverrideDetails

A container for all elements in a V2_0 trigger event.

2
idTokenGeneration

The claims that you want to override, add, or suppress in your user’s ID token. This parent to ID token customization values appears only in version 2 events, but the children elements appear in version 1 events.

2
accessTokenGeneration

The claims and scopes that you want to override, add, or suppress in your user’s access token. This parent to access token customization values appears only in version 2 events.

2
claimsToAddOrOverride

A map of one or more claims and their values that you want to add or modify. For group-related claims, use groupOverrideDetails instead.

In version 2 events, this element appears under both accessTokenGeneration and idTokenGeneration.

1*
claimsToSuppress

A list of claims that you want Amazon Cognito to suppress. If your function both suppresses and replaces a claim value, then Amazon Cognito suppresses the claim.

In version 2 events, this element appears under both accessTokenGeneration and idTokenGeneration.

1
groupOverrideDetails

The output object that contains the current group configuration. The object includes groupsToOverride, iamRolesToOverride, and preferredRole.

Your function replaces the groupOverrideDetails object with the object that you provide. If you provide an empty or null object in the response, then Amazon Cognito suppresses the groups. To keep the existing group configuration the same, copy the value of the groupConfiguration object of the request to the groupOverrideDetails object in the response. Then pass it back to the service.

Amazon Cognito ID and access tokens both contain the cognito:groups claim. Your groupOverrideDetails object replaces the cognito:groups claim in access tokens and ID tokens.

1
scopesToAdd

A list of OAuth 2.0 scopes that you want to add to the scope claim in your user's access token. You can't add scope values that contain one or more blank-space characters.

2
scopesToSuppress

A list of OAuth 2.0 scopes that you want to remove from the scope claim in your user's access token.

2

* Response objects to version 1 events can return strings. Response objects to version 2 events can return complex objects.

Pre token trigger event version two example: Add and suppress claims, scopes, and groups

This example makes the following modifications to a user's tokens.

  1. Sets their family_name as Doe in the ID token.

  2. Prevents email and phone_number claims from appearing in the ID token.

  3. Sets their ID token cognito:roles claim to "arn:aws:iam::123456789012:role\/sns_callerA","arn:aws:iam::123456789012:role\/sns_callerC","arn:aws:iam::123456789012:role\/sns_callerB".

  4. Sets their ID token cognito:preferred_role claim to arn:aws:iam::123456789012:role/sns_caller.

  5. Adds the scopes openid, email, and solar-system-data/asteroids.add to the access token.

  6. Suppresses the scope phone_number and aws.cognito.signin.user.admin from the access token. Removal of phone_number prevents retrieval of the user's phone number from userInfo. Removal of aws.cognito.signin.user.admin prevents API requests by the user to read and modify their own profile with the Amazon Cognito user pools API.

    Note

    The removal of phone_number from scopes only prevents retrieval of a user's phone number if the remaining scopes in the access token include openid and at least one more standard scope. For more information, see About scopes.

  7. Sets their ID and access token cognito:groups claim to "new-group-A","new-group-B","new-group-C".

JavaScript
export const handler = function(event, context) { event.response = { "claimsAndScopeOverrideDetails": { "idTokenGeneration": { "claimsToAddOrOverride": { "family_name": "Doe" }, "claimsToSuppress": [ "email", "phone_number" ] }, "accessTokenGeneration": { "scopesToAdd": [ "openid", "email", "solar-system-data/asteroids.add" ], "scopesToSuppress": [ "phone_number", "aws.cognito.signin.user.admin" ] }, "groupOverrideDetails": { "groupsToOverride": [ "new-group-A", "new-group-B", "new-group-C" ], "iamRolesToOverride": [ "arn:aws:iam::123456789012:role/new_roleA", "arn:aws:iam::123456789012:role/new_roleB", "arn:aws:iam::123456789012:role/new_roleC" ], "preferredRole": "arn:aws:iam::123456789012:role/new_role", } } }; // Return to Amazon Cognito context.done(null, event); };

Amazon Cognito passes event information to your Lambda function. The function then returns the same event object to Amazon Cognito, with any changes in the response. In the Lambda console, you can set up a test event with data that is relevant to your Lambda trigger. The following is a test event for this code sample:

JSON
{ "version": "2", "triggerSource": "TokenGeneration_Authentication", "region": "us-east-1", "userPoolId": "us-east-1_EXAMPLE", "userName": "JaneDoe", "callerContext": { "awsSdkVersion": "aws-sdk-unknown-unknown", "clientId": "1example23456789" }, "request": { "userAttributes": { "sub": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111", "cognito:user_status": "CONFIRMED", "email_verified": "true", "phone_number_verified": "true", "phone_number": "+12065551212", "family_name": "Zoe", "email": "Jane.Doe@example.com" }, "groupConfiguration": { "groupsToOverride": ["group-1", "group-2", "group-3"], "iamRolesToOverride": ["arn:aws:iam::123456789012:role/sns_caller1", "arn:aws:iam::123456789012:role/sns_caller2", "arn:aws:iam::123456789012:role/sns_caller3"], "preferredRole": ["arn:aws:iam::123456789012:role/sns_caller"] }, "scopes": [ "aws.cognito.signin.user.admin", "openid", "email", "phone" ] }, "response": { "claimsAndScopeOverrideDetails": [] } }

Pre token generation event version two example: Add claims with complex objects

This example makes the following modifications to a user's tokens.

  1. Adds claims of number, string, boolean, and JSON types to the ID token. This is the only change that version two trigger events makes available to the ID token.

  2. Adds claims of number, string, boolean, and JSON types to the access token.

  3. Adds three scopes to the access token.

  4. Suppresses the email and sub claims in the ID and access tokens.

  5. Suppresses the aws.cognito.signin.user.admin scope in the access token.

JavaScript
export const handler = function(event, context) { var scopes = ["MyAPI.read", "MyAPI.write", "MyAPI.admin"] var claims = {} claims["aud"]= event.callerContext.clientId; claims["booleanTest"] = false; claims["longTest"] = 9223372036854775807; claims["exponentTest"] = 1.7976931348623157E308; claims["ArrayTest"] = ["test", 9223372036854775807, 1.7976931348623157E308, true]; claims["longStringTest"] = "\{\ \"first_json_block\": \{\ \"key_A\": \"value_A\",\ \"key_B\": \"value_B\"\ \},\ \"second_json_block\": \{\ \"key_C\": \{\ \"subkey_D\": [\ \"value_D\",\ \"value_E\"\ ],\ \"subkey_F\": \"value_F\"\ \},\ \"key_G\": \"value_G\"\ \}\ \}"; claims["jsonTest"] = { "first_json_block": { "key_A": "value_A", "key_B": "value_B" }, "second_json_block": { "key_C": { "subkey_D": [ "value_D", "value_E" ], "subkey_F": "value_F" }, "key_G": "value_G" } }; event.response = { "claimsAndScopeOverrideDetails": { "idTokenGeneration": { "claimsToAddOrOverride": claims, "claimsToSuppress": ["email","sub"] }, "accessTokenGeneration": { "claimsToAddOrOverride": claims, "claimsToSuppress": ["email","sub"], "scopesToAdd": scopes, "scopesToSuppress": ["aws.cognito.signin.user.admin"] } } }; console.info("EVENT response\n" + JSON.stringify(event, (_, v) => typeof v === 'bigint' ? v.toString() : v, 2)) console.info("EVENT response size\n" + JSON.stringify(event, (_, v) => typeof v === 'bigint' ? v.toString() : v).length) // Return to Amazon Cognito context.done(null, event); };

Amazon Cognito passes event information to your Lambda function. The function then returns the same event object to Amazon Cognito, with any changes in the response. In the Lambda console, you can set up a test event with data that is relevant to your Lambda trigger. The following is a test event for this code sample:

JSON
{ "version": "2", "triggerSource": "TokenGeneration_HostedAuth", "region": "us-west-2", "userPoolId": "us-west-2_EXAMPLE", "userName": "JaneDoe", "callerContext": { "awsSdkVersion": "aws-sdk-unknown-unknown", "clientId": "1example23456789" }, "request": { "userAttributes": { "sub": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111", "cognito:user_status": "CONFIRMED" "email_verified": "true", "phone_number_verified": "true", "phone_number": "+12065551212", "email": "Jane.Doe@example.com" }, "groupConfiguration": { "groupsToOverride": ["group-1", "group-2", "group-3"], "iamRolesToOverride": ["arn:aws:iam::123456789012:role/sns_caller1"], "preferredRole": ["arn:aws:iam::123456789012:role/sns_caller1"] }, "scopes": [ "aws.cognito.signin.user.admin", "phone", "openid", "profile", "email" ] }, "response": { "claimsAndScopeOverrideDetails": [] } }

Pre token generation event version one example: Add a new claim and suppress an existing claim

This example uses a version 1 trigger event with a pre token generation Lambda function to add a new claim and suppresses an existing claim.

Node.js
const handler = async (event) => { event.response = { claimsOverrideDetails: { claimsToAddOrOverride: { my_first_attribute: "first_value", my_second_attribute: "second_value", }, claimsToSuppress: ["email"], }, }; return event; }; export { handler };

Amazon Cognito passes event information to your Lambda function. The function then returns the same event object to Amazon Cognito, with any changes in the response. In the Lambda console, you can set up a test event with data that is relevant to your Lambda trigger. The following is a test event for this code sample: Because the code example doesn't process any request parameters, you can use a test event with an empty request. For more information about common request parameters, see User pool Lambda trigger event.

JSON
{ "request": {}, "response": {} }

Pre token generation event version one example: Modify the user's group membership

This example uses a version 1 trigger event with a pre token generation Lambda function to modify the user's group membership.

Node.js
const handler = async (event) => { event.response = { claimsOverrideDetails: { groupOverrideDetails: { groupsToOverride: ["group-A", "group-B", "group-C"], iamRolesToOverride: [ "arn:aws:iam::XXXXXXXXXXXX:role/sns_callerA", "arn:aws:iam::XXXXXXXXX:role/sns_callerB", "arn:aws:iam::XXXXXXXXXX:role/sns_callerC", ], preferredRole: "arn:aws:iam::XXXXXXXXXXX:role/sns_caller", }, }, }; return event; }; export { handler };

Amazon Cognito passes event information to your Lambda function. The function then returns the same event object to Amazon Cognito, with any changes in the response. In the Lambda console, you can set up a test event with data that is relevant to your Lambda trigger. The following is a test event for this code sample:

JSON
{ "request": {}, "response": {} }