Implementing Secure API Communication in Spring Boot
Last Updated :
21 Jun, 2024
In modern web applications, securing API communication is important to protect sensitive data and ensuring the integrity of interactions between clients and servers. In this article, we will learn how to implement secure API communication in a Spring Boot application.
Securing API communication is crucial for protecting sensitive data and ensuring that only authorized clients can access specific endpoints. One common method to achieve this is by using API keys and secrets. This method can be simpler than other authentication mechanisms like OAuth2 or JWT but still provides a robust way to secure APIs.
API Key and Secret
The API key is a unique identifier passed with each request to authenticate the client. An API secret provides additional security measures to further validate the request. Together, they form a pair that the server checks to allow or deny access to the API endpoints of the application.
Working of API Key and Secret
- Client Request: When the client makes a request to the API, it includes the API key and secret in the request headers.
- Server Validation: The server intercepts the request, extracts the API key and secret, and validates them against the known valid values.
- Access Control: If the API key and secret are valid, the server processes the request and returns the response. If they are invalid, the server denies access and returns an unauthorized error.
This method provides a lightweight and effective way to secure APIs without the complexity of token-based authentication mechanisms.
Implementation of the Secure API Communication in Spring Boot
Below are the implementation steps to Secure API Communication in Spring Boot.
Step 1: Create Spring Project
We will now create the spring project using spring Initializr. When creating the project, add the following dependencies to the project.
Dependencies:
- Spring Web
- Spring Security
- Lombok
- Spring DevTools
After the project creation done, the folder structure will be like below image:

Step 2: Configure Application Properties
Open the application.properties file and add the configuration and security credentials of the application.
spring.application.name=secure-API-Demo
spring.security.user.name=user
spring.security.user.password=password
Step 3: Create the ApiKeyFilter class
Go to src > main > java > org.example.secureapidemo > config > ApiKeyFilter and put the below code.
Java
package org.example.secureapidemo.config;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ApiKeyFilter extends HttpFilter {
private static final String API_KEY_HEADER = "x-api-key";
private static final String API_SECRET_HEADER = "x-api-secret";
private static final String VALID_API_KEY = "apikey123";
private static final String VALID_API_SECRET = "secret123";
@Override
protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
String apiKey = request.getHeader(API_KEY_HEADER);
String apiSecret = request.getHeader(API_SECRET_HEADER);
if (VALID_API_KEY.equals(apiKey) && VALID_API_SECRET.equals(apiSecret)) {
chain.doFilter(request, response);
} else {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid API Key or Secret");
}
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// Initialization code, if needed
}
@Override
public void destroy() {
// Cleanup code, if needed
}
}
In this filter:
- API_KEY_HEADER and API_SECRET_HEADER are the names of the headers expected in the request.
- VALID_API_KEY and VALID_API_SECRET are valid for the API key and secret of the application.
The doFilter method checks if the incoming request contains the valid API key and secret. If valid, it allows the request to proceed. if not, it sends the unauthorized error response.
Step 4: Create the SecurityConfig class
Go to src > main > java > org.example.secureapidemo > config > SecurityConfig and put the below code.
Java
package org.example.secureapidemo.config;
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.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests(authorizeRequests ->
authorizeRequests
.requestMatchers("/auth/**").permitAll()
.anyRequest().authenticated()
)
.httpBasic();
http.addFilterBefore(apiKeyFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public ApiKeyFilter apiKeyFilter() {
return new ApiKeyFilter();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
In this security configuration:
- We disable the CSRF protection for the simplicity of the application.
- We permit all the requests to "/api/public/**" but require the authentication for all the other requests.
- We have added the custom ApiKeyFilter before the UsernamePasswordAuthenticationFilter, in the filter chain of the application.
Step 5: Create the SecureController Class
Go to src > main > java > org.example.secureapidemo > controller > SecureController and put the below code.
Java
package org.example.secureapidemo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class SecureController {
@GetMapping("/public/hello")
public String publicHello() {
return "Hello, Public!";
}
@GetMapping("/private/hello")
public String privateHello() {
return "Hello, Private!";
}
}
In this controller:
- "/api/public/hello" can be accessible without any authentication.
- "/api/private/hello" requires the valid API key and secret to access the endpoint.
Step 6: Main Class
No changes are required in the main class.
Java
package org.example.secureapidemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SecureApiDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SecureApiDemoApplication.class, args);
}
}
pom.xml:
XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.example</groupId>
<artifactId>secure-API-Demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>secure-API-Demo</name>
<description>secure-API-Demo</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
Step 7: Run the application
Once the project completed, run the application and it will start at port 8080.

Step 8: Testing the Endpoints
Secure endpoint:
POST http://localhost:8080/api/private/hello
Output:
1. Authentication Details:

2. Headers API Keys:

Public Endpoint:
POST http://localhost:8080/api/public/hello
Output:

This example demonstrates how to secure the API communication in the Spring Boot application using API keys and secrets. This method provides the simple yet effective way to the protect your endpoints that only authorized the clients can access them.
Similar Reads
Implementing CORS Handling in Spring Boot API Gateway
Cross-Origin Resource Sharing (CORS) is a mechanism that allows resources on a web server to be requested from a domain other than the one from which the resource originated. In a microservices architecture using Spring Boot API Gateway, handling CORS is essential to ensure that client applications
6 min read
Implementing CORS in Spring Boot with Spring Security
CORS issue is one of the common issues being faced in web development. We are here going to configure CORS in our backend application built using Spring Boot and Spring security, being used for security purpose.Before going to fix the issue, lets understand what CORS is and how it works and why brow
6 min read
Microservices Communication with Apache Kafka in Spring Boot
Apache Kafka is a distributed streaming platform and can be widely used to create real-time data pipelines and streaming applications. It can publish and subscribe to records in progress, save these records in an error-free manner, and handle floating records as they arrive. Combined with Spring Boo
6 min read
Spring Boot - REST API Documentation using OpenAPI
For any application, API documentation is essential for both users and developers. How to use an API, what will be the request body, and what will the API's response be? API documentation is the answer to all of these questions, springdoc-openapi is a Java library that automates the generation of th
4 min read
Spring Boot Security Auto-Configuration
Spring Boot Security Auto Configuration can simplify the process of securing the Spring Boot applications by providing default security configurations. It can automate the many common security tasks such as setting up the authentication, and authorization and it can handle the common security vulner
4 min read
Spring Boot Microservices Communication using WebClient with Example
WebClient is an interface illustrating the main entry point for performing web requests. It is also known as the reactive web client which is introduced in Spring 5. This new client is a reactive, non-blocking solution that works over the HTTP/1.1 protocol. We can also say that it is a replacement f
14 min read
How to Implement AOP in Spring Boot Application?
AOP(Aspect Oriented Programming) breaks the full program into different smaller units. In numerous situations, we need to log, and audit the details as well as need to pay importance to declarative transactions, security, caching, etc., Let us see the key terminologies of AOP Aspect: It has a set of
10 min read
Spring Boot Microservices Communication using RestTemplate with Example
RestTemplate is a synchronous REST client which performs HTTP requests using a simple template-style API. We can also state that RestTemplate class is a synchronous client and is designed to call REST services. Apart from that, RestTemplate class plays a major role whenever we talk about Spring Boot
14 min read
Spring MVC â Implementing Asynchronous Request Processing
In Spring MVC, asynchronous request processing allows the server to handle requests in a non-blocking manner. This approach improves performance by freeing up resources while waiting for responses, which is especially useful for long-running tasks such as remote service calls, file processing, or da
8 min read
Spring Boot - Externalized Configuration
In Spring Boot, externalized configuration is a feature that allows you to separate configuration settings from your code. This means you can change how your application behaves by modifying configuration files without needing to recompile or redeploy the application. Spring Boot supports various co
4 min read