authenticationendpointasp.net-core-6.0fast-endpoints

Access denied when calling FastEndpoints endpoint when working with Azure AD Authentication


I am working on an ASP.NET 6 POC and I am checking if I can migrate to minimal APIs and FastEndpoints.

I am interested in using only authentication against an Azure AD tenant and my relevant configuration is as follows:

services.AddFastEndpoints();

services.AddMicrosoftIdentityWebApiAuthentication(configuration);

services.AddEndpointsApiExplorer();

services.AddSwaggerDoc(c =>
{
    AddSwaggerDocs_ConfigureAuth(c, auth);
}, addJWTBearerAuth: false);

c.AddAuth("oauth2", new OpenApiSecurityScheme
{
    Type = OpenApiSecuritySchemeType.OAuth2,
    Flows = new OpenApiOAuthFlows
    {
        AuthorizationCode = new OpenApiOAuthFlow()
        {
            AuthorizationUrl = $"{auth.Instance}/{auth.TenantId}/oauth2/v2.0/authorize",
            TokenUrl = $"{auth.Instance}/{auth.TenantId}/oauth2/v2.0/token",
            Scopes = { { $"api://{auth.ClientId}/access_as_user", "Access as user" } }
        }
    }
});

var app = builder.Build();
app.UseAuthorization();
app.UseFastEndpoints();


app.UseOpenApi();
app.UseSwaggerUi3(c =>
{
    c.ConfigureDefaults();

    c.OAuth2Client = new OAuth2ClientSettings
    {
        ClientId = auth.ClientId,
        AppName = "Foo - Swagger",
        UsePkceWithAuthorizationCodeGrant = true
    };
}); 

This correctly configures Swagger and I am able to get a token from my Azure AD:

Swagger Docs oauth2 authorization with

My test endpoint is the following:

public class GetWeatherEndpoint : Endpoint<GetWeatherInput, List<WeatherForecast>>
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    public override void Configure()
    {
        Get("weather/{days:int}");
    }

    public override async Task HandleAsync(GetWeatherInput input, CancellationToken token)
    {
        var response = Enumerable.Range(1, input.Days).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = Summaries[Random.Shared.Next(Summaries.Length)]
        })
        .ToList();

        await SendOkAsync(response, token);
    }
}

If I try to call this, I receive a 401, as authorization is enabled by default. If I add AllowAnonymous(), it works as expected (HandleAsync gets called).

When working with controllers, a simple Authorized attribute would make things work.

Any idea about how to properly configure the endpoint in this case?


Solution

  • this is most likely a minor misconfiguration.

    in order to see why exactly the auth middleware is sending a 401 response, you'd have to do something similar to what's being done in this article to log the reason.

    basically you need to tap in to a hook like OnAuthenticationFailed and log the reason for failure.

    it seems the request is not reaching fastendpoints due to the auth middleware interrupting the flow earlier on.

    maybe try the subscribeToJwtBearerMiddlewareDiagnosticsEvents in AddMicrosoftIdentityWebApiAuthentication

    also don't you need a app.UseAuthentication() call with azure ad?