Describe the bug Following the migration guide for reactive applications, I configured a WebFlux application with http.csrf().csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse()).csrfTokenRequestHandler(new XorServerCsrfTokenRequestAttributeHandler()::handle) and a WebFilter bean to "ensure the token is subscribed to", but I can't find any CSRF cookie anywhere in my browser debugging tools (neither with XSRF-TOKEN "standard" name, nor with any other name: the only cookie is the session one).

To Reproduce With this very simple Boot app:

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @EnableWebFluxSecurity
    @Configuration
    static class WebSecurityConf {
        @Bean
        SecurityWebFilterChain securityFilterChain(ServerHttpSecurity http, ServerProperties serverProperties) {
            http.oauth2Client();
            http.authorizeExchange().pathMatchers("/login/**", "/oauth2/**").permitAll().anyExchange().authenticated();
            http.oauth2Login();
            http.logout().logoutUrl("/logout");

            CookieServerCsrfTokenRepository tokenRepository = CookieServerCsrfTokenRepository.withHttpOnlyFalse();
            XorServerCsrfTokenRequestAttributeHandler delegate = new XorServerCsrfTokenRequestAttributeHandler();
            http.csrf().csrfTokenRepository(tokenRepository).csrfTokenRequestHandler(delegate::handle);
            return http.build();
        }

        @Bean
        WebFilter csrfCookieWebFilter() {
            return (exchange, chain) -> {
                Mono<CsrfToken> csrfToken = exchange.getAttributeOrDefault(CsrfToken.class.getName(), Mono.empty());
                return csrfToken.doOnSuccess(token -> {
                    System.out.println(token);
                }).then(chain.filter(exchange));
            };
        }
    }
}

This prints null and I have no CSRF cookie.

Expected behavior I expect a CSRF cookie to be set

Sample https://github.com/ch4mpy/gh-12871

Comment From: Shaquu

Relates to #12869

Comment From: ch4mpy

Relates to #12869

@Shaquu not exactly: my problem is not related CSRF token validation, it is I don't have a cookie at all.

Comment From: lglauer

@ch4mpy

If you are using a single-page app (SPA) to connect to a backend protected by Spring Security along with CookieCsrfTokenRepository.withHttpOnlyFalse(), you may find that the CSRF token is no longer returned to your application as a cookie on the first request to the server.

https://docs.spring.io/spring-security/reference/5.8/migration/servlet/exploits.html#_i_am_using_a_single_page_application_with_cookiecsrftokenrepository

Comment From: ch4mpy

@lglauer I had missed that part, thank you for pointing me to it. This works for servlets but, unfortunately, the doc seems to be missing something for reactive applications.

I updated the issue with what is in the migration guide for reactive apps (and I'm trying to configure a spring-cloud-gateway instance).

Comment From: ch4mpy

Found my issue: I had accidentally imported org.springframework.security.web.csrf.CsrfToken instead of org.springframework.security.web.server.csrf.CsrfToken which caused the WebFilter to fail retrieving the CSRF token from exchange attributes.