Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to customize the default unauthorized response body in Spring Security Webflux?

I'm starting a new project using Spring boot Webflux, but now i can't figure it out how to handle 401 responses.

I'd want to return a message body with the response code. The response code is OK and working as expected. Now, how do I inject the message body to give a more verbose and descriptive response as below.

{
    "statusCode": "401",
    "statusMessage": "Unauthorized",
    "timestamp": "Sun May 07 10:30:23 GMT 2023"
}

This is part of my spring security config class:

@Bean
public SecurityWebFilterChain securityFilterChain(ServerHttpSecurity http) {
    return http
            .cors().and()
            .csrf().disable()
            //Disable Sessions
            .securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
            // handlers for 401 to return a 401 status, message and timestamp

            //rest services don't have a login form
            .formLogin()
            .disable()
            .authorizeExchange()
            .pathMatchers("/api/v1/get-token").hasRole("API")
            .and()
            .httpBasic()
            .and()
            .build();
}

Everything works well, I just want to return a message body JSON not just the HTTP reponse code. Anyone?

like image 496
James Avatar asked Dec 31 '25 15:12

James


2 Answers

Provide one solution that use the entryPoint which is provided by security . The corresponding code snippet like following .

1.Custom a EntryPoint

public class CustomAuthenticationEntryPoint implements ServerAuthenticationEntryPoint {

    @Override
    public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException authException) {
        // Custom error message or response body
        String errorMessage = "Unauthorized. Please authenticate.";

        // Set the status code and response body
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        exchange.getResponse().getHeaders().add("Content-Type", "application/json");
        return exchange.getResponse().writeWith(Mono.just(exchange.getResponse().bufferFactory()
                .wrap(errorMessage.getBytes())));
    }
}
  1. Register the entrypoint
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {

    private final CustomAuthenticationEntryPoint authenticationEntryPoint;

    @Autowired
    public SecurityConfig(CustomAuthenticationEntryPoint authenticationEntryPoint) {
        this.authenticationEntryPoint = authenticationEntryPoint;
    }

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
        return http
                .exceptionHandling(t -> t.authenticationEntryPoint(authenticationEntryPoint))
                // Configure other security rules
                .build();
    }
}
like image 185
Peng Avatar answered Jan 02 '26 05:01

Peng


You could also use global exception handling to intercept AuthenticationException and return your custom response:

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(AuthenticationException.class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public CustomResponse handleAuthenticationException(AuthenticationException ex) {
        // Your custom response
        CustomResponse response = ...
        return response;
    }
}

You can alse return ResponseEntity<CustomResponse> from your handler, so that you can customize response headers if you need to

like image 21
kerbermeister Avatar answered Jan 02 '26 04:01

kerbermeister



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!