Home > Software engineering >  SpringBoot SpringSecurity 5.7.3 - can't set Origin headers properly
SpringBoot SpringSecurity 5.7.3 - can't set Origin headers properly

Time:09-19

I am trying to set the minimal headers to allow CORS to the same machine on different ports. I am using the latest SpringBoot and SpringSecurity as of writing theses lines. The documentation is poor and the examples are not extensive enough.

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

Bellow 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.

TIA, Asaf Gery

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();
    }
}

CodePudding user response:

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

For more info check out this documentation.

CodePudding user response:

As it happens most of the times, once I ask for help, I find the answer myself.

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() {
      ...
    }
  • Related