I am trying to implement a custom token based authentication with authentication filter:
public class AuthAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
@Override
public Authentication attemptAuthentication(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) throws AuthenticationException,
IOException, ServletException {
//some code here
}
@Override
protected void successfulAuthentication(final HttpServletRequest request,
final HttpServletResponse response, final FilterChain chain) { final Authentication authResult) throws IOException, ServletException {
SecurityContextHolder.getContext().setAuthentication(authResult);
chain.doFilter(request, response);
}
}
Registering it with
@Configuration
@Order(2)
@EnableWebSecurity(debug = true)
public class Security extends WebSecurityConfigurerAdapter {
// constructor and beans etc
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf()
.disable().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.requestMatchers(PROTECTED_URLS).hasAnyRole(getAllrolles()).anyRequest()
.authenticated()
.and()
.addFilterBefore(authAuthenticationFilter(),
UsernamePasswordAuthenticationFilter.class)
.formLogin().disable()
.httpBasic().disable()
.logout().disable();
}
}
I have another websecurity config with order 1 for whitelisted urls:
@Configuration
@Order(1)
public class SecurityWhiteList extends WebSecurityConfigurerAdapter {
//constructor and permitted path etc
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.requestMatchers(permittedPaths()).permitAll()
.and()
.anonymous();
}
}
At last, I have a configuration for method security as follows:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurity extends GlobalMethodSecurityConfiguration {
private final RoleHierarchy roleHierarchy;
@Autowired
public MethodSecurity(RoleHierarchy roleHierarchy) {
this.roleHierarchy = roleHierarchy;
}
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler = new
DefaultMethodSecurityExpressionHandler();
expressionHandler.setRoleHierarchy(roleHierarchy);
return expressionHandler;
}
}
The problem here is, I get 403 for the endpoints having method security in the service method annotated with @PreAuthorize("hasAuthority('ROLE_SOMETHING')) even though the users do have ROLE_SOMETHING.
It works, if @PreAuthorize("hasAuthority('ROLE_SOMETHING')) is not present and roles authentication, permitted path everything works.
After debugging, I found that my method security runs before AuthAuthenticationFilter and thus the security context is not populated yet so the user gets ROLE_ANONYMOUS.
My question is: Is it possible to make the authentication filter fire before method security? Or am I entirely doing it wrong? Like I should instead use oncePerRequestFilter instead of AbstractAuthenticationProcessingFilter?