Hi folks,
I am using Commons HttpClient 3.1 and have hit a problem which leads to an
infinite loop inside the HttpMethodDirector.

While attempting an authentication against Exchange 2007, we were hitting a
strange 401 error which obviously points to an authentication problem,
however all previous tests using our code have worked. (we are successfully
talking to Exchange 2000/2003/2007 using webdav).

Upon investigation, the following lines from
org.apache.commons.httpclient.HttpMethodDirector came into play:

192 if (isAuthenticationNeeded(method)) { 193 if
(processAuthenticationResponse(method)) { 194 LOG.debug("Retry
authentication"); 195 retry = true; 196 } 197 }

Exchange responds to our initial method with a 401, and commons then calls
the processAuthenticationResponse(method), which subsequently
callsprocessWWWAuthChallenge:

729 authstate.setAuthAttempted(true); 730 Credentials credentials =
this.state.getCredentials(authscope); 731 if (credentials == null) {
732 credentials
= promptForCredentials(authscheme, method.getParams(), authscope); ... } if
(credentials == null) { if (LOG.isInfoEnabled()) { LOG.info("No credentials
available for " + authscope); } return false; } else { return true; }

The promptForCredentials method is then called (line 732) which requires an
instance of a org.apache.commons.httpclient.auth.CredentialsProvider
registered in the HttpParams of the method we are executing.

In our original case, we hadn't registered such a provider however when we
did, our 401 error went away and our method executed successfully.

However, this case worked because our credentials were correct. In the event
that the credentials are in-fact faulty, or indeed the appropriate
permissions are not set on the server, this sequence of processing
authentication never completes, and loops forever.

processAuthenticationResponse returns true simply if there are credentials
present. If they are, then the "retry" flag (line 195) in the main
executeMethod method is set to true, but no retry attempt indicator is
incremented. Hence the method continues to loop forever.

We have "solved" this by making our CredentialsProvider implementation
maintain an internal record of the number of times it has been called,
however on face value the code Commons HttpClient code does not appear to
deal with credentials that fail continuously.

Of course we could expect that the server will eventually respond with a
403, indicating that our authentication attempts have failed too many times,
but in the case of Exchange it never does this and simply continues to
return a 401.

I'm not sure if 3.1 is still being supported, however given that the 4.0
release is still beta we will be using 3.1 for quite some time yet I
suspect.

Thanks.

Reply via email to