2

Back in ASP.NET Core 1, authentication would be hooked manually into the request pipeline on its configuration: For a custom authentication process, you would simply define a AuthenticationMiddleware and hook it into your pipeline at the point where the authentication was supposed to happen.

In ASP.NET Core 2, there's no more AuthenticationMiddleware and you're supposed to do a UseAuthentication() at some point in the pipeline where all authentication necessarily happens.

The difference is documented here: https://learn.microsoft.com/en-us/aspnet/core/security/authorization/limitingidentitybyscheme

To distinguish different ways of authentication, there are policies identified by magic strings (lots of magic strings in ASP.NET Core).

I'm then told that I can select the desired scheme with attributes on my controller, but I don't use MVC at all in the scenario in question. So how do I specify for a specific branch of the pipeline:

    app.UseWhen(c => ..., app2 =>
    {
        // auth number 1 desired

        ...
    });

    app.UseWhen(c => ..., app2 =>
    {
        // auth number 2 desired

        ...
    });

And even in MVC, authentication happens before routing, so how can the information which scheme to use possibly be available at the UseAuthentication() point in the pipeline?

2
  • Can you provide some more detail on what you want to do in your middleware? e.g. Return a 401 if the user wasn't authenticated, etc? Commented Apr 9, 2019 at 17:19
  • @KirkLarkin It’s just reading the headers and returns a 403 if authentication fails. Commented Apr 9, 2019 at 17:24

1 Answer 1

4

You can target a specific authentication-scheme using an imperative approach, by calling AuthenticateAsync. Here's an example:

app2.Use(async (ctx, next) =>
{
    var authenticateResult = await ctx.AuthenticateAsync("SchemeName");

    if (!authenticateResult.Succeeded)
    {
        ctx.Response.StatusCode = 401; // e.g.
        return;
    }

    // ...
});

AuthenticateAsync takes the authentication-scheme as an argument and returns an instance of AuthenticateResult, which indicates success or failure via Succeeded and provides the authenticated ClaimsPrincipal via Principal.

You can also perform authorisation against a specific policy using IAuthorizationService. Here's an example of how the Principal from AuthenticateResult can be passed through AuthorizeAsync:

var authorizationService = ctx.RequestServices.GetService<IAuthorizationService>();
var authorizationResult = await authorizationService.AuthorizeAsync(
    authenticateResult.Principal, "PolicyName");

if (!authorizationResult.Succeeded)
{
    ctx.Response.StatusCode = 403; // e.g.
    return;
}

// ...

As with AuthenticateResult, AuthorizationResult indicates success or failure via Succeeded - it also provides information about why authorisation failed via Failure.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.