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 we 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. Instead, 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 negotiation from the previous example is no longer necessary – Basic Authentication is already chosen:

HttpHost targetHost = new HttpHost("localhost", 8082, "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
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:8082
[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:8082
[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

Preemptive Basic Authentication basically means pre-sending the Authorization header.

So, instead of going through the rather complex previous example to set it up, we can take control of this header and construct it by hand:

HttpGet request = new HttpGet(URL_SECURED_BY_BASIC_AUTHENTICATION);
String auth = DEFAULT_USER + ":" + DEFAULT_PASS;
byte[] encodedAuth = Base64.encodeBase64(
  auth.getBytes(StandardCharsets.ISO_8859_1));
String authHeader = "Basic " + new String(encodedAuth);
request.setHeader(HttpHeaders.AUTHORIZATION, authHeader);

HttpClient client = HttpClientBuilder.create().build();
HttpResponse response = client.execute(request);

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

Let’s make sure this is working correctly:

[main] DEBUG ... - Auth cache not set in the context
[main] DEBUG ... - Opening connection {}->http://localhost:8080
[main] DEBUG ... - Connecting to localhost/127.0.0.1:8080
[main] DEBUG ... - Executing request GET /spring-security-rest-basic-auth/api/foos/1 HTTP/1.1
[main] DEBUG ... - Proxy auth state: UNCHALLENGED
[main] DEBUG ... - http-outgoing-0 >> GET /spring-security-rest-basic-auth/api/foos/1 HTTP/1.1
[main] DEBUG ... - http-outgoing-0 >> Authorization: Basic dXNlcjE6dXNlcjFQYXNz
[main] DEBUG ... - http-outgoing-0 << HTTP/1.1 200 OK

So, even though there is no auth cache, Basic Authentication still works correctly and we receive 200 OK.

5. Conclusion

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

As always, the code presented in this article is available over on Github. This is a Maven based project, so it should be easy to import and run as it is.

Related posts:

Java Program to Implement Ternary Search Algorithm
Toán tử trong java
Easy Ways to Write a Java InputStream to an OutputStream
Write/Read cookies using HTTP and Read a file from the internet
Java Byte Array to InputStream
Multi Dimensional ArrayList in Java
Allow user:password in URL
Hướng dẫn Java Design Pattern – MVC
Java Program to Find k Numbers Closest to Median of S, Where S is a Set of n Numbers
Deploy a Spring Boot App to Azure
Thao tác với tập tin và thư mục trong Java
Java Program to Implement Booth Algorithm
Java Program to Generate Random Numbers Using Probability Distribution Function
Java Program to Find ith Largest Number from a Given List Using Order-Statistic Algorithm
Introduction to Spring Data JPA
Hướng dẫn Java Design Pattern – Factory Method
Java Program to Implement WeakHashMap API
Sử dụng JDBC API thực thi câu lệnh truy vấn dữ liệu
Java Program to Perform Preorder Non-Recursive Traversal of a Given Binary Tree
REST Web service: HTTP Status Code và xử lý ngoại lệ RESTful web service với Jersey 2.x
Giới thiệu Google Guice – Dependency injection (DI) framework
Java Program to Implement Merge Sort Algorithm on Linked List
A Guide to the Java ExecutorService
Java Program to Find the Edge Connectivity of a Graph
A Guide to ConcurrentMap
A Guide to Java 9 Modularity
Spring RestTemplate Error Handling
Hướng dẫn Java Design Pattern – State
Hướng dẫn Java Design Pattern – Facade
Registration – Password Strength and Rules
Java Program to Implement Dijkstra’s Algorithm using Set
Cài đặt và sử dụng Swagger UI