401 HttpResponse trying to view the Dashboard using Azure Entra for Authentication and Asp.Net Core 7

Iam getting a 401 when trying to view the Dashboard using Asp.net Core 7.0 and Azure Entra (MS Azure AD) to restrict who can view the dashboard. I am using Visual Studio 2022 as my environment and am currently running under my localhost.

Below is a sample of the code:

appsettings.json:
{
“AzureAd”: {
“Instance”: “https://login.microsoftonline.com/”,
“Domain”: “localhost:3572”,
“ClientId”: “”,
“TenantId”: “<my-azure-tenant-id?”,
“Audience”: “https://localhost:3572
},
“HangfireConnectionString”: “Server=tcp:someSubDomain…database.windows.net,1433;Initial Catalog=SomeDatabase;;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;Authentication="Active Directory Default";”
}

Program.cs

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection(“AzureAD”), JwtBearerDefaults.AuthenticationScheme);

builder.Services.AddAuthorization(options =>
{
var policyBuilder = new AuthorizationPolicyBuilder()
.AddAuthenticationSchemes(OpenIdConnectDefaults.AuthenticationScheme)
.RequireAuthenticatedUser();

options.AddPolicy("HangfireDashboardPolicy", policyBuilder.Build());

});

var options = new SqlServerStorageOptions
{
PrepareSchemaIfNecessary = false
};

builder.Services.AddHangfire(configuration => configuration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_180)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseSqlServerStorage(builder.Configuration[“HangfireConnectionString”], options));

builder.Services.AddHangfireServer();

var app = builder.Build();

app.UseRouting();

app.MapHangfireDashboard(“/Hangfire”, new DashboardOptions()
{
Authorization = new { new HangfireAuthorizationFilter() }
})
.RequireAuthorization(“HangfireDashboardPolicy”);

app.Run();

public class HangfireAuthorizationFilter : IDashboardAuthorizationFilter
{
public bool Authorize(DashboardContext context)
{
var httpContext = context.GetHttpContext();
// Here is where I will place my restrictions on who can view
return httpContext.User.Identity?.IsAuthenticated ?? false;
}
}

Am I missing something?

1 Like

After playing around, below is what needs to be done:

appSettings.json

"AzureAd": {
  "Instance": "",
  "Domain": "",
  "ClientId": "",
  "TenantId": "",
  "CallbackPath": "/signin-oidc",
  "SignedOutCallbackPath": "/signout-oidc"
}

program.cs


var hangfireDashboardPolicy  = "myHangfirePolicy";

builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
  .AddMicrosoftIdentityWebApp(options =>
  {
    builder.Configuration.Bind("AzureAd", options);
    options.Prompt = "select_account";
  });

builder.Services.AddAuthorization(options =>
{
  options.AddPolicy(hangfireDashboardPolicy, builder =>
  {
    builder
     .AddAuthenticationSchemes(OpenIdConnectDefaults.AuthenticationScheme)
     .RequireAuthenticatedUser();

  });
});

var app = builder.Build();

app.UseHangfireDashboard("/hangfire", new DashboardOptions()
{
  DashboardTitle = "My Hangfire Dashboard",
  Authorization = new[] { new HangfireAuthorizationFilter() }
});

app.MapHangfireDashboard("/hangfire")
  .RequireAuthorization(hangfireDashboardPolicy)
public class HangfireAuthorizationFilter : IDashboardAuthorizationFilter
{
  public bool Authorize([NotNull] DashboardContext context)
  {
    var httpContext = context.GetHttpContext();

    // Needs more security here - groups check or explore the use of adding claims to the login

    return httpContext.User.Identity?.IsAuthenticated ?? false;
  }
}

Also, the uri will need to be set in the app registration for the login when publishing to azure.