HttpComponents HttpClient
  1. HttpComponents HttpClient
  2. HTTPCLIENT-1215

http://host and http://host:80 not considered the same for credential matching

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 4.2.1
    • Fix Version/s: 4.2.2
    • Component/s: HttpClient
    • Labels:
      None

      Description

      the following code (taken from http://hc.apache.org/httpcomponents-client-ga/tutorial/html/authentication.html section 4.8 and modified to use a URI) will not add authentication headers to the outgoing http request because the URI string does not explicitely specify the port:

      URI uri = new URI("http://somedomain.com/stuff");
      HttpHost targetHost = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());

      DefaultHttpClient httpclient = new DefaultHttpClient();

      httpclient.getCredentialsProvider().setCredentials(
      new AuthScope(targetHost.getHostName(), targetHost.getPort()),
      new UsernamePasswordCredentials("username", "password"));

      // Create AuthCache instance
      AuthCache authCache = new BasicAuthCache();
      // Generate BASIC scheme object and add it to the local auth cache
      BasicScheme basicAuth = new BasicScheme();
      authCache.put(targetHost, basicAuth);

      // Add AuthCache to the execution context
      BasicHttpContext localcontext = new BasicHttpContext();
      localcontext.setAttribute(ClientContext.AUTH_CACHE, authCache);

      HttpGet httpget = new HttpGet(uri);
      for (int i = 0; i < 3; i++)

      { HttpResponse response = httpclient.execute(targetHost, httpget, localcontext); System.err.println(response.getStatusLine()); HttpEntity entity = response.getEntity(); EntityUtils.consume(entity); }

      the root cause for this is in RequestAuthCache.java line 90:

      HttpHost target = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
      if (target.getPort() < 0)

      { SchemeRegistry schemeRegistry = (SchemeRegistry) context.getAttribute( ClientContext.SCHEME_REGISTRY); Scheme scheme = schemeRegistry.getScheme(target); target = new HttpHost(target.getHostName(), scheme.resolvePort(target.getPort()), target.getSchemeName()); }

      AuthState targetState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);
      if (target != null && targetState != null && targetState.getState() == AuthProtocolState.UNCHALLENGED) {
      AuthScheme authScheme = authCache.get(target);
      if (authScheme != null)

      { doPreemptiveAuth(target, authScheme, targetState, credsProvider); }

      }

      the target has no port (meaning <0 ), so its recreated with the default http scheme port of 80.
      meanwhile authCache uses the original target host as key, and so authScheme will be null.
      explicitely declaring port 80 in the URI string works around this, but i think this should work by default.

        Issue Links

          Activity

          Hide
          Oleg Kalnichevski added a comment -

          Aside from the documentation being obviously wrong I am not sure what the best fix for the problem could be. I am somewhat reluctant to have to do multiple lookups and am leaning towards making AuthCache implementations require HttpHost keys to have an explicit port number.

          Oleg

          Show
          Oleg Kalnichevski added a comment - Aside from the documentation being obviously wrong I am not sure what the best fix for the problem could be. I am somewhat reluctant to have to do multiple lookups and am leaning towards making AuthCache implementations require HttpHost keys to have an explicit port number. Oleg
          Hide
          Radai Rosenblatt added a comment -

          or make the auth cache aware of default ports?
          if memory serves, auth cache is expected to find the "narrowest matching credentials" anyway, right? or was it some higher-level component?

          Show
          Radai Rosenblatt added a comment - or make the auth cache aware of default ports? if memory serves, auth cache is expected to find the "narrowest matching credentials" anyway, right? or was it some higher-level component?
          Hide
          Oleg Kalnichevski added a comment -

          > or make the auth cache aware of default ports?

          Which would entail having to hard couple it with SchemeRegistry

          > if memory serves, auth cache is expected to find the "narrowest matching credentials" anyway, right?

          I believe you are confusing it with BasicCredentialsProvider.

          Oleg

          Show
          Oleg Kalnichevski added a comment - > or make the auth cache aware of default ports? Which would entail having to hard couple it with SchemeRegistry > if memory serves, auth cache is expected to find the "narrowest matching credentials" anyway, right? I believe you are confusing it with BasicCredentialsProvider. Oleg
          Hide
          Radai Rosenblatt added a comment - - edited

          ok then, how about having some higher-up component that has access to both SchemeRegistry and the auth cache "pad" the cache with the "verbose" version of any credentials it already contains?

          Show
          Radai Rosenblatt added a comment - - edited ok then, how about having some higher-up component that has access to both SchemeRegistry and the auth cache "pad" the cache with the "verbose" version of any credentials it already contains?
          Hide
          Oleg Kalnichevski added a comment -

          Probably all it really takes is a map of default ports keyed by scheme generated based on content of a SchemeRegistry.

          Oleg

          Show
          Oleg Kalnichevski added a comment - Probably all it really takes is a map of default ports keyed by scheme generated based on content of a SchemeRegistry. Oleg
          Hide
          Oleg Kalnichevski added a comment -

          I fixed the problem in both trunk and 4.2.x. The fix in trunk relies on SchemeRegistry to resolve default ports. The fix in 4.2.x uses simple translation (443 for https, 80 for all others).

          Please re-test your application against the latest SVN snapshot.

          Oleg

          Show
          Oleg Kalnichevski added a comment - I fixed the problem in both trunk and 4.2.x. The fix in trunk relies on SchemeRegistry to resolve default ports. The fix in 4.2.x uses simple translation (443 for https, 80 for all others). Please re-test your application against the latest SVN snapshot. Oleg

            People

            • Assignee:
              Unassigned
              Reporter:
              Radai Rosenblatt
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development