This topics comes up a lot: “how do I do authorization for my service architecture?” or if they are hip with the kids “how do I do authorization for my microservices”. The answer to both is the same…
Firstly some definitions:
- the process of confirming, to a level of certainty, a user is who they say they are. Often this is done with a username and password pair, but could be done with a certificate, PIN, token, fingerprint or anything else.
- the process of making sure that people can only do the things they should be allowed to and see the data they should be allowed to.
The Authorization-as-a-Service Anti-Pattern
Now at first guess it might make sense to have a service that does authorization. Why not, you can put all that complexity in one place and not worry about it anymore, safe in the knowledge that all that difficult authorization logic is encapsulated.
Trouble is when you add a new feature in an other service you need to make a change to your authorization service, to enforce the correct access to that service. It turns out everytime you make a change to any other service 9 times out of 10 you are then making a modification to the authorization service. This quickly gets tedious - it smells wrong.
Say you decided to live with the inconvience of the above double modification problem, who do you get to maintain and run the authorization service. You could have one team do it. However fairly rapidly they are going to be inundated with change requests, because every change to any other services needs a change to their service (most of the time at least).
The other option is to allow the teams who require the change to make the changes to the authorization service themselves. Trouble is then you have many teams churning a service’s code base that they don’t own then they don’t feel, indeed literally they don’t have, ownership and that’s a recipe to declining quality.
On top of all this, the releases of the authorization service needs to be sychnorized with all the other services that have been modified recently. Pretty soon you are in a stop-the-world type release process where every service in your estate needs releasing at the same time. The logistics are a nightmare.
The simplest solution to the problem is to have authentication as a service; that is proving I am who I say I am.
Once you have the ability for a service to determin within a level of certainty that a user is who they say they are, then you can do authorization in each service. What better place to have the complex logic of who can do what than in the code that does the what.
For example consider a service that is responsible for providing access to a financial trading platform. It allows brokers to buy and sell a stock. Now the service might be aware that certain brokers can only buy €100k of the stock each day, it keeps track of this, because that’s what it does, rather than reaching out to an external service to ask, it has the information right there, it knows who you are, what you’ve bought and the rules for how much you can buy - it’s cohesive. Now say you want to change it so that brokers can only buy stock Monday through Friday, again all the information is there. There is no need to go anywhere else.
Perhaps you might write a library, a shared object, dll, jar or npm for it that others can reuse. JaaS and implementations thereof are a good example of something approximating a good design here, but don’t create a service, you’ll regret it.