Custom authentication middleware - how to check if request is anonymous or authorize?

Viewed 3711

I'm trying to write my own authentication middleware code.

In good old HttpModules, I could use "OnAuthenticateRequest" when a "Authorize" page was requested.

My middleware code is something like this:

public async Task Invoke(HttpContext context)
{
    if (!context.User.Identity.IsAuthenticated)
    {
    }
}

... but that will also check IsAuthenticated on requests with [AllowAnonymous] attribute.

How can I from my middleware, check if the request has attribute [AllowAnonymous] or [Authorize]?

I need to be able to do something like...

public async Task Invoke(HttpContext context)
{
    if (HasAuthorizeAttribute && !context.User.Identity.IsAuthenticated)
    {
    }
    await _next.Invoke(context);
}

Thanks.

2 Answers

There is a way to check, from inside your middleware, if the request is targeting a page marked as [Anonymous].

//inside your middleware
var endpoint = context.GetEndpoint();
if (endpoint?.Metadata?.GetMetadata<IAllowAnonymous>() is object)
{
    await _next(context);
    return;
}

Original solution found on this blog: Anonymous Aware Middleware

If I understand you mean correctly, you're looking for something like this: You want to classify some action(s) in the controller, some action can be executed after authorization, and otherwise.

In this case, you can set [Authorize] and [AllowAnonymous] on the top of that actions:

public class HomeController : Controller
{
    [AllowAnonymous]
    public async Task Invoke(HttpContext context)
    {
        // all of codes here can be executed with unauthorized request(s).
        // code goes here...
    }

    [Authorized]
    public async Task Invoke_2(HttpContext context)
    {
        // all of codes here can be executed WHEN the request is authorized
        // code goes here...
    }
}

And, if you want to authorize all of the requests that will hit the controller, you can set the [Authorize] attribute on the top of the controller name:

[Authorize]
public class HomeController : Controller
{
    // this attribute is still required when you allow anonymous request(s)
    [AllowAnonymous]
    public async Task Invoke(HttpContext context)
    {
        // all of codes here can be executed with unauthorized request(s).
        // code goes here...
    }

    // you can remove [Authorize] attribute from this action, because
    // it's authorized by default
    public async Task Invoke_2(HttpContext context)
    {
        // all of codes here can be executed WHEN the request is authorized
        // code goes here...
    }
}

Note: Because you're working with Task, it's better if you name your action that ends with Async, such as: InvokeAsync or Invoke_2Async.

Related