Reputation: 2535
I managed to work Hangfire on my ASP.NET Core MVC application, and now I am trying to add admin authorization.
I added the following code to the Startup.cs file:
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
Authorization = new[] {new SecurityHelpers.AdminAuthorization.HangFireAuthorizationFilter() }
});
app.UseHangfireServer();
RecurringJob.AddOrUpdate( () => Debug.WriteLine("Minutely Job"), Cron.Minutely);
Now I have a problem with custom authorization filter:
public class HangFireAuthorizationFilter : IDashboardAuthorizationFilter
{
public bool Authorize(DashboardContext context)
{
return true;
}
}
There are samples for old configuration with IAutohorizationFilter, and form version 1.6.8 there is a new interface IDashboardAuthorizationFilter, and I can't figure out how to implement it.
My web application uses claims.
thnx
Upvotes: 16
Views: 29064
Reputation: 2045
Here's my implementation for .NET Core:
public class HangfireAuthorizationFilter : IDashboardAuthorizationFilter {
private string policyName;
public HangfireAuthorizationFilter(string policyName) {
this.policyName = policyName;
}
public bool Authorize([NotNull] DashboardContext context) {
var httpContext = context.GetHttpContext();
var authService = httpContext.RequestServices.GetRequiredService<IAuthorizationService>();
return authService.AuthorizeAsync(httpContext.User, this.policyName).ConfigureAwait(false).GetAwaiter().GetResult().Succeeded;
}
}
Set it up in the Startup
Configure
with:
app.UseHangfireDashboard(
pathMatch: "/hangfire",
options: new DashboardOptions() {
Authorization = new IDashboardAuthorizationFilter[] {
new HangfireAuthorizationFilter("somePolicy")
}
});
Make sure that the policy you've chosen (eg. "somePolicy") is set up previously in Startup
ConfigureServices
. For example:
services.Configure<AuthorizationOptions>(options => {
options.AddPolicy("somePolicy", policy => {
// require the user to be authenticated
policy.RequireAuthenticatedUser();
// Maybe require a claim here, if you need that.
//policy.RequireClaim(ClaimTypes.Role, "some role claim");
});
});
Upvotes: 19
Reputation: 1639
To add custom basic authentication in hangfire for asp.net core
Use Hangfire.Dashboard.Basic.Authentication nuget package.
Install using the command
Install-Package Hangfire.Dashboard.Basic.Authentication
In startup configure method add the following
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
//AppPath = "" //The path for the Back To Site link. Set to null in order to hide the Back To Site link.
DashboardTitle = "My Website",
Authorization = new[]
{
new HangfireCustomBasicAuthenticationFilter{
User = _configuration.GetSection("HangfireSettings:UserName").Value,
Pass = _configuration.GetSection("HangfireSettings:Password").Value
}
}
});
Add the following in the appsettings.json (Use your username and password)
"HangfireSettings": {
"UserName": "admin",
"Password": "password"
}
Upvotes: 31
Reputation:
If you are using .NET Core 2.0, you would need a custom implementation to comply with the new auth standards.
You need to add a middleware. This one's provided by HangFire in their Github page/issues.
public class HangfireDashboardMiddleware
{
private readonly DashboardOptions _dashboardOptions;
private readonly JobStorage _jobStorage;
private readonly RequestDelegate _nextRequestDelegate;
private readonly RouteCollection _routeCollection;
public HangfireDashboardMiddleware(
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 default auth scheme (this will attempt to authenticate using data in request, but doesn't send challenge)
var result = await httpContext.AuthenticateAsync();
if (!httpContext.User.Identity.IsAuthenticated)
{
// request was not authenticated, send challenge and do not continue processing this request
await httpContext.ChallengeAsync();
}
if (_dashboardOptions
.Authorization
.Any(filter =>
filter.Authorize(aspNetCoreDashboardContext) == false))
{
var isAuthenticated = httpContext.User?.Identity?.IsAuthenticated;
httpContext.Response.StatusCode = isAuthenticated == true
? (int) HttpStatusCode.Forbidden
: (int) HttpStatusCode.Unauthorized;
return;
}
aspNetCoreDashboardContext.UriMatch = findResult.Item2;
await findResult.Item1.Dispatch(aspNetCoreDashboardContext);
}
}
Then in your Startup.cs You need to add this method
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<HangfireDashboardMiddleware>(storage, options, routes));
return app;
}
Finally, use the Custom Authorization
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc(routes => routes.MapRoute(
"default",
"{controller=Home}/{action=Index}/{id?}"));
app.UseHangfireServer();
//Voila!
UseHangfireDashboardCustom(app);
}
Upvotes: 5
Reputation: 1368
This is how I implement IDashboardAuthorizationFilter
public class HangfireAuthorizeFilter : IDashboardAuthorizationFilter
{
public bool Authorize(DashboardContext context)
{
var owinEnvironment = context.GetOwinEnvironment();
if (owinEnvironment.ContainsKey("server.User"))
{
if (owinEnvironment["server.User"] is ClaimsPrincipal)
{
return (owinEnvironment["server.User"] as ClaimsPrincipal).Identity.IsAuthenticated;
}
else if (owinEnvironment["server.User"] is GenericPrincipal)
{
return (owinEnvironment["server.User"] as GenericPrincipal).Identity.IsAuthenticated;
}
}
return false;
}
}
In your startup
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
Authorization = new [] { new HangfireAuthorizeFilter() }
});
Upvotes: 1