Http Client API in Java: Authentication
Tags: java, http, client, beginners
Published: 2023-03-19 00:07:47

## Introduction

In the first part of this series (link [here](https://dev.to/noelopez/http-client-api-in-java-26e)), the basic features of the java http client API were presented. Now we are going to explore a few more common use cases widely used in today's applications. 
We will learn how to access a secured endpoint by providing credentials.

## Basic Authentication

Basic Authentication is a simple way to protect web resources on the internet. It works as follows: 

- A client wants to access a protected resource over HTTP and provides username/password. The credentails are sent in the Authorization HTTP header. The format is important and has to be exactly as below: Basic credentials, where credentials is the Base64 encoding of username:password. Note here the single colon in between usename and password.
- The web server recieves the HTTP request, extracts the encoded credentials from the header and verifies it. If it does not match, it will usually return a 401 status code (unauthorized error). If it matches it will allow access.

Now that we know the theory, let's put it into practice. Our endpoint used in the previous articles is now secured thanks to Spring Security module (this will be a future article, so stay tuned!). When trying to get the list of customers by executing the following code

```java
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("http://localhost:8080/api/v1/customers"))
    .GET()
    .build();

HttpResponse<String> response = client
    .send(request, HttpResponse.BodyHandlers.ofString());
System.out.printf("Status %s \n", response.statusCode());
```

the response returns 401 code. Hence, credentials must be sent

```
Status 401
```

## Authenticate using HTTP Header

The first approach to pass the credentials to the endpoint is setting the header in the http request object. HttpRequest class contains two different methods to add/set headers:

- The setHeader method sets the given name/value pair to the set of headers for this request. This overwrites any previously set values for name. 

- On the other hand the header method adds the given name/value pair to the set of headers for this request. The given value is added to the list of values for that name. 

There is also a third option to add multiple headers. Here we will just call header method. Code is shown next 

```java
String credentials = "user1234:password5678";
String headerValue = "Basic " + Base64.getEncoder()
    .encodeToString(credentials.getBytes());

var request = HttpRequest.newBuilder()
    .uri(URI.create("http://localhost:8080/api/v1/customers"))
    .header("Authorization", headerValue)
    .GET()
    .build();
```

Encoding is easily done with the help of the Base64 class in the java.util package. And access to the resource is granted. Output in console

```console
Status 200 
Body [{"id":1,"name":"Joe Smith","email":"joe.smith@gmail.com",...
```

## Authenticate with Authenticator Class

The second approach to provide the credentials is configuring an Authenticator in the HttpCLient object. Authenticator is an abstract class that knows how to obtain authentication for a network connection. An authenticator class performs authentication by prompting the user for credential information like username and password. Applications will implement a concrete sub class and override the getPasswordAuthentication. This function just returns the data holder class PasswordAuthentication with the username and password. 

The code looks as follows

```java
var client = HttpClient.newBuilder()
    .connectTimeout(Duration.ofMillis(500))
    .authenticator(new Authenticator() {
        @Override
       protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(
            "user1234", "password5678".toCharArray());
        }
    })
    .build();
```

And the call to the endpoint is successful as displayed in the console 

```console
Status 200 
Body [{"id":1,"name":"Joe Smith","email":"joe.smith@gmail.com",...
```
## Summary

In this short article, we have seen how to access secured resources with the Java Http Client API. It is straightforward and easy to setup in just a few lines of code. This is achieved with either adding the Authorization header to the HttpRequest object or configuring the Authenticator class in the HttpClient object. 

There will be a third part article related to this series in which we will see how to upload and download files using the common BodyPublishers and BodyHandlers provided by the API to handle the file contents.

Check the code on [GitHub](https://github.com/NoeLopezSan/java-http-client)