How to handle internal service-to-service authentication in an SOA environment

Viewed 209

I'm building an SOA architecture which consists of a simple NGINX-based API gateway which forwards calls from browser clients to an appropriate backend API based on their prefix, for example:

  • /auth/login will route the call to the login endpoint on the Authentication service
  • /users/update/widget-1 will route the call to the update endpoint on the Users service

etc.

Each service has its own datastore and follows SOLID design principles. I use events on a queue to keep services informed about interesting things that happen to data that they both know about. For example, both the Users service and the Authentication service need to store the user's email address as it's used for authentication and emailing. So when a user's email is changed I queue a 'user email change' event onto a User Events queue. The Authentication service subscribes to this queue and uses the event to keep itself up to date.

For simple events, I can include enough details in the event to avoid needing more information. But, thinking ahead, what if a lot of changes have happened to the user and I have a datawarehouse that subscribes to every event type. I don't want to start having huge events - I would rather just include enough information for the interested service to use the event to trigger a call to ask for more details.

So the sequence in this example would be:

  1. Client synchronously calls user update with JWT bearer token
  2. User update service validates JWT and uses it to carry out the update
  3. User update service generates a 'user updated' event to the queue, containing the User ID
  4. Datawarehouse picks up the event and calls a 'get user details' endpoint on the User service to get full details of the update.

How do I authenticate the 'internal service call'? I can't use the original JWT as the internal request is happening asynchronously and the calling service doesn't have the JWT. It might not even be valid any more by the time the Datawarehouse requests the user details. It feels like I need some 'internal' JWT - for example, in this case, would the answer be for the Datawarehouse service to have the ability to generate its own JWT with its own private key then the User service checks the signature using the Datawarehouse service's public key? In which case, doesn't this mean each service would have to know about all the other services that could call it?

If it helps, my current implementation uses Lumen for the services with the jwt-auth package to check the JWT at the API level.

Any advice is appreciated, thanks.

0 Answers
Related