Search code examples
spring-bootspring-securitykeycloakspring-security-oauth2spring-boot-admin

Spring Security oauth2Login OAuth2UserService not executed after authentication


I have a Spring Boot Admin app secured by Keycloak, I defined a user having a realm role ACTUATOR. The problem is that after authentication Spring Security does not have access to realm roles. I can see the granted authorities: Granted Authorities: ROLE_USER, SCOPE_actuator_access, SCOPE_profile'

Looking at the doc I found this section: Delegation-based strategy with OAuth2UserService and this is my configuration:

This is my configuration:

@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;
        };
    }

I hoped use the method oidcUserService() to extract Keycloak realm roles from the token but the method is not executed at all. I mean after successful authentication from Keycloak and redirected to the application, oidcUserService() method is not executed. It seems only executed at application startup, which is strange.

The question is how can I retrieve realm roles in this scenario?

EDIT

I added a sample project here: https://github.com/akuma8/sba-keycloak-spring-security

The security configurations are in application.yml and in SecurityConfig class


Solution

  • I found why the oidcUserService() method was not invoked after authentication. The reason is the type of the token, I have dumbly copied the code from Spring Security documentation without making attention about that information.

    In the documentation it's about OidcUserRequest whereas in my case it's OAuth2UserRequest, so it's a clash between OAUTH2 vs OIDC. Changing the method to:

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

    Solved my issue. I am now able to get Keycloak realm roles from the access token.