Information Security 8 min read

Implementing API Key Authentication in Spring Security for REST APIs

This tutorial explains how to secure a Spring Boot REST API using API key authentication, covering the addition of Maven dependencies, creating a custom filter, extending AbstractAuthenticationToken, configuring the security filter chain, and testing the protected endpoint with curl commands.

Architect
Architect
Architect
Implementing API Key Authentication in Spring Security for REST APIs

Security is crucial for REST APIs; an insecure API can expose sensitive data. This guide shows how to protect a Spring Boot REST API using API‑key authentication with Spring Security.

1. Overview

API keys are tokens that clients provide when calling an API, allowing authentication without a user context.

2. REST API Security

Spring Security can protect REST APIs using Basic authentication, OAuth2, JWT, or API keys. Because REST APIs are stateless, API‑key authentication is a lightweight option.

3. Implement API Key Protection

3.1 Add Maven Dependency

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

3.2 Create Custom Filter

public class AuthenticationFilter extends GenericFilterBean {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
            throws IOException, ServletException {
        try {
            Authentication authentication = AuthenticationService.getAuthentication((HttpServletRequest) request);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        } catch (Exception exp) {
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            httpResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
            PrintWriter writer = httpResponse.getWriter();
            writer.print(exp.getMessage());
            writer.flush();
            writer.close();
        }
        filterChain.doFilter(request, response);
    }
}

3.3 Authentication Service

public class AuthenticationService {
    private static final String AUTH_TOKEN_HEADER_NAME = "X-API-KEY";
    private static final String AUTH_TOKEN = "Baeldung";

    public static Authentication getAuthentication(HttpServletRequest request) {
        String apiKey = request.getHeader(AUTH_TOKEN_HEADER_NAME);
        if (apiKey == null || !apiKey.equals(AUTH_TOKEN)) {
            throw new BadCredentialsException("Invalid API Key");
        }
        return new ApiKeyAuthentication(apiKey, AuthorityUtils.NO_AUTHORITIES);
    }
}

3.4 ApiKeyAuthentication Token

public class ApiKeyAuthentication extends AbstractAuthenticationToken {
    private final String apiKey;

    public ApiKeyAuthentication(String apiKey, Collection
authorities) {
        super(authorities);
        this.apiKey = apiKey;
        setAuthenticated(true);
    }

    @Override
    public Object getCredentials() { return null; }

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

3.5 Security Configuration

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests()
            .antMatchers("/**").authenticated()
            .and()
            .httpBasic()
            .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .addFilterBefore(new AuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }
}

3.6 Resource Controller

@RestController
public class ResourceController {
    @GetMapping("/home")
    public String homeEndpoint() {
        return "Baeldung !";
    }
}

4. Testing

Without providing an API key, the request returns a 401 Unauthorized error.

curl --location --request GET 'http://localhost:8080/home'

When the valid API key is added to the request header, the endpoint returns 200 OK.

curl --location --request GET 'http://localhost:8080/home' \
--header 'X-API-KEY: Baeldung'

Source: Baeldung tutorial on Spring Boot API‑key authentication.

JavaAuthenticationREST APISpring SecurityAPI key
Architect
Written by

Architect

Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.