Given following filter chain:
@Bean
@Order(0)
public SecurityFilterChain securityFilterChain(
HttpSecurity http,
@Qualifier(OpaqueTokenAuthorizationFilter.OPAQUE_TOKEN_AUTHORIZATION_FILTER)
OncePerRequestFilter authorizationFilter
)
http
.authorizeHttpRequests()
.anyRequest()
.authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(authorizationFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
And a OncePerRequestFilter like this:
@Component(OpaqueTokenAuthorizationFilter.OPAQUE_TOKEN_AUTHORIZATION_FILTER)
@Order(Ordered.HIGHEST_PRECEDENCE)
@RequiredArgsConstructor
public class OpaqueTokenAuthorizationFilter extends OncePerRequestFilter {
public static final String OPAQUE_TOKEN_AUTHORIZATION_FILTER =
"OPAQUE_TOKEN_AUTHORIZATION_FILTER";
@Override
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
// Note it always registers autnetication in context
var auth =
UsernamePasswordAuthenticationToken.authenticated(
"test", null, List.of(new SimpleGrantedAuthority("TEST")));
auth.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(auth);
filterChain.doFilter(request, response);
}
}
All of the requests fail in Authorization filter because SecurityContextHolder
returns anonymous authentication when a generic endpoint is being hit. It is being thrown by ObservationDecisionManager
during the decision check (because the authentication object is anonymous).
The custom filter executes and sets authentication.
Is there anything else needed for the new Spring Security configuration?
CodePudding user response:
If you debug the order in which spring security filter chain is invoked in your case it seems adding @Order
annotation causes it to run before FilterChainProxy starts its processing logic and then it sets the SecurityContext to empty inside SecurityContextPersistenceFilter which overwrites what you set in your filter causing the behavior you see. Since you are trying to add a custom auth mechanism it would be recommended to add the filter before UsernamePasswordAuthenticationFilter which your SecurityFilterChain
does but seems to be overridden by @Order
annotation. I guess the Order annotation is redundant in this case anyway and should be removed.. See this post on more details on how the chain is invoked - link
You can play around by setting the debug level logging of spring security to see how these filters are invoked.
logging.level.org.springframework.security=DEBUG