使用 Okta OIDC JWT 的 Spring 安全性问题
Problems using Spring Security with an Okta OIDC JWT
[请参阅下面的更新部分了解最新版本]
我正在尝试使用 Spring 安全设置 Spring 引导 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
class 中设置了断点。进入从该位置调用的代码,错误是由 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);
在同一个 class 中调用以下代码:
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()
来获取 'token'。在我看来,它认为令牌应该是一个用户 ID,它试图用它来查找用户的令牌。当值已经存在时,它使用令牌作为获取值的键似乎很奇怪。
有什么想法吗?
<<<<<<<<<<<<<< 更新>>>>>>>>>>>>>>>>
我遵循了这个 link 中的文档:
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 token/JWT 中返回的 kid
与 Okta [=25] 中的任何键都不匹配=].
我从 Okta 了解到不支持此功能,您需要使用 API 访问管理创建您自己的授权服务器。
[请参阅下面的更新部分了解最新版本]
我正在尝试使用 Spring 安全设置 Spring 引导 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
class 中设置了断点。进入从该位置调用的代码,错误是由 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);
在同一个 class 中调用以下代码:
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()
来获取 'token'。在我看来,它认为令牌应该是一个用户 ID,它试图用它来查找用户的令牌。当值已经存在时,它使用令牌作为获取值的键似乎很奇怪。
有什么想法吗?
<<<<<<<<<<<<<< 更新>>>>>>>>>>>>>>>>
我遵循了这个 link 中的文档: 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 token/JWT 中返回的 kid
与 Okta [=25] 中的任何键都不匹配=].
我从 Okta 了解到不支持此功能,您需要使用 API 访问管理创建您自己的授权服务器。