type1fool

type1fool

Arbiter - Role Based Authorization

Backstory

Before I became a full-time developer on a PHP team in 2018, I had been studying role based authorization (RBA) for an Elixir application I was developing part-time. Ever since, I have missed working in Elixir.

To sharpen my Elixir skills, I want to create an RBA library. There are a few existing libraries, but they seem to be intended for single-tenant applications. I think there is room for a multi-tenant library for B2B applications that serve multiple businesses.

Arbiter :building_construction:

Arbiter on GitHub

So far, I have written about the intent and preliminary design in the readme. I have also created the modules I expect to need, and started writing tests for the Organization module. I’m hoping to TDD this project to discover the optimal abstractions and to satisfy potential security requirements. :crossed_fingers:

As I get started on the design, I want to hear from potential users to test my ideas. It’s worth noting is that this is my first open source project. I have been working on internal PHP applications and a custom framework, but nothing public-facing. I’ve learned the importance of hearing from users before spending hours/weeks on implementation.

Question Time

  • Have you used one of the existing libraries or built custom RBA tools?
    • What were the benefits and pain points?
  • Do I need a Policy module?
  • What are some possible hard requirements for adoption?
  • Could the library accept (potentially decorate) a User struct from other auth libraries/modules?
    • How?
  • If Ecto is a dependency, should it default to ETS, SQLite, or Postgres?
    • Could/should the library avoid persistence entirely, leaving that to the user?
  • Would telemetry be useful in this kind of library?
  • Do you have any other suggestions?

Most Liked

thojanssens1

thojanssens1

Personally I think what’s missing is the API you eventually want to provide for the library users.

I came to the conclusion that authentication and authorization is way too application-specific to make a library out of it. Authorization is actually vague as it can mean many different systems.
But change my mind :sweat_smile:

To elaborate this thought, take for example authentication and Pow. Pow requires you to inject code (use) in many layers of your application (controllers, views, routes, etc.) for it to work. Even though many devs like and use it, it makes more sense for me to use a scaffolding tool like phx.gen.auth that provides a codebase from which you can customize to your application needs. The fact that Pow must inject code application-wide is for me a clear sign that this should be application-specific code.

A lot of the topics and questions you raise concern business logic (user, team, organization, etc.) and I suspect the library might impose a minimum of conventions to follow in one’s business logic for it to work, but that is something I’ll never want to compromise. The library should work over the existing business logic without a change.

In my case, I work on calendars and a huge part of the authorization is sharing calendars between users with permissions. I have a CalendarSharingPermission Ecto schema that holds those permissions. Would I want to replace this calendar sharing table by a more general authorization solution? I think not, as it’s actually quite complex and specific, and I would also lose in terms of semantics and readability, and customization and flexibility.

I’m not sure what is the library’s goal (as I said, missing a demo API/usage), but you might consider the alternative of creating a blog post with your knowledge about authorization systems and provide sample code that someone can copy over and customize (similar to scaffolding).

al2o3cr

al2o3cr

General advice: for the first pass at the idea, MAKE DECISIONS. Yes, eventually you might need to support primary keys of various types or totally different persistence - but trying to force everything to be too generic too early is a recipe for over-abstraction (see also… most of the last 30 years of OOP).


As @thojanssens1 mentioned, the hard part of RBAC is the interface the rest of the system uses: how does application code tell Arbiter what an “action” is? How will Arbiter answer questions like “show me the most recent 20 Widget records that this user can see”?

A good way to learn the answers to these questions (and have a nice demo to show people) is to build your abstractions inside a demo application and only then try to abstract them into a library.


On the organizations branch, it feels like the documentation is already suggesting a limitation of the interface. In this commit this example is added:

Clerks may start an order, add items, remove items, place an order on hold, accept payment method(s), and complete the order.

    permissions: [
      {:order, [:create, :update]},
    ],

Managers would likely include the same permissions as clerks, but would also be able to cancel orders, process refunds, and view reports.

    permissions: [
      {:order, [:create, :read, :update, :delete]},
      {:report, [:read]},
    ],

The words used to describe the permissions (“clerks can place an order on hold”) are much more specific than the actions used to represent the permissions (order: [:create, :update]).

For instance, can a clerk update an order that’s already been shipped? Can a clerk EVER update the address on an order? “update” is very wide…

Some of this may be a matter of picking a better data model - for instance, only giving managers the “process refund” permission is tricky if it’s viewed as an “order update”, but easier if it’s a “refund create”.

harmon25

harmon25

I have been considering using Bodyguard — Bodyguard v2.4.1 (hexdocs.pm) to handle relatively simple authorization requirements.

Elixir/Erlangs pattern matching capabilities lends itself quite well for this type of code, which is one of the reasons I like Bodyguard.

On the more complex end - think AWS/GCP policies. Take a look at Zanzibar: Google’s Consistent, Global Authorization System

And ORY Keto which is “the first and only open source implementation of Zanzibar”

Open Policy Agent is also worth looking into for inspiration. Maybe building on top of something like that would make sense. (OPA is what earlier versions of Keto were built on)

Last Post!

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

This is definitely in the right direction. I think the only other caveat I’d add is that RBAC doesn’t tend to think in terms of types of entities either, instead focusing on operations, and the permissions required to perform that operation. Those operations can be sort of parameterized by type, but those types are largely opaque to the RBAC system.

So you’d have operations like :start_shipment or :onboard_user or :edit_billing_info and those operations will require one or more permissions. Clearly there are entities involved there but the RBAC logic doesn’t really know or care about users or shipments, just the named operations. Then it looks to match the permissions required by those operations up to permissions granted to an actor according to the roles that actor possesses.

I think this is a good plan! Just to clarify what I have in mind by scope, it isn’t usually about “this kind of entity” but rather “within this organization, user A has these roles, but within some other organization A has different roles”. Operations are then performed within the context of an organization, and the relevant roles applied.

Where Next?

Popular in Discussions Top

New
AstonJ
If a newbie asked you about Phoenix Contexts, how would you explain the basics to them? Feel free to be as concise or in-depth as you li...
New
restack_oslo
Hello, Please pardon me for any faux paux. I am 46 and this is my first time on a forum of any kind. I wanted to to get answers from tho...
New
sergio
There’s a new TIOBE index report that came out that shows Elixir is still not in the top 50 used languages. It also goes on to call Elix...
New
Nvim
Elixir appears to be a superior language to Python. I don’t see any advantage of Python over Elixir. Are there any?
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
fireproofsocks
I’ve been working on an Elixir project that has required a lot of scripting. I usually reach for Elixir because I like it more (and in th...
New

Other popular topics Top

jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New

We're in Beta

About us Mission Statement