How to allow CrossOrigin from all domains? - spring-boot

Is there anyway to make this end point allow request from anywhere?
I've tried like but none of them worked.
#CrossOrigin(origins = "")
#CrossOrigin(origins = "http://")
#CrossOrigin(origins = "http://localhost:3001")
#GetMapping(path="/transactions")
public #ResponseBody List<RealEstateTransaction> getTransactions() {
return realEstateTransactionService.findTargets();
}

While working with cross domains, most of the time we tend to worry about what & where it went wrong. There are many factors including security, web components, sockets, etc to be handled at the server side before a request is processed. Many ways to implement the CORS in the Spring Boot application.
1. Annotation
By implementing #CrossOrigin like what you did in the Main class. Also can be done by adding #CrossOrigin to specific controllers/methods, if particular API should be accessed only from specific domain.
#CrossOrigin("*") // to allow from all domains
#CrossOrigin("http://localhost:3001") // to allow from specific domain
#CrossOrigin(origins = "http://localhost:3001")
2. WebConfig
If Spring Application is MVC where the resources could be accessed. Simply add the CORS mappings by overriding WebMvcConfigurer's addCorsMappings function.
#Configuration
#EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowedHeaders("*");
}
}
3. SecurityConfig
When security is enabled in the application then CORS must be implementated in the SecurityConfig. Registering the CORS filter can be done in many ways. One is adding UrlBasedCorsConfigurationSource to the http.cors() function. Another is to create CustomCorsFilter by extending the CorsFilter.
public class CustomCorsFilter extends CorsFilter {
public CustomCorsFilter() {
super(configurationSource());
}
public static UrlBasedCorsConfigurationSource configurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true);
configuration.addAllowedOrigin("*");
configuration.addAllowedHeader("*");
configuration.setMaxAge(3600L);
UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
corsConfigurationSource.registerCorsConfiguration("/**", configuration);
return corsConfigurationSource;
}
}
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
String[] paths = {"/auth/**", "/env"};
//http.cors().configurationSource(CustomCorsFilter.configurationSource()); // Option 1
http
.csrf().disable()
.exceptionHandling()
.authenticationEntryPoint(this.authenticationEntryPoint)
.and()
.authorizeRequests()
.antMatchers(paths)
.permitAll()
.and()
.authorizeRequests()
.antMatchers("/**")
.authenticated()
.and()
.addFilterBefore(new CustomCorsFilter(), UsernamePasswordAuthenticationFilter.class); //option 2
}

Related

Spring Security not working on any endpoint with multiple WebSecurityConfigurerAdapter implementations

I'm trying to setup Spring Security in my application, which has 3 components:
REST API (under v1 path)
Spring Admin & actuator (under /admin path)
Docs (under /docs and /swagger-ui paths)
I want to setup security like this:
REST API secured with JWT token
Admin secured with HTTP basic
Docs unsecured (public resource)
I've tried to configure authentication for those 3 parts in separate implementations of WebSecurityConfigurerAdapter, and the result looks like this:
For REST API:
#Configuration
#EnableWebSecurity
#Order(1)
class ApiWebSecurityConfig : WebSecurityConfigurerAdapter() {
// FIXME: Temporary override to disable auth
public override fun configure(http: HttpSecurity) {
http
.antMatcher("/v1/*")
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.anyRequest().permitAll()
.and()
.csrf().disable()
}
}
For Spring Admin:
#Configuration
#EnableWebSecurity
#Order(2)
class AdminWebSecurityConfig(
private val adminServerProperties: AdminServerProperties
) : WebSecurityConfigurerAdapter() {
public override fun configure(http: HttpSecurity) {
http.antMatcher("${adminServerProperties.contextPath}/**")
.authorizeRequests()
.antMatchers("${adminServerProperties.contextPath}/assets/**").permitAll()
.antMatchers("${adminServerProperties.contextPath}/login").permitAll()
.anyRequest()
.authenticated()
.and()
.cors()
.and()
.formLogin()
.loginPage("${adminServerProperties.contextPath}/login")
.and()
.logout()
.logoutUrl("${adminServerProperties.contextPath}/logout")
.and()
.httpBasic()
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringRequestMatchers(
AntPathRequestMatcher("${adminServerProperties.contextPath}/instances", HttpMethod.POST.toString()),
AntPathRequestMatcher("${adminServerProperties.contextPath}/instances/*", HttpMethod.DELETE.toString()),
AntPathRequestMatcher("${adminServerProperties.contextPath}/actuator/**")
)
}
#Bean
fun corsConfigurationSource(): CorsConfigurationSource = UrlBasedCorsConfigurationSource().apply {
registerCorsConfiguration("/**", CorsConfiguration().apply {
allowedOrigins = listOf("*")
allowedMethods = listOf("HEAD", "GET", "POST", "PUT", "DELETE", "PATCH")
allowCredentials = true
allowedHeaders = listOf("Authorization", "Cache-Control", "Content-Type")
})
}
}
And for public docs:
#Configuration
#EnableWebSecurity
#Order(3)
class DocsWebSecurityConfig : WebSecurityConfigurerAdapter() {
public override fun configure(http: HttpSecurity) {
http
.requestMatchers()
.antMatchers("/swagger-ui/**", "/docs/**", "/docs-oas3/**")
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
}
}
And my main application class looks like this:
#SpringBootApplication
#EnableAdminServer
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
#EnableConfigurationProperties(FirebaseConfigurationProperties::class, JwtConfigurationProperties::class)
class HldpDeviceManagementApplication
fun main(args: Array<String>) {
runApplication<HldpDeviceManagementApplication>(*args)
}
When I run the application, there's no error or any security information, besides this log output:
Will not secure Ant [pattern='/v1/**']
Will not secure Ant [pattern='/admin/**']
Will not secure Or [Ant [pattern='/swagger-ui/**'], Ant [pattern='/docs/**'], Ant [pattern='/docs-oas3/**']]
Any suggestion why doesn't the configuration work? Or maybe another way I can secure the application like this? I've tried doing a few changes in the configuration, but nothing seems to help.
I've found the problem - it's a bug in the latest version of Spring:
https://github.com/spring-projects/spring-security/issues/10909
You didn't mention when it doesn't work, is it when you make a request, or on application startup? However, I can help you with your configuration and get the information needed to solve the problem.
I'll try to simplify your configuration with the new way to configure HttpSecurity, by exposing a SecurityFilterChain bean.
#Configuration
public class SecurityConfiguration {
#Bean
#Order(0)
public SecurityFilterChain api(HttpSecurity http) throws Exception {
http
.requestMatchers(requests -> requests.antMatchers("/v1/**"))
...
// the rest of the configuration
return http.build();
}
#Bean
#Order(1)
public SecurityFilterChain admin(HttpSecurity http) throws Exception {
http
.requestMatchers(requests -> requests.antMatchers("/admin/**"))
...
// the rest of the configuration
return http.build();
}
#Bean
#Order(2)
public SecurityFilterChain docs(HttpSecurity http) throws Exception {
http
.requestMatchers(requests -> requests.antMatchers("/docs/**"))
...
// the rest of the configuration
return http.build();
}
}
This is in Java, but you can adapt to Kotlin easily, I'm sorry to not provide it in Kotlin already. With this simplified configuration, now you can add logging.level.org.springframework.security=TRACE to your application.properties file and check what Spring Security is doing by reading the logs.

oauth2 and basic auth

I use spring boot 2.4.6 with spring security.
Actually we use oauth 2
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private JwtAuthenticationConverter jwtAuthenticationConverter() {
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName("roles");
jwtGrantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
return jwtAuthenticationConverter;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues())
.and() // (1)
.authorizeRequests()
.antMatchers("/actuator/**").permitAll()
.antMatchers("/v2/api-docs").permitAll()
.anyRequest().authenticated() // (2)
.and()
.oauth2ResourceServer().jwt() // (3)
.jwtAuthenticationConverter(jwtAuthenticationConverter());
}
}
For some endpoint, I need to support a login / password.
Is there a way to do that?
You can set up multiple HttpSecurity instances, each matching one or more paths and implementing different authentication schemes. You can add them as separate inner classes extending from WebSecurityConfigurerAdapter. See docs for more information and an example.
Make sure to include an #Order if order matters. In your provided example, the config is generic and matches all requests, so it should be #Order(2). The additional config would be #Order(1) and start with http.antMatcher("/some/path/**").formLogin()... or similar.
Note: Similar (older) questions here and here.

Spring - CORS not working with Security Config

I develop an angular app with a spring webflux backend. Up so far, the CorsFilter worked fine and allowed requests from the frontend.
Then I added a SecurityConfig. Since then the CorsFilter stopped working and I get an exception in the angular app:
Access to XMLHttpRequest at 'http://localhost:8080/users/999/folders/%2F/media/' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource
This filter worked fine:
#Configuration
public class CorsFilter {
private static final String FRONTEND_LOCALHOST = "http://localhost:4200";
private static final String FRONTEND_STAGING = "https://somehost.github.io";
#Bean
CorsWebFilter corsWebFilter() {
CorsConfiguration corsConfig = new CorsConfiguration();
corsConfig.applyPermitDefaultValues();
corsConfig.addAllowedMethod(HttpMethod.PUT);
corsConfig.addAllowedMethod(HttpMethod.DELETE);
corsConfig.setAllowedOrigins(Arrays.asList(FRONTEND_LOCALHOST, FRONTEND_STAGING));
UrlBasedCorsConfigurationSource source =
new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfig);
return new CorsWebFilter(source);
}
}
Then I added authorization (bearer token) with following SecurityConfig:
#EnableWebFluxSecurity
#EnableReactiveMethodSecurity
public class SecurityConfiguration {
#Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http.cors().and().csrf()
.csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse())
.and()
.authorizeExchange()
.anyExchange().authenticated()
.and()
.oauth2ResourceServer()
.jwt();
return http.build();
}
It seems with the security config my CorsFilter is not taken into account anymore. I red that the corsfilter needs to be added explicity in the config, but the examples I found didnt work. I hope somebody can help and knows why.
EDIT: To address the duplication concerns: I already tried adding cors() and cors().configurationSource(corsConfig()) into my security config, but didnt helped either.
I found a working way in Enable CORS in Spring 5 Webflux? by implementing a custom corsfilter.
However I still wasnt happy with the solution as it looked quite like a workaround.
Finally I found the culprit(s)... one is quite embarassing. My posted SecurityConfig was in the wrong package (it was in the default package by accident) and for this reason the config didnt picked up.
Also the cors filter from the question started working when I pasted the code to the securityconfig.
So my final SecurityConfig looks like this:
import java.util.Arrays;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.csrf.CookieServerCsrfTokenRepository;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsConfigurationSource;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
#EnableWebFluxSecurity
#EnableReactiveMethodSecurity
public class SecurityConfiguration {
private static final String FRONTEND_LOCALHOST = "http://localhost:4200";
private static final String FRONTEND_STAGING = "https://somehost.github.io";
#Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http
.csrf()
.csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse())
.and()
.authorizeExchange()
.anyExchange().authenticated()
.and()
.oauth2ResourceServer()
.jwt();
return http.build();
}
#Bean
CorsConfigurationSource corsConfiguration() {
CorsConfiguration corsConfig = new CorsConfiguration();
corsConfig.applyPermitDefaultValues();
corsConfig.addAllowedMethod(HttpMethod.PUT);
corsConfig.addAllowedMethod(HttpMethod.DELETE);
corsConfig.setAllowedOrigins(Arrays.asList(FRONTEND_LOCALHOST, FRONTEND_STAGING));
UrlBasedCorsConfigurationSource source =
new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfig);
return source;
}
}
try add this config
corsConfig.setAllowCredentials(true);

Spring Boot #EnableResourceServer unexpected 401 Unauthorized error [duplicate]

I have created two web applications - client and service apps.The interaction between client and service apps goes fine when they are deployed in same Tomcat instance.
But when the apps are deployed into seperate Tomcat instances (different machines), I get the below error when request to sent service app.
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 401
My Client application uses JQuery, HTML5 and Bootstrap.
AJAX call is made to service as shown below:
var auth = "Basic " + btoa({usname} + ":" + {password});
var service_url = {serviceAppDomainName}/services;
if($("#registrationForm").valid()){
var formData = JSON.stringify(getFormData(registrationForm));
$.ajax({
url: service_url+action,
dataType: 'json',
async: false,
type: 'POST',
headers:{
"Authorization":auth
},
contentType: 'application/json',
data: formData,
success: function(data){
//success code
},
error: function( jqXhr, textStatus, errorThrown ){
alert( errorThrown );
});
}
My service application uses Spring MVC, Spring Data JPA and Spring Security.
I have included CorsConfiguration class as shown below:
CORSConfig.java:
#Configuration
#EnableWebMvc
public class CORSConfig extends WebMvcConfigurerAdapter {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("*");
}
}
SecurityConfig.java:
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
#EnableWebSecurity
#ComponentScan(basePackages = "com.services", scopedProxy = ScopedProxyMode.INTERFACES)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("authenticationService")
private UserDetailsService userDetailsService;
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
auth.authenticationProvider(authenticationProvider());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().fullyAuthenticated();
http.httpBasic();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.csrf().disable();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
}
Spring Security dependencies:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.2.3.RELEASE</version>
</dependency>
I am using Apache Tomcat server for deployment.
CORS' preflight request uses HTTP OPTIONS without credentials, see Cross-Origin Resource Sharing:
Otherwise, make a preflight request. Fetch the request URL from origin source origin using referrer source as override referrer source with the manual redirect flag and the block cookies flag set, using the method OPTIONS, and with the following additional constraints:
Include an Access-Control-Request-Method header with as header field value the request method (even when that is a simple method).
If author request headers is not empty include an Access-Control-Request-Headers header with as header field value a comma-separated list of the header field names from author request headers in lexicographical order, each converted to ASCII lowercase (even when one or more are a simple header).
Exclude the author request headers.
Exclude user credentials.
Exclude the request entity body.
You have to allow anonymous access for HTTP OPTIONS.
Spring Security 3
Your modified (and simplified) code:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers("/login").permitAll()
.anyRequest().fullyAuthenticated()
.and()
.httpBasic()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf().disable();
}
You still need your CORS configuration (probably with some additional values):
#Configuration
#EnableWebMvc
public class CORSConfig extends WebMvcConfigurerAdapter {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("*");
}
}
Spring Security 4
Since Spring Security 4.2.0 you can use the built-in support, see Spring Security Reference:
19. CORS
Spring Framework provides first class support for CORS. CORS must be processed before Spring Security because the pre-flight request will not contain any cookies (i.e. the JSESSIONID). If the request does not contain any cookies and Spring Security is first, the request will determine the user is not authenticated (since there are no cookies in the request) and reject it.
The easiest way to ensure that CORS is handled first is to use the CorsFilter. Users can integrate the CorsFilter with Spring Security by providing a CorsConfigurationSource using the following:
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
// by default uses a Bean by the name of corsConfigurationSource
.cors().and()
...
}
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
Spring Security 5/6
For Spring Security 5/6 see Spring Security Reference:
CORS
Spring Framework provides first class support for CORS. CORS must be processed before Spring Security, because the pre-flight request does not contain any cookies (that is, the JSESSIONID). If the request does not contain any cookies and Spring Security is first, the request determines that the user is not authenticated (since there are no cookies in the request) and rejects it.
The easiest way to ensure that CORS is handled first is to use the CorsFilter. Users can integrate the CorsFilter with Spring Security by providing a CorsConfigurationSource that uses the following:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig {
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// by default uses a Bean by the name of corsConfigurationSource
.cors(withDefaults())
...
return http.build();
}
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
With Spring Security 5/6 you don't need to configure CORS twice (Spring Security and Spring MVC):
If you use Spring MVC’s CORS support, you can omit specifying the CorsConfigurationSource and Spring Security uses the CORS configuration provided to Spring MVC:
Since Spring Security 4.1, this is the proper way to make Spring Security support CORS (also needed in Spring Boot 1.4/1.5):
#Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
}
}
and:
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
// http.csrf().disable();
http.cors();
}
#Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(ImmutableList.of("*"));
configuration.setAllowedMethods(ImmutableList.of("HEAD",
"GET", "POST", "PUT", "DELETE", "PATCH"));
// setAllowCredentials(true) is important, otherwise:
// The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
configuration.setAllowCredentials(true);
// setAllowedHeaders is important! Without it, OPTIONS preflight request
// will fail with 403 Invalid CORS request
configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
Do not do any of below, which are the wrong way to attempt solving the problem:
http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll();
web.ignoring().antMatchers(HttpMethod.OPTIONS);
Reference: http://docs.spring.io/spring-security/site/docs/4.2.x/reference/html/cors.html
In my case, I have Resource Server with OAuth security enabled and any of above solutions didn't work. After some debugging and googling figured why.
#Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
}
Basically in this example Ordered.HIGHEST_PRECEDENCE is key!
https://github.com/spring-projects/spring-security-oauth/issues/938
Various pom dependencies add different kinds of filters and therefore we could have issues based on order.
Add the below configuration in the main application. It worked me in spring boot application 2.3.1
package com.example.restservicecors;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
#SpringBootApplication
public class RestServiceCorsApplication {
public static void main(String[] args) {
SpringApplication.run(RestServiceCorsApplication.class, args);
}
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowedHeaders("*").allowedMethods("*");
}
};
}
}
Reference source: https://spring.io/guides/gs/rest-service-cors/
Since none of this posted examples helped me, I've taken things in my own knowledge.
In this method:
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration cors = new CorsConfiguration();
cors.setAllowedMethods(Arrays.asList("POST", "GET", "PUT", "HEAD", "DELETE"));
UrlBasedCorsConfigurationSource source = new
UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
CorsConfiguration by default have allowed method: POST, HEAD, GET, so PUT, DELETE will not work. What I did is I created a new instance of CorsConfiguration and set allowed methods:
cors.setAllowedMethods(Arrays.asList("POST", "GET", "PUT", "HEAD", "DELETE"));
so now my method looks like:
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration cors = new CorsConfiguration();
cors.setAllowedMethods(Arrays.asList("POST", "GET", "PUT", "HEAD", "DELETE"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", cors.applyPermitDefaultValues());
return source;
}
Of course, all other configuration is made by Spring documentation.
Try this:
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import java.util.Arrays;
import java.util.List;
#Component
public class CorsFilterConfig {
public static final List<String> allowedOrigins = Arrays.asList("*");
#Bean
public FilterRegistrationBean<CorsFilter> initCorsFilter() {
// #formatter:off
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.setAllowedHeaders(Arrays.asList("Authorization", "Cache-Control", "Content-Type"));
config.addAllowedMethod("*");
config.setAllowedOrigins(allowedOrigins);
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
// #formatter:on
}
}
You can easily add the #CrossOrigin annotation to allow all of them if you use UsernamePasswordAuthenticationFilter. And in the security configurations the http.cors().and(). This worked for me.
#CrossOrigin(origins = "*")
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final AuthenticationManager authenticationManager;
#Override
protected void configure(HttpSecurity http) throws Exception {
CustomAuthenticationFilter customAuthenticationFilter = new CustomAuthenticationFilter(authenticationManagerBean());
customAuthenticationFilter.setFilterProcessesUrl("/api/login");
http
.csrf().disable();
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// We can ant match out paths to the corresponding roles --> we allow certain roles to access certain API's
http
.cors()
.and();
http
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/**").permitAll();
...
This worked for: spring-boot-starter-parent 2.2.6.RELEASE
#Configuration
#EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowedHeaders("*").allowedMethods("*");
}
}
Change "*" to something meaningful in prod

How to turn off Spring Security in Spring Boot Application

I have implemented authentication in my Spring Boot Application with Spring Security.
The main class controlling authentication should be websecurityconfig:
#Configuration
#EnableWebSecurity
#PropertySource(value = { "classpath:/config/application.properties" })
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private RestAuthenticationSuccessHandler authenticationSuccessHandler;
#Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(
SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/logout").permitAll()
.antMatchers("/ristore/**").authenticated()
.anyRequest().authenticated()
.and()
.formLogin()
.successHandler(authenticationSuccessHandler)
.failureHandler(new SimpleUrlAuthenticationFailureHandler());
}
Since I am doing OAuth, I have AuthServerConfig and ResourceServerConfig as well. My main application class looks like this:
#SpringBootApplication
#EnableSpringDataWebSupport
#EntityScan({"org.mdacc.ristore.fm.models"})
public class RistoreWebApplication extends SpringBootServletInitializer
{
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*");
}
};
}
public static void main( String[] args )
{
SpringApplication.run(RistoreWebApplication.class, args);
}
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(RistoreWebApplication.class);
}
}
Since we are doing code consolidation, we need to turn off authentication temporarily. However, I tried the following methods and nothing seems to work. I am still getting 401 when I hit these rest api urls.
Comment out all the annotations in classes related to security including #Configuration, #EnableWebSecurity. In Spring boot Security Disable security, it was suggested at the bottom adding #EnableWebSecurity will DISABLE auth which I don't think make any sense. Tried it anyway, did not work.
Modify websecurityconfig by removing all the security stuff and only do
http
.authorizeRequests()
.anyRequest().permitAll();
Disable Basic Authentication while using Spring Security Java configuration. Does not help either.
Remove security auto config
#EnableAutoConfiguration(exclude = {
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration.class,
org.springframework.boot.actuate.autoconfigure.ManagementSecurityAutoConfiguration.class})
like what they did in disabling spring security in spring boot app. However I think this feature only works with spring-boot-actuator which I don't have. So didn't try this.
What is the correct way disable spring security?
As #Maciej Walkowiak mentioned, you should do this for your main class:
#SpringBootApplication(exclude = org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration.class)
public class MainClass {
try this
1->Comment annotation #EnableWebSecurity in your security config
//#EnableWebSecurity
2->Add these lines in your security config
spring.security.enabled=false
management.security.enabled=false
security.basic.enabled=false
What worked for me is this. Creating WebFilter and PermitAll Request Exchange and disabling CSRF.
#Bean
public SecurityWebFilterChain chain(ServerHttpSecurity http, AuthenticationWebFilter webFilter) {
return http.authorizeExchange().anyExchange().permitAll().and()
.csrf().disable()
.build();
}
Just put this code in #SpringBootApplication class, Like this and will work like charm
#SpringBootApplication
public class ConverterApplication {
public static void main(String[] args) {
SpringApplication.run(ConverterApplication.class, args);
}
#Bean
public SecurityWebFilterChain chain(ServerHttpSecurity http, AuthenticationWebFilter webFilter) {
return http.authorizeExchange().anyExchange().permitAll().and()
.csrf().disable()
.build();
}

Resources