Search code examples
spring-bootspring-securitycsrfsamesitecross-site

SpringBoot - How I can configure samesite none Csrf Cookie (Spring Security 6.2)


What I have:

  • I have sprint boot api, and angular app in diferents domains (not subdomains), and is not an option change it.
  • I only grant access by cors to my angular domain app.

What I need:

  • I need use Csrf cookie with samesite=none to allow authentication from Chrome browser, beacuse it doesn't work, I think because of default samesite=lax default policy. In firefox is working ok.

What I tried

  • I have updated to spring 2.7 to try use server.servlet.session.cookie.same-site= none property, but it only affect to JSESSIONID cookie. It didn`t work with csrf cookie.
  • I have updated to spring 3 to try use CookieCsrfTokenRepository.setCookieCustomizer() method, I can`t found information about I can use this method to configure the cookie
  • I tried to implement OncePerRequestFilter and modied header Set-cookie, but then, I lost the set-cookie header of JSESSIONID cookie.

¿What i can do to get csrf cookie samesite=none? ¿Is there other solution to run csrf authentication in chrome with diferents domains?

Thanks in advance


Solution

  • I found the solution

    1. First, create a custom CookieCsrfTokenRepository using setCookieCustomizer metohd with a Consumer<ResponseCookie.ResponseCookieBuilder>
            CookieCsrfTokenRepository tokenRepository = new CookieCsrfTokenRepository();
            tokenRepository.setCookieCustomizer(new Consumer<ResponseCookie.ResponseCookieBuilder>() {
                
                @Override
                public void accept(ResponseCookieBuilder t) {
                    t.sameSite("none");
                    t.secure(true);
                    t.httpOnly(false); //Js can read
                }
            });
    
    
    1. Apply at filterChain(HttpSecurity http) method:
    
    @Configuration
    @EnableWebSecurity
    public class SecurityJavaConfig {
    @Bean
        public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
            
            //Configuramos el Csrf Token repository para tener una cookie cross domnain
            CookieCsrfTokenRepository tokenRepository = new CookieCsrfTokenRepository();
            tokenRepository.setCookieCustomizer(new Consumer<ResponseCookie.ResponseCookieBuilder>() {
                
                @Override
                public void accept(ResponseCookieBuilder t) {
                    t.sameSite(csrfSameSiteCookie);
                    t.secure(csrfSecureCookie);
                    t.httpOnly(false); //Para que js pueda leer la cookie
                }
            });        
            
            http
                .cors((cors) -> cors.configurationSource(corsConfigurationSource()))
                .csrf((csrf) -> csrf
                        .csrfTokenRepository(tokenRepository)
                )
                .sessionManagement(session  -> session.sessionCreationPolicy(SessionCreationPolicy.ALWAYS))
                //Autorizaciones end-points
                .authorizeHttpRequests((authorize) -> authorize
                        .requestMatchers(HttpMethod.OPTIONS,"/**").permitAll()
                        .requestMatchers(HttpMethod.GET,"/csrf").permitAll()
                        .anyRequest().authenticated()
                )
                .httpBasic(withDefaults());;
    
     
            return http.build();
        }
    }