Uploaded image for project: 'HttpComponents HttpClient'
  1. HttpComponents HttpClient
  2. HTTPCLIENT-1457

HttpClientBuilder.useSystemProperties() is incompatible with NTLM scheme

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 4.3.2
    • 4.3.3, 4.4 Alpha1
    • HttpClient (classic)
    • None
    • Client: JRE 5 - JRE 7
      Proxy: Squid with Winbind & NTLM authentication
      Auth server: Windows server 2003 / 2008

    Description

      I ran into this with NTLM proxy authentication.

      Summary:
      HttpClientBuilder.useSystemProperties() results in SystemDefaultCredentialsProvider being specified. SystemDefaultCredentialsProvider delegates authentication to java.net.Authenticator and always returns credentials as UsernamePasswordCredentials. NTLMScheme expects credentials to be an instance of NTCredentials.

      Note: This works in "plain old Java". That is: URL connections work through an NTLM authenticating proxy if the default java.net.Authenticator is set.

      NTLMScheme casts provided credentials to NTCredentials, generating an exception. The end result (for proxy auth) is a HTTP 407 status and the following log message:

      WARN org.apache.http.impl.auth.HttpAuthenticator - NTLM authentication error: Credentials cannot be used for NTLM authentication: org.apache.http.auth.UsernamePasswordCredentials

      Nitpick: NTLMScheme.authenticate() should guard the argument with an "instanceof" instead of catching a ClassCastException.

      The code boils down to this:
      java.net.Authenticator.setDefault(new Authenticator()
      {
      @Override
      protected PasswordAuthentication getPasswordAuthentication()
      {
      if (getRequestorType() == RequestorType.PROXY)
      {
      String prot = getRequestingProtocol().toLowerCase();
      String host = System.getProperty(prot + ".proxyHost", "");
      String port = System.getProperty(prot + ".proxyPort", "80");
      String user = System.getProperty(prot + ".proxyUser", "");
      String password = System.getProperty(prot + ".proxyPassword", "");

      if (getRequestingHost().equalsIgnoreCase(host))
      {
      if (port != null && port.equals(Integer.toString(getRequestingPort())))

      { return new PasswordAuthentication(user, password.toCharArray()); }

      }
      }
      return null;
      }
      });

      HttpClients.custom().useSystemProperties().build().execute(new HttpGet("http://example.com"));

      Workaround
      ===============
      This following works in my initial tests:
      class SystemDefaultCredentialsProviderFixed extends SystemDefaultCredentialsProvider
      {
      @Override
      public Credentials getCredentials(AuthScope authscope)
      {
      Credentials credentials = super.getCredentials(authscope);
      if (credentials != null && "NTLM".equals(authscope.getScheme()))

      { String domain = System.getProperty("http.auth.ntlm.domain"); credentials = new NTCredentials(credentials.getUserPrincipal().getName(), credentials.getPassword(), null, domain); }

      return credentials;
      }
      }

      HttpClients.custom().useSystemProperties().setDefaultCredentialsProvider(SystemDefaultCredentialsProviderFixed).build().execute(new HttpGet("http://example.com"));

      Attachments

        Activity

          People

            Unassigned Unassigned
            mgessel Mat Gessel
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: