Search code examples
javaspring-securityspring-cloud

Spring Cloud - Security 403 Forbidden Error


I have a problem about sending some requests from management service to advertisement service through the port number of management service.

http://localhost:9002/api/v1/admin_role/alladvertisements
http://localhost:9002/api/v1/user_role/alladvertisements

I got 403 forbidden issue for two urls shown above. I used access token as bearer token for both user and admin. While admin is responsible for its own requests, user can only handle with its process.

Here are the results of two urls.

{
    "timestamp": "2022-08-31T23:58:15.250+00:00",
    "status": 403,
    "error": "Forbidden",
    "path": "/api/v1/admin_role/alladvertisements"
}

{
    "timestamp": "2022-08-31T23:58:15.250+00:00",
    "status": 403,
    "error": "Forbidden",
    "path": "/api/v1/user_role/alladvertisements"
}

Here is the web security part of management service.

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(jsr250Enabled = true)
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.csrf().disable();
        http.authorizeRequests()
                .antMatchers("/api/v1/admin_role/*").hasAnyRole("ROLE_ADMIN")
                .antMatchers("/api/v1/user_role/*").hasAnyRole("ROLE_USER")
                .antMatchers("/actuator/health").hasAnyRole("ROLE_ADMIN")
                .antMatchers("/actuator/circuitbreakerevents").hasAnyRole("ROLE_ADMIN")
                .anyRequest()
                .permitAll();

    }

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

    @Override
    @Bean
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }
}

How can I fix it?

Here is my github repository : Link


Solution

  • If you did not change the default GrantedAuthority prefix - "ROLE_", then SecurityExpressionRoot's .hasRole() and .hasAnyRole() methods will add this prefix to passed arguments. You can read it here and here.
    Also, as stated in the javadoc, SimpleAuthorityMapper also adds "ROLE_" prefix to roles, when it maps GrantedAuthority.

    That means, when you pass "ROLE_ADMIN" to there methods, it converts it into "ROLE_ROLE_ADMIN", and you get 403 status as a result.

    So, try to configure security without prefixes, like this:

    .antMatchers("/api/v1/admin_role/*").hasRole("ADMIN")
    .antMatchers("/api/v1/user_role/*").hasRole("USER")
    

    Or you can use .hasAuthority() or .hasAnyAuthority() method instead, which doesn't change passed argument:

    .antMatchers("/api/v1/admin_role/*").hasAuthority("ROLE_ADMIN")
    .antMatchers("/api/v1/user_role/*").hasAuthority("ROLE_USER")