Brute Force Attack in Spring Boot with Bearer Tokens
Brute Force Attack in Spring Boot with Bearer Tokens — how this specific combination creates or exposes the vulnerability
A brute force attack against an API using Bearer tokens in a Spring Boot application typically targets authentication endpoints or token validation paths. In this setup, an attacker attempts many token values or token request parameters to discover valid tokens or to bypass token checks. Spring Boot does not inherently prevent high-rate authentication attempts unless explicit mechanisms are configured, so an unprotected login or token-introspection endpoint can be probed at scale.
Consider an endpoint that validates a Bearer token via a custom filter:
@Component
public class BearerTokenFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String header = request.getHeader("Authorization");
if (header != null && header.startsWith("Bearer ")) {
String token = header.substring(7);
if (isValid(token)) {
// proceed
} else {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid token");
}
} else {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Missing token");
}
filterChain.doFilter(request, response);
}
}
If isValid performs a lookup with variable time or reveals different responses for malformed vs unknown tokens, an attacker can iteratively submit guessed tokens and observe timing or status differences. Without rate limiting, each request is independent and fast, enabling rapid enumeration. This becomes more pronounced when token entropy is low, tokens are predictable, or token issuance logic leaks information (e.g., account enumeration via timing or messages). The attack surface includes not only the resource server but also any introspection or revocation checks that accept token values as input.
Spring Security’s default configuration for OAuth2 Resource Server with Bearer tokens validates JWT signatures and claims, but does not automatically enforce strict rate controls on token validation paths. An attacker can send many requests with slightly altered tokens to test validity, especially if error handling is inconsistent. This maps to authentication weaknesses and can intersect with BOLA/IDOR when token scopes or identifiers are guessable. Intrusion patterns such as token spraying—trying a few common tokens across many user IDs—further illustrate how the combination of Spring Boot, Bearer tokens, and missing anti-abuse controls creates exploitable conditions.
Bearer Tokens-Specific Remediation in Spring Boot — concrete code fixes
Remediation focuses on making token validation resilient to enumeration and brute force by standardizing responses, enforcing rate limits, and ensuring token handling does not leak information. Below is a hardened filter example that uses constant-time comparison and returns uniform error messages regardless of token format.
@Component
public class BearerTokenFilter extends OncePerRequestFilter {
private final RateLimiter rateLimiter; // e.g., Guava or Resilience4j
public BearerTokenFilter(RateLimiter rateLimiter) {
this.rateLimiter = rateLimiter;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String header = request.getHeader("Authorization");
boolean shouldProceed = false;
if (header != null && header.startsWith("Bearer ")) {
String token = header.substring(7);
// Rate limit by IP or API key subject extracted from token claims if available
if (rateLimiter.tryAcquire(request.getRemoteAddr())) {
shouldProceed = validateTokenConstantTime(token);
}
}
if (!shouldProceed) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write("Unauthorized");
return;
}
filterChain.doFilter(request, response);
}
private boolean validateTokenConstantTime(String token) {
// Use a stable expected token or lookup with fixed cost
String expected = computeExpectedToken(); // e.g., from secure vault
return MessageDigest.isEqual(expected.getBytes(StandardCharsets.UTF_8),
token.getBytes(StandardCharsets.UTF_8));
}
}
In Spring Security Java configuration, integrate the filter and set authentication entry points to avoid leaking stack traces:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http, BearerTokenFilter bearerTokenFilter) throws Exception {
http.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(bearerTokenFilter, UsernamePasswordAuthenticationFilter.class)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
)
.exceptionHandling(ex -> ex.authenticationEntryPoint(
(req, res, ex1) -> res.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized")
));
return http.build();
}
}
Complement these code fixes with operational controls: enable rate limiting at the gateway or via Spring Cloud Gateway, use tokens with sufficient entropy, rotate secrets regularly, and monitor for repeated 401 patterns. The dashboard can track authentication-related risk indicators over time, while the CLI allows you to run middlebrick scan <url> to verify that your endpoints no longer expose token validation anomalies. For CI/CD, the GitHub Action can enforce a maximum risk score before merge, and the MCP Server enables on-demand scans from your AI coding assistant during development.