Securing Spring Boot API With API Key and Secret (original) (raw)

Last Updated : 4 Jun, 2026

Securing APIs is essential to ensure that only authorized clients can access application resources. One common approach is using an API Key and API Secret, which act as credentials sent with each request. Spring Security allows us to validate these credentials before granting access to protected endpoints.

Major concepts

The following concepts are fundamental to understanding how API Key and Secret authentication works in Spring Security.

**Authentication: It verifies the identity of the client making the request.

**Example: Checking whether the provided API Key and Secret are valid.

**Authorization:It determines whether the authenticated client has permission to access a resource.

**Example: Allowing authenticated users to access /api/** endpoints.

2. API Key and Secret

3. Custom Authentication token

A custom authentication token stores the API Key and Secret during the authentication process.

4. Custom Authentication Filter

The filter intercepts incoming HTTP requests and extracts credentials from request headers.

5. Security Configuration

Spring Security configuration defines:

6. API Endpoint

The controller exposes secured REST endpoints that can only be accessed after successful authentication.

Implementation to Secure Spring Boot API With API Key and Secret

We can develop the simple spring boot application that can demonstrates the securing spring boot API key and secret of the application.

Step 1: Create the Spring project.

Create a new Spring Boot project using Spring Initializr and add the required dependencies,

**pom.xml

XML `

4.0.0 org.springframework.boot spring-boot-starter-parent 3.2.5 org.example spring-boot-secure-API 0.0.1-SNAPSHOT spring-boot-secure-API spring-boot-secure-API <java.version>17</java.version> org.springframework.boot spring-boot-starter-security org.springframework.boot spring-boot-starter-web

    <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>

`

After the creation of the project has done, the folder structure will be like below image.

Folder Structure

Step 2: Configure the Application properties

Open application.properties file and add the configuration for the server port in the project.

spring.application.name=spring-boot-secure-api
server.port=8081

Step 3: Create the ApiKeyAuthentication Token class

Create a custom authentication token class.

package org.example.springbootsecureapi.config;

import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.core.GrantedAuthority;

import java.util.Collection;

public class ApiKeyAuthenticationToken extends AbstractAuthenticationToken {

private final String apiKey;
private final String apiSecret;

public ApiKeyAuthenticationToken(String apiKey, String apiSecret) {
    super(null);
    this.apiKey = apiKey;
    this.apiSecret = apiSecret;
    setAuthenticated(false);
}

public ApiKeyAuthenticationToken(String apiKey, String apiSecret, Collection<? extends GrantedAuthority> authorities) {
    super(authorities);
    this.apiKey = apiKey;
    this.apiSecret = apiSecret;
    super.setAuthenticated(true);
}

@Override
public Object getCredentials() {
    return this.apiSecret;
}

@Override
public Object getPrincipal() {
    return this.apiKey;
}

@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
    if (isAuthenticated) {
        throw new IllegalArgumentException("Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
    }
    super.setAuthenticated(false);
}

@Override
public void eraseCredentials() {
    super.eraseCredentials();
}

}

`

Step 4: Create the ApiKeyAuthFilter class

Create a custom filter that intercepts requests.

package org.example.springbootsecureapi.config;

import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; import org.springframework.security.web.util.matcher.RequestMatcher;

import java.io.IOException;

public class ApiKeyAuthFilter extends AbstractAuthenticationProcessingFilter {

private static final String API_KEY_HEADER = "API-Key";
private static final String API_SECRET_HEADER = "API-Secret";

public ApiKeyAuthFilter(RequestMatcher requiresAuth) {
    super(requiresAuth);
}

@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
        throws AuthenticationException, IOException {
    String apiKey = request.getHeader(API_KEY_HEADER);
    String apiSecret = request.getHeader(API_SECRET_HEADER);

    if (apiKey == null || apiSecret == null) {
        throw new RuntimeException("Missing API Key or Secret");
    }

    Authentication auth = new ApiKeyAuthenticationToken(apiKey, apiSecret);
    return getAuthenticationManager().authenticate(auth);
}

@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
    super.successfulAuthentication(request, response, chain, authResult);
    chain.doFilter(request, response);
}

}

`

Step 5: Create the SecurityConfig class

Create the SecurityConfig class.

package org.example.springbootsecureapi.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.core.authority.SimpleGrantedAuthority; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import java.util.Collections;

import java.util.Collections;

@Configuration @EnableWebSecurity public class SecurityConfig {

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    ApiKeyAuthFilter filter = new ApiKeyAuthFilter(new AntPathRequestMatcher("/api/**"));
    filter.setAuthenticationManager(authentication -> {
        String apiKey = (String) authentication.getPrincipal();
        String apiSecret = (String) authentication.getCredentials();

        if ("valid-api-key".equals(apiKey) && "valid-api-secret".equals(apiSecret)) {
            return new ApiKeyAuthenticationToken(apiKey, apiSecret, Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")));
        } else {
            authentication.setAuthenticated(false);
        }

        return authentication;
    });

    http
            .csrf().disable()
            .authorizeRequests(authorizeRequests ->
                    authorizeRequests
                            .requestMatchers("/api/**").authenticated()
                            .anyRequest().permitAll()
            )
            .addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);

    return http.build();
}

}

`

Step 6: Create the ApiController class

package org.example.springbootsecureapi.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 ApiController {

@GetMapping("/data")
public String getSecureData() {
    return "This is Spring Boot API secured data!";
}

}

`

Step 7: Main Class

Create the Spring Boot entry point.

Java `

package org.example.springbootsecureapi;

import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication public class SpringBootSecureApiApplication {

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

}

`

Step 8: Run the application

Once, we run the application, it will start at port 8081.

Application Runs

Step 9: Endpoint Testing

1. Endpoint without the api key and secret

GET http://localhost:8081/api/data

Then show the error like below:

Missing API Key and secret

**Output:

API Missing Error Message

2. Endpoint Test with API key and secret

GET http://localhost:8081/api/data

Add the API key and secret in Header section.

API Key : valid-api-key
API Secret: valid-api-key

Output:

API Key and Secret

By the following these steps, we can secure the Spring Boot API using API keys and secrets. This method ensures that only the clients with valid credentials can access the API endpoints and thereby adding the extra layer of the security to the Spring Boot application.