Spring Security oauth2Login OAuth2UserService 身份验证后未执行

问题描述 投票:0回答:3

我有一个由 Keycloak 保护的 Spring Boot 管理应用程序,我定义了一个具有领域角色的用户

ACTUATOR
。 问题是身份验证后 Spring Security 无权访问领域角色。我可以看到授予的权限:
Granted Authorities: ROLE_USER, SCOPE_actuator_access, SCOPE_profile'

查看文档,我找到了这一部分: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.yml
SecurityConfig

spring-boot spring-security keycloak spring-security-oauth2 spring-boot-admin
3个回答
5
投票

我找到了为什么认证后没有调用

oidcUserService()
方法。原因是令牌的类型,我愚蠢地从 Spring Security 文档中复制了代码,而没有注意该信息。

在文档中它是关于

OidcUserRequest
而在我的例子中是
OAuth2UserRequest
,所以这是
OAUTH2
OIDC
之间的冲突。将方法更改为:

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

}

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


1
投票

我不知道为什么这个 oidcUserService 没有被调用。您可以使用 JwtAuthenticationConverter 来代替,并将 JWT 映射到您需要的任何角色。

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

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


0
投票

我也遇到了同样的问题,问题出在范围

openid

从范围中删除 openid 后(我不需要它),

userService
按预期工作

userInfoEndpoint(userInfoEndpointConfig -> userInfoEndpointConfig.userService(customOauth2UserService))

配置

spring.security.oauth2.client.registration.google.scope=profile,email
© www.soinside.com 2019 - 2024. All rights reserved.