Xabaril / AspNetCore.Diagnostics.HealthChecks

Enterprise HealthChecks for ASP.NET Core Diagnostics Package
Apache License 2.0
3.98k stars 771 forks source link

Authorization error using the UI (/healthchecks-ui endpoint) but works fine when calling the JSON endpoint (/health). Works on localhost, not in Azure App Service.. #2168

Open gleneccles opened 4 months ago

gleneccles commented 4 months ago

What happened: I am getting an Unauthorized error in the UI of healthchecks-ui. Calling /health alone works fine. Everything even works fine in my localhost environment. I have an assumption that there is a problem passing the authentication token through. However, the /health endpoint seems to be obeying the Roles I have set up so it is partially working with the bearer token. Everything is .net 8.0.

I am using Azure AD (Entra ID) for authentication. To get to my site at all you need to log in with a Microsoft account linked to AAD and have the appropriate permissions. All of the permissions work fine throughout the site and even in the /health endpoint.

This is what I see

What you expected to happen:

Ultimately I would like to use the HealthChecks.UI actual UI and not the JSON because it is a lot prettier and has the 5 second polling retry.

website.com/health = loads fine and returns this JSON: {"status":"Healthy","totalDuration":"00:00:01.1584121","entries":{"sqlserver":{"data":{},"duration":"00:00:01.1117668","status":"Healthy","tags":[]}}}

website.com/healthchecks-ui = loads fine, but the health check says "unhealthy". The exact error is: HTTP response is not in valid state (Unauthorized) when trying to get report from /health configured with name All Health Checks.

The error can be found here in the source code: https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/blob/73abc7a094f9ef625b83455898a21d22d2fa6a82/src/HealthChecks.UI/Core/HostedService/HealthCheckReportCollector.cs#L147

How to reproduce it (as minimally and precisely as possible):

Simply visit the UI healthchecks-ui endpoint.

Source code sample:

I set up a very simple example that demonstrates the problem.

Here is the service registration:

services.AddHealthChecks().AddSqlServer(Configuration.GetConnectionString("OpkCoreDatabaseProduction")); services.AddHealthChecksUI().AddInMemoryStorage();

Here is the endpoint registration:

app.UseRouting();

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

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "areas",
        pattern: "{area}/{controller}/{action=Index}/{id?}");
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{area=General}/{controller=Home}/{action=Index}/{id?}");
    endpoints.MapGraphQL("/graphql");
    endpoints.MapHealthChecks("/health", new HealthCheckOptions
    {
        ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse,
    }).AllowAnonymous();
    endpoints.MapHealthChecksUI().AllowAnonymous();
});

Here is the appsettings.json setup: "HealthChecksUI": { "HealthChecks": [ { "Name": "All Health Checks", "Uri": "/health" } ], "EvaluationTimeInSeconds": 5 } }

Here is my Authorization setup: services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme).AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"));

Anything else we need to know?:

Am I missing somewhere that I set up the header to be passed along?

I've tried all sorts of flavors of AddAuthorization() and AllowAnonymous() and they all seem to work for /heath but I can't get /healthchecks-ui to authorize.

I've attempted to debug this on the server as I cannot reproduce it using localhost. Nothing of value has turned up because I cannot debug the actual code library where the problem lies.

I've also tried changing the endpoints to have a Uri of "https://mysite.azurewebsites.net/health" and other variations.

There is a similar problem here: AspNetCore Health Checks UI could not get endpoint URI from configuration

Their solution was to set IIS to allow anonymous, but I don't want my whole site to be publicly accessible.

Environment: