演習 - 多要素認証を構成する

完了

前のユニットでは、ASP.NET Core Identity で多要素認証 (MFA) のために時間ベースのワンタイム パスワード (TOTP) を実装する方法について説明しました。 このユニットでは、既存の [Configure authenticator app] (Authenticator アプリの構成) を、登録キーを含む QR コードが提供されるようにカスタマイズします。

QR コードの生成

QR コードを生成するには複数の方法があります。 ドキュメントの例では、クライアント側の JavaScript ライブラリを使います。 しかしながら、このユニットでは、サードパーティの NuGet パッケージを使用して、サーバー上で C# で QR コードを生成します。 生成された QR コード イメージは、base-64 でエンコードされた文字列として、HTML のプレースホルダー要素に挿入されます。

QR コード サービスの追加

認証アプリ構成フォームで QR コードを生成するために必要なすべてのものを構築しましょう。

  1. ターミナル ペインで、QRCoder NuGet パッケージをインストールします。

    dotnet add package QRCoder --version 1.6.0
    
  2. [エクスプローラー] ペインで、Services フォルダーを右クリックし、QRCodeService.cs という名前の新しいファイルを追加します。 次のコードを追加します。

    using QRCoder;
    
    namespace RazorPagesPizza.Services;
    public class QRCodeService
    {
        private readonly QRCodeGenerator _generator;
    
        public QRCodeService(QRCodeGenerator generator)
        {
            _generator = generator;
        }
    
        public string GetQRCodeAsBase64(string textToEncode)
        {
            QRCodeData qrCodeData = _generator.CreateQrCode(textToEncode, QRCodeGenerator.ECCLevel.Q);
            var qrCode = new PngByteQRCode(qrCodeData);
    
            return Convert.ToBase64String(qrCode.GetGraphic(4));
        }
    }
    

    上記のコードでは次の操作が行われます。

    • ライブラリの QRCodeGenerator クラスのインスタンスにアクセスできるようにするために、コンストラクターの挿入が使用されます。
    • base-64 でエンコードされた文字列を返すために、GetQRCodeAsBase64 メソッドが公開されます。 GetGraphic に渡される整数値によって、QR コードのディメンションが決まります。 この場合、生成される QR コードは、一辺が 4 ピクセルの正方形のブロックで構成されます。
  3. Program.cs で、強調表示されている行を追加します。

    using Microsoft.AspNetCore.Identity;
    using Microsoft.EntityFrameworkCore;
    using RazorPagesPizza.Areas.Identity.Data;
    using Microsoft.AspNetCore.Identity.UI.Services;
    using RazorPagesPizza.Services;
    using QRCoder;
    
    var builder = WebApplication.CreateBuilder(args);
    var connectionString = builder.Configuration.GetConnectionString("RazorPagesPizzaAuthConnection");
    builder.Services.AddDbContext<RazorPagesPizzaAuth>(options => options.UseSqlServer(connectionString)); 
    builder.Services.AddDefaultIdentity<RazorPagesPizzaUser>(options => options.SignIn.RequireConfirmedAccount = true)
          .AddEntityFrameworkStores<RazorPagesPizzaAuth>();
    
    // Add services to the container.
    builder.Services.AddRazorPages();
    builder.Services.AddTransient<IEmailSender, EmailSender>();
    builder.Services.AddSingleton(new QRCodeService(new QRCodeGenerator()));
    
    var app = builder.Build();
    

    QRCodeService は、Program.cs 内の IoC コンテナーにシングルトン サービスとして登録されます。

多要素認証をカスタマイズする

QR コードを生成できるようになったので、認証アプリ構成フォームに QR コードを埋め込むことができます。

  1. Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml.cs を開き、次の変更を行います。

    1. QR コードの base-64 文字列表現を格納するには、次のプロパティを EnableAuthenticatorModel クラスに追加します。

      public class EnableAuthenticatorModel : PageModel
      {
          private readonly UserManager<RazorPagesPizzaUser> _userManager;
          private readonly ILogger<EnableAuthenticatorModel> _logger;
          private readonly UrlEncoder _urlEncoder;
      
          public string QrCodeAsBase64 { get; set; }    
      
    2. 強調表示された変更を、OnGetAsync ページ ハンドラーに組み込みます。

      public async Task<IActionResult> OnGetAsync([FromServices] QRCodeService qrCodeService)
      {
          var user = await _userManager.GetUserAsync(User);
          if (user == null)
          {
              return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
          }
      
          await LoadSharedKeyAndQrCodeUriAsync(user);
          QrCodeAsBase64 = qrCodeService.GetQRCodeAsBase64(AuthenticatorUri);
      
          return Page();
      }
      

      上記のページ ハンドラーでは、パラメーターの挿入により QRCodeService シングルトン サービスへの参照が提供されます。

    3. QRCodeService への参照を解決するには、ファイルの先頭に次の using ステートメントを追加します。 変更を保存します。

      using RazorPagesPizza.Services;
      
    4. 強調表示されている変更を GenerateQrCodeUri メソッドに組み込みます。

      private string GenerateQrCodeUri(string email, string unformattedKey)
      {
          return string.Format(
              CultureInfo.InvariantCulture,
              AuthenticatorUriFormat,
              _urlEncoder.Encode("RazorPagesPizza"),
              _urlEncoder.Encode(email),
              unformattedKey);
      }
      

      これにより、TOTP アプリのキーの表示名が設定されます。

  2. Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml で、次の強調表示されている変更を行って保存します。

    <li>
        <p>Scan the QR Code or enter this key <kbd>@Model.SharedKey</kbd> into your two factor authenticator app. Spaces and casing do not matter.</p>
        <div class="alert alert-info">Learn how to <a href="https://go.microsoft.com/fwlink/?Linkid=852423">enable QR code generation</a>.</div>
        <div id="qrCode">
            <img alt="embedded QR code" src="data:image/png;base64,@Model.QrCodeAsBase64" />
        </div>
        <div id="qrCodeData" data-url="@Model.AuthenticatorUri"></div>
    </li>
            
    

    上記のマークアップでは、base-64 でエンコードされたイメージがページに埋め込まれます。

多要素認証のテスト

認証アプリ構成フォーム上で、QR コードに必要なすべての変更を行いました。 これで、MFA 機能を簡単にテストできます。

  1. すべての変更を確実に保存します。

  2. dotnet run を使用してアプリをビルドおよび実行します。

  3. サイトに移動し、まだサインインしていない場合は、いずれかの登録済みユーザーでサインインします。 [Hello, [First name] [Last name]!] (こんにちは、[名] [姓]!) リンクを選択してプロファイル管理ページに移動し、[Two-factor authentication] (2 要素認証) を選択します。

  4. [Add authenticator app](認証アプリの追加) ボタンを選択します。

  5. 画面の指示に従って、このユーザーに対する認証アプリを登録して確認します。

    たとえば Android 上の Microsoft Authenticator を使い、次の手順に従ってアカウントをアプリに追加します。

    1. Microsoft Authenticator アプリを開きます。
    2. 右上にあるケバブ メニュー (縦の省略記号) を選択します。
    3. [アカウントの追加] を選択します。
    4. [他のアカウント (Google、Facebook など)] を選択します。
    5. 示されているとおりに QR コードをスキャンします。
  6. TOTP アプリによって提供された確認コードを、[確認コード] テキスト ボックスに入力します。

  7. [確認] を選択します。

    検証が成功すると、[Your authenticator app has been verified](認証アプリが確認されました) というバナーといくつかの復旧コードが、ページに表示されます。

  8. VS Code の [SQL Server] タブで、RazorPagesPizza データベースを右クリックし、[新しいクエリ] を選択します。 次のクエリを入力し、Ctrl+Shift+E を押して実行します。

    SELECT FirstName, LastName, Email, TwoFactorEnabled
    FROM dbo.AspNetUsers
    

    サインインしているユーザーの場合、TwoFactorEnabled 列が 1 と等しいことが出力で示されます。 他の登録済みユーザーに対しては多要素認証が有効になっていないため、レコードの列の値は 0 です。

  9. Web アプリで、[ログアウト] を選び、同じユーザーでもう一度サインインします。

  10. TOTP 認証アプリからの確認コードを、[Authenticator code](認証コード) テキスト ボックスに入力します。 [ログイン] ボタンを選択します。

  11. [こんにちは、<名> <姓>!] を選択します。 その後、[Two-factor authentication](2 要素認証) タブを選択します。

    Microsoft Authenticator が設定されているため、次のボタンが表示されます。

    • Disable 2FA (2FA を無効にする)
    • Reset recovery codes (復旧コードをリセットする)
    • Set up authenticator app (認証アプリを設定する)
    • Reset authenticator app (認証アプリをリセットする)
  12. VS Code のターミナル ペインで、Ctrl+C を押してアプリを停止します。

まとめ

このユニットでは、認証アプリ構成フォームに QR コードを生成する機能を追加しました。 次のユニットでは、Identity を使って要求を格納し、認可ポリシーを適用する方法について説明します。