Mediatr: Suggested practice for using MediatR and authorization?

Created on 11 Dec 2019  路  10Comments  路  Source: jbogard/MediatR

Heads Up: this is similar/inspired by issue #433


I'm wondering if there's a suggested practice for handling Authorization within an ASP.NET Core Web App that is using MediatR.

Authentication -> who are you? This is handled by the [Authorize] attribute on a controller (for example). I personally like using JWT's as the payload with some JWT middleware deserializing the JWT content into a ClaimsPrincipal.

Authorization -> (now that I know who you are) What are you allowed to do/access?
Not sure where this should be handled. In the controller action method? Or in the Handler method?

What are people doing and any sample code for reference, please?

I _usually_ like to think of my controllers as _really thin_ as possible and place logic in the Handlers.

Anyone have some info which they can suggest?

Most helpful comment

If you are looking for concrete implementation of authorization behavior follow json sources... https://github.com/jasontaylordev/CleanArchitecture/blob/main/src/Application/Common/Behaviours/AuthorizationBehaviour.cs

All 10 comments

You could you a pipeline behavior for this. @jbogard speaks to auth behaviors here.

I had a read of that blog post ... but ... I'm still sorta confused.

It's suggesting that I create a new class called MediatorPipeline which inherits : IRequestHandler<TRequest, TResponse>. Okay ... but where is this used? Does this have to get wired up somewhere? I'm missing the link between this and the rest of my project where I just create a class that inherits from IMediator.

Secondly, asp.net core has the concept of middlewear and thus a pipeline ... is this the same? are we adding another pipeline in when we can use the existing one? what are the differences between the two?

Pipeline behaviors are different now than they were in that blog post, there are some examples of them in the src of this project. Yes they have to be wired up, and yes aspnet core middleware is very similar. The difference is where you want your business logic to reside and what you want it to depend on. In the case of an aspnet core project you may be fine with all the aspnet core dependencies. In some cases people like their business logic to not have these dependencies so creating their own pipeline is preferred. It鈥檚 up to you how you use the tools.

Hi @lilasquared - thanks heaps for jumping into the discussion, I _really_ appreciate it.

I'm still trying to grok this, based on your additional info.

The difference is where you want your business logic to reside and what you want it to depend on

Okay - I sorta can guess what you mean by that statement, but I'm not sure _in practice_ how the two differ. Are you able to give an example of this? I'm usually a fan of 'light controllers' which makes the business logic 'host/app agnostic'. This is why the MediatR framework/library appeals to me. I _feel_ like i can create my "features" and easily use them in a webapi app or over in an iphone app using xamarin (note: i've never done any xam stuff ... but was just thinking out aloud).

So that's why I'm saying "i sorta understand" having less stuff in controllers and more stuff in "features" ... but I'm still not seeing this _exactly_.

Yes - I'm a slow learner, so please bear with me 馃槉

The difference i'm referring to here is whether to use mediator pipelines or take advantage of the middleware that is built into aspnet core web projects. In the case of "light controllers" it would make sense to have a mediator pipeline to handle your authorization since your business logic will then be host/app agnostic. If you were to handle authorization in the aspnet core middleware pipeline then your business logic is dependent on aspnet core.

For authorization I can see something like this being how it would be done (note: we don't have an implementation of this currently I'm just making it up)

some base "authorized request" - say all of these carry a user ID of authenticated user, and roles allowed to perform the action

public abstract class AuthorizedRequest : IRequest
{
    public abstract IEnumerable<String> Roles { get; }
    public Int32 UserId { get; }
}

some implementation of this class

public class DoAuthorizedThing : AuthorizedRequest
{
    public override IEnumerable<String> Roles => new [] { "can_do_thing_role" };
    public Object Payload { get; set; } // Some random other payload
}

pipeline behavior:

public class CheckAuthorizationBehavior : IPipelineBehavior<TRequest, TResponse>
    where TRequest : AuthorizedRequest
{
    private readonly IUserRepository _users;
    public CheckAuthorizationBehavior(IUserRepository users)
    {
        _users = users;
    }
    public async Task<TResponse> Handle(TRequest request, CancellationToken token, RequestHandlerDelegate<TResponse> next)
    {
        var user = await _users.GetUser(request.UserId);
        if (user.HasRoles(request.Roles)) // can continue
        {
            return next();
        }

        // handle failed authorization
    }
}

This is just a very trivial example but hopefully it gets you in the right direction.

Awesome - this is starting to help.

Firstly, this bit:

In the case of "light controllers" it would make sense to have a mediator pipeline to handle your authorization since your business logic will then be host/app agnostic

That's one of the main selling points for me - so great! I'm going to give this a go ...

then this bit ..

public class CheckAuthorizationBehavior : IPipelineBehavior<TRequest, TResponse>
    where TRequest : AuthorizedRequest
....

Ok - so we've now created a new Pipeline behaviour. But .. how is this "used" ? I've never seen anywhere where this is 'wired up' so MediatR knows to use this.

Like, if this was doing asp.netcore middleware, we manually wire those pieces up on the ConfigureServices method in startup.cs file (for example). Is there something similar we have to do here, for our own custom Pipeline Behaviors?

Yep there is, check out his samples in the repo. Here is the one for aspnet core https://github.com/jbogard/MediatR/blob/master/samples/MediatR.Examples.AspNetCore/Program.cs

Thanks heaps @lilasquared - i _really_ appreciate your patience and help, with me on this issue.

I'll be giving this a go, tonight when I get home, in my free time.

Again, thanks!

If you are looking for concrete implementation of authorization behavior follow json sources... https://github.com/jasontaylordev/CleanArchitecture/blob/main/src/Application/Common/Behaviours/AuthorizationBehaviour.cs

Was this page helpful?
0 / 5 - 0 ratings