I have been building a user authentication system with user roles. I am now at a point where I am starting to really dig into routing based on roles and I am running into problems. I have built it with the idea that a role is required. I am now finding that this has some pitfalls and I want to know if I should have done it another way. What are the benefits to have every user have a role compared to only having a role if needed otherwise assume not special user?
In my understanding users are dispatched by roles. So there would be for example
default users. For the last ones, the role could be called
member, or even
default. There should not be many roles, or at least not much more than there are user interfaces. This way the routing will be easier I think.
For example we can things like:
# somewhere in a router to allow only `admins` and `superadmins` pipeline :admin do plug :browser plug :ensure_role, [:admin, :superadmin] end
# Then in some Controller plug(:ensure_role, :superadmin when action in [:delete])
If for example
superadmins had their own UI, and so for for
admins, it would be even more straightforward to do the routing,
For routes allowed to all authenticated user, I just use some plug like
require_user, for ones that need not to be authenticated I have
One issue I encountered was when I tried to assign multiple roles to the same user. That will complicate things a lot. So I try to avoid that and create roles that fully qualified users.
I’m a Phoenix/Elixir noob, but I did a PHP app using Role Based Access Control (https://auth0.com/docs/authorization/concepts/rbac), in which every user has one or more roles, and every role has one or more permissions. Each permission usually would map to a route. Hopefully that helps.
When i can do the job without permissions’ complexity, I really prefer that. But It’s certain that for some kind of requirements, just roles won’t be sufficient to handle authorization. I guess what I call “role” should rather be called “user type”?
You can define two pipelines, one requiring the user to be authenticated (with role), the other without such requirement.
pipeline :api do plug(:accepts, ["json"]) end pipeline :jwt_authenticated do plug(Guardian.AuthPipeline) end scope "/api", AtmWeb do pipe_through(:api) post("/sign_up", UserController, :create) post("/sign_in", UserController, :sign_in) resources("/categories", CategoryController, except: [:new, :edit]) # no role required ... end scope "/api", AtmWeb do pipe_through([:api, :jwt_authenticated]) resources("/records", RecordController, except: [:new, :edit]) # role is needed and verified by controller. ... end