Thoughts on implementing RBAC (role-based access control) within a mixed environment?

Hi,

I am building a platform, where I have few services. Lets say I have 2 elixir services (as standalone releases), 1 rust/golang service… and probably one or two more comming.

I would like to implement RBAC on the level of platform. My question/dilema is how to approach this due to the fact that it would not be just elixir codebase.

Options I am thinking about:

  1. Implement RBAC withing one of the elixir services and expose this for instance via REST to others
  2. Implement RBAC as standalone service and expose functionalities via REST to others.
    2A. Here I was checking Casbin (https://casbin.org) and perhaps based on this (https://github.com/casbin/casbin-ex)
    2B. Implement kind of my own RBAC - haven’t really find any nice library yet

Right now I feel like … this Authentication / Authorization part of elixir ecosystem is still a bit unmature, where I don’t mean libraries that exists are unmature, but common best practices, approaches how to solve problems, design patterns around this are still not well documented.

For me as a beginner for instance… you have Phx.gen.auth, Guardian, Ueberauth, Pow, Pow_assent, Bodyguard, … and many more. Should I go with this or that… what would be best approach to easily maintain and further develop not just for weekend project, but for a something that would need to run in production next 2 years for instance.

Next, dilemas… if I go with this… would I be able to cover SPAs, liveview, channels, OAuth, stateless, statefull… and all other buzzwords and components. What combination would be best. And I guess this is really important for options above. I am pretty sure, I will use channels/liveview too in my services, as regular templates too. There will be probably React SPA too as part of this. What to choose, how to aproach this?

I know one could say I mixed everthing in the same basket, but intentionaly I want to emphasize what probably someone who starts with this see.

It would be really great if there would be more documentation on this, based on examples.
I apprechiate @josevalim suggestion few days back on documenting more use cases around Phx.gen.auth. That would be really awesome.

Until then, … dilemas like this make mess in my head. :wink:

So if someone can share a bit of feedback on my options above I would really appreciate.

Bye
Tomaz

3 Likes

Looks like I need to write first reply myself :slight_smile: though I really hope others with experience will follow.
I was told that all the buzzwords are in my post. But my comment on this would be, not all of us are building yet another Blog site.

In relation to what I already wrote above, about what @josevalim wrote a while back, I really want to share first of such blog posts that I was able to find. Thanks to @iacobson a blog about joining Phx_gen_auth with Oauth. If there are more like this, please share them here.

1 Like

Hey,

another one!

Phx.gen.Auth + JWT

Regards,
Tomaz

1 Like

Hi,

I have implemented a RBAC based authentication and authorization service in Elixir and it’s used in production in our company.

I would suggest that if the use-case is a real production use and your requirements allow it, use existing solutions like Keycloak. Their authorization overview guide.

At least authorization for websockets works with Keycloak when using Nginx (Example). I don’t know if Liveview works too.

If it’s not possible to use existing solutions and since you are already using microservices(?) then I would suggest going for option 2. I’m not familiar with libraries in this area but I can say that authentication is easy, authorization can be easy but with RBAC, it usually gets complicated.

If you have only few services and aren’t using API gateway/reverse proxy solution, then you need to handle parsing request data in each service and making validation request to the authentication&authorization service. This means that you can use whatever means of communication between services (backend and frontend) but there’s more work for each service.

If you are using API gateway/reverse proxy solution like Nginx, then services can just make requests to each other without worrying (too much) about authentication and authorization since the gateway will handle it. Of course you need to implement necessary code in the gateway. This varies for each solution.

As for those OAuth, stateless, stateful, and other buzzwords, I would suggest that you evaluate your requirements and try to keep everything as simple as possible. OAuth + OpenID is complex and if you don’t have clear use-cases for it, then I wouldn’t choose it.

There’s not much difference between stateful and stateless authentication. If your requirements mandate that you must be able to easily revoke authentication, then I would suggest going for stateful authentication.

Basic flow with stateful authentication:

  1. User logins to system
  2. Save all required information (at least user_id, session_key) in database
  3. Set user_id into httponly cookie which can be signed/encrypted
  4. SPA knows that login was a success the request returns 200
  5. The browser adds the cookie to each following request from the SPA to backend
  6. The authentication and authorization service checks that cookie is in the request, it’s valid, and the information is valid.

Hanny, thanks for your feedback. I appreciate it. I noticed Keycloak myself. Are you using any client for that?
I found this, but only 122 downloads are reported. Is its usage really that rare or is it something else?

I imagine you found a client that you ended up using, as your reply is from a while back.

I wanted to make mention that we are using this client: GitHub - scrogson/oauth2: An Elixir OAuth 2.0 Client Library at work for handling the OAuth flows. Not sure if there are other clients that others are using. It has worked well for us so far.