Spring Boot cookbook · Intermediate
Authenticate machine clients with API keys in Spring Security
Allow server-to-server clients to call your API with hashed, revocable API keys.
Approach
Add a filter to the SecurityFilterChain that reads X-API-Key, hashes it (SHA-256), looks up an active client, and sets an Authentication with the client's authorities. Store only hashes, show keys once on creation, and support multiple keys per client for rotation.
Solution
public class ApiKeyAuthFilter extends OncePerRequestFilter {
private final ApiClientRepository clients;
public ApiKeyAuthFilter(ApiClientRepository clients) { this.clients = clients; }
@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
throws ServletException, IOException {
String key = req.getHeader("X-API-Key");
if (key != null) {
String hash = HexFormat.of().formatHex(MessageDigest.getInstance("SHA-256") // wrap NoSuchAlgorithmException in real code
.digest(key.getBytes(StandardCharsets.UTF_8)));
clients.findActiveByKeyHash(hash).ifPresent(client -> {
var authorities = client.scopes().stream().map(s -> new SimpleGrantedAuthority("SCOPE_" + s)).toList();
var auth = new UsernamePasswordAuthenticationToken("client:" + client.id(), null, authorities);
SecurityContextHolder.getContext().setAuthentication(auth);
});
}
chain.doFilter(req, res);
}
}
@Bean
SecurityFilterChain machineApi(HttpSecurity http, ApiClientRepository clients) throws Exception {
return http.securityMatcher("/api/partner/**")
.addFilterBefore(new ApiKeyAuthFilter(clients), UsernamePasswordAuthenticationFilter.class)
.authorizeHttpRequests(a -> a.anyRequest().hasAuthority("SCOPE_partner:read"))
.sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.csrf(c -> c.disable())
.build();
}
Pitfalls
- Registering the filter as a
@Componenttoo (Boot auto-registers it for every request). - Plaintext key storage.
- Keys in query strings (logged by proxies).
Variations
- OAuth2 client credentials with an IdP for larger partner ecosystems.
- mTLS for high-assurance service-to-service auth.
Further reading: Spring Security: Architecture
Reference: https://docs.spring.io/spring-security/reference/servlet/architecture.html
More Spring Boot recipes
- Add correlation IDs to Spring Boot logs
- Add retries and a circuit breaker with Resilience4j
- Cache service results in Redis with @Cacheable
- Consume Kafka messages with retries and a dead-letter topic
- Handle concurrent updates with optimistic locking
- Implement soft delete with Hibernate
- Make POST endpoints idempotent in Spring Boot
- Map entities to DTOs with MapStruct