在 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 【问题描述】:我们突然开始低于error
而decoding
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
Grails Spring Security 使用 https 重定向到登录页面