Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8306745

Authorization header is removed when a prox Authenticator is set on HttpClient

XMLWordPrintable

    • b15
    • 17
    • generic
    • generic

      A DESCRIPTION OF THE PROBLEM :
      I am using the java.net.http.HttpClient to access a service that requires preemptive authentication.
      I also configure an HTTP proxy with regular/challenge authentication.
      Last important point is that I am doing an async request.

      I found in the JDK code this code plus comment:

          // Headers that are not generally restricted, and can therefore be set by users,
          // but can in some contexts be overridden by the implementation.
          // Currently, only contains "Authorization" which will
          // be overridden, when an Authenticator is set on the HttpClient.
          // Needs to be BiPred<String,String> to fit with general form of predicates
          // used by caller.

          public static final BiPredicate<String, String> CONTEXT_RESTRICTED(HttpClient client) {
              return (k, v) -> !client.authenticator().isPresent() ||
                      (!k.equalsIgnoreCase("Authorization")
                              && !k.equalsIgnoreCase("Proxy-Authorization"));
          }

      So from what I understand, as soon as you declare an Authenticator on the HttpClient (in my case to be used only for proxy authentication), then it is not possible to use preemptive authentication anymore, which is bad for my needs.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Create an HTTPClient with a ProxySelector and an Authenticator that is only returning credentials if requestorType is proxy:

      var httpClient = java.net.http.HttpClient.newBuilder()
            .version(java.net.http.HttpClient.Version.HTTP_1_1)
            .proxy(new ProxySelector() {
              @Override
              public List<Proxy> select(URI uri) {
                // In my code, get the real list of proxies
                return List.of();
              }

              @Override
              public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {

              }
            })
            .authenticator(new Authenticator() {
              @Override
              protected PasswordAuthentication getPasswordAuthentication() {
                if (getRequestorType() != RequestorType.PROXY) {
                  // We only handle proxy authentication here
                  return null;
                }
                // Simplified code
                return new PasswordAuthentication(proxyUser, proxyPassword);
              }
            })
            .build();
      2. Send an async request with user defined Authorization headers:

      var request = HttpRequest.newBuilder().uri(URI.create(url))
        .setHeader("Authorization", "Basic " + credentialsEncoded);

      httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofInputStream());

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      User defined Authorization header is send to the server.
      ACTUAL -
      No Authorization header sent (checked with Wireshark).

      CUSTOMER SUBMITTED WORKAROUND :
      Could not find one so far.

      FREQUENCY : always


            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: