0

I have a strange problem, I have a spring boot backend and angular frontend from localhost:4200

The csrf works perfectly from postman, but does not work from angular

I don't understand the problem, I did several tests

I don't use interceptors, I'm testing by obtaining the token directly, which I then reuse, from postman it works perfect

my securconfig.java

@Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.cors(cors -> cors.configurationSource(request -> {
            List<String> allowedOrigins = new ArrayList<>();
            allowedOrigins.add("http://localhost");
            allowedOrigins.add("http://localhost:4200");
            CorsConfiguration config = new CorsConfiguration();
            config.setAllowedOrigins(allowedOrigins);
            config.setAllowedMethods(Arrays.asList("GET", "POST", "PATCH", "DELETE"));
            config.setAllowedHeaders(Arrays.asList("*"));
            config.setAllowCredentials(true);
            return config;
        }))
                .authorizeHttpRequests((requests) -> requests
                        .requestMatchers(HttpMethod.OPTIONS, "/api/v1/**").permitAll()
                        .requestMatchers("/", "/home", "/public", "/actuator/**", "/api/v1/error", "/api/v1/login",
                                "/api/v1/csrf",
                                "swagger-ui.html", "/swagger-ui/**", "/v3/**")
                        .permitAll()
                        .anyRequest().authenticated())

                .formLogin((form) -> form
                        .loginPage("/api/v1/signin")
                        .permitAll())
                .logout((logout) -> logout.permitAll())

                .authenticationProvider(authenticationProvider())
                
                .csrf(csrf -> csrf
                        .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/api/v1/**", "POST"))
                         .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/api/v1/**",
                         "PATCH"))
                         .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/api/v1/**",
                         "DELETE"))
                        .ignoringRequestMatchers(new AntPathRequestMatcher("/api/v1/csrf", "POST"),
                                new AntPathRequestMatcher("/api/v1/login", "POST")))
                .addFilterBefore(authFilter, UsernamePasswordAuthenticationFilter.class)
                .exceptionHandling((exceptionHandling) -> exceptionHandling
                        .authenticationEntryPoint((request, response, authException) -> {
                            response.setContentType("application/json");
                            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                            response.getWriter().write("{ \"message\": \"Unauthorized\" }");
                        }));
        return http.build();
    }

angular request


  createProduct(
    id: string,
    name: string,
    description: string,
    idCategory: number,
    price: number
  ) {
    const bearerToken = this.bearerToken;
    const csrfUrl = 'http://localhost:8081/api/v1/csrf';

    this.http
      .post(csrfUrl, null, {
        headers: new HttpHeaders({
          Authorization: `Bearer ${bearerToken.trim()}`,
        }),
      })
      .subscribe(
        (response: any) => {
          const csrfToken = response.token.trim();


          const headers = new HttpHeaders({
            'Content-Type': 'application/json',
            'X-CSRF-TOKEN': csrfToken,
            Accept: '*/*',
            Authorization: `Bearer ${bearerToken.trim()}`,
          });

         
          const postData: Product = {
            id,
            name,
            description,
            idCategory,
            price,
          };

      
          this.http
            .post(`http://localhost:8081/api/v1/products/add`, postData, {
              withCredentials: true,
              headers,
            })
            .subscribe(
              (response) => {
                this.error.next(null);
                console.log('Product added successfully', response);
              },
              (error) => {
                console.error('Error adding product', error);
                this.error.next(error.message);
              }
            );
        },
        (error) => {
          console.error('Error fetching CSRF token', error);
          this.error.next(error.message);
        }
      );
  }

Please help me solve this problem

7
  • Can you try doing this in your backend config.setAllowedMethods(Arrays.asList("GET", "POST", "PATCH", "DELETE", "OPTIONS")); config.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type", "X-CSRF-TOKEN")); it might be because you are specifying specific header In your angular file Commented Jun 11, 2024 at 9:18
  • would be nice to see some error messages / stacktrace that you are getting Commented Jun 11, 2024 at 10:51
  • 401 Unauthorized, the csrf is not read/recognized, but only from angular Commented Jun 11, 2024 at 12:25
  • I can't undertand if the problem is angular, or localhost:4200 Commented Jun 11, 2024 at 12:29
  • if I add these 2 lines everything works, backend doesn't read the csrf that angular sends, .ignoringRequestMatchers(new AntPathRequestMatcher("/api/v1/csrf", "POST"), new AntPathRequestMatcher("/api/v1/products/add", "POST"))) Commented Jun 11, 2024 at 12:53

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.