Home > OS >  Is it possible to use custom RequireAuthorization and AllowAnonymous for custom middleware authentic
Is it possible to use custom RequireAuthorization and AllowAnonymous for custom middleware authentic

Time:09-08

I currently have this web app in which I need to use a custom authentication/authorization middleware. We're registering the routes using minimap APIs like so:

// snip
app.UseEndpoints(x => {
    x.MapGet("/api/something", () => { ... returns something ... });
})
// snip

Our custom middleware requires us to configure a list of all the paths that need to be authorized to certain types of users and those that allow for anonymous access. But what I would really like to do is define extension methods that would work similarly to how AllowAnonymous() and RequiresAuthorization(...) work:

// snip
app.UseEndpoints(x => {
    x.MapGet("/api/something", () => { ... returns something ... }).RequiresAuthorization("Admins");
})
// snip

This way I can avoid having to remember to update the configuration values in the middleware, while also having the auth information in the same place as the route definition. So far I can't seem to figure out what to set up in the extension method to be able to then inspect the context of each request inside the custom middleware to know if the route should have auth or not. I'm guessing I have to set some sort of metadata on the route, but I'm not sure what or where to set it up. I tried checking the source code for asp net core, but it's so meta and indirect that you really never know what anything actually does in that code. Any guidance or pointers would be very much appreciated :D

CodePudding user response:

You can just add any metadata and analyze it in your custom middleware:

public class SomeCustomMeta
{
    public string Meta { get; set; }
}

app.MapGet("/test", () => Results.Ok("Hello World!"))
    .WithMetadata(new SomeCustomMeta{ Meta = "Test"});

And in the middleware:

public async Task InvokeAsync(HttpContext context)
{
    if(context.GetEndpoint()?.Metadata.GetMetadata<SomeCustomMeta>() is { } meta)
    {
        Console.WriteLine($"SomeCustomMeta: {meta.Meta}");
    }
    
    await _next(context);
}

The WithMetadata... call can be moved to nice extension method:

public static class BuilderExts
{
    public static TBuilder RequireCustomAuth<TBuilder>(this TBuilder builder, string meta) where TBuilder : IEndpointConventionBuilder
    {
        if (builder == null)
        {
            throw new ArgumentNullException(nameof(builder));
        }

        return builder.WithMetadata(new SomeCustomMeta { Meta = meta });
    }
}
  • Related