Reactive Security with Spring Security and WebFlux

๐Ÿ“‘ Table of Contents:

  1. Why Reactive Security?
  2. Spring Security + WebFlux Basics
  3. Dependencies for Reactive Security
  4. Creating a Reactive Security Configuration
  5. Adding JWT Support
  6. Custom Authentication Manager
  7. Securing Routes Based on Roles
  8. Final Thoughts
Reactive Security with Spring WebFlux

๐Ÿ” 1. Why Reactive Security?

Traditional FilterChain-based security wonโ€™t work effectively in a reactive pipeline. Spring Security for WebFlux provides a reactive security chain using non-blocking authentication, authorization, and session handling.

Benefits:

  • Works with Mono/Flux pipelines
  • Stateless JWT support
  • Non-blocking security filters

๐Ÿงฑ 2. Spring Security + WebFlux Basics

Spring Security introduces a different model for reactive apps:

  • SecurityWebFilterChain replaces HttpSecurity
  • Stateless by default
  • Can use ReactiveAuthenticationManager

๐Ÿ“ฆ 3. Dependencies for Reactive Security



  org.springframework.boot
  spring-boot-starter-security


  org.springframework.boot
  spring-boot-starter-webflux


  io.jsonwebtoken
  jjwt
  0.9.1


๐Ÿงฉ 4. Creating a Reactive Security Configuration


package com.kscodes.springboot.reactive.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        return http
                .csrf(ServerHttpSecurity.CsrfSpec::disable)
                .authorizeExchange(exchanges -> exchanges
                    .pathMatchers("/auth/**").permitAll()
                    .anyExchange().authenticated()
                )
                .httpBasic().disable()
                .formLogin().disable()
                .build();
    }
}

๐Ÿ” 5. Adding JWT Support

Token Utility


package com.kscodes.springboot.reactive.util;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;

public class JwtUtil {
    private static final String SECRET_KEY = "kscodesSecretKey";

    public static String generateToken(String username) {
        return Jwts.builder()
            .setSubject(username)
            .setIssuedAt(new Date())
            .setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1 hr
            .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
            .compact();
    }

    public static String extractUsername(String token) {
        return Jwts.parser()
            .setSigningKey(SECRET_KEY)
            .parseClaimsJws(token)
            .getBody()
            .getSubject();
    }
}

๐Ÿ‘ฎโ€โ™‚๏ธ 6. Custom Authentication Manager


package com.kscodes.springboot.reactive.security;

import com.kscodes.springboot.reactive.util.JwtUtil;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.web.server.authentication.ServerAuthenticationConverter;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.List;

@Component
public class JwtAuthenticationConverter implements ServerAuthenticationConverter {

    @Override
    public Mono convert(org.springframework.web.server.ServerWebExchange exchange) {
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        if (token != null && token.startsWith("Bearer ")) {
            String username = JwtUtil.extractUsername(token.substring(7));
            return Mono.just(
                new UsernamePasswordAuthenticationToken(
                    username, null, List.of(new SimpleGrantedAuthority("ROLE_USER"))
                )
            );
        }
        return Mono.empty();
    }
}

You can inject this converter using .authenticationManager(...) in the filter chain.

๐Ÿ”’ 7. Securing Routes Based on Roles


.authorizeExchange(exchanges -> exchanges
    .pathMatchers("/auth/**").permitAll()
    .pathMatchers("/admin/**").hasRole("ADMIN")
    .anyExchange().authenticated()
)

โœ… 8. Final Thoughts

Reactive Security with Spring WebFlux is a powerful way to secure APIs while staying fully non-blocking. With JWT, custom filters, and fine-grained route protection, your application will remain scalable and secure.

References

Spring Security Official Docs