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?
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());
}