I have the following FilterChain (@EnableWebSecurity(debug = true) Logger:)
Security filter chain: [
DisableEncodeUrlFilter
WebAsyncManagerIntegrationFilter
SecurityContextHolderFilter
HeaderWriterFilter
CorsFilter
CsrfFilter
LogoutFilter
NegotiateSecurityFilter
BasicAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
ExceptionTranslationFilter
AuthorizationFilter
]
I encountered a problem with stateless Single Sign-On (SSO) and Cross-Site Request Forgery (CSRF). The SSO process causes the standard "Ping Pong" request to become three requests (as seen in Fiddler: 401, 401, 200/403). The third authenticated request results in an "Invalid CSRF Token found" error. My hypothesis is that the CSRF filter takes the token from the first request and marks it as "used" or deletes it from the repository. As a result, after the SSO negotiation is complete, the token is invalid and causes the error.
I am currently attempting to move the CSRF filter down the chain, after the Basic Authentication Filter. However, it is proving to be more difficult than anticipated.
Here is my SecurityConfig:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import jakarta.servlet.Filter;
import waffle.spring.NegotiateSecurityFilter;
import waffle.spring.NegotiateSecurityFilterEntryPoint;
@Configuration
@EnableWebSecurity(debug = true)
@EnableMethodSecurity(securedEnabled = true)
public class SecurityConfig {
@Autowired
private NegotiateSecurityFilter negotiateSecurityFilter;
@Autowired
private NegotiateSecurityFilterEntryPoint entryPoint;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.cors()
.and().authorizeHttpRequests().anyRequest().authenticated()
.and().httpBasic().authenticationEntryPoint(entryPoint)
.and().csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and().addFilterAfter(negotiateSecurityFilter, BasicAuthenticationFilter.class);
return http.build();
}
}
I have tried changing the HTTP configuration by moving the CSRF filter up or down and using "addFilterBefore" or "addFilterAfter", but it did not alter the filter chain order. Since the CSRF filter is added automatically by Spring Security, I am not sure how to change its order. Any guess?