5

In our environment (as in many others), it is often the case that one microservice must call another in order to accomplish a task.

In our environment, authentication is clear enough - we have a signed JWT containing a list of permissions and roles, as well as a user ID, client ID, and so on.

What we're less clear on is authorization - ensuring that the authenticated client can (or can't) do the right stuff, but that the underlying services have all the access they need to do their jobs (even if the client wouldn't be able to do the same things directly).

We've examined a few different options:

  1. Each service does all of its own authorization, and if a privilege escalation is needed, it generates a "God mode" token with an otherwise unchanged payload and a different keypair and makes the call using that. The main concern here is copy/pasted authorization code, and the fact that there'll be a strong incentive to just always enable God mode when making cross-service calls (which makes it somewhat redundant).
  2. Each service does all of its own authorization, and just forwards the user's token if it needs to make a call. The concern here is code duplication like in option 1, and also the fact that this is likely to cause a complex interdependent web of permissions that imply other permissions that imply other permissions that... (ad nauseam), creating a maintenance headache as the number of services grows.
  3. A lightweight API gateway service that does "simple" authorization (nothing more advanced than "is this client allowed to use this endpoint at all?"), attaches a user object to the payload, and leaves more specific behaviours to the underlying services, which accept any call as being authorized out of the gate. The major concern with this option is performance and stability - the API gateway service creates a single point of failure that can make the entire system inaccessible if it malfunctions, plus creating a frequently-changing dependency for every service.

The question here is twofold:

  1. Are there any additional pitfalls to the three patterns described above that we haven't considered?
  2. Which of these is the most common in the wild?

Note that this question is not about service mesh offerings like Istio, as we consider them to be somewhat orthogonal to this issue.

1
  • You should look into ABAC and XACML. These standards are there for that very reason. Aug 23, 2019 at 21:06

1 Answer 1

1

All of these options will, of course, work; however, this is largely what API gateways exist for - providing the consumer interface and applying concerns that cut across multiple services.

Authorization is the epitome of this type of concern. This way you can tie permissions to consumer "actions," regardless of how many underlying services and calls are involved and keep your microservices focused on their respective domains.

Performance and stability shouldn't really be a concern - this is a well-established pattern and there are many well-established, stable products available with existing support and integrations for common authorization patterns.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.