Spring RestTemplate Basic Authentication

Upasana | December 26, 2020 | 3 min read | 2,287 views


In this tutorial we will explore different ways to configure HTTP Basic Authentication credentials in RestTemplate using a Spring Boot application.

Basic HTTP Authentication

In basic HTTP authentication, a request contains a header field in the form of

Authorization: Basic <credentials>

where credentials is the Base64 encoding of ID and password joined by a single colon : . It is specified in RFC 7617 from 2015, which obsoletes RFC 2617 from 1999.

Perquisites

  1. Gradle 6

  2. Java 8 or 11

  3. Basic Auth Sever with a protected endpoint

  4. IDE - IntelliJ IDEA or Eclipse

Download Basic Auth Server

Creating the basic auth server is outside the scope for this tutorial, you can just clone this project and run it from command line.

Starting the Server

$ ./gradlew :bootRun

Now we should have the following endpoint running on the server - http://localhost:8080/secured/hello

Credentials
username: admin
password: password

We will use this endpoint in this tutorial to validate our RestTemplate authentication setup.

Gradle Setup

We will setup Spring Boot dependencies in build.gradle

build.gradle
plugins {
    id 'org.springframework.boot' version '2.4.1.RELEASE'
    id 'java'
}

apply plugin: 'io.spring.dependency-management'

group = 'com.shunya.tutorial'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
}

We will explore 4 different approaches to configure basic authentication in RestTemplate:

  1. Creating a customized RestTemplate using RestTemplateBuilder (preferred approach for Spring Boot)

  2. Using RestTemplate Interceptors

  3. Using Http Request Headers at individual request level

  4. Using Plain Java/Kotlin to generate Basic Auth Headers

1. RestTemplate customization with RestTemplateBuilder

We will be using RestTemplateBuilder to create a customized version of RestTemplate that attaches Basic Authentication headers with each outgoing request.

RestTemplate with Basic Authentication
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

@Component
public class BasicAuthClient {

    private final RestTemplate restTemplate;

    public BasicAuthClient(RestTemplateBuilder restTemplateBuilder) {
        restTemplate = restTemplateBuilder
                    .basicAuthentication("admin", "password")
                    .build();
    }

    public void invokeProtectedResource() {
        final ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://localhost:8080/secured/hello", String.class);
        final String body = responseEntity.getBody();
        System.out.println("body = " + body);
    }
}

2. Using RestTemplate Interceptors

We can configure interceptor at RestTemplate instance level that will inject required basic auth headers on each outgoing request.

BasicAuthClient.java
public class BasicAuthClient {

    private final RestTemplate restTemplate;

    public BasicAuthClient(RestTemplateBuilder restTemplateBuilder) {
        restTemplate = restTemplateBuilder.build();
        restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor("admin", "password"));
    }

    private void invokeProtectedResource() {
        final ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://localhost:8080/secured/hello", String.class);
        final String body = responseEntity.getBody();
        System.out.println("body = " + body);
    }
}

BasicAuthenticationInterceptor is provided by Spring Framework. You can also provide your own Interceptor definition.

Custom Interceptor for RestTemplate
restTemplate.getInterceptors().add(new ClientHttpRequestInterceptor() {
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        String auth = "admin" + ":" + "password";
        byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(StandardCharsets.US_ASCII));
        request.getHeaders().add("Authorization", "Basic " + new String(encodedAuth));
        return execution.execute(request, body);
    }
});

3. Request level headers

Instead of setting basic auth at instance level, we can also set it at individual request level using the following code:

RestTemplate request level headers for basic auth
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;

@Component
public class BasicAuthClient {

    private final RestTemplate restTemplate;

    public BasicAuthClient(RestTemplateBuilder restTemplateBuilder) {
        restTemplate = restTemplateBuilder.build();
    }

    HttpHeaders createHeaders(String username, String password) {
        return new HttpHeaders() {{
            final String basicAuth = HttpHeaders.encodeBasicAuth(username, password, StandardCharsets.US_ASCII);
            setBasicAuth(basicAuth);
        }};
    }

    private void invokeProtectedResource() {
        final ResponseEntity<String> responseEntity = restTemplate.exchange("http://localhost:8080/secured/hello", HttpMethod.GET, new HttpEntity<Void>(createHeaders("admin", "password")), String.class);
        System.out.println(responseEntity.getBody());
    }
}

4. Using Java 8

We can even generate Basic Authorization header string using Java 8 without help from Spring.

Generating basic auth headers using plain Java
import org.springframework.http.HttpEntity
import org.springframework.http.HttpHeaders
import org.springframework.http.MediaType
import org.springframework.web.client.RestTemplate
import java.nio.charset.Charset
import java.util.*

fun basicAuth(username: String, password: String) {
    val restTemplate = RestTemplate()
    val headers = HttpHeaders()
    headers.contentType = MediaType.APPLICATION_JSON
    val auth = "$username:$password"
    val encodedAuth = Base64.getEncoder().encodeToString(auth.toByteArray(Charset.forName("UTF-8")))
    headers.set("Authorization", "Basic $encodedAuth")
    val entity: HttpEntity<String> = HttpEntity<String>("", headers)
    val authURL = "http://localhost:8080/protected/listing"
    val response = restTemplate.postForEntity(authURL, entity, String::class.java)
}

Top articles in this category:
  1. Basic Auth Security in Spring Boot 2
  2. Spring Data ElasticSearch with Basic Auth
  3. Spring Boot WebClient Basic Authentication
  4. Disable SSL validation in Spring RestTemplate
  5. Prevent Lost Updates in Database Transaction using Spring Hibernate
  6. Redis rate limiter in Spring Boot
  7. Send Gupshup SMS using Java API

Recommended books for interview preparation:

Find more on this topic: