Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP - Where to put RBAC and Authentification in an MVC application? [duplicate]

I'm working on an MVC application with this structure:

   Request
      V
FrontController <-> Router
      V
  Controller <-> Model
      V
     View

I have two other components that I need to place in this structure:

  • Authentification: Logs the user in using the $_SESSION global variable;
  • RBAC: Role Based Access Control that can check if a role has access granted to a "ressource" (Controller method).

Every users can have any given number of roles (they can also have none).

Now, I need to place those two components in my applications, I need them to be able to:

  • If the User isn't authed and that the Request requires a authed User to be executed, the client should be redirected to a login page;
  • If the RBAC sees that the authed User doesn't have a role that has access granted to the required "ressource" to execute the Controller's method, the Controller's method should still be executed but with knowledge that the User did not have the permission to do so (Example: A User writes an article but doesn't have the right to publish it, so the article is saved as a draft and the User is told that a Moderator will have to publish it).

I already have a few ideas where to locate the Authentification and RBAC but I'm not sure:

  • Authentification could go in the FrontController or the Router;
  • RBAC could go in the FrontController or the Controller.

I saw someone putting the RBAC in the model but I don't understand why.

I'd like to have some insight on the subject please. Where should I put the Authentification and RBAC components?

Thank you!

like image 534
Informancien Avatar asked Oct 19 '22 03:10

Informancien


1 Answers

In my experience, access control business logic changes as new features are added, so it pays to design flexibility and motility into your access control system. Thus, I would engineer Authentication and RBAC as separate traits, then incorporate those traits into the controller space as necessary.

As described, it sounds like the authentication trait would best be incorporated into your front controller: you know that all dependent controllers require authentication, so incorporate that check early in the life cycle to free up request sockets. If your requirements ever change to need some controllers to be ungated, you can push the trait down into specific controllers or into a base controller class.

As for RBAC, that may apply globally to all controllers as well as locally to some controllers. For example, your FrontController may query the RBAC to build the routing table, while dependent controllers would use the RBAC for their specific needs.

One thing to consider, though: you may also have some RBAC needs in the model. That is, some roles may have limited access to some fields in some models: role A can access all of model X, but role B can only read fields 1, 2, and 3 of model X. (Trust me, I have seen very, very complicated rules around roles that can see and act on what fields.)

Engineering RBAC as a controller trait may make porting to model space difficult. Thus, you may find it better to engineer RBAC as a service delegate and inject it on demand. With a well-provisioned IoC container, a service delegate is just as easy as compile-time traiting.

Finally, I'll add that you're going to want both of these under heavy test (they are important, after all). So whatever you choose, engineer so they can be tested. In my opinion, both traits and delegates are easy to test in isolation and either would be a good choice for implementing the necessary logic.

like image 190
bishop Avatar answered Oct 21 '22 06:10

bishop