自定义 Amazon Cognito 用户池中的访问令牌
关键要点
在本文中,我们将介绍如何在 Amazon Cognito 中实现自定义访问令牌的功能。通过访问令牌自定义功能,您可以为用户提供更个性化的体验,并根据特定的应用程序需求进行精细权限决策。
使用 Amazon Cognito,您可以将客户身份和访问管理CIAM集成到您的Web和移动应用程序中,迅速为应用程序添加用户身份验证和访问控制功能。
在本文中,我将向您介绍 Amazon Cognito 用户池中新增的访问令牌自定义功能,并演示如何使用它。访问令牌自定义是 Amazon Cognito 高级安全功能(ASF)的一部分。注意,使用 ASF 可能会产生额外费用,详细信息可在 Amazon Cognito 定价 页面查看。
什么是访问令牌自定义?
当用户登录您的应用程序时,Amazon Cognito 会验证他们的登录信息,如果用户成功通过身份验证,则返回 ID 令牌、访问令牌和刷新令牌。访问令牌采用遵循 RFC7519 标准的 JSON Web Token (JWT) 格式,包含识别被认证主体的声明,以及如身份验证时间和令牌过期时间等会话属性。更重要的是,访问令牌还包含以用户组成员资格和 OAuth 范围的形式存在的授权属性。您的应用程序或 API 资源服务器可以评估令牌声明,以帮助授权用户的特定操作。
通过访问令牌自定义,您可以将特定于应用程序的声明添加到标准访问令牌中,并进行细致的授权决策,以提供差异化的终端用户体验。您可以细化原始范围声明,以进一步限制对资源的访问,并强制执行最小权限访问。您还可以从其他来源如存储在 Amazon DynamoDB 表中的用户订阅信息丰富访问令牌。这使得应用程序可以使用来自其他源的丰富声明来确定用户可以访问的内容和级别,从而减少在应用程序代码中查找属性的需求,从而降低应用程序复杂性,提高性能,并简化与下游应用程序的集成体验。
如何使用访问令牌自定义功能?
Amazon Cognito 与 AWS Lambda 函数协作,以修改您的用户池的身份验证行为和最终用户体验。在这一节中,您将学习如何配置 预令牌生成 Lambda 触发器 函数,并在 Amazon Cognito 身份验证过程中调用它。我还将向您展示一个示例函数,帮助您编写自己的 Lambda 函数。
Lambda 触发器流程
在用户身份验证期间,您可以选择让 Amazon Cognito 调用 预令牌生成触发器,以丰富和自定义您的令牌。
图 1 展示了预令牌生成触发器的工作流程,该流程包含以下步骤:
最终用户登录到您的应用程序,并通过 Amazon Cognito 用户池进行身份验证。用户完成身份验证后,Amazon Cognito 调用预令牌生成 Lambda 触发器,并在预令牌生成触发事件中将事件数据如 userAttributes 和 scopes发送到您的 Lambda 函数。您的 Lambda 函数代码处理令牌丰富逻辑,并返回一个响应事件,指示想要添加或抑制的声明。Amazon Cognito 将定制的 JWT 发送到您的应用程序。预令牌生成触发器流程支持 OAuth 20 授权 类型,例如授权代码授权流和隐式授权流,同时也支持通过 AWS SDK 进行用户身份验证。
启用访问令牌自定义
您的 Amazon Cognito 用户池为 Lambda 函数提供了两个不同版本的 预令牌生成触发器 事件。触发器事件版本 1 包含 userAttributes、groupConfiguration 和 clientMetadata,您可以使用这些信息自定义 ID 令牌声明。触发器事件版本 2 在事件请求中增加了范围,您可以使用其自定义访问令牌中的范围。
在本节中,我将向您展示如何更新用户池以触发事件版本 2,并启用访问令牌自定义。
启用访问令牌自定义的步骤
打开 Cognito 用户池控制台,然后选择 用户池。选择要进行令牌自定义的目标用户池。在 用户池属性 标签下,在 Lambda 触发器 部分,选择 添加 Lambda 触发器。在 Lambda 触发器 部分进行以下操作:在 触发器类型 中,选择 身份验证。在 身份验证 中,选择 预令牌生成触发器。在 触发器事件版本 中,选择 基本功能 访问令牌自定义 推荐。如果此选项不可用,请确保您已 启用高级安全功能。你必须启用高级安全功能才能访问此选项。选择您的 Lambda 函数,并将其指定为预令牌生成触发器,然后选择 添加 Lambda 触发器。示例预令牌生成触发器
现在您已经启用了访问令牌自定义,我将带您通过预令牌生成 Lambda 触发器的代码示例,以及版本 2 触发事件。此代码示例检查触发事件请求,并在 Amazon Cognito 的响应中添加一个新的自定义声明和一个自定义 OAuth 范围,以定制访问令牌以适应不同的授权方案。
以下是一个版本 2 触发事件的示例。事件请求包含来自 Amazon Cognito 用户池的用户属性、原始范围声明和原始组配置。它包含两个自定义属性membership 和 location在用户注册过程中收集,并存储在 Cognito 用户池中。
json{ version 2 triggerSource TokenGenerationHostedAuth region useast1 userPoolId useast101EXAMPLE userName mytestuser callerContext { awsSdkVersion awssdkunknownunknown clientId 1example23456789 } request { userAttributes { sub a1b2c3d4567890abcdefEXAMPLE11111 cognitouserstatus CONFIRMED email mytestuser@examplecom emailverified true custommembership Premium customlocation USA } groupConfiguration { groupsToOverride [] iamRolesToOverride [] preferredRole null } scopes [ openid profile email ] } response { claimsAndScopeOverrideDetails null }}

在以下代码示例中,我将用户的 location 属性和 membership 属性转换为自定义声明和自定义范围。通过 claimsToAddOrOverride 字段,我创建了一个新的自定义声明,命名为 demomembershipLevel,并从事件请求中获取 membership 的值“Premium”。我还通过 scopesToAdd 声明构建了一个新的范围,值为 membershipUSAPremium,并在事件响应中添加新的声明和范围。
javascriptexport const handler = function(event context) { // 从事件请求中获取用户属性 const userAttributes = eventrequestuserAttributes // 将范围添加到事件响应中 eventresponse = { claimsAndScopeOverrideDetails { idTokenGeneration {} accessTokenGeneration { claimsToAddOrOverride { demomembershipLevel userAttributes[custommembership] } scopesToAdd [membership userAttributes[customlocation] userAttributes[custommembership]] } } } // 返回到 Amazon Cognito contextdone(null event)}
通过以上代码,Lambda 触发器将以下响应发送回 Amazon Cognito,以指示访问令牌所需的自定义内容。
jsonresponse { claimsAndScopeOverrideDetails { idTokenGeneration {} accessTokenGeneration { claimsToAddOrOverride { demomembershipLevel Premium } scopesToAdd [ membershipUSAPremium ] } }}
然后,Amazon Cognito 在运行时发出具有这些自定义内容的令牌:
json{ sub a1b2c3d4567890abcdefEXAMPLE11111 iss https//cognitoidpuseast1amazonawscom/useast101EXAMPLE version 2 clientid 1example23456789 eventid 01faa385562d47308c3b458e5c8f537b tokenuse access demomembershipLevel Premium scope openid profile email membershipUSAPremium authtime 1702270800 exp 1702271100 iat 1702270800 jti d903dcdf8c7345e3bf4451bf7c395e06 username mytestuser}
您的应用程序可以使用新生成的自定义范围和声明来授权用户,提供个性化的体验。
注意事项和最佳实践
以下是四个一般性注意事项和最佳实践,您可以遵循:
某些声明和范围不可自定义。例如,您无法自定义 authtime、iss 和 sub 等声明,或 awscognitosigninuseradmin 等范围。有关于哪些声明和范围不可自定义的完整列表,您可以参考 排除的声明和范围。
基于授权反向工作。在自定义访问令牌时,您应该从现有的授权架构开始,然后决定是否自定义范围、声明,或两者都自定义。标准的基于 OAuth 的授权场景例如 Amazon API Gateway 授权器通常使用自定义范围来提供访问权限。但是,如果您有复杂或细微的授权要求,则应考虑同时使用范围和自定义声明,以将额外的上下文数据传递到应用程序或基于策略的访问控制服务中,如 Amazon Verified Permissions。
在令牌自定义中建立治理。应有一致的公司工程政策,以提供范围和声明的命名指导标准。一个语法标准促进全局唯一变量,避免不同应用程序团队之间的名称冲突。例如,任何公司的应用程序 X 可以选择将其范围命名为 acappxclaimname,其中 ac 代表公司作为全局标识符,appxclaimname 代表应用程序 X 的自定义声明。
注意限制。因为令牌通过各种网络和系统传递,您需要意识到系统中潜在的令牌大小限制。您应尽可能缩短范围和声明名称,同时仍保持描述性。
结论
在本文中,您学习了如何将预令牌生成 Lambda 触发器与您的 Amazon Cognito 用户池集成,以自定义访问令牌。您可以利用访问令牌自定义功能,基于声明和 OAuth 范围为最终用户提供差异化的服务。有关更多信息,请参见 Amazon Cognito 开发者指南中的 预令牌生成 Lambda 触发器。
如果您对本文有任何反馈,请在下面的 评论 部分留言。如果您有任何关于本文的问题,请 联系 AWS 支持。
想要获取更多 AWS 安全新闻?请关注我们在 Twitter 上的动态。
飞鱼vnp官网Edward Sun
Edward 是一名专注于身份和访问管理的安全专家解决方案架构师。他喜欢在客户的云转型过程中提供建筑设计、安全最佳实践、迁移和成本优化方面的帮助。在工作之外,Edward 喜欢远足、打高尔夫,并为他的母校乔治亚大学加油。
标签 Amazon Cognito 安全博客