I am using JWT in my Spring Boot app. When I try to login from the Angular 6 client, I get the CORS error
Access to XMLHttpRequest at \'http://localhost:8082
Since message is about your preflight request i.e. OPTIONS
request,
I guess, you need to do two things on server side / Spring Boot code ,
attemptAuthentication
method as first check i.e. don't do real authentication for preflight requests, if (CorsUtils.isPreFlightRequest(httpServletRequest)) {
httpServletResponse.setStatus(HttpServletResponse.SC_OK);
return new Authentication() ; //whatever your token implementation class is - return an instance of it
}
CorsUtils is - org.springframework.web.cors.CorsUtils
.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
You can allow unauthorized OPTIONS requests too but I guess , that wouldn't be a good idea. Also, try to narrow down "/**" to specific URLs if possible.
I was also facing the same issue.When i tried from postman it worked fine but same call made from react app i faced issue.
Generally we disable cors in configuration while working with the spring security. But here you should allow it. Check the below code snippet.
Just added http.cors(); in below code
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtFilter jwtFilter;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(getPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().antMatchers("/secure/authenticate")
.permitAll().anyRequest().authenticated()
.and().exceptionHandling().and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);;
http.cors();
}
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder getPasswordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
}
I had a similar error and the problem was the name of the packages... Try to rename your packages in this model: groupId.artifactId.security.jwt
1) Create a bean returning CorsFilter
I did it in SecurityConfig
class which extends WebSecurityConfigurerAdapter
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final JwtTokenProvider jwtTokenProvider;
@Autowired
public SecurityConfig(JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
}
@Override
public void configure(HttpSecurity http) throws Exception {
//....
http.cors();
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("GET");
config.addAllowedMethod("POST");
config.addAllowedMethod("PUT");
config.addAllowedMethod("DELETE");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
2) Provide this CorsFilter
to the class extending SecurityConfigurerAdapter
public class JwtConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
private final JwtTokenProvider jwtTokenProvider;
public JwtConfigurer(JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
}
@Override
public void configure(HttpSecurity httpSecurity) throws Exception {
JwtTokenFilter jwtTokenFilter = new JwtTokenFilter(jwtTokenProvider);
httpSecurity.addFilterBefore(
new SecurityConfig(jwtTokenProvider).corsFilter(),
UsernamePasswordAuthenticationFilter.class);
httpSecurity.addFilterBefore(
jwtTokenFilter, UsernamePasswordAuthenticationFilter.class);
}
}
3) Add in method configure(HttpSecurity http) { /* ... */ http.cors(); }
in SecurityConfig
class
Shown in the first code snippet above.
i had the same problem, finally i only added httpRequest.cors();
at the end of configure method in the WebSecurityConfig class and it worked well, the explanation of why is :
explicitly the preflight requests are not excluded from authorization in Spring Security configuration. Remember that Spring Security secures all endpoints by default.
As a result, API expects an authorization token in the OPTIONS request as well.
Spring provides an out of the box solution to exclude OPTIONS requests from authorization checks:
The cors()
method will add the Spring-provided CorsFilter to the application context which in turn bypasses the authorization checks for OPTIONS requests.
for all details https://www.baeldung.com/spring-security-cors-preflight