HttpClient Basic Authentication

1. Overview

This tutorial will illustrate how to configure Basic Authentication on the Apache HttpClient 4.

If you want to dig deeper and learn other cool things you can do with the HttpClient – head on over to the main HttpClient tutorial.

2. Basic Authentication with the API

Let’s start with the standard way of configuring Basic Authentication on the HttpClient – via a CredentialsProvider:

CredentialsProvider provider = new BasicCredentialsProvider();
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("user1", "user1Pass");
provider.setCredentials(AuthScope.ANY, credentials);
HttpClient client = HttpClientBuilder.create().setDefaultCredentialsProvider(provider).build();

HttpResponse response = client.execute(new HttpGet(URL_SECURED_BY_BASIC_AUTHENTICATION));
int statusCode = response.getStatusLine().getStatusCode();
assertThat(statusCode, equalTo(HttpStatus.SC_OK));

As you can see, creating the client with a credentials provider to set it up with Basic Authentication is not difficult.

Now, to understand what HttpClient will actually do behind the scenes, we’ll need to look at the logs:

# ... request is sent with no credentials
[main] DEBUG ... - Authentication required
[main] DEBUG ... - localhost:8080 requested authentication
[main] DEBUG ... - Authentication schemes in the order of preference: 
  [negotiate, Kerberos, NTLM, Digest, Basic]
[main] DEBUG ... - Challenge for negotiate authentication scheme not available
[main] DEBUG ... - Challenge for Kerberos authentication scheme not available
[main] DEBUG ... - Challenge for NTLM authentication scheme not available
[main] DEBUG ... - Challenge for Digest authentication scheme not available
[main] DEBUG ... - Selected authentication options: [BASIC]
# ... the request is sent again - with credentials

The entire Client-Server communication is now clear:

  • the Client sends the HTTP Request with no credentials
  • the Server sends back a challenge
  • the Client negotiates and identifies the right authentication scheme
  • the Client sends a second Request, this time with credentials

3. Preemptive Basic Authentication

Out of the box, the HttpClient doesn’t do preemptive authentication – this has to be an explicit decision made by the client.

First, we need to create the HttpContext – pre-populating it with an authentication cache with the right type of authentication scheme pre-selected. This will mean that the negatiation from the previous example is no longer necessary – Basic Authentication is already chosen:

HttpHost targetHost = new HttpHost("localhost", 8080, "http");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY, 
  new UsernamePasswordCredentials(DEFAULT_USER, DEFAULT_PASS));

AuthCache authCache = new BasicAuthCache();
authCache.put(targetHost, new BasicScheme());

// Add AuthCache to the execution context
final HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
context.setAuthCache(authCache);

Now we can use the client with the new context and send the pre-authentication request:

HttpClient client = HttpClientBuilder.create().build();
response = client.execute(new HttpGet(URL_SECURED_BY_BASIC_AUTHENTICATION), context);

int statusCode = response.getStatusLine().getStatusCode();
assertThat(statusCode, equalTo(HttpStatus.SC_OK));

Let’s look at the logs:

[main] DEBUG ... - Re-using cached 'basic' auth scheme for http://localhost:8080
[main] DEBUG ... - Executing request GET /spring-security-rest-basic-auth/api/foos/1 HTTP/1.1
[main] DEBUG ... >> GET /spring-security-rest-basic-auth/api/foos/1 HTTP/1.1
[main] DEBUG ... >> Host: localhost:8080
[main] DEBUG ... >> Authorization: Basic dXNlcjE6dXNlcjFQYXNz
[main] DEBUG ... << HTTP/1.1 200 OK
[main] DEBUG ... - Authentication succeeded

Everything looks OK:

  • the “Basic Authentication” scheme is pre-selected
  • the Request is sent with the Authorization header
  • the Server responds with a 200 OK
  • Authentication succeeds

4. Basic Auth with Raw HTTP Headers

5. Conclusion

This article illustrated various ways to set up and use basic authentication with the Apache HttpClient 4.

The implementation of all these examples and code snippets can be found in the working sample project.

This is an Eclipse based project, so it should be easy to import and run as it is.

I usually post about Dev stuff on Google+ - you can follow me there:

GET THE 3 EBOOKS >>
Download the 3 eBooks: "Rest with Spring", "Persistence with Spring" and "Learn HttpClient"
×
Build Your Web App with Spring (and quickly prototype it to 90%)

,

  • TowiPanda

    Thank you

    This resolved my problem with NTLM Authentication, now I just need to consume wsdl service with CXF.

    • http://www.baeldung.com/ Eugen Paraschiv

      Hey Towi – glad you found it useful. Cheers,
      Eugen.

  • mikec711

    this is very good, but what if I’m multiThreaded (ie: emulating n virtual users) and I want to have different uid/pw combos on different threads. I get my CloseableHttpClient from a PoolingHttpClientConnectionManager and, for each request, I get a HttpGet and use the CloseableHttpClient with: CloseableHttpResponse chr = httpClient.execute(httpGet) ;
    // So I’m wondering, do I get a separate httpClient per thread and set it that way and leave everything else the same? I tried the preEmptive route, but with that, I am suddenly getting an odd error:
    java.lang.IllegalArgumentException: Cookie name “Path” is a reserved token
    at javax.servlet.http.Cookie.(Cookie.java:139)
    (I don’t have any explicit refs to PATH in my code). Thanks,