JWT トークンを使用して .NET Web API で Hangfire ダッシュボードを承認する


Hangfire は、.NET 用の最高のバックグラウンド処理ライブラリの 1 つです.最近、定期的なジョブをスケジュールするために .NET 5.0 Web API アプリケーションで使用する必要がありましたが、非常に簡単で使いやすかったです.私が直面した唯一の課題は、運用環境で Hangfire ダッシュボードにアクセスする方法を見つけることでした.

Hangfire ダッシュボードは、既定では localhost でのみアクセス可能であり、他の環境ではある種の承認を実装する必要があります.私のシナリオでは、API 承認は AzureAD を使用して実装されました.クライアント アプリは認証操作を実行し、すべてのリクエストで JWT トークンを REST API に送信します.その場合、同じ認証方法を使用して、クライアント アプリで Hangfire ダッシュボードを表示する方法を見つける必要がありました.

ありがたいことに、Hangfire はカスタム認証フィルターをサポートしています.私が従わなければならなかったすべてのステップは
  • HangfireDashboardJwtAuthorizationFilter から継承されたカスタム IDashboardAuthorizationFilter の実装
  • Startup.cs (私の場合は/hangfire) で定義された Hangfire ダッシュボード ルートに渡された JWT トークンの抽出
  • ダッシュボードへのアクセスを許可/拒否するために必要なクレーム/ロールが JWT トークンに含まれているかどうかを確認しています.
  • Hangfire ダッシュボードによって作成された cunsecutive リクエストによってアクセスされるように、Cookie 内の JWT を設定します.

  • クライアント側では、使用しているもの (純粋な HTML/JS、Angular、Vue、React など) に関係なく、取得した JWT をクエリ文字列.

    そして、あなたは完了です!コードをお見せしましょう!

    HangfireDashboardJwtAuthorizationFilter.cs




    using System;
    using System.IdentityModel.Tokens.Jwt;
    using System.Linq;
    using Hangfire.Dashboard;
    using Microsoft.AspNetCore.Http;
    
    namespace Company.Api.Authorization
    {
        public class HangfireDashboardJwtAuthorizationFilter : IDashboardAuthorizationFilter
        {
            public HangfireDashboardJwtAuthorizationFilter() {}
    
            private void SetCookie(string jwtToken)
            {
                httpContext.Response.Cookies.Append("_hangfireCookie",
                        jwtToken,
                        new CookieOptions()
                        {
                            Expires = DateTime.Now.AddMinutes(30)
                        });
            }
    
            public bool Authorize(DashboardContext context)
            {
                var httpContext = context.GetHttpContext();
                var jwtToken = String.Empty;
    
                if (httpContext.Request.Query.ContainsKey("jwt_token"))
                {
                    jwtToken = httpContext.Request.Query["jwt_token"].FirstOrDefault();
                    SetCookie(jwt_token);
                } 
                else
                {
                    jwtToken = httpContext.Request.Cookies["_hangfireCookie"];
                }
    
                if (String.IsNullOrEmpty(jwtToken))
                {
                    return false;
                }
    
                var handler = new JwtSecurityTokenHandler();
                var jwtSecurityToken = handler.ReadJwtToken(jwtToken);
    
                try
                {
                    // Only authenticated users who have the required claim (AzureAD group in this demo) can access the dashboard.
                    return jwtSecurityToken.Claims.Any(t => t.Type == "groups" && t.Value == "SOME_VALUE");
                }
                catch (Exception exception)
                {
                    throw exception;
                }
            }
        }
    }
    


    Startup.cs で Hangfire ダッシュボードを保護する




    app.UseHangfireDashboard("/hangfire", 
                    new DashboardOptions { Authorization = new [] { new HangfireDashboardJwtAuthorizationFilter() } });
    


    IFRAME を使用してクライアント アプリで /hangfire ページを表示する




    <iframe :src="hangfireUrl" frameborder="0" width="100%" height="100%"></iframe>
    


    上記は Vue.js ビューの IFRAME です.IFRAME src に渡される hangfireUrl の値は、API の Hangfire ダッシュボード ルートの完全な URL + "?jwt_token=XXXXX "です.XXXXX は、クライアント アプリが承認から既に取得したトークンです.サービス (私のデモでは AzureAD).

    これで、ブラウザーでクライアント ページを開くたびに、インライン IFRAME が Web API アプリケーションで実際の Hangfire ダッシュボード ページを開こうとします.渡された jwt_token の値は、カスタム承認フィルターが必要なクレームでユーザーを承認し、ダッシュボードを表示するのに役立ちます.または 401 http ステータスを返します.