Search code examples
spring-securityjwtmicroservicesspring-security-oauth2spring-security-rest

How to Authorize micro-services internal communication?


I have multiple micro-services. which can be called by client through API gateway and also micro-services can communicate each other.

Ideally request will come from API gateway from user which will have all permissions. here i am trying to assign only required role to user for example if user(browser) need data from micro-service A then only that role will be given to user and if internally micro-service A needs data from B(rest call) then that role should not be assigned to user.

Requirement: how to restrict/authorize internal communication between micro-services so that only authorized micro-service can make call to others.

Options:

  1. Assign all roles to user, even for internal communication(passing same token in all communications).

  2. Assign only user facing micro-services role to user if internal communication is require then each micro-services will act as a user itself to other micro-service and generate there own token before call.

  3. Do not allow micro-service to communicate internally rather fetch all data from all micro-services and process at client.

What option will be best using above or any other?


Solution

  • I'd go with option number 2. For intra-service communication, backend services (applications) will act as a client and would request a token first (/oauth/token). To validate these tokens all services will need a mechanism to verify these tokens (/oauth/check_token). You can use Client Credentials Grant type for this. These /oauth/** endpoints are provided by Spring. For making REST request from one service to another, use OAuth2RestTemplate and its not thread-safe.

    In each application, you'd need to define security protection rules for various endpoints. Something like this:

    <sec:filter-security-metadata-source id="securityMetadataSource"
                                             request-matcher="ant"
                                             use-expressions="true">
            <sec:intercept-url pattern="/accounts/**" access="isFullyAuthenticated() and hasRole('PRIVATE_SERVICE')"/>
            <sec:intercept-url pattern="/members/member-details" method="GET" access="isFullyAuthenticated() and hasRole('PORTAL_USER')"/>
    

    For more restriction, you issue self-signed certificate per application (not per application instance). Add public key of all applications in a single truststore. During application startup, let all application download this truststore. With this application will talk to only those applications it trust.