本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
验证 JSON Web 令牌
这些步骤描述了验证用户池 JSON Web 令牌(JWT)的过程。
先决条件
您的库、开发工具包或软件框架可能已处理本部分中的任务。 Amazon 软件开发工具包为应用程序中的 Amazon Cognito 用户池令牌处理和管理提供了工具。 Amazon Amplify 包括检索和刷新 Amazon Cognito 令牌的功能。
有关更多信息,请参阅以下页面。
-
Amplify Dev Center(Amplify 开发中心)中的 Advanced workflows
(高级工作流)
许多库可用于解码和验证 JSON Web 令牌 (JWT)。如果您要手动处理用于服务器端 API 处理的令牌,或者您使用的是其他编程语言,则这些库可以为您提供帮助。请参阅用于处理 JWT 令牌库的 OpenID Foundation 列表
使用验证令牌 aws-jwt-verify
在 Node.js 应用程序中, Amazon 建议使用该aws-jwt-verify库aws-jwt-verify
,您可以使用要为一个或多个用户群体验证的声明值填充 CognitoJwtVerifier
。它可以检查的一些值包括以下内容。
-
该访问令牌或 ID 令牌的格式不正确或已过期,但具有有效的签名。
-
这些访问令牌来自正确的用户群体和应用程序客户端
。 -
该访问令牌声明包含正确的 OAuth 2.0 范围
。 -
对访问令牌和 ID 令牌进行签名的密钥与用户群体的 JWKS URI 中的签名密钥
kid
匹配。 JWKS URI 包含有关对用户令牌进行签名的私有密钥的公有信息。您可以在以下位置找到用户群体的 JWKS URI:
https://cognito-idp.
。<Region>
.amazonaws.com/<userPoolId>
/.well-known/jwks.json
有关您可以在 Node.js 应用程序或 Amazon Lambda
授权方中使用的更多信息和示例代码,请参阅aws-jwt-verify
了解和检查令牌
在将令牌检查与应用程序集成之前,请考虑 Amazon Cognito 如何组装 JWT。从用户群体中检索示例令牌。解码并详细检查它们,以了解它们的特征,并确定要验证的内容和时间。例如,您可能希望检查一个场景中的组成员资格,而在另一个场景中,您可能想要检查范围。
以下部分描述在准备应用程序时手动检查 Amazon Cognito JWT 的过程。
确认 JWT 的结构
JSON Web 令牌 (JWT) 包括三个部分,各部分之间有一个 .
(圆点)分隔符。
- 标题
-
Amazon Cognito 用来对令牌进行签名的密钥 ID
kid
和 RSA 算法alg
。Amazon Cognito 使用alg
(RS256
) 对令牌进行签名。 - 有效负载
-
令牌声明。在 ID 令牌中,声明包括用户属性和有关用户群体
iss
和应用程序客户端aud
的信息。在访问令牌中,有效负载包括范围、组成员资格、用户群体身份 (iss
) 和应用程序客户端 (client_id
)。 - 签名
-
签名不是像标头和有效负载那样的可解码 base64。它是一个 RSA256 标识符,派生自签名密钥和参数(您可以在 JWKS URI 上观察到)。
标头和有效负载是以 base64 编码的 JSON。您可以通过解码为起始字符 eyJ
的开头字符 {
来识别它们。如果用户向您的应用程序提供了以 base64 编码的 JWT,但其格式不是 [JSON
Header].[JSON Payload].[Signature]
,则它不是有效的 Amazon Cognito 令牌,您可以将其丢弃。
验证 JWT
JWT 签名是标头和负载的哈希组合。Amazon Cognito 为每个用户池生成两对 RSA 加密密钥。一个私有密钥对访问令牌进行签名,另一个私有密钥对 ID 令牌进行签名。
验证 JWT 令牌的签名
-
解码 ID 令牌。
OpenID Foundation 还维护用于处理 JWT 令牌的库列表
。 您还可以使用 Amazon Lambda 解码用户池 JWT。有关更多信息,请参阅使用解码和验证 Amazon Cognito J
WT 令牌。 Amazon Lambda -
将本地密钥 ID (
kid
) 与公有kid
进行比较。-
下载并存储适用于用户池的对应的公有 JSON Web Key(JWK)。它可作为 JSON Web Key Set (JWKS) 的一部分提供。您可以通过为您的环境构建以下
jwks_uri
URL 来找到它:https://cognito-idp.
<Region>
.amazonaws.com/<userPoolId>
/.well-known/jwks.json有关更多 JWK 和 JWK 集的更多信息,请参阅 JSON Web 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 公有密钥的指数值。它表示为采用 Base64urlUInt 编码的值。 - RSA 模数(
n
) -
n
参数包含 RSA 公有密钥的模数值。它表示为采用 Base64urlUInt 编码的值。 - 使用(
use
) -
use
参数描述了公有密钥的预期用途。在本示例中,use
值sig
表示签名。
- 密钥 ID(
-
搜索与您 JWT 的
kid
相匹配的kid
的公有 JSON Web 密钥。
-
-
使用 JWT 库将颁发者的签名与令牌中的签名进行比较。发布者签名来自在 jwks.json 中的
kid
公有密钥(RSA 模数"n"
),该公有密钥与令牌kid
匹配。您可能首先需要将 JWK 转换为 PEM 格式。以下示例采用 JWT 和 JWK 格式,并且使用 Node.js 库 jsonwebtoken来验证 JWT 签名:
验证声明
验证 JWT 声明
-
通过以下方法之一,验证令牌是否未过期。
-
对令牌解码并将
exp
声明与当前时间进行比较。 -
如果您的访问令牌包含
aws.cognito.signin.user.admin
索赔,请向类似的 API 发送请求GetUser。如果令牌已过期,您使用访问令牌进行授权的 API 请求会返回错误。 -
在针对UserInfo 端点的请求中提供您的访问令牌。如果您的令牌已过期,则请求会返回错误。
-
-
ID 令牌中的
aud
声明和访问令牌中的client_id
声明应与在 Amazon Cognito 用户池中创建的应用程序客户端 ID 匹配。 -
发布者 (
iss
) 声明应与您的用户池匹配。例如,在us-east-1
区域中创建的用户池将有下列iss
值:https://cognito-idp.us-east-1.amazonaws.com/
.<userpoolID>
-
检查
token_use
声明。-
如果您在 Web API 操作中只接受访问令牌,则其值必须为
access
。 -
如果您只使用 ID 令牌,则其值必须为
id
。 -
如果您同时使用 ID 令牌和访问令牌,则
token_use
声明必须为id
或access
。
-
您现在可以信任该令牌内的声明。