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
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:
TokenRelay
filter to work (keep OAuth2 tokens associated with each browser session). As a consequence, CSRF must be enabled and, as your app is Javascript based, with Cookie repo (http.csrf().csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse());
on a reactive application like spring-cloud-gateway
). You'll then have to configure your frontend to send the CSRF token (received as cookie) as X-XSRF-TOKEN
header (same requirement for Postman if you want to send requests through the gateway instead of querying the API(s) directly). I wrote a complete guide on Baeldung.