为啥 Amazon Cognito 不在其访问令牌中返回受众字段?

Posted

技术标签:

【中文标题】为啥 Amazon Cognito 不在其访问令牌中返回受众字段?【英文标题】:Why doesn't Amazon Cognito return an audience field in its access tokens?为什么 Amazon Cognito 不在其访问令牌中返回受众字段? 【发布时间】:2019-04-08 11:27:14 【问题描述】:

当 Amazon Cognito 颁发访问令牌时,它不包含 aud 字段。

在documentation for Cognito tokens 中,aud 字段针对 id 令牌(始终设置为与 client_id 相同的值)列出,但不针对访问令牌。

relevant section of the JWT specification 说:

如果处理该声明的主体在此声明存在时未使用“aud”声明中的值标识自己,则必须拒绝 JWT。

那么,这里发生了什么。谁是对的?这是安全问题吗?

我注意到令牌的 iss 部分特定于我的用户池,并且不能被篡改,因为它是由亚马逊签名的,所以我认为我应该是安全的

OAuth 2 和 JWT 非常令人困惑,所以我想获得更多意见。

【问题讨论】:

【参考方案1】:

通常,aud 声明用于标识 recipientsprincipal,以便接收者可以验证 jwt 是否适合其验证。

但是,aud 是可选声明。 因此,AWS 将其保留为可选。

AWS 没有使用 aud 声明来限制谁可以处理 jwt,而是让接收者(例如 aws api gw)检查 client_id 声明以确定是否应该处理 jwt。

参考资料:

https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3

【讨论】:

【参考方案2】:

根据我对 RFC 的阅读,我不认为 AWS 做错了什么,特别是(注意我的重点):

如果处理该声明的主体在存在此声明时未将自己标识为“aud”声明中的值,则必须拒绝 JWT。

使用此声明是可选

我相信这意味着 AWS 很好,因为它只是在访问令牌的情况下省略了声明,但它通过设置它来标识自己(以它自己的方式) client_id 当它确实对 id 令牌提出声明时。

应该注意,访问令牌本身确实对受众进行编码和强制执行;因为当您针对 AWS 的 API 使用它时,它将强制您仅接收为其发布的 client_id/scope 上可用的资源。

【讨论】:

感谢您的回复。我联系了 AWS,与他们讨论了一些事情,包括这个,他们因此向 cognito 开发团队提交了一个功能请求,以考虑选择性地允许在访问令牌中包含“aud”声明,模仿 auth0 和好的。 @Kyanite 你有关于该功能请求的更多信息吗? @Kyanite 关于功能请求的任何消息?缺少 audience 声明使得 API Gateway JWT Authorizer 无用,因为它需要一个有效的 audience 值列表。 对于 JWT 授权者,文档说明(现在,如果不是,那么!)授权者的受众条目使用如下:“aud 或 client_id – 必须匹配配置的受众条目之一为授权人。”见docs.aws.amazon.com/apigateway/latest/developerguide/…【参考方案3】:

许多 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;

            );

【讨论】:

【参考方案4】:

AWS Cognito 现在似乎在访问令牌上包含 client_id 声明。我没有在任何 AWS 文档中找到它,我唯一能找到的是这个 GitHub 问题:https://github.com/ghdna/cognito-express/issues/11

【讨论】:

是的,包括 client_id 声明,对于 JWT 授权者,文档说明(现在,如果不是,那么!)授权者的受众条目使用如下:“aud 或 client_id – 必须匹配为授权人配置的受众条目之一。”见docs.aws.amazon.com/apigateway/latest/developerguide/…

以上是关于为啥 Amazon Cognito 不在其访问令牌中返回受众字段?的主要内容,如果未能解决你的问题,请参考以下文章

使用 amazon cognito 域 UI(从用户池生成)登录后未获得 cognito 访问令牌?

cognito 用户会话被持久化,而不在本地存储中存储令牌

在预认证用户的情况下如何使用 amazon cognito 获取刷新令牌

AWS cognito 快速将令牌交换为凭证

如何在 Go 中验证来自 AWS Cognito 的 JWT 令牌?

如何从 AWS cognito 授权代码获取访问和刷新令牌