Search code examples
javaspring-bootspring-securitymicroservices

Should internal micro-services communication goes through zuul gateway?


I am creating a microservices project using the Spring framework, but I have problems with internal microservices calls. when a user calls an endpoint of microservice A, the request goes through zuul gateway to check whether the jwt token is valid, and whether the user's role allows him to access this endpoint.. if everything is valid, the user is redirected to the endpoint of microservice A.. so far everything is clear. but the problem starts when the endpoint of microservice A calls another endpoint of microservice B. normally, what I have to do is passing the user's jwt in the header of the request going to microservice B.. but what if the role of the user does not allow him to access the endpoint of microservice B? what I am doing now is generating a new jwt in microservice A with a SYSTEM role to use it when calling microservice B.. but I think it's not a good practice for this reason : generating a new jwt forces me to put my private key in each microservice so that it can create a valid jwt each time i need it.. I know that I can make only one microservice doing this, and letting other microservices calling it for asking a new jwt.. but I risk falling into more serious security vulnerabilities, for example if a user looks its internet traffic, he will be able to see the jwt whose role is SYSTEM and use it to do what he wants.

all this is just because microservice A calls microservice B through zuul gateway.

my question is : is it mandatory to go through zuul if the call is internal? can microservice A call microservice B without going through zuul? in this case the validation of the jwt is done only when the user calls microservice A, and once it is validated by zuul, the microservices can communicate internally without needing to validate the jwt in each internal call? it also allows me to avoid creating a jwt with a SYSTEM role for each internal call.

is this a good practice? can't this cause security problems? can't this cause any other problem for example during deployment? are there other more good solutions?


Solution

  • Yes, you can call microservice B using microservice A without going through Zull. Probably you are using an Eureka Server/Client then you can take advantage of it using @LoadBalanced annotation. Assuming that you will do it using RestTemplate:

    Create a Bean in a Configuration class:

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate;
    }
    

    Then when you want to call the microservice B using the microservice A, you just have to put the name in the http request (assuming of the application.name of microservice be is "microserviceb":

    @Autowired
    RestTemplate restTemplate;
            
        public Object getObject(String xyz) {
        Object result = restTemplate.getForObject("http://microserviceb/someresource/{xyz}", Object.class, xyz);        
        return result;
    }
    

    If you want to continue passing the token in this requisition, you can get him in the RestController method, like it:

    @GetMapping("/someMapping")
    public String someMethod(@RequestHeader("Authorization") String accessToken) {
                
       HttpHeaders headers = new HttpHeaders();
       headers.setContentType(MediaType.APPLICATION_JSON);
       headers.set("Authorization", "Bearer "+accessToken);
                
       HttpEntity<String> entity = new HttpEntity<String>(requestJson,headers);
       String result = restTemplate.postForObject(http://microserviceb/someresource, entity, String.class);
       return result;           
    }
    

    I don't have any problem in microservices communication, the only thing that you should avoid is the client calling some microservice directly without pass in gateway (in this case you can use some firewall configuration or spring security)