New Update
After being encouraged to implement debug logs, I have discovered that the issue lies with Spring reporting an invalid CSRF token for the notices controller. I have compared the headers generated by Postman and the fetch requests, but found no discrepancies. The token is successfully placed into the request header, yet nothing significant is appearing in the Spring logs, so the debugging process continues.
Currently, I am delving into learning Spring Security and connecting the React frontend to the Spring backend. I am facing challenges as the POST
request made to the desired endpoint results in a 401 error. I have ensured that CORS is properly configured and the endpoints are permitted, making this error confusing to me.
In essence, the process involves calling an endpoint /token
to acquire a CSRF token, and then calling /notices
while passing the token as a header. Using Postman works flawlessly, leading me to initially suspect a CORS issue. However, running the frontend on a different port also triggers a CORS block, indicating that the problem may lie elsewhere.
Additional information:
/notices
and/token
are bothPOST
operations.- Both the Spring backend and React frontend are operating on the same local machine.
- Error code 401 is being received.
The JavaScript code for the frontend call is as follows:
const debugNotices = () => {
let tokenData:any;
fetch('http://localhost:8080/token', {method:"POST"})
.then((response) => response.json())
.then((data) => tokenData = data).then((data:any) => fetch("http://localhost:8080/notices",
{
method:"POST",
headers: {
"X-XSRF-TOKEN": tokenData.token
}
}))
}
Below is the Spring security configuration:
@Bean
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http
.cors()
.configurationSource(new CorsConfigurationSource() {
@Override
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(Collections.singletonList("http://localhost:3000"));
config.setAllowedMethods(Collections.singletonList(("*")));
config.setAllowCredentials(true);
config.setAllowedHeaders(Collections.singletonList("*"));
config.setMaxAge(3600L);
return config;
}
})
.and()
.csrf()
.ignoringRequestMatchers("/contact", "/register", "/token")
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.securityContext()
.requireExplicitSave(false)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.authorizeHttpRequests()
.requestMatchers("/myAccount", "/myBalance", "/myLoans", "/myCards", "/user").authenticated()
.requestMatchers("/notices", "/contact", "/register", "/test", "/token").permitAll()
.and()
.httpBasic()
.and()
.formLogin();
return http.build();
}
I have attempted including
credentials:'include'
in the request body, but it triggers a login prompt that does not align with the intended direction.
Moreover, I have tried manually inserting the CSRF token instead of fetching it from the server, yielding the same unsuccessful outcome.
CORS has also been thoroughly tested to the best of my knowledge, and any attempts to access the endpoints from sources other than localhost:3000
are denied with an expected CORS error.