RestTemplate Example with Basic Authentication

This tutorial will teach you how to leverage RestTemplate to access RESTful APIs protected by basic authentication. You will learn to create a Basic Authentication-secured REST API and access it via RestTemplate.

What is Basic Authentication

As the name suggests, it is a basic form of authentication in which we must provide the correct username and password to access a resource.

What is RestTemplate

Simply put, it is a client provided by Spring to perform synchronous HTTP requests to consume a REST-based API endpoint. It provides templates for some common scenarios and is therefore named as RestTemplate.

Rest API Setup

Initially, I’ll demonstrate a straightforward REST API example for retrieving users from a fake API endpoint. Afterward, I’ll use Basic Authentication to secure this REST API. Finally, I will demonstrate how to call this REST API using Basic Authentication via Rest Template.

The following is the REST controller class for this API to retrieve users:

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.security.UserService.UserService;

@RestController
public class UserController {
    @Autowired
    private UserService userService;

    @RequestMapping(value = "/user/", method = RequestMethod.GET)
    public ResponseEntity<List<User>> listAllUsers() {
        List<User> users = userService.getUsers();
        if (users.isEmpty()) {
            return new ResponseEntity<List<User>>(HttpStatus.NO_CONTENT);
        }
        return new ResponseEntity<>(users, HttpStatus.OK);
    }
}

Our UserService Interface will look like the following:

public interface UserService{
    List<User> getUsers();
}

The implementation:

import java.util.Arrays;

import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {

    @Override
    public List<User> getUsers() {
        User user1 = new User();
        user1.setFirstName("John");
        user1.setLastName("Doe");
        user1.setEmail("john.doe@mail.com");

        User user2 = new User();
        user2.setFirstName("Muhammad");
        user2.setLastName("Ali");
        user2.setEmail("muhammad.ali@mail.com");

        return new ArrayList<>(Arrays.asList(user1, user2));
    }
}

With this, we have an API ready, but it isn’t secured.

Securing API with Basic Authentication

To secure the API, we must first add Spring Security to our project.

For Maven:

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

For Gradle:

implementation group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: '3.0.2'

As soon as we add the above dependency to our application, we will get a 401 unauthorized error by default on access.

@SpringBootApplication
public class RestBasicAuthApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(RestBasicAuthApplication.class, args);
    }
}

To allow a user to access the API endpoint, we have to create a configuration class that will have the @EnableWebSecurity annotation and provides Spring the SecurityFilterChain and InMemoryUserDetailsManager beans required for authorization and authentication.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.
                authorizeHttpRequests((authz) -> authz
                        .anyRequest().authenticated()
                )
                .httpBasic();
        return http.build();
    }

    @Bean
    public InMemoryUserDetailsManager userDetailsService() {
        UserDetails user = User
                .withUsername("admin")
                .password(passwordEncoder().encode("admin123"))
                .roles("ADMIN")
                .build();

        return new InMemoryUserDetailsManager(user);
    }

    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

The InMemoryUserDetailsManager is setting the credentials for Basic Auth, and the SecurityFilterChain bean is set to authorize any request and set the authentication type to Basic Auth.

Finally, the PasswordEncoder bean helps decrypt the password and then store it in memory, without which Spring will warn us that our password is not encrypted.

Consuming an API secured with Basic Authentication via RestTemplate

Now we’ll create a client class to access our API programmatically.

import java.awt.PageAttributes.MediaType;
import java.net.http.HttpHeaders;
import java.util.Arrays;
import java.util.Base64;
import java.util.LinkedHashMap;
import java.util.List;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

public class RestTemplateClient {
    public static final String REST_SERVICE_URL = "http://localhost:8080/user/";

    private static HttpHeaders httpHeaders() {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Authorization", "Basic " + getBasicAuthHeader());
        httpHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
        return httpHeaders;
    }

    private static String getBasicAuthHeader() {
        String credentials = "admin:admin123";
        return new String(Base64.encodeBase64(credentials.getBytes()));
    }

    private static void listUserName() {
        ResponseEntity<List> responseEntity = new RestTemplate().exchange(REST_SERVICE_URL,
                HttpMethod.GET, new HttpEntity<>(httpHeaders()), List.class);

        if (responseEntity.hasBody()) {
            List<LinkedHashMap<String, Object>> users = responseEntity.getBody();

            for (LinkedHashMap<String, Object> userMap : users) {
                System.out.println("User Name: " + userMap.get("firstName") + " " + userMap.get("lastName"));
                System.out.println("Email: " + userMap.get("email"));
            }
        }
    }

    public static void main(String[] args) {
        listUserName();
    }
}

The getBasicAuthHeader() returns a Base64 encoded string of the Basic Auth credentials, which we add to the HttpHeaders. HttpHeaders are then included in the GET request. We are consuming our API using RestTemplate.exchange() method.

Following is the output:

19:31:25.128 [main] DEBUG org.springframework.web.client.RestTemplate - HTTP GET http://localhost:8080/user/
19:31:25.214 [main] DEBUG org.springframework.web.client.RestTemplate - Accept=[application/json, application/*+json]
19:31:25.803 [main] DEBUG org.springframework.web.client.RestTemplate - Response 200 OK
19:31:25.815 [main] DEBUG org.springframework.web.client.RestTemplate - Reading to [java.util.List<?>]
User Name: John Doe
Email: john.doe@mail.com
User Name: Muhammad Ali
Email: muhammad.ali@mail.com

Thanks for following the tutorial till the end. I hope that this adds to your knowledge.

Happy learning!