令牌生成前 Lambda 触发器 - Amazon Cognito
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

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

令牌生成前 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 函数或通过 Amazon Command Line Interface(Amazon CLI)更新用户池 LambdaConfig

事件版本

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 modification of ID tokens and access tokens. User pools deliver V1_0 events by default. To configure your user pool to send a V2_0 event, choose a 触发器事件版本 of 基本功能 + 访问令牌自定义 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 定价.

排除的声明和范围

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:

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

自定义身份令牌

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

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

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

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

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

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

自定义访问令牌

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

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

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

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

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

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

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

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

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

  3. 如果尚未激活高级安全功能,请从应用程序集成选项卡中激活该功能。

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

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

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

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

User pools API

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

生成 CreateUserPoolUpdateUserPool API 请求。必须为所有您不想设置为默认值的参数指定一个值。有关更多信息,请参阅 更新用户群体配置

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

"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
{ "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
{ "request": { "userAttributes": { "string": "string" }, "scopes": ["string", "string"], "groupConfiguration": { "groupsToOverride": ["string", "string"], "iamRolesToOverride": ["string", "string"], "preferredRole": "string" }, "clientMetadata": { "string": "string" } }, "response": { "claimsAndScopeOverrideDetails": { "idTokenGeneration": { "claimsToAddOrOverride": { "string": "string" }, "claimsToSuppress": ["string", "string"] }, "accessTokenGeneration": { "claimsToAddOrOverride": { "string": "string" }, "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
iamRolesToOverride

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

1
preferredRole

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

1
clientMetadata

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

要将此数据传递给 Lambda 函数,请在 AdminRespondToAuthChallengeRespondToAuthChallenge API 操作中使用 ClientMetadata 参数。在 Amazon Cognito 传递到令牌生成前函数的请求中,不包括来自 AdminInitiateAuthInitiateAuth API 操作中的 ClientMetadata 参数的数据。

1
scopes

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

2

令牌生成前响应参数

名称 描述 最低触发器事件版本
claimsOverrideDetails A container for all elements in a V1_0 trigger event. 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

令牌生成前触发器事件版本 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 可阻止用户通过 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_number" ] }, "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": {} }