Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC: Authorization inside an Action - Suggested Patterns or this is a smell?

I have an ASP.NET MVC application using Authorization Attributes on Controllers and Actions. This has been working well but a new wrinkle has shown up.

Object: Shipment

Roles: Shipping, Accounting, General User

The Shipment moves through a workflow. In state A it can be edited by Shipping only. In state B it can be edited by Accounting only.

I have a ShipmentController, and an Edit Action. I can put an Authorization attribute to limit the Edit action to only those two roles, but this doesn't distinguish between which state the Shipment is in. I would need to do some Authorization inside the action before the service call to determine if the user is really authorized to execute the edit action.

So I'm left with two questions:

1) Whats a good way to have authorization inside an Action. The Controller Action calls to a service, and the service then makes appropriate calls to the Shipment object (update quantity, update date, etc). I know for sure I want the Shipment object to be agnostic of any authorization requirements. On the other hand, I don't have a real grasp if I would want the service object to know about authorization or not. Are there any good patterns for this?

2) Is my problem actually a symptom of bad design? Instead of ShipmentController should I have a StateAShipmentController and StateBShipmentController? I don't have any polymorphism built into the Shipment object (the state is just an enum), but maybe I should and maybe the Controllers should reflect that.

I guess I'm after more general solutions, not a specific one for my case. I just wanted to provide an example to illustrate the question.

Thanks!

like image 754
anonymous Avatar asked May 20 '09 18:05

anonymous


People also ask

How does authorization work in MVC?

The Authorize Attribute In ASP.NET MVC, any incoming request is bound to a controller/method pair and served. This means that once the request matches a supported route and is resolved to controller and method, it gets executed no matter what.

What is authorization and authentication in MVC?

ASP.NET MVC Authentication is a feature in MVC that helps in making the website highly secure and safe. Authentication is the process of confirming or validating the user's identity if the user who is trying to access the web page or web application is a genuine user or not.

Where can the Authorize attribute can be applied?

The Authorize attribute enables you to restrict access to resources based on roles. It is a declarative attribute that can be applied to a controller or an action method.


3 Answers

I don't see a problem with an Action method doing further authorization checks within it. You can leverage the Roles provider for the fine-grained authorization you're looking for. Please excuse my syntax here - it's likely rough and I haven't tested this.

[Authorize(Roles="Shipping, Accounting")]
public ActionResult Edit(int id)
{
    Shipment shipment = repos.GetShipment(id);


    switch (shipment.State)
    {
         case ShipmentState.A:
         if (Roles.IsUserInRole("Shipping"))
                return View(shipment);
         else
                return View("NotAuthorized");
         break;
         case ShipmentState.B:
         if (Roles.IsUserInRole("Accounting"))
                return View(shipment);
         else
               return View("NotAuthorized");
         break;
         default:
              return View("NotAuthorized");
     }
}
like image 187
Josh E Avatar answered Sep 27 '22 19:09

Josh E


Your authorization attribute could get the Shipment from action parameters or route data and then make a decision.

For number 1, there are a number of patterns that enable rich behavior in domain objects. In double-dispatch, you pass a reference to a service abstraction (interface) to a method on the object. Then it can do its thing. You can also write an application service that takes the Shipment and does the work.

On number 2, not necessarily. You may need to abstract the concept of a "contextual Shipment" into a service that figures out which Shipment context you're in. But I'd YAGNI that until you need it again.

like image 23
Matt Hinze Avatar answered Sep 27 '22 18:09

Matt Hinze


You could take a look at Rhino.Security, it could be used to implement user authorization in these kinds of scenarios.

like image 40
Igor Brejc Avatar answered Sep 27 '22 17:09

Igor Brejc