MVC -- Where would you put the security?



  • I've been having this debate recently with a co-worker.

    Our application is a web app that is supposedly MVC ... specifically, it uses "Passive View" MVC, where the view isn't directly linked to the model; instead, the controller mediates the relationships between views and models, limiting the interaction that the view has with the model.

    Anyway, our debate is where to put some of the cross-cutting functions, like audit logging and access control.

    I believe these items should go into the model, because our application is very data-centric, and the access control is designed to be very fine-grained. For example, you might have a privilege tuple like (fruit, create), and that would mean that you have the right to create new Fruit objects. In some cases, the model might even be more fine-grained than that, such as specifying which fields in an object a particular user is allowed to modify.

    My co-worker thinks this logic should be in the model; if ACL is in the model, then that will complicate unit testing. I don't really see this being a problem, because our ORM lets us create objects in memory, and some of the aspect oriented tasks (like audit logging) only need to be performed when saving changes out to persistent storage. Other tasks (like access control) might have to be selectively disabled when running unit tests.

    His other argument is that putting this kind of logic into the model violates the MVC paradigm... I don't know how to reply to that, since there are as many flavors of MVC as there are ice cream at Ben & Jerry's.

    Naturally, before either of us (or both) WTFs the shit outta this app, I wanted to hear some other opinions.


  • :belt_onion:

    @savar said:

    I believe these items should go into the model, because...
     @savar said:
    My co-worker thinks this logic should be in the model;
    Typo? Or do you actually agree to put it in the model?

    Anyway, to answer the question: in my opinion, the ACL could be part of the model, but it is up to the controller to enforce it by properly managing the views. Wouldn't MVP be a better choice when using "Passive View"? In this case the Presenter can call the view directly through an interface to indicate which fields are enabled/visible/readonly etc...

     



  • It should be in both the model as well as the controller. Your model should never return values or execute actions that the current user or environment has no rights to and as bjollin said as well, the controller should use the ACL to not even make those calls.

    MVC paradigm has very little to do with this. afaik security should be seperatly implemented in it's own class structure. Your model and controller can then just call the security object to verify rights.  




  • @stratos said:

    It should be in both the model as well as the controller. Your model should never return values or execute actions that the current user or environment has no rights to and as bjollin said as well, the controller should use the ACL to not even make those calls.

    MVC paradigm has very little to do with this. afaik security should be seperatly implemented in it's own class structure. Your model and controller can then just call the security object to verify rights.

    Well, as a intrigued listener to this thread, I'm curious how one would go about that. MVC / MVP are not exactly the sort of thing they taught us at Uni (heh, multi-user programming? My school barely touched on multi-threaded programming...).

    I get the concept of separating security into a different class, but shouldn't what you have access to change what you see on the Presentation aspect of the system? For instance, if you are in group Sales, then you probably need to see the CRM stuff, but not the payroll stuff. If you're in a Manager role, you probably should see Payroll Approval, but not Tax Codes. Or do you just show everything, and then bounce back a message of "that's not for you" when they try and use it?

    For that matter, while I get that Security should never be a once-loaded singleton, but should check against the security store to ensure authorization in real-time, this approach ensures that for every request for data, you're also making a secondary request (if not more than one) for data from the security tables. This could potentially kill a system by stressing the transaction rate, no?

    Hmmm.. guess it shows where my mind has been the past few days eh? All the more reason why I'm curious for someone to explain in more depth, OR to recommend a very excellent website (cream-level, not lmgtfy.com style) or book on the topic.



  • @drachenstern said:

    @stratos said:

    It should be in both the model as well as the controller. Your model should never return values or execute actions that the current user or environment has no rights to and as bjollin said as well, the controller should use the ACL to not even make those calls.

    MVC paradigm has very little to do with this. afaik security should be seperatly implemented in it's own class structure. Your model and controller can then just call the security object to verify rights.

    Well, as a intrigued listener to this thread, I'm curious how one would go about that. MVC / MVP are not exactly the sort of thing they taught us at Uni (heh, multi-user programming? My school barely touched on multi-threaded programming...).

    I get the concept of separating security into a different class, but shouldn't what you have access to change what you see on the Presentation aspect of the system? For instance, if you are in group Sales, then you probably need to see the CRM stuff, but not the payroll stuff. If you're in a Manager role, you probably should see Payroll Approval, but not Tax Codes. Or do you just show everything, and then bounce back a message of "that's not for you" when they try and use it?

    Well it all depends on needs and personal taste really. Personally I would create a "dumb" security object that just knows how to  get the bits it needs and see if the user is allowed. What i would probebly do (an bear in mind, this also heavily depends on your setup) is create a rights map per controller. This map would include all actions taken and specify which model data is also allowed. Then in the database or config file or whatever you can map the security map to users/groups and give them the rights to it.  You could probebly also sort of get the security map via reflection, but that often results in edge cases that need to be solved.

    Now the ACL should dictate the menu, although again, i am assuming a lot here. I am heavily opposed to ever present a user with options that he can never use. It is simply silly. 

     


    For that matter, while I get that Security should never be a once-loaded singleton, but should check against the security store to ensure authorization in real-time, this approach ensures that for every request for data, you're also making a secondary request (if not more than one) for data from the security tables.

    Well I was sort of assuming this was a web site. Which means you don't have state. I see no apparent reason why you couldn't have a singleton for your security object. Unless you where planning on doing weird shit to keep the object alive over multiple requests it is going to be re-instantiated each request anyway.

    This could potentially kill a system by stressing the transaction rate, no?

    Lots of things can kill a system, but don't try to optimise something before you know it is a problem, also don't do stupid shit that will cause preformance problems down the way. Basically you can just retrieve the ACL once each request. That one query won't bring the system down. The validation of actions against the ACL after that is negligible.

    Hmmm.. guess it shows where my mind has been the past few days eh? All the more reason why I'm curious for someone to explain in more depth, OR to recommend a very excellent website (cream-level, not lmgtfy.com style) or book on the topic.
     

    From the sound of it, and again this is assuming you are building a web site. Use a fucking framework. If you are using PHP then try out stuff like kohana, code ignitor or zend framework. They already built the MVC and the security for you. You just have to fill in the details. If you are using something else, ask someone else, i'm sure there are frameworks for java and .net and python and ruby and perl too. Don't try to reinvent the wheel, we have a perfectly round one already. (some spokes may be missing)

    -edit-

    Re-read the first post. seems like you have a existing code base. In that instance, just use a component library like PEAR, eZcomponents or zend frame work (when using PHP)  for the ACL part. 



  • @stratos said:

    Well I was sort of assuming this was a web site. Which means you don't have state. I see no apparent reason why you couldn't have a singleton for your security object. Unless you where planning on doing weird shit to keep the object alive over multiple requests it is going to be re-instantiated each request anyway.

    From the sound of it, and again this is assuming you are building a web site. Use a fucking framework. If you are using PHP then try out stuff like kohana, code ignitor or zend framework. They already built the MVC and the security for you. You just have to fill in the details. If you are using something else, ask someone else, i'm sure there are frameworks for java and .net and python and ruby and perl too. Don't try to reinvent the wheel, we have a perfectly round one already. (some spokes may be missing)

    Re-read the first post. seems like you have a existing code base. In that instance, just use a component library like PEAR, eZcomponents or zend frame work (when using PHP)  for the ACL part.

    Ah, I see where we have a differing then, as I'm not building something web based, atm anyways. Who knows what they'll want to do with this next. I was just thinking portable security semantics in general, separate from a particular framework. But your post made me requestion my own initial thought: MVC are always built with a framework, and said framework has a builtin security model, so it's moot.

    Laters.


  • :belt_onion:

    @drachenstern said:

    I get the concept of separating security into a different class, but shouldn't what you have access to change what you see on the Presentation aspect of the system? For instance, if you are in group Sales, then you probably need to see the CRM stuff, but not the payroll stuff. If you're in a Manager role, you probably should see Payroll Approval, but not Tax Codes. Or do you just show everything, and then bounce back a message of "that's not for you" when they try and use it?
    The way it works in the bjolling MVC flavour is:

    • When starting the application the MainController class is instantiated. This class checks what your user is permitted to do and updates a presentation model (IObservable in the Observer pattern) saying which fields are visible, mandatory, editable...
    • Based on your role the controller invokes the appropriate view who subscribes as an observer to the presentation model. The view is responsible for updating its state in accordance to the presentation model (and the business model of course).
    • When the controller changes the model, the model notifies all its observers (views) who update/refresh/reload
    • The Controller will never let you navigate to a view for which you don't have the rights

    Checking security can be done in many ways. I usually use Windows integrated security and check the roles to which a user belongs on Active Directory. Detailed user profiles could be stored in ADAM, but the client I currently work for uses profiles stored in a SQL database.


  • @bjolling said:

    @savar said:

    I believe these items should go into the model, because...
     @savar said:
    My co-worker thinks this logic should be in the model;
    Typo? Or do you actually agree to put it in the model?

    Anyway, to answer the question: in my opinion, the ACL could be part of the model, but it is up to the controller to enforce it by properly managing the views. Wouldn't MVP be a better choice when using "Passive View"? In this case the Presenter can call the view directly through an interface to indicate which fields are enabled/visible/readonly etc...

     

    Doh.. yeah it was a typo. He wants to put all of the ACL querying logic into the controller. So the controller would say if ($user->hasPrivilege($resource, $privilege)) {$resource->modifyData()}, and then $resource->modifyData() would purely contain business logic and would make a call to the ORM to persist the data.

    Never heard the term MVP before, but reading the Wikipedia article, it sounds similar to what I want, except for this part: "The View is an interface that displays data (the Model) and routes user commands to the Presenter to act upon that data." That doesn't make sense to me in a [server-side] web app, where all of the user input is ultimately going to come in the form of HTTP requests.

    And you're right, the controllers and views obviously consume ACL information, in order to know how to properly route events, and what controls and to display on the screen. But all of our ideas of privileges (in this application) ultimately pertain directly to [i]data[/i], generally just the simple CRUD operations. While the view may hide the "edit" button when a user is looking at an object, and the controller may reject a request to load the "edit" page for an object, I still think the model has the ultimate responsibility for enforcing ACL.

    Any developer who writes a new controller or a new view will have to explicitly know what ACL logic to include, unless that ACL logic is built into the model. Say there's an existing functionality that allows a user to edit an object from a web interface. This new developer wants to write a controller which allows the user to edit an object using a SOAP interface. There are a series of fine grained access control checks, such as which fields a user can set, and what time of day they can set them, etc. It would be quite easy for this developer to write the controller in such a way that it actually had different access control properties than the original controller, even though both are based on the same underlying model.

    @stratos said:

    MVC paradigm has very little to do with this. afaik security should be seperatly implemented in it's own class structure. Your model and controller can then just call the security object to verify rights.

    Definitely. I didn't make it clear in my post, but we're actually using the Zend_Acl module in Zend Framework to handle the ACL queries. Zend_Acl allows us to build a tree of roles and resources and then enumerate rights between the two. Once the tree is constructed, that instance can be persisted and then queried throughout the application. My original question should really have been: "Where should we QUERY the ACL?"

    @drachenstern said:

    I get the concept of separating security into a different class, but shouldn't what you have access to change what you see on the Presentation aspect of the system? For instance, if you are in group Sales, then you probably need to see the CRM stuff, but not the payroll stuff. If you're in a Manager role, you probably should see Payroll Approval, but not Tax Codes. Or do you just show everything, and then bounce back a message of "that's not for you" when they try and use it?

    You're definitely right.

    In my app, we have two ACL primitives: $acl->hasPrivilege($resource, $privilege) and $acl->requirePrivilege($resource, $privilege). The former performs a query to see if the ACL contains the rights to do something, and this is used in the views to determine what data and controls to show on screen. The latter is similar, except instead of returning a boolean, it throws an exception. This is used in the model (and/or controller) as an assertion that a user is actually allowed to do something.

    The reason it throws an exception is because the application is designed so that in normal usage, each call to requirePrivilege will always succeed. The UI shouldn't show the user an controls which he isn't allowed to use. There are two cases where requirePrivilege would fail:

    1. application bug. you showed the user a control you weren't supposed to show them.
    2. malicious user. somebody typed in their own URI query or modified form data before it was posted to try to access something that the view wouldn't reveal to them.
    My app is open source, so people will be able to see what form values are allowed and what controller actions can be invoked.

    Anyway, thanks for the feedback. I'm still a bit lost, but now at least I've got some ideas to chew on.


  • :belt_onion:

    @savar said:

    @bjolling said:

    ... Wouldn't MVP be a better choice when using "Passive View"? In this case the Presenter can call the view directly through an interface to indicate which fields are enabled/visible/readonly etc...


    Never heard the term MVP before, but reading the Wikipedia article, it sounds similar to what I want, except for this part: "The View is an interface that displays data (the Model) and routes user commands to the Presenter to act upon that data." That doesn't make sense to me in a [server-side] web app, where all of the user input is ultimately going to come in the form of HTTP requests.

    You're right. MVP doesn't work in web context. Wasn't paying enough attention when I suggested it.



  • @bjolling said:

    @savar said:
    Never heard the term MVP before, but reading the Wikipedia article, it sounds similar to what I want, except for this part: "The View is an interface that displays data (the Model) and routes user commands to the Presenter to act upon that data." That doesn't make sense to me in a [server-side] web app, where all of the user input is ultimately going to come in the form of HTTP requests.
    You're right. MVP doesn't work in web context. Wasn't paying enough attention when I suggested it.

    Hmmm? Web context is MVP pur sang.

    MVP has the User communicate his input with a View. The View translates this input to a standardized format and sends it off to a Presenter selected by the View. This Presenter mutates the Model and ships the results back to the View. The View formats and presents these results to the User. The View is the User's web browser; the Presenter is most often two-tiered: consisting of the page rendering framework at the top and the business logic beneath it; the Model is the set of business objects, data persistence frameworks, etc.

    Ofcourse, you could leave the browser out of things. In that case the View becomes the page rendering framework which takes your HTTP request and kicks off the proper Presenter to gather and shape data and mutate the Model. The gathered data goes back to the page rendering framework to be transformed into HTML wrapped in a HTTP response. In this case the Presenter uses the initial data from the View and the data taken from the Model to shape some type of in-memory DOM (which is what the View transforms into the flat HTML).

    Doesn't that sound an awful lot like asp.net? The asp.net framework (View) hands off a sessionstate, viewstate, etc. and post data to a page (Presenter), which constructs and configures an in-memory collection of controls (textboxes, buttons, tables, etc.) based on this data. The page runs some mutation on the business objects / database / etc. (Model) and reformats its user controls based on this mutation's results. The page finishes execution and hands its created and configured control tree back to the asp.net framework which uses a HtmlWriter class to convert everything to flat HTML and sends it off as a http response.


  • :belt_onion:

    @Ragnax said:

    @bjolling said:
    @savar said:
    Never heard the term MVP before, but reading the Wikipedia article, it sounds similar to what I want, except for this part: "The View is an interface that displays data (the Model) and routes user commands to the Presenter to act upon that data." That doesn't make sense to me in a [server-side] web app, where all of the user input is ultimately going to come in the form of HTTP requests.
    You're right. MVP doesn't work in web context. Wasn't paying enough attention when I suggested it.
    Hmmm? Web context is MVP pur sang. <snip>
    I'm afraid I got blinded by the ASP.NET MVC story and by the way my client is currently trying to roll their custom MVC implementation. Their framework is putting insane limits and is effectively making MVP impossible here. For a moment I thought this situation was universal.

    I'd better shut up now :-|


Log in to reply