0
votes

I wanna authenticate users via Keycloak, but I need to add additional roles to Authentication object, that is using by Spring Security. Adding roles are saved in Postgres database.

  1. I tried to override configureGlobal with custom AuthenticationProvider, but it didn't work.

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        ApplicationAuthenticationProvider provider = new ApplicationAuthenticationProvider();
        provider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(provider);
    }
    

    @Component public class ApplicationAuthenticationProvider extends KeycloakAuthenticationProvider {

    @Autowired
    private UserService userService;
    
    private GrantedAuthoritiesMapper grantedAuthoritiesMapper;
    
    public void setGrantedAuthoritiesMapper(GrantedAuthoritiesMapper grantedAuthoritiesMapper) {
        this.grantedAuthoritiesMapper = grantedAuthoritiesMapper;
    }
    
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) authentication;
        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
    
        String username = ((KeycloakAuthenticationToken) authentication)
                .getAccount().getKeycloakSecurityContext().getToken().getPreferredUsername();
        List<Role> roles = userService.findRoles(username);
    
        for (Role role : roles) {
            grantedAuthorities.add(new KeycloakRole(role.toString()));
        }
        return new KeycloakAuthenticationToken(token.getAccount(), token.isInteractive(), mapAuthorities(grantedAuthorities));
    }
    
    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
    
    private Collection<? extends GrantedAuthority> mapAuthorities(
            Collection<? extends GrantedAuthority> authorities) {
        return grantedAuthoritiesMapper != null
                ? grantedAuthoritiesMapper.mapAuthorities(authorities)
                : authorities;
    }
    

    }

  2. Tried to add additional filter, but i'm not sure in correct configuration.

    @Bean

    @Override
    protected KeycloakAuthenticationProcessingFilter keycloakAuthenticationProcessingFilter() throws Exception {
        RequestMatcher requestMatcher =
                new OrRequestMatcher(
                        new AntPathRequestMatcher("/api/login"),
                        new QueryParamPresenceRequestMatcher(OAuth2Constants.ACCESS_TOKEN),
                        // We're providing our own authorization header matcher
                        new IgnoreKeycloakProcessingFilterRequestMatcher()
                );
        return new KeycloakAuthenticationProcessingFilter(authenticationManagerBean(), requestMatcher);
    }
    
    // Matches request with Authorization header which value doesn't start with "Basic " prefix
    private class IgnoreKeycloakProcessingFilterRequestMatcher implements RequestMatcher {
        IgnoreKeycloakProcessingFilterRequestMatcher() {
        }
    
    public boolean matches(HttpServletRequest request) {
        String authorizationHeaderValue = request.getHeader("Authorization");
        return authorizationHeaderValue != null && !authorizationHeaderValue.startsWith("Basic ");
    }
    

    }

1
How did you solve it? - Miletos

1 Answers

0
votes

Now I use Keycloak only for login/password. Roles and permissions now saved in local DB.