开发者

Full authentication is required to access this resource after enable CSRF

开发者 https://www.devze.com 2022-12-07 20:43 出处:网络
stack: Java spring boot, svelte I received message "403 Full authentication is required to access this resource" after I 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

  1. 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"
     }
    
  2. 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

  1. 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()
    
  2. I add GET /csrf for collecting CSRF token

    @RestController
    public class CsrfController {
    
        @GetMapping("/csrf")
        public CsrfToken csrf(CsrfToken token) {
            return token;
        }
    }
    
  3. 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);
      });
    }
    
  4. 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

  1. Assign credentials to request header
    fetch(isUrl(url) ? url : `${apiBaseURL}${url}`, {
        method: 'post',
        headers: `${headers}`,
        credentials: 'include',
        body: body ? JSON.stringify(body) : (body || null),
    })
    
  2. 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;
     }
    
0

精彩评论

暂无评论...
验证码 换一张
取 消