【问题标题】:Problems using Spring Security with an Okta OIDC JWT使用带有 Okta OIDC JWT 的 Spring Security 时出现问题
【发布时间】:2020-03-05 12:56:16
【问题描述】:

[请参阅下面的更新部分了解最新版本]

我正在尝试使用 Spring Security 设置 Spring Boot REST 应用程序。我们的前端在 Okta 中使用 OIDC 对我们的用户进行身份验证,并在 Authorization Bearer 令牌中传递 JWT。 Okta 正在使用 PKCE。

我引用了以下示例,它似乎是一个非常简单的设置: https://docs.spring.io/spring-security-oauth2-boot/docs/current/reference/html/boot-features-security-oauth2-resource-server.html

我们的 Spring Boot 应用程序只是一个资源服务器,所以我想我只需要按照 2.1 到 2.2.3 节中的说明进行操作即可。我的应用程序中有@EnableResourceServer,我的application.yml 中有以下内容:

spring:
  security:
    oauth2:
      resource:
        jwt:
          key-set-uri: https://dcsg-hub-dev.okta.com/oauth2/v1/keysZ?client_id=???

当我使用 Postman 调用我的应用时,我收到 401 错误:

{
    "error": "invalid_token",
    "error_description": "Invalid access token: eyJraWQ..."
}

它显示了有效的令牌,我可以通过调用 Okta userinfo 端点来验证它。不幸的是,它没有给我任何其他信息。

我最终在org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter 类中设置了断点。进入从该位置调用的代码,错误是由org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager中的代码引起的:

public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    if (authentication == null) {
        throw new InvalidTokenException("Invalid token (token not found)");
    } else {
        String token = (String)authentication.getPrincipal();
        OAuth2Authentication auth = this.tokenServices.loadAuthentication(token);
        if (auth == null) {
            throw new InvalidTokenException("Invalid token: " + token);

在同一个类中调用如下代码:

public OAuth2Authentication loadAuthentication(String accessTokenValue) throws AuthenticationException, InvalidTokenException {
    OAuth2AccessToken accessToken = this.tokenStore.readAccessToken(accessTokenValue);
    if (accessToken == null) {
        throw new InvalidTokenException("Invalid access token: " + accessTokenValue);

似乎代码使用令牌本身作为从哈希映射中检索令牌的键。正如您在上面看到的,它使用getPrincipal() 来获取“令牌”。在我看来,它认为令牌应该是一个用户 ID,它试图用它来查找用户的令牌。当值已经存在时,它使用令牌作为获取值的键似乎很奇怪。

有什么想法吗?

>>>>>>>>>>>>>>

我关注了此链接中的文档: https://github.com/spring-projects/spring-security/tree/5.2.1.RELEASE/samples/boot/oauth2resourceserver-jwe

我的application.yml 现在看起来像这样:

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: https://dcsg-hub-dev.okta.com
          jwk-set-uri: https://dcsg-hub-dev.okta.com/oauth2/v1/keys?client_id=

这现在肯定是调用 JWK URI,而之前不是。但是,现在我收到以下错误:

Caused by: com.nimbusds.jose.proc.BadJOSEException: Signed JWT rejected: Another algorithm expected, or no matching key(s) found

我在该代码中设置了断点,无论出于何种原因,从 Okta 返回的令牌/JWT 中的 kid 与 Okta jwk-set-uri 中的任何键都不匹配。

【问题讨论】:

  • 你是对的。虽然看起来违反直觉,但它使用 String accessToken 来获取 OAuth2AccessToken(Authentication 对象)
  • 您确定您使用的是 Spring Boot 自动配置吗? spring-security-oauth2-autoconfigure
  • @EnableResourceServer 适用于 Spring Boot 1.5.x,Spring Boot 2.1+ 已将其内置到其 http 配置中。请参阅developer.okta.com/blog/2019/03/05/spring-boot-migration 了解更多信息。
  • 我正在使用 spring-security-oauth2-autoconfigure。当我删除 @EnableResourceServer 时,无效的令牌错误消失了,但现在我只是得到一个普通的 401。我正在继续研究这个。我忘了在上面提到我们在 Okta 中使用 PKCE。

标签: spring-security jwt openid-connect okta pkce


【解决方案1】:

我从 Okta 得知不支持此功能,您需要使用 API 访问管理创建自己的授权服务器。

【讨论】:

    猜你喜欢
    • 2018-03-24
    • 2017-05-23
    • 2011-11-11
    • 2019-01-18
    • 2018-01-29
    • 2011-11-13
    • 2017-09-09
    • 1970-01-01
    • 2016-04-20
    相关资源
    最近更新 更多