2

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.

0

1 Answer 1

3

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=""
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.