How to Prevent Direct Access to Microservices Using Spring Boot API Gateway

In a microservices architecture, the API Gateway is the single entry point for clients. It handles authentication, logging, routing, rate limiting, and many other cross-cutting concerns.

But there is a common mistake: Even after building an API Gateway, microservices are still directly accessible.

This means anyone can bypass the gateway and call your services directly — which is a serious security risk.

In this article, we will learn how to force all requests to go through the API Gateway and block direct access to Spring Boot microservices

We want this flow:

Client → API Gateway → Order Service → Product Service        

And we want to block this:

Client → Order Service   ❌
Client → Product Service ❌        

Step 1 — Add a secret header in the API Gateway : The API Gateway will attach a secret key to every request sent to microservices.This secret will act as proof that the request came from the gateway.

application.yml in API Gateway

spring:
  cloud:
    gateway:
      default-filters:
        - AddRequestHeader=X-GATEWAY-TOKEN, my-super-secret-key
        

Now every request sent from the gateway will contain:

X-GATEWAY-TOKEN: my-super-secret-key        

Step 2 — Configure the secret in microservices

In Order Service, Product Service, etc.

application.yml

gateway:
  secret: my-super-secret-key        

This value must be the same as the gateway token.

Step 3 — Create a filter in each microservice

This filter will check if the request contains the gateway token. If the token is missing or invalid, the request will be rejected.

Create GatewayOnlyFilter.java

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

@Component
public class GatewayOnlyFilter extends OncePerRequestFilter {

    @Value("${gateway.secret}")
    private String gatewaySecret;

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain)
            throws ServletException, IOException {

        String token = request.getHeader("X-GATEWAY-TOKEN");

        if (token == null || !token.equals(gatewaySecret)) {
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            response.getWriter().write("Direct access is not allowed");
            return;
        }

        filterChain.doFilter(request, response);
    }
}
        

This code ensures:

  • If the request is not from the API Gateway, it will be blocked.
  • If it is from the gateway, it will be allowed.

If you use Spring Security

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
      .csrf().disable()
      .authorizeHttpRequests()
      .anyRequest().authenticated()
      .and()
      .addFilterBefore(new GatewayAuthFilter(),
                       UsernamePasswordAuthenticationFilter.class);

    return http.build();
}
        


Step 4 — Test the behavior

Direct call to microservice (should fail)

curl http://localhost:8081/orders        

Response:

403 Forbidden
Direct access is not allowed        

Call through API Gateway (should succeed)

curl http://localhost:8080/orders        

Response:

200 OK
[ Order data... ]        

Because the API Gateway automatically adds:

X-GATEWAY-TOKEN: my-super-secret-key        




Thanks for the clear explanation

To view or add a comment, sign in

More articles by Vinothkumar P

Explore content categories