Search code examples
springspring-bootspring-webfluxspring-webclient

Spring Boot WebClient - Basic Auth (username & password) in URL (401)


I am trying to consume a REST API in my Spring Boot application using WebClient.

This particular API takes basic-auth username and password as parameters in the URL, in the format http://username:password@hostname:8080/api/route.

I am currently building the full URL including username, password and route and passing it to the webclient when I am making my request, but it appears like the WebClient is not correctly sending the authentication parameters.

My current setup is as follows:

URI url = new URI("http://username:password@hostname:8080/api/route");

WebClient.Builder webClientBuilder = WebClient.builder()
                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
        
WebClient webClient = webClientBuilder.build(); // I also have a customizer to add logging to the requests and responses

String requestBody = ""; // The body does not matter for this example

try {
            response = webClient.post()
            .uri(url)
            .bodyValue(requestBody)
            .retrieve()
            .bodyToMono(String.class)
            .toFuture()
            .get();
        } catch (Exception e) {
            logger.error(e.toString());
        }

I am receiving a 401 unauthorised every time I make a request using this setup. When I manually make the same request using the same URL in Postman I am able to receive an authorized response from the server. It seems to me like WebClient is stripping out the authentication parameters from the call.

I have a logging customizer (like this answer WebClient - how to get request body?) that logs the requests and response method, URI, body and headers. It is giving the URI as /api/route and the host header as host: localhost:8080. I cannot see from the output whether the authentication parameters are actually being passed to the server.

Does anyone know if there is something special I must do in order to pass authentication parameters as part of the URL in WebClient?


Solution

  • To pass basic authentication parameters in WebClient, you can use the BasicAuthenticationInterceptor class provided by Spring Security. Here's how you can modify your code to include basic authentication:

    URI url = new URI("http://hostname:8080/api/route");
    String username = "username";
    String password = "password";
    
    WebClient.Builder webClientBuilder = WebClient.builder()
            .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
            .filter(basicAuthentication(username, password));
    
    WebClient webClient = webClientBuilder.build();
    
    String requestBody = ""; // The body does not matter for this example
    
    try {
        String response = webClient.post()
                .uri(url)
                .bodyValue(requestBody)
                .retrieve()
                .bodyToMono(String.class)
                .block(); // Use block() instead of toFuture().get()
        
        // Process the response
    } catch (Exception e) {
        logger.error(e.toString());
    }