本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
验证JSON网络令牌
JSONWeb 令牌 (JWTs) 可以轻松解码、读取和修改。修改后的访问令牌会带来权限升级的风险。修改后的 ID 令牌会带来被冒充的风险。您的应用程序信任您的用户池作为令牌发行者,但是如果用户拦截了传输中的令牌怎么办? 您必须确保您的应用程序收到的令牌与 Amazon Cognito 发放的令牌相同。
Amazon Cognito 发行的令牌使用 OpenID Connect () 规范的某些完整性和保密性功能。OIDC用户池令牌使用过期时间、颁发者和数字签名等对象表示有效性。签名是 .
-分隔符的第三部分,也是最后一段JWT,是令牌验证的关键组成部分。恶意用户可以修改令牌,但是如果您的应用程序检索到公钥并比较签名,则该令牌将不匹配。任何通过OIDC身份验证进行处理JWTs的应用程序都必须在每次登录时执行此验证操作。
在本页上,我们提出了一些一般和具体的验证建议JWTs。应用程序开发跨越各种编程语言和平台。由于 Amazon Cognito 的实现与公共规范非常接近,OIDC因此您选择的开发者环境中的任何信誉良好的JWT库都可以满足您的验证要求。
以下步骤描述了验证用户池 JSON Web Token (JWT)。
先决条件
您的库或软件框架可能已经处理了本节中的任务。SDK AWS SDKs为应用程序中的 Amazon Cognito 用户池令牌处理和管理提供工具。 AWS Amplify 包括检索和刷新 Amazon Cognito 令牌的功能。
有关更多信息,请参阅以下页面。
-
Amplify Dev Center(Amplify 开发中心)中的 Advanced workflows
(高级工作流)
许多库都可用于解码和验证 JSON Web 令牌 (JWT)。如果您想手动处理令牌以进行服务器端API处理,或者您正在使用其他编程语言,这些库可以提供帮助。有关使用令牌的信息,请参阅 OpenID 基础库列表
使用验证令牌 aws-jwt-verify
在 Node.js 应用程序中, AWS 建议 aws-jwt-verify 库用于验证用户传递aws-jwt-verify
,您可以使用要为一个或多个用户群体验证的声明值填充 CognitoJwtVerifier
。它可以检查的一些值包括以下内容。
-
该访问令牌或 ID 令牌的格式不正确或已过期,但具有有效的签名。
-
这些访问令牌来自正确的用户群体和应用程序客户端
。 -
该访问令牌声明包含正确的 OAuth 2.0 范围
。 -
签名您的访问权限的密钥和 ID 令牌与您的用户池
kid
中的JWKSURI签名密钥相匹配。 JWKSURI包含有关签署用户令牌的私钥的公开信息。你可以在以下网址找到JWKSURI适合你的用户池的
https://cognito-idp.
。<Region>
.amazonaws.com/<userPoolId>
/.well-known/jwks.json
有关您可以在 Node.js 应用程序或 AWS Lambda
授权方中使用的更多信息和示例代码,请参阅 aws-jwt-verify
了解和检查令牌
在将令牌检查与应用程序集成之前,请考虑一下 Amazon Cognito 是如何组装的。JWTs从用户群体中检索示例令牌。解码并详细检查它们,以了解它们的特征,并确定要验证的内容和时间。例如,您可能希望检查一个场景中的组成员资格,而在另一个场景中,您可能想要检查范围。
以下各节描述了在准备应用程序时手动检查 Amazon Cognito JWTs 的过程。
确认的结构 JWT
JSONWeb Token (JWT) 包括三个部分,它们之间有一个.
(点)分隔符。
- 标题
-
Amazon Cognito 用于签署令牌的密钥 ID 和RSA算法。
kid
alg
Amazon Cognito 使用alg
(RS256
) 对令牌进行签名。kid
是对您的用户池持有的 2048 位RSA私有签名密钥的截断引用。 - 有效负载
-
令牌声明。在 ID 令牌中,声明包括用户属性和有关用户群体
iss
和应用程序客户端aud
的信息。在访问令牌中,有效负载包括范围、组成员资格、用户群体身份 (iss
) 和应用程序客户端 (client_id
)。 - 签名
-
签名不是像标头和有效负载那样的可解码 base64。它是从签名密钥和参数派生的RSA256标识符,您可以在自己的位置观察到JWKSURI。
标头和有效负载均采用 base64 编码JSON。您可以通过解码为起始字符 eyJ
的开头字符 {
来识别它们。如果您的用户JWT向您的应用程序提供了 base64 编码但其格式不正确[JSON
Header].[JSON Payload].[Signature]
,则它不是有效的 Amazon Cognito 令牌,您可以将其丢弃。
验证 JWT
JWT签名是标头和有效载荷的哈希组合。Amazon Cognito 为每个用户池生成两对RSA加密密钥。一个私有密钥对访问令牌进行签名,另一个私有密钥对 ID 令牌进行签名。
验证令牌的签JWT名
-
解码 ID 令牌。
OpenID 基金会还维护着一份用于处理令牌的库清单
。JWT 您也可以使用 AWS Lambda 解码用户池JWTs。有关更多信息,请参阅使用解码和验证 Amazon JWT Cognito 令牌
。 AWS Lambda -
将本地密钥 ID (
kid
) 与公有kid
进行比较。-
为您的用户池下载并存储相应的公共 JSON Web 密钥 (JWK)。它作为 JSON Web 密钥集 (JWKS) 的一部分提供。你可以通过
jwks_uri
URI为你的环境构造以下内容来找到它:https://cognito-idp.
<Region>
.amazonaws.com/<userPoolId>
/.well-known/jwks.json有关JWK和JWK集的更多信息,请参阅 JSONWeb Key (JWK)
。 注意
Amazon Cognito 可能会轮换用户群体中的签名密钥。最佳做法是使用
kid
作为缓存密钥在应用程序中缓存公有密钥,并定期刷新缓存。将您的应用程序收到的令牌中的kid
与缓存进行比较。如果您收到的令牌的颁发者是正确的,但
kid
不同,则 Amazon Cognito 可能已经轮换了签名密钥。从您的用户群体jwks_uri
端点刷新缓存。这是个
jwks.json
文件示例:{ "keys": [{ "kid": "1234example=", "alg": "RS256", "kty": "RSA", "e": "AQAB", "n": "1234567890", "use": "sig" }, { "kid": "5678example=", "alg": "RS256", "kty": "RSA", "e": "AQAB", "n": "987654321", "use": "sig" }] }
- 密钥 ID(
kid
) -
kid
这是一个提示,用于指示使用哪个密钥来保护令牌JSON的 Web 签名 (JWS)。 - 算法(
alg
) -
alg
标头参数表示用于保护 ID 令牌的加密算法。用户池使用RS256加密算法,即带有 SHA -256 的RSA签名。有关的更多信息RSA,请参阅RSA密码学。 - 密钥类型(
kty
) -
该
kty
参数标识与密钥一起使用的加密算法系列,例如本示例中的 RSA “”。 - RSA指数 ()
e
-
该
e
参数包含RSA公钥的指数值。它以 Base64 urlUInt 编码的值表示。 - RSA模量 ()
n
-
该
n
参数包含RSA公钥的模数值。它以 Base64 urlUInt 编码的值表示。 - 使用(
use
) -
use
参数描述了公有密钥的预期用途。在本示例中,use
值sig
表示签名。
- 密钥 ID(
-
在公共 JSON Web 密钥中搜索与您的密钥
kid
相匹配的JWT。kid
-
-
使用JWT库将发行者的签名与令牌中的签名进行比较。颁发者签名源自 jwks.json
kid
中与令牌匹配的公钥(RSA模数"n"
)。kid
您可能需要先将 to PEM 格式JWK转换为格式。以下示例采用JWT和JWK并使用 Node.js 库 jsonwebtoken来验证签名:JWT
验证声明
验证JWT索赔
-
通过以下方法之一,验证令牌是否未过期。
-
对令牌解码并将
exp
声明与当前时间进行比较。 -
如果您的访问令牌包含
aws.cognito.signin.user.admin
索赔,请向点赞发送请求GetUser。APIAPI如果您的令牌已过期,则使用访问令牌授权的请求会返回错误。 -
在针对userInfo 端点的请求中提供您的访问令牌。如果您的令牌已过期,则请求会返回错误。
-
-
ID 令牌中的
aud
声明和访问令牌中的client_id
声明应与在 Amazon Cognito 用户池中创建的应用程序客户端 ID 匹配。 -
发布者 (
iss
) 声明应与您的用户池匹配。例如,在us-east-1
区域中创建的用户池将有下列iss
值:https://cognito-idp.us-east-1.amazonaws.com/
.<userpoolID>
-
检查
token_use
声明。-
如果您只在网络API操作中接受访问令牌,则其值必须为
access
。 -
如果您只使用 ID 令牌,则其值必须为
id
。 -
如果您同时使用 ID 令牌和访问令牌,则
token_use
声明必须为id
或access
。
-
您现在可以信任该令牌内的声明。