Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTTPClient sends out two requests when using Basic Auth?

I have been using HTTPClient version 4.1.2 to try to access a REST over HTTP API that requires Basic Authentication. Here is client code:

DefaultHttpClient httpClient = new DefaultHttpClient(new ThreadSafeClientConnManager());
// Enable HTTP Basic Auth
httpClient.getCredentialsProvider().setCredentials(
    new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), 
    new UsernamePasswordCredentials(this.username, this.password));

HttpHost proxy = new HttpHost(this.proxyURI.getHost(), this.proxyURI.getPort());

httpClient.getParams().setParameter(ConnRouteParams.DEFAULT_PROXY, proxy);

When I construct a POST request, like this:

HttpPost request = new HttpPost("http://my/url");
request.addHeader(new BasicHeader("Content-type", "application/atom+xml; type=entry")); // required by vendor
request.setEntity(new StringEntity("My content"));

HttpResponse response = client.execute(request);

I see in Charles Proxy that there are two requests being sent. One without the Authorization: Basic ... header and one with it. The first one fails with a 401, as you would expect, but the second goes through just fine with a 201.

Does anyone know why this happens? Thanks!

EDIT:

I should make clear that I have already looked at this question, but as you can see I set the AuthScope the same way and it didn't solve my problem. Also, I am creating a new HttpClient every time I made a request (though I use the same ConnectionManager), but even if I use the same HttpClient for multiple requests, the problem still persists.

EDIT 2:

So it looks like what @LastCoder was suggesting is the way to do. See this answer to another question. The problem stems from my lack of knowledge around the HTTP spec. What I'm looking to do is called "preemptive authentication" and the HttpClient docs mention it here. Thankfully, the answer linked to above is a much shorter and cleaner way to do it.

like image 565
daveslab Avatar asked Mar 02 '12 19:03

daveslab


People also ask

Why you should not use Basic Auth?

Because Basic authentication involves the cleartext transmission of passwords, it SHOULD NOT be used (without enhancements such as HTTPS RFC2818) to protect sensitive or valuable information.

Is Basic Auth over HTTP Secure?

Note: The HTTP basic authentication scheme can be considered secure only when the connection between the web client and the server is secure. If the connection is insecure, the scheme does not provide sufficient security to prevent unauthorized users from discovering the authentication information for a server.

How do I add basic authentication to HttpClient Java?

Let's add an authenticator to our client: HttpClient client = HttpClient. newBuilder() . authenticator(new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("postman", "password".


1 Answers

Rather than using .setCredentials() why don't you just encode USERNAME:PASSWORD and add the authentication header with .addHeader()

like image 52
Louis Ricci Avatar answered Sep 22 '22 03:09

Louis Ricci