javaspring-bootspring-securityoauth-2.0csrf

How to generate and pass CSRF token for a route in spring cloud gateway with Spring Security


I'm trying to implement Oauth2 based authentication using Okta, Spring Cloud Gateway & Spring Security. The objective that I want to achieve is I want a route of spring cloud gateway to be available for all without any authentication. I know spring cloud gateway uses WebFlux. So according to that only I'm configuring Spring Security. I have three routes in spring cloud gateway.

I want any of these /auth/** routes should be available to all because here my users signup so I can not put authentication there. For the other two /doctors/** and /patients/** I want authentication and Authorisation. In the SecurityConfig in cloud gateway I'm trying to achieve the same. Currently I have made this config:

    package com.sb.projects.medica.gateway.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
    import org.springframework.security.config.web.server.ServerHttpSecurity;
    import org.springframework.security.web.server.SecurityWebFilterChain;
    
    @Configuration
    @EnableWebFluxSecurity
    public class SecurityConfig {
        @Bean
        public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity httpSecurity) {
            httpSecurity.authorizeExchange(exchanges -> {
                exchanges.pathMatchers("/doctor/**", "/patient/**").authenticated();
                exchanges.pathMatchers("/auth/**").permitAll();
            }).oauth2Client().and().oauth2ResourceServer().jwt();
            return httpSecurity.build();
        }
    }

But it does not seem to work. When I try to hit any route of /auth/** I get

An expected CSRF token cannot be found

How can I solve this error. How can I create a csrf token and send it to frontend


Solution

  • You are obviously just beginning your journey to CSRF configuration. I recommand you start with the Spring documentation. Like really. Read it carefully even before the rest of this answer.

    The REST API(s) behind the gateway can probably be configured as "stateless" (http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) in a servlet or http.securityContextRepository(NoOpServerSecurityContextRepository.getInstance()) in a reactive app) and, as a consequence, CSRF protection can be disabled on it (http.csrf().disable()). You then configure Postman with OAuth2 authorization and query the API directly (not through the gateway).

    Depending on your React frontend being configured as an OAuth2 public client or the gateway as a Backend For Frontend (OAuth2 confidential client with TokenRelay filter), the needs for CSRF protection are quite different: