-2

I am trying to set the minimal headers to allow CORS to the same machine on different ports. I am using the latest Spring Boot and Spring Security as of writing theses lines.

The documentation is poor and the examples are not extensive enough. There are plenty of examples for previous versions of Spring Security, but in version 5.7.x they changed the API, which means that all the examples are now outdated.

I find myself wasting too many hours on trying to figure out how to do things right, yet without success.

Below is my last try to configure CORS.

If any of you has any idea why ORIGIN headers are missing and how to enable them, that would be greatly appreciated.

package com.madas.restapi;

import java.util.Arrays;

import org.springframework.context.annotation.Bean;
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.header.writers.ContentSecurityPolicyHeaderWriter;
import org.springframework.security.web.header.writers.CrossOriginResourcePolicyHeaderWriter;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter.XFrameOptionsMode;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

@EnableWebSecurity
public class WebSecurityConfig {

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("http://localhost"));
        configuration.setAllowedMethods(Arrays.asList("GET","POST"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
    
    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .anyRequest().permitAll()
            )
            .headers(headers -> headers
                    .addHeaderWriter(new CrossOriginResourcePolicyHeaderWriter())
                    .addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN))
                    .addHeaderWriter(new ContentSecurityPolicyHeaderWriter("object-src localhost;"))
            );
        return http.build();
    }
}

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Asaf Gery
  • 35
  • 5
  • Well... if you are well experienced with Spring, then you might be right. If you are less experienced, my solution allows copy & paste, while yours requires more digging. I leave the decision up to the editors. I wonder whether this web site's purpose is to help all developers or whether its purpose is to make experienced developers feel good for having more experience than others... If we're here to help, I expect that the solution I provided here would be accepted rather than marked as duplicate, since it does not require as further digging as the question your referred to does. – Asaf Gery Sep 29 '22 at 14:14
  • 1
    However, CORS problems are the most often ask questions with the most answers. No need to ask again. But duplicates are not that bad, no reason to complain. – dur Sep 29 '22 at 21:02

2 Answers2

-1

You have to register your CORS config within the filterchain by using .cors(withDefaults()).

For more info check out this documentation.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
tickrate
  • 39
  • 3
-1

The problem with Spring Framework, is that every few versions they break their own API and invent a new way to do the same things. This practice makes Stack Overflow less useful, since it holds many historical solutions that worked for previous versions but no longer work.

So, the minimal way to enable CORS in Spring Security 5.7.3 (and probably all Spring 5.7.x versions), without any limitation on host/port, etc. (i.e. permit all), is as follows:

Configuration

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class RestConfig {
    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers(HttpMethod.GET, "/resource").permitAll();
        return http.build();
    }
}

Controller

...
@GetMapping("/resource")
@CrossOrigin(
        // Access-Control-Allow-Origin
        origins = { "*" },
        
        // Alternative to origins that supports more flexible originpatterns. 
        // Please, see CorsConfiguration.setAllowedOriginPatterns(List)for details.
        // originPatterns = { "" },   
        
        // Access-Control-Allow-Credentials
        allowCredentials = "false",
        
        // Access-Control-Allow-Headers
        allowedHeaders = { "*" },
        
        // Access-Control-Expose-Headers
        exposedHeaders = { "*" },
        
        // Access-Control-Max-Age
        maxAge = 60 * 30,
        
        // Access-Control-Allow-Methods
        methods = {RequestMethod.GET}
    )
public @ResponseBody ResponseEntity<CollectionModel<EntityModel<Resource>>> get() {
  ...
}
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Asaf Gery
  • 35
  • 5
  • *The problem with Spring Framework, is that every few versions they break their own API and invent a new way to do the same things.* This solution is available since version 4.2 (6 years ago). – dur Sep 19 '22 at 10:16
  • Could you please show a reference proving your point? As far as I have seen here all the answers here in Stack Overflow refer to the API prior to version 5.7 . – Asaf Gery Sep 29 '22 at 14:09