Search code examples
c#asp.netauthenticationauthorizationminimal-apis

ASP.NET custom middleware after authorization/authentication


I wanted to have my API support AOT so I've decided to move away from MVC Controllers.

I don't like the minimal API approach though so I've decided to write my own middleware to handle the requests and responses manually (with my own code generation but that's not important).

app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();

app.UseMiddleware<MyRequestResponseMiddleware>();

The problem is that authentication/authorization stopped working. HttpContext.User is not configured, claims are empty, IsAuthenticated is always false even after the authentication/authorization middleware.

public async Task InvokeAsync(HttpContext context)
{
    Debug.WriteLine(context.User.Identity.IsAuthenticated); //always false
}

I guess it makes sense. I use two auth schemas and multiple policies and I want to manually handle what policy needs to be applied to a different request path like this:

//EXAMPLE 
public async Task InvokeAsync(HttpContext context)
{
    if (context.Request.Path.Value == "/auth-request")
    {
        var result = authenticationService.Authenticate("policyName");
    
        //if authentication fails, return 401
        //otherwise user is authenticated
        //process request as usual
    }
}

But I have no idea how to do this.

How is MVC doing it? How is minimal api doing it?

How to check for authentication/authorization configured with methods like AddJwtBearer,AddScheme,AddAuthorization,AddPolicy etc. in custom request/response middleware?


Solution

  • Okay that was easier than I expected.

    using Microsoft.AspNetCore.Authentication;
    
    namespace MyProject;
    
    public class MyMiddleware(IAuthorizationService authorizationService)
    {
        public async Task InvokeAsync(HttpContext context)
        {
            if (context.Request.Path.Value == "/auth-request")
            {
                var authenticateResult = await context.AuthenticateAsync("myScheme");
                if (authenticateResult.Succeeded)
                {
                    //authenticated
                    context.User = authenticateResult.Principal;
                    var authorizeResult = await authorizationService.AuthorizeAsync(context.User, "myPolicy");
                    if (authorizeResult.Succeeded)
                    {
                        //authenticated and authorized
                    }
                }
            }
        }
    }