Joumen Harzli
Joumen Harzli

Reputation: 81

Cannot use Proxy Authentification with Https in Java

Description

I’m trying to connect to a web server that uses https through a proxy which requires authentication, but it doesn’t work.

The HttpsURLConnection class is sending the first request to open the tunnel without the « Proxy-Authorization » header even if forced.

In this case the server will return « 407 Proxy Authentication Required ».

The code to reproduce the problem

public class TestProxy {

  @Test
  public void testOne() throws IOException {

    final String PROXY_USERNAME = "username";
    final String PROXY_PASSWORD = "password";
    final String PROXY_HOSTNAME = "hostname";
    final int PROXY_PORT = 8080;

    Authenticator.setDefault(
        new Authenticator() {
          @Override
          public PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(PROXY_USERNAME, PROXY_PASSWORD.toCharArray());
          }
        });

    Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_HOSTNAME, PROXY_PORT));

    URL url = new URL("https://www.google.com");

    HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(proxy);

    assertNotEquals(407, connection.getResponseCode());

  }

  @Test
  public void testTwo() throws IOException {

    final String PROXY_USERNAME = "username";
    final String PROXY_PASSWORD = "password";
    final String PROXY_HOSTNAME = "hostname";
    final int PROXY_PORT = 8080;

    Authenticator.setDefault(
        new Authenticator() {
          @Override
          public PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(PROXY_USERNAME, PROXY_PASSWORD.toCharArray());
          }
        });

    Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_HOSTNAME, PROXY_PORT));

    URL url = new URL("https://www.google.com");

    HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(proxy);

    String userCredentials = PROXY_USERNAME + ":" + PROXY_PASSWORD;
    String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userCredentials.getBytes()));
    connection.setRequestProperty("Proxy-Authorization", basicAuth);

    assertNotEquals(407, connection.getResponseCode());

  }

}

The request sent

CONNECT www.google.com:443 HTTP/1.1
User-Agent: Java/1.8.0_162
Host: www.google.com
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Proxy-Connection: keep-alive

Possible cause

I think that this behavior is caused by the method sun.net.www.protocol.http.HttpURLConnection.sendCONNECTRequest() It creates a new « connect request » without adding the « Proxy-Authorization » header.

Workaround

The workaround is to connect to a http address at first so the proxy server will register the user agent and authorize connecting without adding Proxy-Authorization header

The jdk version is 1.8.0_181-b13.

Upvotes: 2

Views: 2701

Answers (1)

Joumen Harzli
Joumen Harzli

Reputation: 81

To be able to connect to webservice using https over a proxy we need to disable a system property.

This is required only for jdk > 8u11

See Disable Basic authentication for HTTPS tunneling

Setting the system preperty in the application will not work

  private void allowAuthenticationForHttps() {
    System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");
  }

it should be passed as a flag in the command line

-Djdk.http.auth.tunneling.disabledSchemes=""

Upvotes: 3

Related Questions