Skip to content

Instantly share code, notes, and snippets.

@ndc
Created September 1, 2018 12:30
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save ndc/a1cc8e2515e5e0d941a884fc6a6267f5 to your computer and use it in GitHub Desktop.
Save ndc/a1cc8e2515e5e0d941a884fc6a6267f5 to your computer and use it in GitHub Desktop.
Hangfire dashboard authorization filter using basic authentication and relying on browser support to allow user to input username and password.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Hangfire.Annotations;
using Hangfire.Dashboard;
using Microsoft.AspNetCore.Http;
namespace MyApp.ScheduledTask
{
public class HFDashboardAuthFilter : Hangfire.Dashboard.IDashboardAuthorizationFilter
{
public bool Authorize([NotNull] DashboardContext context)
{
var httpContext = context.GetHttpContext();
var header = httpContext.Request.Headers["Authorization"];
if (string.IsNullOrWhiteSpace(header))
{
SetChallengeResponse(httpContext);
return false;
}
var authValues = System.Net.Http.Headers.AuthenticationHeaderValue.Parse(header);
if (!"Basic".Equals(authValues.Scheme, StringComparison.InvariantCultureIgnoreCase))
{
SetChallengeResponse(httpContext);
return false;
}
var parameter = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(authValues.Parameter));
var parts = parameter.Split(':');
if (parts.Length < 2)
{
SetChallengeResponse(httpContext);
return false;
}
var username = parts[0];
var password = parts[1];
if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
{
SetChallengeResponse(httpContext);
return false;
}
if (username == "johndoe" && password == "123")
{
return true;
}
SetChallengeResponse(httpContext);
return false;
}
private void SetChallengeResponse(HttpContext httpContext)
{
httpContext.Response.StatusCode = 401;
httpContext.Response.Headers.Append("WWW-Authenticate", "Basic realm=\"Hangfire Dashboard\"");
httpContext.Response.WriteAsync("Authentication is required.");
}
}
}
@mebius4789
Copy link

great

@jmtejada
Copy link

Gracias! 👍

@rafaelbm
Copy link

rafaelbm commented Feb 7, 2019

Obrigado 👍

@phi17
Copy link

phi17 commented May 1, 2019

Thank you. Works great. Question, how do you sign out of dashboard after login?

@kkaradag2
Copy link

Thank you. it is work for me. Great work.

@matjazbravc
Copy link

Works great, but how to sign out? Because the same Authorization header stays forever in requests ...

@ndc
Copy link
Author

ndc commented Jul 15, 2019

This gist uses HTTP basic authentication, so the way to log out is the same as other HTTP basic authentication, for example https://stackoverflow.com/questions/233507/how-to-log-out-user-from-web-site-using-basic-authentication

I haven't tried to log out though.

@matjazbravc
Copy link

matjazbravc commented Jul 15, 2019 via email

@kaveshy
Copy link

kaveshy commented Aug 12, 2019

Does this Class get triggered when accessing /hangfire ?
And will the same idea work with .Net Framework ?

@rmotam
Copy link

rmotam commented Jul 22, 2020

Esse código funciona rodando local, ao publicar em produção, fica em loop a solicitação de login e senha. Alguém sabe porque?

@igorgomeslima
Copy link

igorgomeslima commented Mar 16, 2022

Nice work!

Recent viewers:

Now finally we have an official implementation... Hangfire.Dashboard.Authorization.Basic.

@vukasinpetrovic
Copy link

Wow man, this is amazing. I was struggling to find a good solution for API type projects. I had an idea with query strings, but then hangfire does not allow them. This solution is perfect, I honestly did not know you can trigger built in browser login popup!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment