javaspringspring-mvcspring-securityspring-security4

SecurityContext authorities does not equal ServletRequest roles?


I was trying to replace some manual authority checking with annotations (@Secured and @PreAuthorize). While debugging why it doesn't work I was surprised to find that the second of these two assertions failed at the top of a @RequestMapping controller method.

Authentication auth = SecurityContextHolder.getContext().getAuthentication();
assert(auth.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_READER"))); // passes
assert(request.isUserInRole("ROLE_READER")); // fails

I assume (as I can't get them to authorise anything) @Secured and hasRole() make use of the latter lookup?

Are the roles not supposed to be automatically populated from the SecurityContext authorities?

Was the filter that set the Authentication supposed to add the roles separately?


Edit:

Cut down the spring security config to spring boot's (1.3.0) default, plus the filter that sets the authentication.

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(new JwtAuthenticationFilter(), FilterSecurityInterceptor.class);
    }
}

Solution

  • I assume (as I can't get them to authorise anything) @Secured and hasRole() make use of the latter lookup?

    My assumption was wrong. Both use the granted authorities, but in different ways.

    The prefix can be configured with RoleVoter's rolePrefix property.

    HttpServletRequest.isUserInRole uses a completely separate system, unrelated to Spring security. It is not populated by default, and does not need to be. I believe adding a SecurityContextHolderAwareRequestFilter to the chain will populate it