Spring Boot security restrict requests to IP address range

Spring Boot security restrict requests to IP address range

In a microservice architecture, it is crucial to restrict access to the APIs. So that we do not run into the problem that every microservice calls another and create a dependency mess. For that reason, services should only accept requests from specific services in which their IP addresses are whitelisted. That can be accomplished using Spring Boot Security. In this tutorial, we discuss how to configure Spring Boot security to restrict requests to a specifc IP address range.

An imaginary scenario

Let’s assume we have two microservices for a music player application, User and Song. The Song microservice interacts often with the User microservice to get the necessary information. But we don’t want any other services to access the User service for whatever reason. For that, our objective is to restrict incoming requests to those that originated from the Song service. Both services are also behind a load balancer, so we need to take that into consideration when implementing the solution. To understand the use case better, have a look at the following diagram,

Spring Boot security restrict requests to IP address range
Architecture overview

Restricting incoming requests to certain IP range with Spring Boot security

Before implementing anything, we need to add the Spring Boot security dependency to the classpath. In the Maven project, we can do that by adding spring-boot-starter-security as follow,

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

Spring Security has a nice feature that can restrict incoming requests. If any does not match the criteria defined, the client will get a 403 (forbidden) response. So all we have to do is to create a SecurityConfig file that extends WebSecurityConfigurerAdapter as follows,

import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private static final String HAS_SONG_SERVICE_IPS = "hasIpAddress('90.100.1.0/22') or hasIpAddress('140.134.165.0/20')";

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests().antMatchers(HttpMethod.POST,"/v1/**").access(HAS_SONG_SERVICE_IPS);
    }
}

In the above code, we intentionally disable the csrf token since the service exposes APIs only and has no web interface. Then we need to specify which path we intend to apply authorization. Lastly, limit the APIs based on an IP address range.

We can apply the IP restriction in two ways, one using the hasIpAddress() method that accepts a single IP or IP range or passes a string to the access method and provide as many IP or IP range as we want. For the current example, the assumption was that we have more than one IP range. Hence, we use the latter.

Now if we run the program, nothing works. As stated earlier in the use case section, the User microservice is behind a load balancer, hence, it rejects all the requests. That’s because the client IP is stored in X-Forwarded-For that Spring security does not handle by default. The simplest solution is to use the X-Forwarded-For value instead. For that, we need to add the following configuration to the application.properties,

server.use-forward-headers=true

After that, we should get the result as expected, and incoming requests are filtered properly.

Conclusion

In this article, we covered how to use Spring Boot Security to restrict requests to IP address range. Only applying the filter only doesn’t work as in most environments services are behind load balancers. Therefore, one should set the X-Forwarded-For flag to true.

Besides Spring Security, there is another approach to restrict incoming requests by creating a filter. We cover that in the “Spring Boot filter incoming requests based on IP” post.

Inline/featured images credits