A big challenge with API based microservices architecture is handling authentication (authN) and authorization (authZ) . If you are like most companies today, you are probably using some sort of OAuth identity provider like OpenID, Google, GitHub, etc. This takes care of both identity and authentication, but authorization (AuthZ) is not addressed by this.
In our previous blog posts, we discussed two REST API best practices for making one Database call per API route and assembling complex objects that need to be displayed in the UI. In response, one of our readers asked a great question: If the design pattern is to always make one DB call per API route and then handle joins in the UI to create complex objects, how do we manage authorization/permissions? With a finished API, you can abstract it across the lower level APIs.
This blog describes pros and cons of two options we considered for handling authZ and why we chose the approach we did. Our two possible approaches were:
- Create a user on the DB for every single user who interacted with our service and manage all permissions at the DB level
- Create a superuser DB account that has “data modification access” and no “data definition access,” and use that account to access data
We were initially hesitant to go with option 2 since it meant accessing all data with superuser credentials, which felt like we weren't enforcing permissions at the lowest level we could.
Let's look at both options in greater detail.