Spring Boot RestTemplate with Basic Auth: A Modern Guide

Communicating between microservices is a fundamental aspect of modern application development. Often, these services need to be secured. One of the simplest and most widely supported methods for securing REST APIs is Basic Authentication. In this guide, we’ll walk through how to configure and use Spring Boot’s RestTemplate to consume a REST API protected with Basic Auth.

We’ll cover the modern, recommended approach using Spring Security’s component-based configuration, updating older patterns you might find in other tutorials.

Project Setup

First, ensure your Spring Boot project includes the spring-boot-starter-web dependency. This starter conveniently bundles everything we need, including Spring MVC for creating the REST service, Tomcat as the embedded server, and RestTemplate support.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

You’ll also need the spring-boot-starter-security dependency to enable security features.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

Step 1: Create a Secured REST Endpoint

Let’s start by creating a simple REST endpoint that we want to secure. This endpoint will return a greeting message. Without proper authentication, any request to this endpoint should be denied.

package com.ankurm.examples.rest;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SecuredController {

    @GetMapping("/api/hello")
    public String getSecuredGreeting() {
        return "Hello, you have accessed a secured endpoint!";
    }
}

Step 2: Configure Spring Security for Basic Authentication

With Spring Security on the classpath, all endpoints are secured by default. Now, we need to configure it to use Basic Authentication and define a valid user.

As of Spring Security 5.7+, WebSecurityConfigurerAdapter is deprecated. The modern, recommended approach is to define a SecurityFilterChain bean. This makes the configuration more modular and easier to read.

Let’s create a configuration class to set up our security rules and an in-memory user.

package com.ankurm.examples.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class AppSecurityConfig {

    // 1. Define the SecurityFilterChain bean
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf.disable()) // Disabling CSRF for stateless REST APIs
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/**").authenticated() // Secure all endpoints under /api/
                .anyRequest().permitAll() // Allow all other requests
            )
            .httpBasic(Customizer.withDefaults()); // Enable HTTP Basic Authentication

        return http.build();
    }

    // 2. Define an in-memory user for demonstration
    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails user = User.builder()
            .username("admin")
            .password("{noop}password123") // {noop} indicates plain text password (for demo only!)
            .roles("USER", "ADMIN")
            .build();

        return new InMemoryUserDetailsManager(user);
    }
}

Understanding the Security Configuration:

  • @EnableWebSecurity: Enables Spring Security’s web security support.
  • securityFilterChain(HttpSecurity http): This bean defines the core security rules.
    • .csrf(csrf -> csrf.disable()): We disable Cross-Site Request Forgery (CSRF) protection, which is common for stateless REST APIs consumed by non-browser clients.
    • .authorizeHttpRequests(...): This is where we define which paths are secured. We specify that any request to /api/** must be authenticated.
    • .httpBasic(...): This explicitly enables the Basic Authentication scheme.
  • userDetailsService(): This bean sets up an in-memory user store. We create a user with the username admin and password password123. The {noop} prefix tells Spring Security that the password is not encoded and should be treated as plain text. This is for demonstration purposes only. In a production environment, you must always use a password encoder like BCrypt.

Step 3: Configure RestTemplate with Basic Auth Credentials

Now for the client side. We need to create a RestTemplate bean that is pre-configured to send the Basic Auth credentials with every request. The most idiomatic Spring Boot way to do this is by using the RestTemplateBuilder.

Let’s add this bean to a configuration class.

package com.ankurm.examples.config;

import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestClientConfig {

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder
                .basicAuthentication("admin", "password123")
                .build();
    }
}

This is incredibly clean and readable. The .basicAuthentication("admin", "password123") method configures the underlying client to automatically add the Authorization header with the Base64-encoded credentials for every request made by this RestTemplate instance.

Step 4: Putting It All Together and Testing

To see our client in action, let’s create a CommandLineRunner. This is a simple component that runs its code once the Spring Boot application has started. We’ll inject our configured RestTemplate and use it to call our secured endpoint.

package com.ankurm.examples;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.client.HttpClientErrorException;

@Component
public class ApiClientRunner implements CommandLineRunner {

    private static final Logger LOG = LoggerFactory.getLogger(ApiClientRunner.class);

    private final RestTemplate restTemplate;

    public ApiClientRunner(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @Override
    public void run(String... args) {
        LOG.info("...::: Starting REST API Client Test :::...");

        try {
            String apiUrl = "http://localhost:8080/api/hello";
            ResponseEntity<String> response = restTemplate.getForEntity(apiUrl, String.class);

            if (response.getStatusCode().is2xxSuccessful()) {
                LOG.info("Success! Received response: {}", response.getBody());
            }

        } catch (HttpClientErrorException e) {
            LOG.error("Error accessing API: {} - {}", e.getStatusCode(), e.getStatusText());
            LOG.error("Response Body: {}", e.getResponseBodyAsString());
        } catch (Exception e) {
            LOG.error("An unexpected error occurred", e);
        }

        LOG.info("...::: REST API Client Test Finished :::...");
    }
}

Running the Application

Now, run your Spring Boot application. When it starts, the ApiClientRunner will execute. You should see output in your console similar to this:

...
...::: Starting REST API Client Test :::...
... Success! Received response: Hello, you have accessed a secured endpoint!
...::: REST API Client Test Finished :::...
...

This confirms that our pre-configured RestTemplate successfully authenticated against the secured endpoint and received the expected response.


Alternative Method: Using a ClientHttpRequestInterceptor

While RestTemplateBuilder is preferred, another way to achieve the same result is by using a ClientHttpRequestInterceptor. This approach is more manual but can be useful if you need to add the authentication logic to an existing RestTemplate instance or require more complex conditional logic.

The BasicAuthenticationInterceptor does exactly what we need.

package com.ankurm.examples.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.support.BasicAuthenticationInterceptor;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestClientConfigWithInterceptor {

    // A different way to create the same configured RestTemplate
    @Bean
    public RestTemplate restTemplateWithInterceptor() {
        RestTemplate restTemplate = new RestTemplate();
        
        restTemplate.getInterceptors().add(
          new BasicAuthenticationInterceptor("admin", "password123"));
          
        return restTemplate;
    }
}

To use this bean, you would need to inject it into your client component, for example, by using Spring’s @Qualifier("restTemplateWithInterceptor") annotation. The end result is identical to the RestTemplateBuilder method.

Conclusion

In this guide, we successfully demonstrated how to consume a Basic Auth-secured REST API using Spring Boot’s RestTemplate. We saw two effective methods:

  1. Using RestTemplateBuilder: The modern, clean, and recommended approach for creating configured RestTemplate instances in Spring Boot.
  2. Using BasicAuthenticationInterceptor: A flexible alternative that manually adds authentication behavior to a RestTemplate.

We also covered how to set up the server-side security using the current, component-based Spring Security configuration, which is the standard moving forward. By following these patterns, you can confidently and securely handle service-to-service communication in your Spring ecosystem.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.