I have a spring boot API hosted at Heroku and when I try to access it via a Angular app in Google Chrome (In Firefox it works fine) I'm facing the following problem:
It seems that the JSESSIONID cookie was blocked because it wasn't set to SameSite=None. But how can I set it as SameSite=None?
The following are my configuration classes:
SecurityConfig:
@Configuration
@EnableWebSecurity
@Order(SecurityProperties.DEFAULT_FILTER_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private ClienteUserDetailsService clienteUserDetailsService;
private static final String[] PUBLIC_MATCHERS = {"/login", "/logout", "/error.html", "/error"};
private static final String[] PUBLIC_MATCHERS_GET = {"/login", "/logout", "/error.html", "/error"};
private static final String[] PUBLIC_MATCHERS_POST = {"/login", "/logout"};
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.POST, PUBLIC_MATCHERS_POST).permitAll()
.antMatchers(HttpMethod.GET, PUBLIC_MATCHERS_GET).permitAll()
.antMatchers(PUBLIC_MATCHERS).permitAll()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.anyRequest().authenticated()
.and().formLogin()
.and().httpBasic()
.and().logout().logoutUrl("/logout").logoutSuccessHandler((new HttpStatusReturningLogoutSuccessHandler(HttpStatus.OK)))
.clearAuthentication(true).invalidateHttpSession(true)
.deleteCookies("JSESSIONID", "XSRF-TOKEN");
}
private CsrfTokenRepository getCsrfTokenRepository() {
CookieCsrfTokenRepository tokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
tokenRepository.setCookiePath("/");
return tokenRepository;
}
@Override
protected void configure(AuthenticationManagerBuilder builder) throws Exception {
builder.userDetailsService(clienteUserDetailsService)
.passwordEncoder(passwordEncoder());
}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("**")
.allowedOrigins("http://localhost:4200", "https://dogwalk-teste.web.app")
.allowedMethods("POST, GET, PUT, OPTIONS, DELETE, PATCH")
.allowCredentials(true);
}
};
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
CorsFilter:
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {
@Context
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers",
"X-PINGOTHER, Content-Type, X-Requested-With, Accept, Origin, Access-Control-Request-Method, "
+ "Access-Control-Request-Headers, Authorization, if-modified-since, remember-me, "
+ "x-csrf-token, x-xsrf-token, xsrf-token ");
response.addHeader("Access-Control-Expose-Headers", "xsrf-token");
response.addHeader("Access-Control-Allow-Headers", "x-csrf-token, x-xsrf-token");
response.setHeader("Set-Cookie", "locale=pt-BR; HttpOnly; Secure; SameSite=None;");
chain.doFilter(req, res);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}