Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How an authorization service implements ownership checks in a role-based microservice architecture

Let's say I have three types of users on a blogging app

  1. Author (is able to modify their own posts but not others)
  2. Administrator (is able to modify all posts)
  3. Reader (can not modify any posts)

To manage this system I want to have three main services:

  • An API Gateway that exposes all the APIs clients will consume, composing services as needed.
  • A Post Management Service which provides the CRUD operations for blog posts (including the data of who owns what posts)
  • An Authorization Service which stores roles and permissions, exposing an API which takes in an array of roles (the roles a requesting user has) and an array of permissions (the permissions needed to access an API) and determines if those inputted roles cover all the permissions inputted.

Now what I am struggling with is ownership of a resource (and where ownership should be checked).

Without communicating with other services how would an authorization service determine if a user should be able to access something they own without knowing how to determine if a user owns a given resource.

I've come up with a few different solutions to this problem, although I'm not quite happy with any of them.

  1. The API Gateway would query a different service that manages the posts to determine if a requesting user owns the post they are trying to access, this would mean there is authorization logic that happens outside of the authorization service.
  2. The service managing blog posts would handle authorization based on ownership, this would also mean authorization logic is happening outside the authorization service as well as the fact that unauthorized requests are being marked as authorized initially (since they will still pass through the authorization service)
  3. The Authorization service could be given the knowledge of how to check ownership, the API would have to be able to be told whether or not it should check for ownership along with the permissions. This would add complexity to the authorization service and increase the cross-service communication which I'd like to relegate as much as possible to the API gateway since it should be the primary service composer.

Looking for ideas on alternative methods or insight into what the best solution to this problem might be.

like image 871
Ben Sears Avatar asked Nov 18 '22 08:11

Ben Sears


1 Answers

Usually access to resources is based on the ownership of the resources. For example, a resource that represents insurance quotes. To access an insurance quote, you must be the user who made the quote.

Our approach is to expose the /quotes resource over the gateway with the path:

GET /quotes/{quoteId}

but to have the quotes microservice introduce the user ID into the quotes resource path like:

GET /quotes/{userId}/{quoteId}

This allows the quotes microservice to search for the quote within the context of the user, and to return a 404 if this path is not valid.

In order to enable this architecture, the gateway needs to gather the claims for the caller based on the caller's bearer token, and inject the value of the userId claim into the downstream path. This is illustrated below:

enter image description here

This ownership-based approach to access can be extended to include other claims (such as administrative claims, etc) very easily.

like image 61
tom redfern Avatar answered Dec 23 '22 04:12

tom redfern