当 Amazon Cognito 颁发访问令牌时,它不包含
aud
字段。
在 Cognito 令牌文档中,列出了 id 令牌的
aud
字段(始终设置为与 client_id
相同的值),但不列出访问令牌。
JWT 规范的相关部分说:
如果处理该声明的主体在存在此声明时未将自己标识为“aud”声明中的值,则必须拒绝 JWT。
那么,这是怎么回事。谁是对的?这是安全问题吗?
我注意到令牌的
iss
部分是特定于我的用户池的,并且不可能被篡改,因为它是由亚马逊签名的,所以我认为我应该是安全的
OAuth 2 和 JWT 非常令人困惑,所以我想获得更多意见。
根据我对 RFC 的阅读,我不认为 AWS 做错了什么,特别是(注意我的强调):
如果处理声明的主体未将自己标识为“aud”声明中的值当此声明存在时,则必须拒绝 JWT。
使用此声明是可选。
我相信,这意味着 AWS 没问题,因为它只是省略了访问令牌的声明,但它通过在出现时将其设置为
client_id
来识别自己(以它自己的方式)对 id 令牌进行声明。
应该注意的是,访问令牌本身确实对受众进行编码和强制执行;因为当您针对 AWS 的 API 使用它时,它将强制您仅接收为其颁发的 client_id/scope 上可用的资源。
许多 dotnet Web 应用程序认知教程都基于错误的假设,即客户端 ID 将是以下设置中的受众 ID,这将不起作用。
services
.AddAuthentication(options => {
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Audience = "Client ID";
options.Authority = "https://cognito-idp.ap-southeast-2.amazonaws.com/USERPOOLID";
options.RequireHttpsMetadata = false;
});
临时解决方法是不验证受众:
services
.AddAuthentication(options => {
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
// AWS cognito jwt token does not have aud included so that we cannot validate audience.
// options.Audience = "Client ID";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false
};
options.Authority = "https://cognito-idp.ap-southeast-2.amazonaws.com/USERPOOLID";
options.RequireHttpsMetadata = false;
});
看起来 AWS Cognito 现在包含对访问令牌的
client_id
声明。我没有在任何 AWS 文档中找到它,我唯一能找到的是这个 GitHub 问题:https://github.com/ghdna/cognito-express/issues/11
通常,
aud
声明用于识别recipients
或principal
,以便接收者可以验证jwt是否适合其验证。
但是,
aud
是可选声明。
因此,AWS 将其保留为可选。
AWS 没有使用 aud 声明来绑定谁可以处理 jwt,而是将其留给接收者(例如 aws api gw)来检查
client_id
声明以确定是否应该处理 jwt。
参考资料:
我发现这篇文章解释了如何使用 lambda 函数来修改返回的令牌,并可能添加 aud 声明。
https://aws.amazon.com/blogs/security/how-to-customize-access-tokens-in-amazon-cognito-user-pools/