I created simple Spring Boot 3.0 web service and configured Spring Security Oauth 2.0 authorization with Google/Github (https://www.wimdeblauwe.com/blog/2023/01/24/using-google-login-with-spring-boot-3-and-thymeleaf/ - example of similar app). Everything seems working and ok until I try to make requests not directly to back end but using front end (react). Then I get CORS exception in Get request with 302 code: "Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource."
I tried to handle this exception for several days for now, tried configurations from different resources I could find: setting beans corsConfigurationSource, securityFilterChain, webMvcConfigurer, implementing Filter, usage of Controller's annotation CrossOrigin. Nothing seems to work. In spring boot debug mode I see that request is sent with cors header: "Redirecting to http://localhost:8080/oauth2/authorization/github" if I have correct cors settings in my security config. But the last log says: "Redirecting to https://github.com/login/oauth/authorize..." and then I see error in browser about absence of Access-Control-Allow-Origin header.
@Configuration
public class WebSecurityConfig {
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(List.of("http://localhost:3000"));
configuration.setAllowedMethods(List.of("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH"));
configuration.setAllowedHeaders(List.of("*"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors()
.configurationSource(corsConfigurationSource())
.and()
.csrf()
.disable()
.authorizeHttpRequests()
.anyRequest()
.authenticated()
.and()
.oauth2Login();
return http.build();
}
}
Has someone managed to solve this problem? I am out of ideas. Maybe this thing isn't working in latest versions?
My bet is that your Spring application is a REST API you want to secure with OAuth2 access tokens, in which case it is an OAuth2 resource server, not an OAuth2 client like Thymeleaf pages in the article you link and this makes it a completely different use-case.
Responsibilities and security requirements are very different for clients and resource servers:
This means that login (and logout) are responsibility of the client, not of the resource server.
REST API should be configured as
http.oauth2ResourceServer()..., not as client like in your conf (implied by your dependencies andoauth2Login). The dependency to pull isspring-boot-starter-oauth2-resource-server, notspring-boot-starter-oauth2-client.oauth2Loginshould be handled by client, not by resource server. Two options there:I have written tutorials for all those scenarios (resource server, client, BFF, both resource server and Thymeleaf client in the same app, etc.) there.