1

I'm trying to send a simple GET to an HTTP endpoint with java.net.http.HttpClient. The endpoint requires basic authentication. Simple enough, I'm doing what everyone's doing:

HttpClient httpClient = HttpClient.newBuilder()
                                  .version(HttpClient.Version.HTTP_1_1)
                                  .authenticator(new Authenticator(){
                                    @Override
                                    protected PasswordAuthentication getPasswordAuthentication() {
                                      return new PasswordAuthentication("guest","guest".toCharArray());
                                    }
                                   })
                                  .build();
HttpRequest request = HttpRequest.newBuilder()
                                 .GET()
                                 .uri(URI.create("localhost:15672/api/overview")
                                 .build();
HttpResponse<Void> httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.discarding());

However, this throws an IOException "WWW-Authenticate header missing for response code 401". It is not completely unreasonable to me that the server initially responds with 401 and the client then re-tries the request with the help of the Authenticator. The header is mandatory and if it is absent, that warrants an exception.

So far, so good. However, when I do the same request via curl, the header is present:

> curl -i http://localhost:15672/api/overview
HTTP/1.1 401 Unauthorized
content-length: 0
content-security-policy: script-src 'self' 'unsafe-eval' 'unsafe-inline'; object-src 'self'
date: Thu, 08 Jul 2021 11:06:45 GMT
server: Cowboy
vary: origin
www-authenticate: Basic realm="RabbitMQ Management"

What am I doing wrong here?

Johannes Hahn
  • 363
  • 3
  • 18

2 Answers2

0

In the mean time I found out what the problem was: The server I'm contacting is buggy. The first GET returned exactly what is shown as the curl result. The Java HttpClient reacted correctly and sent a second GET with credentials. The credentials were wrong (for testing purposes) but the response was not a 403 as one would expect, but another 401 and this second 401 response is the one missing the header.

Johannes Hahn
  • 363
  • 3
  • 18
-1

For basic authorization, you can do

String plainCreds = "myuser:mypassword";
byte[] base64Bytes = Base64.encodeBase64(plainCreds.getBytes());

HttpRequest request = HttpRequest.newBuilder()
   .get()
   .uri(URI.create("localhost:15672/api/overview"))
   .header("Authorization", "Basic " + new String(base64Bytes))
   .build();
lance-java
  • 25,497
  • 4
  • 59
  • 101
  • I know, but I want to know why my approach does not work. The Java Http Client should do this automatically if I understand correctly. It also does not explain why I'm getting the exception. – Johannes Hahn Jul 08 '21 at 12:45
  • I believe you should be using [BasicCredentialsProvider](https://www.baeldung.com/httpclient-4-basic-authentication) instead of PasswordAuthentication – lance-java Jul 08 '21 at 14:59
  • That is for the Apache HttpClient, not the JDK one – Johannes Hahn Jul 08 '21 at 19:48