Site icon Vinsguru

Spring WebFlux Security

Overview:

In this tutorial, I would like to demo Spring WebFlux Security – security for reactive web applications.

Sample Application:

Lets consider a simple application which has 3 API endpoints. We need to have the security as shown below.

Path Allowed Roles
/home/admin ADMIN
/home/user ADMIN, USER
/home/any N/A

Project Setup:

Create a Spring Boot project with these dependencies.

Spring WebFlux Security – API Controller:

I create a REST controller with below endpoints.

@RestController
@RequestMapping("home")
public class AuthController {

    @GetMapping("user")
    public Mono<String> userHome(){
        return Mono.just("user home");
    }

    @GetMapping("admin")
    public Mono<String> adminHome(){
        return Mono.just("admin home");
    }

    @GetMapping("any")
    public Mono<String> any(){
        return Mono.just("authenticated home");
    }

}

Spring WebFlux Security Configuration:

@EnableWebFluxSecurity
public class WebSecurityConfig {

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        http.authorizeExchange()
                .pathMatchers("/home/user").hasAnyRole("USER", "ADMIN")
                .pathMatchers("/home/admin").hasRole("ADMIN")
                .anyExchange()
                .authenticated()
                .and()
                .formLogin();
        return http.build();
    }

}

User Database:

I need a user database. I am using this map for this demo purpose.

@Configuration
public class UserDB {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Bean
    public Map<String, UserDetails> map(){
        return Map.of(
                "user", User.withUsername("user").password(passwordEncoder.encode("user")).roles("USER").build(),
                "admin", User.withUsername("admin").password(passwordEncoder.encode("admin")).roles("ADMIN").build(),
                "any", User.withUsername("any").password(passwordEncoder.encode("any")).authorities(Collections.emptyList()).build()
        );
    }

}

Reactive User Details Service:

This is the last important piece! We need to provide an implementation of ReactiveUserDetailsService. It needs to return user details based on the username.

@Service
public class UserDetailsServiceImpl implements ReactiveUserDetailsService {

    @Autowired
    private Map<String, UserDetails> map;

    @Override
    public Mono<UserDetails> findByUsername(String username) {
       return Mono.just(this.map.get(username));
    }

}

Spring WebFlux Security – Demo:

Start the application. Try to access any of the above configured endpoint. The application will automatically redirect you to the login page.

If we login as admin and try to access admin page, we get the appropriate response.

If we use the ‘any’ authenticated who does not have sufficient role, we get the below response.

@EnableReactiveMethodSecurity

If you do not like to configure the path matchers and roles, we can keep the security as simple as shown below.

@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class WebSecurityConfig {

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        http.authorizeExchange()
                .anyExchange()
                .authenticated()
                .and()
                .formLogin();
        return http.build();
    }

}

We could add the PreAuthorize/PostAuthorize annotations on the method to provide the similar behavior.

@GetMapping("user")
@PreAuthorize("hasRole('USER')")
public Mono<String> userHome(){
    return Mono.just("user home");
}

@GetMapping("admin")
@PreAuthorize("hasRole('ADMIN')")
public Mono<String> adminHome(){
    return Mono.just("admin home");
}

Summary:

We were able to successfully demonstrate the Spring WebFlux Security for our reactive web application.

Learn more about Spring WebFlux.

The source code is available here.

Happy learning 🙂

 

Share This:

Exit mobile version