16

The question's title resumes pretty much: where do I verify authorization for a Command?

For example, setting a customer as preferred involves:

  • MarkAsPreferred controller action (could be Winforms or whatever);
  • SetCustomerAsPreferredCommand;
  • SetCustomerAsPreferredCommandHandler;
  • Customer.MarkAsPreferred() (domain);

I identified 3 places to check for authorization:

  • UI for displaying purposes (user should not see a link/button if he/she does not have access to it);
  • controller action to verify the user is authorized to call that command; commands are assumed to always succeed (regarding validation, but I'm assuming authorization too) and we have a chance to inform the user about lack of access;
  • inside the command just before calling domain logic;

SomeView.cshtml

if (authorizationService.Authorize("MarkCustomerAsPreferred))
{
    // show link
}

CustomerController

[HttpPost]
public ActionResult MarkAsPreferred(Guid id)
{
    if (!authorizationService.Authorize("MarkCustomerAsPreferred))
    {
        return RedirectToAction("Unauthorized");
    }

    var MarkCustomerAsPreferredCommand { Id = id };
    ...
}

MarkCustomerAsPreferredCommandHandler

public void Handle(MarkCustomerAsPreferredCommand command)
{
    if (!authorizationService.Authorize("MarkCustomerAsPreferred"))
    {
        throw new Exception("...");
    }

    customer.MarkAsPreferred();
}

My question is: Do I need to verify authorization in 3 places or I'm just being overzealous?

I searched all over the internet but couldn't find any example or reference about this.

Edit

After more research and some tests I think wrapping the commands to add behavior (authorization, validation, logging) as Dennis Taub suggested is easier and cleaner to implement.

I found this blog post which explains exactly this concept.

About having multiple handlers for one command, I don't need to implement one command handler for each behavior for each original command, one wrapping command can wrap all handlers.

Steven
  • 166,672
  • 24
  • 332
  • 435
Luiz Damim
  • 3,803
  • 2
  • 27
  • 31

2 Answers2

7

I think final authorization should be done on the application service level, i.e. as part of handling the command. You could wrap the command handler with an authorization handler for example.

class AuthorizationHandler : IHandle<SetCustomerAsPreferred> {

    IHandle<SetCustomerAsPreferred> innerHandler;

    public AuthorizationHandler(IHandle<SetCustomerAsPreferred> handler)
    {
        innerHandler = handler;
    }

    public void Handle(SetCustomerAsPreferred command) 
    {
        if (/* not authorized */)
            throw ...
        innerHandler.Handle(command);
    }

}

class SetCustomerAsPreferredCommandHandler : IHandle<SetCustomerAsPreferred> {

    public void Handle(SetCustomerAsPreferred command) 
    {
        // do the work
    }

}
Dennis Traub
  • 50,557
  • 7
  • 93
  • 108
  • Wrapping the command is a nice way to add functionality, but it raises a couple questions: 1) This opens up a lot of possibilities, for example logging and validation; so for each command I will implement N command handlers (actual handler, logging, validation, authorization, etc)? 2) Now I have two or more handlers for the same command, how do my IoC container will setup them correctly to inject into the controller? 3) Should I still check for authorization in the controller before handling commands, to minimize the risk of them not being accepted? – Luiz Damim Jun 18 '13 at 17:49
  • 2
    This approach is a bit smelly from my point of view, as you have defined 2 handlers for the same command. I do think that auth check should be done at the moment when the command is issued. at least with asp.net mvc I'd have an authorization filter (which would probably work with web api as well). It is a matter of preference here. @LuizDamim At least my ServiceBus (which I recently wrote) has the option to ignore some types when doing automatic configuration and probably the service bus you're using has this option as well. – MikeSW Jun 19 '13 at 08:10
  • @LuizDamim 1)Logging shouldn't be done as a command handler, I mean any message handler can take a logger dependency. Validation is done in 2 palces with different purposes: you have input validation done at the controller level and business rules validation which is done by the domain object itself. 3) With asp.net mvc I'd say that the user shouldn't reach that action if he doesn't have the right to issue that command. – MikeSW Jun 19 '13 at 08:15
  • @MikeSW I'm not sure I understand your concern. Even when chaining handlers, from an external point of view there's still just one single handler per command. The API is unified, it basically boils down to a pipes and filters type of approach. – Dennis Traub Jun 19 '13 at 11:34
  • I don't chain handlers directly. I chain command -> handler -> command/event -> handler. There is always only 1 handler for a given command. IMO a handler has the responsibility to manage directly one specific context. Your approach works but IMO is confusing. After all the real handler is not the Auth one. It just happens that you're using a handler to implement filter functionality (which doesn't really handle the command). – MikeSW Jun 19 '13 at 13:06
  • Decorated command handlers seem like a big step in the wrong direction. Command objects are a SRP-friendly way of implementing the application/service layer, the layer that "coordinates tasks and delegates work to collaborations of domain objects in the next layer down" (Evans.) That layer also uses services from the infrastructure (also Evans.) Logging and authorization are context-specific and, IMO, should not be obscured and generalized through abuse of the decorator pattern. I don't see a need for the 'handler' either (just `Execute` the command!), YMMV. – tuespetre May 22 '14 at 15:13
  • I think you should check the command before sending it on the bus. The bus should be responsible for calling the handlers and not your security handler... So your code is probably violating SRP. – inf3rno Sep 26 '14 at 05:39
  • @inf3rno I don't know where you found a bus in my code example. Just multiple handlers. And those handlers each have a single responsibility. – Dennis Traub Sep 26 '14 at 06:37
  • For me, it makes more sense to perform authorization in 2 places, firstly before the command is published (if the client doesn't have permissions at the time they issue the command then chances of them having those permissions before it hits the domain are slim to none) and then secondly in the domain itself (whether that be as part of the command handler or the actual domain object is up for debate). It's not impossible for permissions may be revoked mid-flow, just because a command was valid at that point in time doesn't mean it still is when it's actually executed. – James Jul 03 '15 at 11:23
3

It's good UI to have that verification in the View, so the user won't click it by mistake. I consider the controller verification the 'real' one, because there is where the command is created. If an user doesn;t have the rights, she shouldn't be able to create (or even reach that action) the command.

I think that putting the check in the handler is a bit overzelous, as it's not its responsibility to do authorization and is not like that handler can be reached by an user directly.

MikeSW
  • 16,140
  • 3
  • 39
  • 53
  • 1
    It would be worth having the authorisation check in the command handler to allow reuse of the domain with another service. As an example, providing an API using ASP.NET Web API. You could create a command handler decorator that is invoked before each command handler to 'automagically' call the authorisation service with the command as the operation to verify. – Ben Smith Jun 18 '13 at 14:51
  • I was pretty much set on checking authorization on UI and controller, but as Dennis suggested, a wrapping command that does this before actual handling (and if it's so easy to implement as it seems) gives another layer of verification _for free_. Reusing commands as @Ben Smith said is another benefit I hadn't thought of. – Luiz Damim Jun 18 '13 at 18:01
  • 1
    @BenSmith Actually it's not a bad idea for a service bus to support pre and post command handler actions, similar to asp.net mvc filters. – MikeSW Jun 19 '13 at 08:25