Hangfire Dashboard Auth inside Web API project

Viewed 220

We have an .NET 5.0 Web API project with as frontend an Angular project. In de Web API we use Hangfire to do some jobs. I'm trying to make it work so that our admins can access the hangfire dashboard to be able to check the jobs. So I followed the documentation to do this (https://docs.hangfire.io/en/latest/configuration/using-dashboard.html). The Owin package does not seem to work with our Web API project so I've tried many other options such as added middleware, without Owen, changing the order of UseAuthentication and others.

The problem is that the HttpContext is always mostly empty and so the User is also empty.

As I see it the problem is that it is a Web API and not a MVC project as you see in many online examples. My knowledge of auth is also not that great so any help is welcome!

Some more information:

  • We use Azure AD as Authentication service

StartUp

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory, IServiceProvider sp)
{
    UseHangfireDashboardCustom(app);
    app.UseHangfireServer();
    app.UseHangfireDashboard("/hangfire");
    app.UseAuthentication();
    app.UseAuthorization();
}

private static IApplicationBuilder UseHangfireDashboardCustom(IApplicationBuilder app, string pathMatch = "/hangfire", DashboardOptions options = null, JobStorage storage = null)
{
    var services = app.ApplicationServices;
    storage = storage ?? services.GetRequiredService<JobStorage>();
    options = options ?? services.GetService<DashboardOptions>() ?? new DashboardOptions();
    var routes = app.ApplicationServices.GetRequiredService<RouteCollection>();

    app.Map(new PathString(pathMatch), x =>
                x.UseMiddleware<CustomHangfireDashboardMiddleware>(storage, options, routes));

    return app;
}

CustomHangfireDashboardMiddleware

    public class CustomHangfireDashboardMiddleware
    {
        private readonly RequestDelegate _nextRequestDelegate;
        private readonly JobStorage _jobStorage;
        private readonly DashboardOptions _dashboardOptions;
        private readonly RouteCollection _routeCollection;

        public CustomHangfireDashboardMiddleware(RequestDelegate nextRequestDelegate,
                                                 JobStorage storage,
                                                 DashboardOptions options,
                                                 RouteCollection routes)
        {
            _nextRequestDelegate = nextRequestDelegate;
            _jobStorage = storage;
            _dashboardOptions = options;
            _routeCollection = routes;
        }

        public async Task Invoke(HttpContext httpContext)
        {
            var aspNetCoreDashboardContext = new AspNetCoreDashboardContext(_jobStorage, _dashboardOptions, httpContext);
            var findResult = _routeCollection.FindDispatcher(httpContext.Request.Path.Value);
            if (findResult == null)
            {
                await _nextRequestDelegate.Invoke(httpContext);
                return;
            }

            // Attempt to authenticate against Cookies scheme.
            // This will attempt to authenticate using data in request, but doesn't send challenge.
            var result = await httpContext.AuthenticateAsync();
            if (!result.Succeeded)
            {
                // Request was not authenticated, send challenge and do not continue processing this request.
                await httpContext.ChallengeAsync();
                return;
            }

            if (_dashboardOptions.Authorization.Any(filter => filter.Authorize(aspNetCoreDashboardContext) == false))
            {
                var isAuthenticated = result.Principal?.Identity?.IsAuthenticated ?? false;
                if (isAuthenticated == false)
                {
                    httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                }
                else
                {
                    httpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
                }

                return;
            }

            aspNetCoreDashboardContext.UriMatch = findResult.Item2;
            await findResult.Item1.Dispatch(aspNetCoreDashboardContext);
        }
    }
0 Answers
Related