Microservices and permissions

5,359 views
Skip to first unread message

Erol Merdanović

unread,
Sep 26, 2015, 3:47:10 PM9/26/15
to microservices
Hello

I'm interested how to "correctly" implement permissions into microservices. 

a) Should each microservice has it's own permissions system (user can add/edit/delete). Each microservice then exposes API endpoint to retrieve all available permissions, so that UI can be correctly rendered.

b) Should there be one microservice that holds permissions from all microservices. Once other microservices update permissions, it also updates main Permissions Service. There is one API endpoint for all permissions for UI to retrieve data for rendering.

Am I thinking in the right direction? Which option is better? Or is there option c? 

Chris Richardson

unread,
Sep 26, 2015, 4:33:00 PM9/26/15
to Erol Merdanović, microservices
Hi,

I'd imagine having some kind of "User Service" that manages users and their roles/permissions.

The UI would consult the User Services in order to tailor the UI.
Similarly, other microservices would query the user service in order to verify that the user is authorized to perform a particular request.

Chris

--
You received this message because you are subscribed to the Google Groups "microservices" group.
To unsubscribe from this group and stop receiving emails from it, send an email to microservice...@googlegroups.com.
To post to this group, send email to micros...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/microservices/34d2d3e0-6754-4f15-bfcc-4194804f872c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Erol Merdanović

unread,
Sep 28, 2015, 3:55:06 AM9/28/15
to microservices, zase...@gmail.com
Hi Chris

Thank you for your reply.

But using one service, don't I create a single-point-of-failure problem? I know that other services could cache the permissions. The other idea that I have is, shouldn't an API gateway hold all permissions? If it's handling authentication and authorization, I could also handle roles and permissions. In a way it's similar to UserService, but it should be able to filter the requests (user cannot create a company, so POST /api/companies is denied) before they hit under-laying microservices.

What do you think? Do you use something similar to UserService in production?

Luiz Francisco Artigas de Prá

unread,
Sep 28, 2015, 9:28:47 AM9/28/15
to microservices
Hi,

Interesting topic, Erol. I'm looking for asnwer for all these questions too.
Complementing, what about inter service permissions? What to do if I have a external service or a specific interface that must only access a part of my microservice methods? I can figure out to solutions: use user permissions even for another applications, something like oauth2 do with applications keys; or use another specific service to manage that kind of permission. Deal it application as if is an user seens more simples and lightweight in terms of request exchange. There are another option for this kind os problem?

Ty,
Luiz

Carsten Saathoff

unread,
Oct 6, 2015, 5:37:36 AM10/6/15
to microservices
Hi,

we had the same discussion a couple of weeks ago. We came up with an architecture in which each service is responsible for handling authentication and authorization itself, but the management of roles is handled by a single user service. We use Keycloak (http://keycloak.jboss.org/) as the identity provider that supports OAuth/openid-connect and provides JWT based access tokens. All services and users are managed in keycloak, authentication is done using OAuth standard flows. Keycloak then adds the roles of the authenticated user to the JWT token, which is sent around with all backend requests. Each microservices verifies the token and extracts the identity of the user and his roles. When the signature is valid, we can check whether the token is expired or not. If it is not expired we know that the user is still "logged in". We then use the provided roles to figure out the permissions of the user and accept or deny the request accordingly. So while the concrete "log in" (i.e. verification of credentials) is done by Keycloak, each microservices decides on its own (based on the token) whether the user is still authenticated and authorized for the requested action.

The advantage is that we don't have to scale out the user service as much, as it is not hit for every request on a backend service, and we don't need any caching in place to reduce that load. The caching happens through the JWT, so to say.

Using an api gateway to handle all auth* was another option, but we didn't like the idea of externalizing knowledge about what users in certain roles are allowed to do from the microservice, since we believe that authorization is part of domain and should be modelled accordingly within a bounded context, which corresponds to a microservice in our architecture.

best

Carsten

John S. Ryan

unread,
Nov 22, 2015, 9:55:16 AM11/22/15
to microservices
Hey Carsten.  Thanks for sharing; this is exactly the kind of thing I'm entertaining for one of my clients (except we're looking at Cloud Foundry's UAA as the auth* provider and source of JWTs).

It's been a few more weeks since you mentioned this; how's it going?  You glad you've taking this path, so far?

Carsten Saathoff

unread,
Nov 23, 2015, 7:41:34 AM11/23/15
to microservices
Hi John,

absolutely. We have just gone into production for a customer, and the approach works very well. The overhead introduced by the JWTs is negligible in our case, and having authorization related logic within the service makes things much easier IMO. The statelessness of the JWTs also improves decoupling, which in turn simplifies the whole infrastructure. Therefore, we are satisfied with our decision and would take the same path again.

best

Carsten

John S. Ryan

unread,
Nov 23, 2015, 10:27:09 AM11/23/15
to microservices
Thanks for the follow-up Carsten.  Great to hear it went so well for you!  Sounds pretty solid.  Nice.

--
You received this message because you are subscribed to a topic in the Google Groups "microservices" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/microservices/n_jL3atxPhQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to microservice...@googlegroups.com.

To post to this group, send email to micros...@googlegroups.com.

Ron Dagostino

unread,
Nov 29, 2015, 12:26:07 PM11/29/15
to microservices
Hi John and Carsten.  We looked at Keycloak and were concerned about the administrative overhead -- it seemed as if every application would need to be declared/defined/maintained within Keycloak. If we need a new role in an app we would have to go into Keycloak and add the role there and associate it with the application so that tokens for that application can potentially have that role in them. Is this correct based on your experience, and assuming so, what is your impression of any administrative burden so far?

We liked the idea of using signed OAuth 2 tokens, but we didn't want the administrative overhead that we perceived in Keycloak; we didn't want to have to define "applications" because we anticipate the boundaries of applications changing over time as we add functionality and integrate with more services.  So the UI responds to an HTTP 403 service response by looking for the attributes error="insufficient_scope" and scope="<the-required-scope>" and then goes back to the token endpoint to get a new token with an expanded scope.  This way an application doesn't have to know what roles it will need; it can just discover them over time based on HTTP 403 responses.  An application may want to customize the view based on whether the user is authorized for a particular role; in that case the application always performs a union of the scope a service says is required in its HTTP 403 response and a hard-coded list of roles that the UI wants to use to make view decisions; that way the UI will always have a token with at least the roles in the hard-coded list that the user is authorized for; the UI can then accurately make its view enable/disable decisions while still being able to dynamically expand scope.

Ron

Carsten Saathoff

unread,
Dec 3, 2015, 9:49:11 AM12/3/15
to microservices
Hi Ron,


Am Sonntag, 29. November 2015 18:26:07 UTC+1 schrieb Ron Dagostino:
Hi John and Carsten.  We looked at Keycloak and were concerned about the administrative overhead -- it seemed as if every application would need to be declared/defined/maintained within Keycloak. If we need a new role in an app we would have to go into Keycloak and add the role there and associate it with the application so that tokens for that application can potentially have that role in them. Is this correct based on your experience, and assuming so, what is your impression of any administrative burden so far?

yes, you need to configure the permissions and roles for each application, but ...
 

We liked the idea of using signed OAuth 2 tokens, but we didn't want the administrative overhead that we perceived in Keycloak; we didn't want to have to define "applications" because we anticipate the boundaries of applications changing over time as we add functionality and integrate with more services.  So the UI responds to an HTTP 403 service response by looking for the attributes error="insufficient_scope" and scope="<the-required-scope>" and then goes back to the token endpoint to get a new token with an expanded scope.  This way an application doesn't have to know what roles it will need; it can just discover them over time based on HTTP 403 responses.  An application may want to customize the view based on whether the user is authorized for a particular role; in that case the application always performs a union of the scope a service says is required in its HTTP 403 response and a hard-coded list of roles that the UI wants to use to make view decisions; that way the UI will always have a token with at least the roles in the hard-coded list that the user is authorized for; the UI can then accurately make its view enable/disable decisions while still being able to dynamically expand scope.

I assume you also need to maintain a list of apps and roles here in your token endpoint? If not, I don't see how you are able to define who is allowed to do what, or am I missing something?

best

Carsten

Ron Dagostino

unread,
Dec 4, 2015, 7:03:11 AM12/4/15
to microservices
Hi Carsten. Thanks for the reply. We have a separate, pre-existing system where we maintain roles and users' role assignments. The roles can be hierarchical, so it is possible to assign someone a functional role like "finance dept member" so they automatically get any role(s) underneath it. The role "finance dept mgr" has "finance dept member" underneath it plus anything extra the manager is authorized for, etc.

Our token endpoint has access to our pre-existing role/assignment database so it can decide what to do when it recieves a request to expand scope.

I think you are using Keycloak as your book-of-record role repository/assignment database. That would be a different use case than our situation -- we have a separate system for that already, and using Keycloak would force us to duplicate work that we are already doing.

Ron

John S. Ryan

unread,
Dec 4, 2015, 12:03:40 PM12/4/15
to Ron Dagostino, microservices
Thanks for asking the question, Carsten, I had the same one.  And that makes sense, Ron; thanks for taking the time to explain.

--
You received this message because you are subscribed to a topic in the Google Groups "microservices" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/microservices/n_jL3atxPhQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to microservice...@googlegroups.com.
To post to this group, send email to micros...@googlegroups.com.

Carsten Saathoff

unread,
Dec 7, 2015, 9:36:01 AM12/7/15
to microservices
Hi Ron,
that's right. In our case, Keycloak is the central auth service, since we didn't have any pre-existing one.

But Keycloak also offers to integrate third-party tools, such as LDAP, and some APIs to implement your own mappings. However, I have never used the API nor used an external user/role provider, so I have no idea how that works out in practice. But if your current approach works well in your scenario, there probably is no need to use Keycloak anyway ;)

best

Carsten

Максим Коринец

unread,
Dec 17, 2015, 3:21:10 AM12/17/15
to microservices
Hi!

The implementation of access control (AC) for microservices was my concern for the last week. I'm only planning now and yet have no running architecture.

I came up with the following thoughts:

- implementing AC within a microservice would complicate it and break one of its core ideas - to do just one thing. It finally will do two things: authorize access (which is not a trivial task) and actually do what its meant for
- while one can gracefully abstract the AC-code into a dependency (a plugin if you, say, use senecajs), updating this dependency would require microservice code rebuild; and if we have a dozen of microservices with AC on top - we'll have to rebuild them all. This breaks another core idea - the ease of deployment
- in some cases you could reuse your microservice in another project, AC-dependency will make it more complicated
- if you practice distributing development to teams - a new team would have to study the AC mechanic (depending on how gracefully you abstracted the AC-code) while developing a new microservice 

Thus, I personally am going to separate access control into a dedicated service (router with exposed endpoints of some kind) and let the rest of microservices not to worry about it. And yes, this dedicated AC service would create bottlenecks and `single-point-of-failure` problem but then I'd rather invest into improving/scaling it.


Regards, Max

воскресенье, 27 сентября 2015 г., 2:47:10 UTC+7 пользователь Erol Merdanović написал:

John S. Ryan

unread,
Dec 17, 2015, 11:32:05 AM12/17/15
to microservices
Thank you for sharing your thoughts, Max. I'm also wrestling with this decision and I'm finding what you write insightful.

Another factor that has pushed the authorization bulwark back onto our layer of gateways and applications is that many of our authorizations are application-data-based. That is, making that authorization decision requires information that the application has and would have to share with the authorization service (whether to generate an auth token like a JWT or to delegate to that service).

Carsten Saathoff

unread,
Dec 18, 2015, 3:27:08 AM12/18/15
to microservices
IMHO, authorization is part of the domain and should therefore be handled within a single microservice. If you push authorization into a gateway, it means the gateway has to know about every microservice behind it (at least in the worst case). Authentication is another topic. That's something that can easily be done using a dedicated service.

I also do not quite agree with Max points:

 
- implementing AC within a microservice would complicate it and break one of its core ideas - to do just one thing. It finally will do two things: authorize access (which is not a trivial task) and actually do what its meant for

Concerning authentication, I agree. When it comes to access control, which I think refers also to authorization, I think it's absolutely valid to handle that within a microservice. If it comes to object level access rights, you have to take care of that in the service anyway. If we talk about user roles, I think they also naturally fall into the scope of the service. Authorization is not easy in some cases, however, doing it outside the service doesn't make it easier either. And I don't see serving its domain and performing authorization as doing two things.

A requirement we regularly face is that also the backend services need to have their own security measures in place. Therefore, handling auth* within the gateway, and let the backend services just answer all request without further authentication and authorization might be an approach that's not feasible depending on the security requirements of your customer or organization.

Then there is the point I mentioned above. If you have a single service doing authorization for every other service, it has to know about all those other services. You have to model their domains somehow in that authorization service. If you add a new microservice, you have to modify the authorization service as well. I don't think that this will make your architecture more simple or easier to implement. Actually, I think that it will become more brittle and error-prone.
 
- while one can gracefully abstract the AC-code into a dependency (a plugin if you, say, use senecajs), updating this dependency would require microservice code rebuild; and if we have a dozen of microservices with AC on top - we'll have to rebuild them all. This breaks another core idea - the ease of deployment
 
- in some cases you could reuse your microservice in another project, AC-dependency will make it more complicated

- if you practice distributing development to teams - a new team would have to study the AC mechanic (depending on how gracefully you abstracted the AC-code) while developing a new microservice 

These arguments hold true for any library you use system wide, for any protocol you choose to implement within your system, for all contracts you have to implement between microservices. While I think it's an important goal to reduce the complexity of your microservices and the whole system, I am not sure if the arguments above are enough to justify moving it out of the service into a gateway. I personally still am convinced that authorization is part of the domain and should therefore be handled within a service.

best

Carsten

Ron Dagostino

unread,
Dec 18, 2015, 8:41:17 AM12/18/15
to Carsten Saathoff, microservices
Here is something else to consider.  Information about the roles required to invoke a service seems like reasonable documentation.  Documentation can be auto-generated from annotated code (e.g. Swagger, which I believe includes support for role information).  It follows that ideally the role information should appear in a manner that facilitates both generation of documentation and runtime decision-making.  I suspect this is not yet common practice, but it is something to think about when making decisions about where to put role information.

Ron
--
You received this message because you are subscribed to a topic in the Google Groups "microservices" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/microservices/n_jL3atxPhQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to microservice...@googlegroups.com.
To post to this group, send email to micros...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages