'Authorisation in microservices - how to approach domain object or entity level access control using ACL?

I am currently building microservices based system on java Spring Cloud. Some microservices use PostgreSQL and some of them MongoDB. REST and JMS is used for communication. The plan is to use SSO and OAuth2 for authentication

The challenge I am facing is that authorisation have to be done on domain object/entity level. It means some kind of ACL (Access Control List) is needed. The best practice for this kind of architecture is to avoid something like this and have coarse grained security probably on application/service layer level in every microservice but unfortunately it is not possible.

My final idea is to use Spring Security ACL and have the ACL tables in shared database between all microservices. The database would be accessed only by Spring infrastructure or through Spring api. The DB schema looks stable and unlikely will change. In this case I would simply break the rule about sharing db between microservices.

I was considering different kinds of distributed solutions but left them:

  • One microservice with ACL and accessing it using rest - The problem is too many http calls and performance degradation. I would have to extend Spring Security ACL to replace db access by rest calls
  • ACL in every microservice for its own entities - Sounds quite reasonable but imagine a case having some read models of entities synchronised to some other microservices or same entity that exists in different bounded contexts (different microservices). ACLs can become really unmanageable and can be source of errors.
  • One microservice with ACL tables that are synchronised to other microservices as a read model. The problem is that there is no support in Spring Security ACL for MongoDB. I have seen some custom solutions on github and yes it is doable. But...when creating a new entity I have to create record in the microservice that owns ACL and then it is asynchronously synchronised as a read model to microservice owning the entity. It does not sound as a easy solution
  • Choose some URL based access control on API gateway. But I would have to modify Spring Security ACL somehow. The API gateway would have to know too much about other services. Granularity of access control is bound to REST api granularity. Maybe I can not imagine all the consequences and other problems that would this approach bring
  • Finally the solution with shared db that I mentioned is my favorite. Actually it was the first one I have disqualified because it is “shared” database. But after going through possibilities it seemed to me that this is the only one that would work. There is some more additional complexity in case I would like to use some kind of caching because distributed cache would be needed.

I would really use some advice and opinions how to approach the architecture because this is really tricky and a lot of things can go wrong here.

Many thanks,

Lukas



Solution 1:[1]

I don't have a full and clear picture of your authorization requirements. I'm assuming a correlation between authenticated users and domain object/entity permissions.

One option to consider is to define user attributes corresponding to your domain object/entity permissions, and implement an Attribute-based Access Control (ABAC) policy.

The attributes are tied to and stored with the users identity in your repository, and retrieved when performing your authentication.

Solution 2:[2]

Shared Db is the best option with two data sources RO and RW. RO is for regular usage and RW for creating and modifying acl. We can think of storing the ACL in index server for faster look up. One final say for fastness is define / create more accessible fashion so that we can transact less. Especially acl based data approach has this caveat. In micro services approach the way to access data subjected to acl is first get data and filter based on the acl

Solution 3:[3]

I think nowadays a Google Zanzibar based approach would be best suited for this. While tying services closer to each other - because every ACL related request must talk to the zanzibar service to evaluate on permissions - Googles paper on zanzibar describes really well how they solved the problem of latency and eventual consistency (or the "new enemy" problem in this case).

This is pretty much the "Shared Database" approach, but with a problem specific way of storing the database.

OSS implementations exist see SpiceDB (which supports CockroachDB as Backend) or Ory Kratos for example.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Anthony
Solution 2 Sri
Solution 3 Eifoen