令牌生成前 Lambda 触发器 - Amazon Cognito

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

令牌生成前 Lambda 触发器

由于 Amazon Cognito 会在令牌生成之前调用此触发器,您可以自定义用户池令牌中的声明。使用版本 1 或 V1_0 令牌生成前触发器事件的基本功能,可以自定义身份(ID)令牌。在启用了高级安全功能的用户池中,您可以通过自定义访问令牌来生成版本 2 或 V2_0 触发器事件。

Amazon Cognito 将向您的函数发送 V1_0 请求,其中包含将写入 ID 令牌的数据。V2_0 事件是包含将由 Amazon Cognito 写入身份和访问令牌的数据的单个请求。要自定义这两个令牌,您必须更新函数以使用最新的触发器版本,并在同一个响应中发送两个令牌的数据。

在 Amazon Cognito 向您的应用程序发布身份和访问令牌之前,此 Lambda 触发器可以添加、删除和修改这些令牌中的某些声明。要使用此功能,可以从 Amazon Cognito 用户池控制台关联 Lambda 函数或通过 AWS Command Line Interface (AWS CLI)更新用户池 LambdaConfig

事件版本

您的用户池可以向您的 Lambda 函数提供不同版本的令牌生成前触发事件。V1_0触发器提供用于修改 ID 令牌的参数。V2_0触发器为以下内容提供参数。

  1. V1_0触发器的功能。

  2. 能够自定义访问令牌。

  3. 能够将复杂的数据类型传递给 ID 并访问令牌声明值:

    • String

    • 数字

    • 布尔值

    • 字符串、数字、布尔值的数组或其中任何一个的组合

    • JSON

注意

在 ID 令牌中,您可以将复杂对象填充到除了phone_number_verifiedemail_verifiedupdated_at、和address之外的声明值。

默认情况下,用户池传送V1_0事件。要将您的用户池配置为发送V2_0事件,请在 Amazon Cognito 控制台中配置触发器时,选择基本功能+访问令牌自定义的触发事件版本。您也可以在UpdateUserPool CreateUserPool API请求的LambdaVersionLambdaConfig参数中设置的值。使用V2_0事件自定义访问令牌需要支付额外费用。有关更多信息,请参阅 Amazon Cognito 定价

排除的声明和范围

Amazon Cognito 限制了您可以在访问令牌和身份令牌中添加、修改或隐藏的声明和范围。如果您的 Lambda 函数尝试为这些声明中的任何一个设置值,Amazon Cognito 会颁发一个具有原始声明值的令牌(如果请求中存在原始声明值)。

共享声明
  • acr

  • amr

  • at_hash

  • auth_time

  • azp

  • exp

  • iat

  • iss

  • jti

  • nbf

  • nonce

  • origin_jti

  • sub

  • token_use

ID 令牌声明
  • identities

  • aud

  • cognito:username

访问令牌声明
  • username

  • client_id

  • scope

    注意

    您可以使用 scopesToAddscopesToSuppress 响应值更改访问令牌中的范围,但不能直接修改 scope 声明。您不能添加以 aws.cognito 开头的范围,包括用户池的保留范围 aws.cognito.signin.user.admin

  • device_key

  • event_id

  • version

您不能添加或覆盖带有以下前缀的声明,但可以将其隐藏,或者阻止它们出现在令牌中。

  • dev:

  • cognito:

默认情况下cognito:preferred_role,IAM角色声明cognito:roles并链接到用户池组。要抑制这些声明,请在claimsToSuppress对象cognito:groups中隐藏。

您可以向访问令牌添加 aud 声明,但其值必须与当前会话的应用程序客户端 ID 相匹配。您可以从 event.callerContext.clientId 获取请求事件中的客户端 ID。

自定义身份令牌

使用令牌生成前 Lambda 触发器,您可以自定义来自用户池的身份(ID)令牌的内容。ID 令牌提供来自可信身份源的用户属性,用于登录 Web 或移动应用程序。有关 ID 令牌的更多信息,请参阅了解身份 (ID) 令牌

将令牌生成前 Lambda 触发器与 ID 令牌结合使用,可实现以下目的。

  • 在运行时更改您的用户从身份池中请求的IAM角色。

  • 从外部来源添加用户属性。

  • 添加或替换现有用户属性值。

  • 隐藏用户属性,否则这些属性由于用户获得的授权范围以及您授予应用程序客户端的属性读取权限,会传递给您的应用程序。

自定义访问令牌

使用令牌生成前 Lambda 触发器,您可以自定义来自用户池的访问令牌的内容。访问令牌授权用户从受访问保护的资源(例如 Amazon Cognito 令牌授权的操作和第三方)中检索信息。API APIs尽管您可以使用客户端凭证授予的 Amazon Cognito 生成访问令牌 machine-to-machine(M2M)授权,但是 M2M 请求不会调用令牌生成前的触发函数,也无法发布自定义访问令牌。有关访问令牌的更多信息,请参阅了解访问令牌

将令牌生成前 Lambda 触发器与访问令牌结合使用,可实现以下目的。

  • scope声明中添加或隐藏 OAuth 2.0 范围。例如,您可以将范围添加到由 Amazon Cognito 用户池API身份验证生成的访问令牌中,该身份验证仅分配范围。aws.cognito.signin.user.admin

  • 更改用户在用户池组中的成员资格。

  • 添加尚不存在于 Amazon Cognito 访问令牌中的声明。

  • 隐藏原本会传递到应用程序的声明。

要在用户池中支持访问自定义,必须将用户池配置为生成触发器请求的更新版本。请按照如下所示的过程更新用户池。

AWS Management Console
在令牌生成前 Lambda 触发器中支持访问令牌自定义
  1. 转到 Amazon Cognito 控制台,然后选择用户池

  2. 从列表中选择一个现有用户池,或创建一个用户池

  3. 如果尚未激活高级安全功能,请从 “高级安全” 选项卡中激活高级安全功能。

  4. 选择用户池属性选项卡,并找到 Lambda 触发器

  5. 添加或编辑令牌生成前触发器

  6. 分配 Lambda 函数下选择一个 Lambda 函数。

  7. 选择基本功能 + 访问令牌自定义触发事件版本。此设置会更新 Amazon Cognito 发送给您的函数的请求参数,使该函数包含用于自定义访问令牌的字段。

User pools API

在令牌生成前 Lambda 触发器中支持访问令牌自定义

生成CreateUserPoolUpdateUserPoolAPI请求。必须为所有您不想设置为默认值的参数指定一个值。有关更多信息,请参阅 更新用户池和应用程序客户端配置

在请求的 LambdaVersion 参数中包含以下内容。LambdaVersion 的值为 V2_0 会使您的用户池添加用于自定义访问令牌的参数。要调用特定的函数版本,请使用以函数ARN版本为值的 Lambda 函数。LambdaArn

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

令牌生成前 Lambda 触发器源

triggerSource 价值 事件
TokenGeneration_HostedAuth 通过 Amazon Cognito 托管 UI 登录页进行身份验证时调用。
TokenGeneration_Authentication 用户身份验证流完成之后调用。
TokenGeneration_NewPasswordChallenge 管理员创建用户之后调用。当用户必须更改临时密码时调用此流。
TokenGeneration_AuthenticateDevice 用户设备身份验证结束时调用。
TokenGeneration_RefreshTokens 用户尝试刷新身份和令牌时调用。

令牌生成前 Lambda 触发器参数

Amazon Cognito 传递给此 Lambda 函数的请求是以下参数和 Amazon Cognito 添加到所有请求中的常用参数的组合。在向用户池添加令牌生成前 Lambda 触发器时,您可以选择触发器版本。此版本决定 Amazon Cognito 是否将请求以及用于自定义访问令牌的附加参数传递给您的 Lambda 函数。

Version 1

版本 1 令牌可以在 ID 令牌中设置群组成员资格、IAM角色和新声明。

{ "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

版本 2 请求事件添加了自定义访问令牌的字段。它还增加了对响应对象中复杂claimsToOverride数据类型的支持。您的 Lambda 函数可以返回以下类型的数据,其值为:claimsToOverride

  • String

  • 数字

  • 布尔值

  • 字符串、数字、布尔值的数组或其中任何一个的组合

  • 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" } } } }

令牌生成前请求参数

名称 描述 最低触发器事件版本
userAttributes

用户池中用户配置文件的属性。

1
groupConfiguration

包含当前组配置的输入对象。对象包括 groupsToOverrideiamRolesToOverridepreferredRole

1
groupsToOverride

您的用户所属的用户池组

1
iamRolesTo覆盖

您可以将用户池组与 AWS Identity and Access Management (IAM) 角色关联。此元素是您的用户所属群组中所有IAM角色的列表。

1
preferredRole

您可以为用户池组设置一个优先级。此元素包含该元素中优先级最高的组中IAM角色的groupsToOverride名称。

1
clientMetadata

一个或多个键值对,您可以指定它们并将它们作为自定义输入提供给 Lambda 函数以用于令牌生成前的触发器。

要将此数据传递给您的 Lambda 函数,请使用AdminRespondToAuthChallengeRespondToAuthChallengeAPI操作中的 ClientMetadata参数。Amazon Cognito 在传递给令牌生成前函数的请求中不包含来自ClientMetadata参数AdminInitiateAuthInitiateAuthAPI操作的数据。

1
范围

您的用户的 OAuth 2.0 范围。访问令牌中的范围是您的用户请求且您授权应用程序客户端发布的用户池标准范围和自定义范围。

2

令牌生成前响应参数

名称 描述 最低触发器事件版本
claimsOverrideDetails 用于存放 V1_0 触发器事件中所有元素的容器。 1
claimsAndScopeOverrideDetails

用于存放 V2_0 触发器事件中所有元素的容器。

2
idTokenGeneration

您要在用户的 ID 令牌中覆盖、添加或隐藏的声明。这是 ID 令牌自定义值的父元素,仅出现在版本 2 事件中,但子元素出现在版本 1 事件中。

2
accessTokenGeneration

您要在用户的访问令牌中覆盖、添加或隐藏的声明和范围。这是访问令牌自定义值的父元素,仅出现在版本 2 事件中。

2
claimsToAddOrOverride

您要添加或修改的一个或多个声明及其值的映射。对于与组相关的声明,请改用 groupOverrideDetails

在版本 2 事件中,此元素同时出现在 accessTokenGenerationidTokenGeneration 下。

1*
claimsToSuppress

您希望 Amazon Cognito 隐藏的声明列表。如果您的函数同时隐藏并替换了声明值,则 Amazon Cognito 会隐藏声明。

在版本 2 事件中,此元素同时出现在 accessTokenGenerationidTokenGeneration 下。

1
groupOverrideDetails

包含当前组配置的输出对象。对象包括 groupsToOverrideiamRolesToOverridepreferredRole

您的函数将 groupOverrideDetails 对象替换为您提供的对象。如果您在响应中提供空的或空对象,则 Amazon Cognito 将隐藏组。要保持现有组配置不变,请将请求的 groupConfiguration 对象的值复制到响应中的 groupOverrideDetails 对象。然后将其传回服务。

Amazon Cognito ID 令牌和访问令牌都包含 cognito:groups 声明。在访问令牌和 ID 令牌中,您的 groupOverrideDetails 对象将替换 cognito:groups 声明。

1
scopesToAdd

您要添加到用户访问令牌中的scope声明中的 OAuth 2.0 范围列表。不能添加包含一个或多个空格字符的范围值。

2
scopesToSuppress

您要从用户访问令牌中的scope声明中移除的 OAuth 2.0 范围列表。

2

* 版本 1 事件的响应对象可以返回字符串。版本 2 事件的响应对象可以返回复杂的对象

令牌生成前触发器事件版本 2 示例:添加和隐藏声明、范围及组

此示例对用户的令牌进行了以下修改。

  1. 在 ID 令牌中将其 family_name 设置为 Doe

  2. 防止 emailphone_number 声明出现在 ID 令牌中。

  3. 将其 ID 令牌 cognito:roles 声明设置为 "arn:aws:iam::123456789012:role\/sns_callerA","arn:aws:iam::123456789012:role\/sns_callerC","arn:aws:iam::123456789012:role\/sns_callerB"

  4. 将其 ID 令牌 cognito:preferred_role 声明设置为 arn:aws:iam::123456789012:role/sns_caller

  5. 将作用域 openidemailsolar-system-data/asteroids.add 添加到访问令牌中。

  6. 隐藏访问令牌的作用域 phone_numberaws.cognito.signin.user.admin。删除 phone_number 可阻止从 userInfo 中检索用户的电话号码。删除aws.cognito.signin.user.admin会阻止用户API请求在 Amazon Cognito 用户池中读取和修改自己的个人资料。API

    注意

    只有当访问令牌中的剩余作用域包括 openid 和至少一个其他标准作用域时,从作用域中删除 phone_number 才会阻止检索用户的电话号码。有关更多信息,请参阅 关于范围

  7. 将其 ID 和访问令牌 cognito:groups 声明设置为 "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 将事件信息传递给 Lambda 函数。随后,该函数将相同事件对象随同响应中的任何更改返回给 Amazon Cognito。在 Lambda 控制台中,您可以设置一个测试事件,该事件包含与您的 Lambda 触发器相关的数据。以下是此代码示例的一个测试事件:

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": [] } }

代币生成前事件版本二示例:添加包含复杂对象的声明

此示例对用户的令牌进行了以下修改。

  1. 将数字、字符串、布尔值和JSON类型的声明添加到 ID 令牌中。这是第二版触发器事件对 ID 令牌提供的唯一更改。

  2. 将数字、字符串、布尔值和JSON类型的声明添加到访问令牌中。

  3. 向访问令牌添加三个范围。

  4. 隐藏 ID email 和访问令牌中的和sub声明。

  5. 抑制访问令牌中的aws.cognito.signin.user.admin作用域。

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 将事件信息传递给 Lambda 函数。随后,该函数将相同事件对象随同响应中的任何更改返回给 Amazon Cognito。在 Lambda 控制台中,您可以设置一个测试事件,该事件包含与您的 Lambda 触发器相关的数据。以下是此代码示例的一个测试事件:

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": [] } }

令牌生成前事件版本 1 示例:添加新声明并隐藏现有声明

此示例将版本 1 触发器事件与令牌生成前 Lambda 函数结合使用,以添加新声明并隐藏现有声明。

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 将事件信息传递给 Lambda 函数。随后,该函数将相同事件对象随同响应中的任何更改返回给 Amazon Cognito。在 Lambda 控制台中,您可以设置一个测试事件,该事件包含与您的 Lambda 触发器相关的数据。以下是此代码示例的测试事件:由于该代码示例不处理任何请求参数,因此您可以使用带有空请求的测试事件。有关常见请求参数的更多信息,请参阅用户池 Lambda 触发器事件

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

令牌生成前事件版本 1 示例:修改用户的组成员资格

此示例将版本 1 触发器事件与令牌生成前 Lambda 函数结合使用,以修改用户的组成员资格。

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 将事件信息传递给 Lambda 函数。随后,该函数将相同事件对象随同响应中的任何更改返回给 Amazon Cognito。在 Lambda 控制台中,您可以设置一个测试事件,该事件包含与您的 Lambda 触发器相关的数据。以下是此代码示例的一个测试事件:

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