Spring 验证后未执行安全 oauth2Login OAuth2UserService

Spring Security oauth2Login OAuth2UserService not executed after authentication

我有一个 Spring 受 Keycloak 保护的 Boot Admin 应用程序,我定义了一个具有领域角色 ACTUATOR 的用户。 问题是身份验证后 Spring 安全性无法访问领域角色。我可以看到授予的权限:Granted Authorities: ROLE_USER, SCOPE_actuator_access, SCOPE_profile'

查看文档,我找到了这个部分:Delegation-based strategy with OAuth2UserService 这是我的配置:

这是我的配置:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure( HttpSecurity http ) throws Exception {
        http.csrf().disable().cors().disable();
        http.authorizeRequests()
                .antMatchers( "/error","/instances", "/**/*.css", "/**/img/**", "/**/third-party/**", "/*.js" )
                .permitAll()
                .anyRequest().hasRole( "ACTUATOR" )
                .and()
                .oauth2Login( oauth2 -> oauth2.userInfoEndpoint(
                        userInfo -> userInfo.oidcUserService( this.oidcUserService() ) ) );
    }

    // I just copy-paste the doc's code to play with it...
    private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {

        final OidcUserService delegate = new OidcUserService();

        return ( userRequest ) -> {
            OidcUser oidcUser = delegate.loadUser( userRequest );

            //TODO find a way to extract realm roles 
            OAuth2AccessToken accessToken = userRequest.getAccessToken();

            Set<GrantedAuthority> mappedAuthorities = new HashSet<>();

            oidcUser = new DefaultOidcUser( mappedAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo() );

            return oidcUser;
        };
    }

我希望使用方法 oidcUserService() 从令牌中提取 Keycloak 领域角色,但该方法根本没有执行。我的意思是在从 Keycloak 成功验证并重定向到应用程序后,oidcUserService() 方法未执行。好像只在应用程序启动时执行,奇怪。

问题是在这种情况下如何检索领域角色?

编辑

我在这里添加了一个示例项目:https://github.com/akuma8/sba-keycloak-spring-security

安全配置在 application.ymlSecurityConfig class

我不知道为什么没有调用此 oidcUserService。您可以改用 JwtAuthenticationConverter 并将您的 JWT 映射到您需要的任何角色。

这有点棘手,所以这里有两个例子:

请注意,我不知道您是否应该在解析之前自行检查 JWT 签名,或者 Spring OAuth 是否会这样做。这值得一试。

我找到了为什么 oidcUserService() 方法在验证后没有被调用。原因是令牌的类型,我愚蠢地从 Spring 安全文档中复制了代码,而没有注意该信息。

在文档中它是关于 OidcUserRequest 而在我的例子中它是 OAuth2UserRequest,所以这是 OAUTH2OIDC 之间的冲突。将方法更改为:

private OAuth2UserService<OAuth2UserRequest, OAuth2User> oauth2UserService() {
   // code extracting authorities from JWT here

}

解决了我的问题。我现在可以从访问令牌中获取 Keycloak 领域角色。