wthamira
wthamira

Reputation: 2250

Spring webflux with jwt + csrf token

I need to implement CSRF protection to my backend. I am using the below configurations. But applications allow Post and Get requests without CSRF token.

@Slf4j
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SecurityConfig {

    @Bean
    SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        http
                .csrf(csrf -> csrf.csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse()))
                .authorizeExchange()
                .anyExchange().authenticated()
                .and().oauth2ResourceServer().jwt();
        return http.build();
    }
}

include the actual CSRF token in the HTTP request

 @ControllerAdvice
    public class SecurityControllerAdvice {
        @ModelAttribute
        Mono<CsrfToken> csrfToken(ServerWebExchange exchange) {
            Mono<CsrfToken> csrfToken = exchange.getAttribute(CsrfToken.class.getName());
            return csrfToken.doOnSuccess(token -> {
                exchange.getAttributes()
                        .put(CsrfRequestDataValueProcessor.DEFAULT_CSRF_ATTR_NAME, token);
            });
        }
    }

I tried the API using postman. But this is not working for me.

Spring version

 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.3</version>
        <relativePath/>
   </parent> 

Dependencies:

<dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-resource-server</artifactId>
            <version>RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-jose</artifactId>
            <version>RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

Final target: My frontend is Vuejs + nuxtjs. Can someone help me to find the best way for implement this?

Upvotes: 2

Views: 1465

Answers (1)

Marcus Hert da Coregio
Marcus Hert da Coregio

Reputation: 6248

By using the oauth2ResourceServer() DSL, you are telling Spring Security that you are not using cookie-based authentication, therefore you do not need CSRF protection.

If you take a look at the OAuth2ResourceServerConfigurer#registerDefaultCsrfOverride you will notice that it doesn't apply the CSRF token validation to requests that contain a Bearer token, by using the BearerTokenRequestMatcher.

private void registerDefaultCsrfOverride(H http) {
    CsrfConfigurer<H> csrf = http.getConfigurer(CsrfConfigurer.class);
    if (csrf != null) {
        csrf.ignoringRequestMatchers(this.requestMatcher);
    }
}

CSRF exploits the browser behavior that automatically attaches the Cookies for the request, so I can trick users from my website www.malicioussite.example to click on a button and send a request to www.fakebank.example/transferMoneyToMe.

When you are using the Authorization header to send the JWT, the browser does not know about the access token, and therefore, will not attach the header automatically.

You can dive more deeply into this behavior starting from this answer https://security.stackexchange.com/questions/189326/do-i-need-csrf-protection-in-this-setup-with-a-rest-api-backed-with-oauth2-and-a

Upvotes: 8

Related Questions