Full authentication is required to access this resource after enable CSRF
stack: Java spring boot, svelte
I received message "403 Full authentication is required to access this resource" after I enable CSRF How do I check or debug which made that error?
Here is step that produce error
When I sign in application, web app send request to "GET {api server}/csrf"
this is response from endpoint{ "token":"d4cb2245-be82-4b61-ace5-8d52c6068182", "parameterName":"_csrf", "headerName":"X-XSRF-TOKEN" }
I collect response.token and add it to "X-XRF-TOKEN"
this is header when sending request to "POST {api server}/auth/signin" request header
I follow step 4. (4.1, 4.2) https://www.baeldung.com/spring-security-csrf
This is Security configure on my side
protected void configure(HttpSecurity http) throws Exception { http.cors().and().csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and() .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() .authorizeRequests() .antMatchers(HttpMethod.OPTIONS,"**").permitAll() .antMatchers("/csrf").permitAll() .antMatchers("/auth/**").permitAll() .anyRequest().authenticated(); http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAu开发者_如何学GothenticationFilter.class); }
It works if I set Security Config like this
http.csrf().disable()
I add GET /csrf for collecting CSRF token
@RestController public class CsrfController { @GetMapping("/csrf") public CsrfToken csrf(CsrfToken token) { return token; } }
For front-end side I add function which is fire the "/csrf"
function getCsrf(headers) { return request('/csrf', 'get', null, headers) .then(response => { return response; }); }
function post(url, data, headers) { return getCsrf(headers) .then(resp => { headers = { ...headers, 'X-XSRF-TOKEN': resp.token, } return request(url, 'post', data, headers); }); }
The way to prove that is not related with "Authorization" header. I was try to add "Authorization" to request header with valid token. I still got the same error
function post(url, data, headers) { return getCsrf(headers) .then(resp => { headers = { ...headers, 'X-XSRF-TOKEN': resp.token, 'Authorization': `Bearer ${token}` } return request(url, 'post', data, headers); }); }
Update 7 Dec 2022 11:58
I add logging.level.org.springframework.security=TRACE
I found some error message
2022-12-07 11:55:42,243 TRACE [XNIO-1 task-2] org.springframework.security.web.FilterChainProxy$VirtualFilterChain: Invoking WebAsyncManagerIntegrationFilter (1/13)
2022-12-07 11:55:42,243 TRACE [XNIO-1 task-2] org.springframework.security.web.FilterChainProxy$VirtualFilterChain: Invoking SecurityContextPersistenceFilter (2/13)
2022-12-07 11:55:42,243 DEBUG [XNIO-1 task-2] org.springframework.security.web.context.SecurityContextPersistenceFilter: Set SecurityContextHolder to empty SecurityContext
2022-12-07 11:55:42,244 TRACE [XNIO-1 task-2] org.springframework.security.web.FilterChainProxy$VirtualFilterChain: Invoking HeaderWriterFilter (3/13)
2022-12-07 11:55:42,244 TRACE [XNIO-1 task-2] org.springframework.security.web.FilterChainProxy$VirtualFilterChain: Invoking CorsFilter (4/13)
2022-12-07 11:55:42,244 TRACE [XNIO-1 task-2] org.springframework.security.web.FilterChainProxy$VirtualFilterChain: Invoking CsrfFilter (5/13)
2022-12-07 11:55:42,245 DEBUG [XNIO-1 task-2] org.springframework.security.web.csrf.CsrfFilter: Invalid CSRF token found for http://127.0.0.1:8080/auth/signin
2022-12-07 11:55:42,245 DEBUG [XNIO-1 task-2] org.springframework.security.web.access.AccessDeniedHandlerImpl: Responding with 403 status code
2022-12-07 11:55:42,245 TRACE [XNIO-1 task-2] org.springframework.security.web.header.writers.HstsHeaderWriter: Not injecting HSTS header since it did not match request to [Is Secure]
2022-12-07 11:55:42,246 DEBUG [XNIO-1 task-2] org.springframework.security.web.context.SecurityContextPersistenceFilter: Cleared SecurityContextHolder to complete request
look like I use invalid CSRF token. But how do I get the valid CSRF token?
Update 7 Dec 2022 12:38
I try send request via POSTMAN with this it works fine.
curl --location --request POST 'http://127.0.0.1:8080/auth/signin' \
--header 'X-XSRF-TOKEN: b05438d7-530a-48fa-9b11-11de56b5a87a' \
--header 'Content-Type: application/json' \
--header 'Cookie: XSRF-TOKEN=b05438d7-530a-48fa-9b11-11de56b5a87a' \
--data-raw '{....}'
Look like request that web api send doesn't contains "Cookie" in request header
I have resolved this by
- Assign credentials to request header
fetch(isUrl(url) ? url : `${apiBaseURL}${url}`, { method: 'post', headers: `${headers}`, credentials: 'include', body: body ? JSON.stringify(body) : (body || null), })
- Update CORS on back-end side
public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(Arrays.asList("http://127.0.0.1:3000")); configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")); configuration.setAllowedHeaders(Arrays.asList("*")); configuration.setExposedHeaders(Arrays.asList("*")); configuration.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; }
精彩评论