We are trying to determine the best way to authorise users in a microservice architecture, while ensuring microservices have limited permissions. Our architecture uses a central authorisation service to handle issuing of JWT tokens.
We have the following requirements:
Users should be limited to perform certain roles. e.g. a user should only be able to create/modify/read content that he owns.
Microservices should be limited to only the permissions they require. e.g. a microservice that only needs to read data from another service should be explicitly forbidden from writing data to that service.
As an example, suppose we have a system where users can upload pictures to an image store service. We have a tagging service that automatically tags pictures with a location. Users can only CRUD their own pictures. The tagging service can read any image from the image store service, however should not be able to modify/delete.
What is a good way to achieve the above using JWT tokens? Some solutions that we've discussed are:
The image store service expose 2 APIs, one that is available externally (giving user CRUD access), and one that is available internally (giving internal read-only access). Seems inflexible - what if another internal service needs read/write access to all images (e.g. one that automatically deletes explicit images)?
We set up two permissions in the user's JWT, one being CRUD_OwnImages, the other being READ_ForAnalysis. The tagging service can see if the user has READ_ForAnalysis permissions, and if so, make the appropriate request. We have another microservice that checks to see if user has CRUD_OwnImages for CRUD operations on the user's own images. This puts the responsibility on each microservice to ensure that the user is restricted to the actions he requires. The image store has no way to restrict each microservice with this approach, so it is potentially flakey and error prone.
We give the tagging microservice its own user, with READ_ForAnalysis as a permission. Then, when the tagging service requests images from the image store, it is given access to those, but is forbidden from modifying them. The user's user only has CRUD_OwnImages permission, so he is able to retrieve and get access to only his images from the frontend. If another service needs CRUD to all data, we can give it CRUD_AllData or similar. We like this approach as each service is now responsible for its own data (rather than that logic being duplicated across multiple services), but what if the service requires both user permissions and microservice permissions? Can we send two JWT tokens (both the user's and the microservice's) securely? Is there a way to combine permissions securely and send that through? e.g. the tagging service can read all images but can also write the user's images with the location?
The problem is exacerbated if the user information is needed further downstream (2 or 3 microservices away). Do we just assume that it is up to individual microservices to restrict themselves to the actions that they need, and not make that explicit?