Toparvion
Toparvion

Reputation: 839

Proxy Authentication with JDK 11 HttpClient

I'm trying to use JDK 11 HttpClient to make requests through a corporate proxy which requires authentication by login and password. According to JDK's intro, I'm building an instance of client by means of:

HttpClient httpClient = HttpClient.newBuilder()
        .version(HTTP_1_1)
        .proxy(ProxySelector.of(new InetSocketAddress("proxy.mycompany.com", 3128)))
        .authenticator(authenticator)
        .build();

, where authenticator is:

Authenticator authenticator = new Authenticator() {
  @Override
  protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication("login", "password".toCharArray());
  }
};

And then I execute the request itself:

HttpRequest outRequest = HttpRequest.newBuilder()
        .version(HTTP_1_1)
        .GET()
        .uri(URI.create("https://httpwg.org/asset/http.svg")) // no matter which URI to request
        .build();
HttpResponse<String> inResponse = httpClient.send(outRequest, BodyHandlers.ofString());

But instead of valid response from the target server (https://httpwg.org) I receive HTTP 407 (Proxy Authentication Required), i.e. HttpClient does not use the provided authenticator.

I've tried various solutions mentioned here and here but none of them helped.

What is the correct way to make it work?

Upvotes: 11

Views: 13540

Answers (3)

pepemsk
pepemsk

Reputation: 21

Use

System.setProperty("jdk.http.auth.proxying.disabledSchemes", "");
System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");

Construct your http client with proxy selector and authenticator

HttpClient client = HttpClient.newBuilder()
    .authenticator(yourCustomAuthenticator)
    .proxy(yourCustomProxySelector)
    .build();

In your Authenticator override

@Override
protected PasswordAuthentication getPasswordAuthentication() {
    if (getRequestorType().equals(RequestorType.PROXY)) {
        return getPasswordAuthentication(getRequestingHost());
    } else {
        return null;
    }
}
protected PasswordAuthentication getPasswordAuthentication(String proxyHost) {
    // your logic to find username and password for proxyHost
    return new PasswordAuthentication(proxyUsername, proxyPassword.toCharArray());
    // or return null
}

Upvotes: 2

hbelmiro
hbelmiro

Reputation: 1027

You have to set the "Proxy-Authorization" header on the request.

HttpClient httpClient = HttpClient.newBuilder()
        .version(HTTP_1_1)
        .proxy(ProxySelector.of(new InetSocketAddress("proxy.mycompany.com", 3128)))
        .build();

String encoded = new String(Base64.getEncoder().encode("login:password".getBytes()));

HttpRequest outRequest = HttpRequest.newBuilder()
                                    .version(HTTP_1_1)
                                    .GET()
                                    .uri(URI.create("https://httpwg.org/asset/http.svg")) // no matter which URI to request
                                    .setHeader("Proxy-Authorization", "Basic " + encoded)
                                    .build();

Upvotes: 9

daniel
daniel

Reputation: 3288

By default, basic authentication with the proxy is disabled when tunneling through an authenticating proxy since java 8u111.

You can re-enable it by specifying -Djdk.http.auth.tunneling.disabledSchemes="" on the java command line.

See the jdk 8u111 release notes

Upvotes: 8

Related Questions