在 Spring Security 中解码 AWS Cognito 生成的 JWT 时出错

Posted

技术标签:

【中文标题】在 Spring Security 中解码 AWS Cognito 生成的 JWT 时出错【英文标题】:Getting error while decoding JWT generated by AWS Cognito in spring security 【发布时间】:2020-02-12 01:52:34 【问题描述】:

我们突然开始低于errordecoding AWS Cognito 生成的JWT。 Spring Security JWT


    "error": "access_denied",
    "error_description": "Invalid token does not contain resource id (oauth2-resource)"

我们使用的是 Spring Boot 版本:2.0.3.RELEASE

这更具体到 AWS Cognito 生成的令牌。以及为什么它突然停止工作而代码库/spring lib 或基础设施没有变化


最新更新: 似乎 AWS 已在解码的 JWT 下方恢复了更改(添加了“aud 声明”)

今天(2019 年 10 月 16 日)智威汤逊

 
    "sub": "XXXXXXXXXXXX-6a8dd388a720",
    "token_use": "access",
    "scope": "XXXXXXXXXXXX",
    "auth_time": 1571227222,
    "iss": "YYYYYYYYYYYYYYYY",
    "exp": 1571230822,
    "iat": 1571227222,
    "version": 2,
    "jti": "XXXXXXXXXXXXXYYYYYYYYYYYYY",
    "client_id": "someclient_id",
    "username": "someusername"
     

昨天我们得到了:

  
  "sub": "xxxxxxxxxxxxx",
  **"aud": "sameasclientid",**
  "token_use": "access",
  "scope": "somescope",
  "auth_time": 1571132619,
  "iss": "rrrrrrrrrrrrrrrrrrrrr",
  "exp": 1571136219,
  "iat": 1571132619,
  "version": 2,
  "jti": "xxxxxxxxxxxxxxxxx",
  "client_id": "sameasclientid",
  "username": "someusername"
 

【问题讨论】:

Why is my token being rejected? What is a resource ID? "Invalid token does not contain resource id (oauth2-resource)"的可能重复 【参考方案1】:

我们使用 SO 链接 here 解决了这个问题。

AWS Cognito 生成的令牌现在似乎在令牌中添加了一个新声明 aud。 Spring OAuth 期望 JWT 令牌中的 aud 声明默认为 oauth2-resource

修复方法是在 Spring 资源服务器配置中的 JWT 令牌中添加 aud,其值为 client_id

  @Value("$security.oauth2.resource.id:")
  private String jwtAudResourceId;

  @Override
  public void configure(ResourceServerSecurityConfigurer resources) throws Exception 
    resources.resourceId(jwtAudResourceId);
  

有关 cognito 令牌中的 JWT 声明的信息,请访问 here。


更新


似乎 AWS 已经恢复了他们在 JWT 令牌中添加“aud”声明的更改。 我们不再收到 JWT 中的“aud”声明

我们昨天(2019 年 10 月 15 日)获得的解码 JWT


  "sub": "XXXXXXXXXXXXXXXXX",
  "aud": "SAME_AS_CLIENT_ID",
  "token_use": "access",
  "scope": "SOMESCOPE",
  "auth_time": 1571132619,
  "iss": "SOME_ISSUER",
  "exp": 1571136219,
  "iat": 1571132619,
  "version": 2,
  "jti": "8XXXXXXXXXXXXXXXX",
  "client_id": "SAME_AS_CLIENT_ID",
  "username": "SOME_USERNAME"

我们今天获得的解码 JWT(2019 年 10 月 16 日


  "sub": "XXXXXXXXXXXXXXXXX",
  "token_use": "access",
  "scope": "SOMESCOPE",
  "auth_time": 1571227222,
  "iss": "SOME_ISSUER",
  "exp": 1571230822,
  "iat": 1571227222,
  "version": 2,
  "jti": "8XXXXXXXXXXXXXXXX",
  "client_id": "SAME_AS_CLIENT_ID",
  "username": "SOME_USERNAME"

所以现在即使我们不按如下方式配置它也应该可以工作。或者从配置类中删除下面的 sn-p :

@Override
public void configure(ResourceServerSecurityConfigurer config) throws 
Exception 
    config.resourceId(null).tokenServices(tokenServices());

【讨论】:

这是不正确的,一个token可以包含多个resource id,以空格分隔。请参考 Oauth2 标准的文档。 “aud” 参数的值设置与 clientId 相同是 Coginto 的错误实现,这就是为什么他们今天可能已经恢复了他们的更改。而是将 resourceId 设置为“null”,以便 spring security 绕过检查。 答案是一种变通方法。因为我们已经向 AWS 提出了请求。此外,AWS,Cognito 并没有完全实现 OAuth,似乎他们做了一些量身定制的解决方案。它是否正确取决于答案的有用性。【参考方案2】:

我遇到了类似的问题,在我的情况下,我不需要验证 JWT 声明中添加的“aud”参数。

这不是来自 AWS Cognito 的正确实现,这意味着“aud”应该包含将使用携带令牌的资源服务器的资源 ID,但 Cognito 只是复制了与“clientId”相同的值。在我们的例子中,有多个客户端可以调用一个资源服务器,根据 Coginto 的实现,资源服务器需要知道 clientId 的列表,这在 Oauth2 标准中是错误的。

要了解更多信息,请访问https://www.rfc-editor.org/rfc/rfc7523,上面写着

JWT 必须包含一个“aud”(受众)声明,其中包含 将授权服务器标识为预期的值 观众。授权服务器的令牌端点 URL 可以用作“aud”元素的值来标识 授权服务器作为 JWT 的目标受众。这 授权服务器必须拒绝任何不包含 它自己作为目标受众的身份。在没有一个 应用程序配置文件以其他方式指定,兼容的应用程序 必须使用简单字符串比较受众值 RFC 3986 第 6.2.1 节中定义的比较方法 [RFC3986]。如第 5 节所述,精确的字符串是 用作给定授权服务器的受众必须是 由授权服务器和 JWT 的发行者。

所以如果你不需要验证“aud”参数,将资源服务器的resourceId设置为null(默认值'oauth2-resource')如下所示。

@Override
public void configure(ResourceServerSecurityConfigurer config) throws Exception 
    config.resourceId(null).tokenServices(tokenServices());

如果资源服务器的resourceId为null,Spring security会忽略“aud”参数。

【讨论】:

以上是关于在 Spring Security 中解码 AWS Cognito 生成的 JWT 时出错的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spring Security、Spring Boot 和 MongoDB 进行密码编码和解码

IIS 7.5 与 aws elb 问题 http 到 https j_spring_security_check.action

Spring Security 5中的默认密码编码器

Grails Spring Security 使用 https 重定向到登录页面

Spring Boot > 2.2.7 的令牌类型为“at+jwt”时 JWT 错误的解码

Spring Security 3 身份验证与 Hibernate 3(JPA) 注释的集成