8

I've been doing a lot of tutorials for different MVC frameworks, and it seems very typical for Authorization to take place in the Controller. Why?

My thought is the Controller should only be used to orchestrate Model actions, to handle redirection and to handle error events. These are the things that are dependent on the specific request. Putting Authorization in the Controller seems like you're going to have to duplicate the authorization whenever you're using the same Model action in different Controller actions or different Controllers. If Auth is in the Model, you have consistent requirements for carrying out an action or state change on the data.

I've been googling and looking at other questions such as Should authorization be part of the model or controller? but I don't really see why it's the accepted convention.

Is there a specific reason I'm missing for putting Authorization in the controller over the model?

To sum up points in the comments:

  • Controllers are responsible for altering the state of the model layer and the current view. Nothing else.
  • Authorization belongs where an action is being carried out, if you're following a strict MVC pattern this would most likely be the model, and a Controller is certainly not responsible for authorizing the use of model actions.
  • Cookies should be treated like any other datastore: abstracted and used within the models, not directly by controllers.
  • Authentication and Authorization are separate issues, though they both usually go in the model layer, because they usually involve checks against values in datastores (such as cookies).
Community
  • 1
  • 1
Charles
  • 889
  • 1
  • 7
  • 15
  • I would say, that it [neither](http://stackoverflow.com/a/9685039/727208) controllers nor model layers should have anything to do with authorization checks. People mostly dump it in the "controller", because that's where they dump everything else, when using Rails-like architecture. – tereško Oct 18 '13 at 19:13
  • I'm using a class that has authorization rules, but where do you actually carry out the enforcement? If not in the controller or the model, where do you say "to do this, you must pass these rules"? – Charles Oct 18 '13 at 19:18
  • Hmm. I read in your comment there are rules. I would say that those rules should already give you some pointers to what they relate to. – hakre Oct 18 '13 at 19:28
  • @Charles , I would actually argue that authorization (just like logging of user's actions) should be "above" instance, that it affects. Let's say you want to verify, if user can access `AdminPanel::deleteEverything()`. Does it make sense for application to initialize `AdminPanel` instance to check if user has clearance to access a method in that class? And on other hand: if you change some authentication process, must you go though all your classes manually, to see if nothing will break? As I see it, that approach would violate both SRP and OCP. – tereško Oct 18 '13 at 22:28
  • Where would it go if not in the Model or in the Controller? Makes sense to me to have authorization rules in their own class, and have a model action call, say, $this->auth->requireAdmin(..); If you want to change the auth rules of requiring an admin, it's in one place. – Charles Oct 19 '13 at 00:09

3 Answers3

9

Is there a specific reason I'm missing for putting Authorization in the controller over the model?

Well, the most common reason I can imagine is laziness. I don't mean that morally, it's just far easier to flunge some authorization concept on top into a layer that is more close to the concrete request then to have differentiated access on the model layer. To have authorization with the models is a much higher design.

To add some more practical advice to the answer, I think you should analyse for each program where and for what you would want to introduce authorization. The needs for that can be (extremely) different.

Then only in the next step you should think about which design is most beneficial to introduce authorization and authentication to fulfill these needs.

hakre
  • 178,314
  • 47
  • 389
  • 754
  • Just to expand on this answer a little, imagine if you were sending requests through multiple controllers which include APIControllers too, then you would have to do it in both controllers (and attribute both sets of functions). This can all be ignored if your business logic throws some error back to your controllers which causes them to do some default error action and write error details to the Viewbag. – Worthy7 Aug 24 '16 at 06:02
2

In an MVC approach, you need to put security in a location where:

  1. it cannot be circumvented
  2. it can be configured, managed and updated easily

This applies - as a matter of fact - to any architecture / type of application.

Specifically, in MVC, imagine you put authorization in the view. For instance you decide to control who can approve a transaction by enabling / disabling a button. A user of your view will not be able to approve a transaction if he/she is not allowed. Imagine now that you expose your controller over an API rather than a view. The approve authorization check now needs to be reimplemented in the API layer.

This example shows you are better off moving authorization away from the view / the different end-points and into a common, central point - your controller.

Similarly, if you want to control access to large sets of data (e.g. medical records), you ideally want to put the authorization in the model. This is both for performance reasons and for security reasons: you'd rather have the controller handle less data and you should always strive to protect as close as possible to the source of the sensitive data.

Note that having authorization hooks / checks in the view, controller, and model at the same time may lead to an altogether enhanced experience. See authorization in the view as a "safety / usability" mechanism whereby a user is only presenetd with those relevant menus and widgets on screen based on their permissions. If they were malicious and knew their way around the UI to the controller, authorization there would still kick in.

Finally, generally speaking, you want to decouple non-functional requirements / logic from functional requirements / logic. Much like you do not implement logging in code but use a configurable framework (e.g. Log4J) or you rely on the container for authentication (e.g. HTTP BASIC in Apache Tomcat), you want to use an externalized authorization framework such as Claims-based authorization in the Microsofct MVC4 world, Spring Security in Java, CanCan in Ruby, or XACML, a standard part of the same body as SAML (OASIS) and which will let you apply authorization to any type of application and any layer.

David Brossard
  • 12,223
  • 6
  • 42
  • 72
1

Authorization as an entire process should be involved in both: Controller and Model layers.

But, all the logc (SQL queries, etc) should definitely happen in the model. Controller is kind of an intermediate layer between the view (representation) and the Model. But, you simply cannot throw away the Controller from this scheme, because Controller is responsible for handling Sessions and Cookies. Without these two things all your Authentication/Authorization logic is useless, because it is stateless by its nature. Sessions and Cookies bring state to it. Moreover, as you correctly mentioned, Controller is responsible for redirects.

Dmitri
  • 2,297
  • 6
  • 30
  • 53
  • 3
    -1: controler does NOT intermediate between model and views, controller has nothing to do with sessions and cookies (those are forms of storage). Also authentication and authorization are separate responsibilities. And redirect is a form of a response. It's an "output" which contains only an HTTP Location header. – tereško Oct 18 '13 at 19:24
  • Controller is an end-point for your HTTP request. So it is also responsible for rendering the layouts/templates. – Dmitri Oct 18 '13 at 19:27
  • And the **point** is that controller is **responsible** for altering state of model layer and current view. Nothing else. In the MVC pattern views are responsible for rendering and managing templates, because responsibility of a view is to deal with UI logic. – tereško Oct 18 '13 at 19:29
  • 1
    Well ideally it shouldn't matter if that was a HTTP or some other type of request. The controller should be non-specific to the type of request. – hakre Oct 18 '13 at 19:29
  • tereško, I'm seeing your point, but not the conclusion. Where do you actually put these things if not in the controller? – Charles Oct 18 '13 at 19:30
  • And controller still remains responsible for Session/Cookie I/O, simply because you cannot put it model or in view, because view - is an end-production of the request, and cannot do basic stuff like redirects. So it brings state to your application. – Dmitri Oct 18 '13 at 19:34
  • Cookies and session is a persistent form of storage (like cache, database, soap or rest API). All of those are handles inside model layer (preferably by data mappers or some other form of storage abstraction). The state of application resides in the model later. And, please, stop treating views as dumb templates. It would be nice if you actually learned the basics of MVC. The small things, like "what are the responsibilities for each piece". Because right now you seem somewhat confused. – tereško Oct 18 '13 at 19:56
  • @tereško well, you've confused me now. Why would a model be interacting with a cookie handler? That would mean models would be sending off http responses wouldn't it? Do you have a link to a guide or something that explains the roles you're thinking of? I don't think I've ever seen a guide explaining divisions like you're saying. – Charles Oct 18 '13 at 20:02
  • Model has absolutely nothing to do with Sessions and Cookies. Learn stuff before claiming something. I'm a Rails guy, btw. So, I use it hell of a lot. – Dmitri Oct 18 '13 at 20:04
  • @Charles That's not how php works. The cookies are NOT sent when you change the value, but when you start sending content. – tereško Oct 18 '13 at 20:05
  • I understand that, but why would a model be interacting with the HTTP response? – Charles Oct 18 '13 at 20:07
  • setcookie() defines a cookie to be sent along with the rest of the HTTP headers. – Charles Oct 18 '13 at 20:09
  • 1
    MVC has nothing to do with underlaying server/platform behavior. It is about separating responsibilities. When you call `setcookie()` it does not do anything to header. NOTHING. It only tells PHP: "use this parameter, when you are going to send headers". The point here is that cookies store information. Information that is mapped to various domain objects within the model layer. At no point is model interaction with HTTP response. – tereško Oct 18 '13 at 20:20
  • Okay, I get it. Sounds logical to me. – Charles Oct 18 '13 at 20:22