演習 - 多要素認証を構成する
前のユニットでは、ASP.NET Core Identity で多要素認証 (MFA) のために時間ベースのワンタイム パスワード (TOTP) を実装する方法について説明しました。 このユニットでは、既存の [Configure authenticator app] (Authenticator アプリの構成) を、登録キーを含む QR コードが提供されるようにカスタマイズします。
QR コードの生成
QR コードを生成するには複数の方法があります。 ドキュメントの例では、クライアント側の JavaScript ライブラリを使います。 しかしながら、このユニットでは、サードパーティの NuGet パッケージを使用して、サーバー上で C# で QR コードを生成します。 生成された QR コード イメージは、base-64 でエンコードされた文字列として、HTML のプレースホルダー要素に挿入されます。
QR コード サービスの追加
認証アプリ構成フォームで QR コードを生成するために必要なすべてのものを構築しましょう。
ターミナル ペインで、
QRCoder
NuGet パッケージをインストールします。dotnet add package QRCoder --version 1.6.0
[エクスプローラー] ペインで、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 ピクセルの正方形のブロックで構成されます。
- ライブラリの
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 コードを埋め込むことができます。
Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml.cs を開き、次の変更を行います。
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; }
強調表示された変更を、
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
シングルトン サービスへの参照が提供されます。QRCodeService
への参照を解決するには、ファイルの先頭に次のusing
ステートメントを追加します。 変更を保存します。using RazorPagesPizza.Services;
強調表示されている変更を
GenerateQrCodeUri
メソッドに組み込みます。private string GenerateQrCodeUri(string email, string unformattedKey) { return string.Format( CultureInfo.InvariantCulture, AuthenticatorUriFormat, _urlEncoder.Encode("RazorPagesPizza"), _urlEncoder.Encode(email), unformattedKey); }
これにより、TOTP アプリのキーの表示名が設定されます。
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 機能を簡単にテストできます。
すべての変更を確実に保存します。
dotnet run
を使用してアプリをビルドおよび実行します。サイトに移動し、まだサインインしていない場合は、いずれかの登録済みユーザーでサインインします。 [Hello, [First name] [Last name]!] (こんにちは、[名] [姓]!) リンクを選択してプロファイル管理ページに移動し、[Two-factor authentication] (2 要素認証) を選択します。
[Add authenticator app](認証アプリの追加) ボタンを選択します。
画面の指示に従って、このユーザーに対する認証アプリを登録して確認します。
たとえば Android 上の Microsoft Authenticator を使い、次の手順に従ってアカウントをアプリに追加します。
- Microsoft Authenticator アプリを開きます。
- 右上にあるケバブ メニュー (縦の省略記号) を選択します。
- [アカウントの追加] を選択します。
- [他のアカウント (Google、Facebook など)] を選択します。
- 示されているとおりに QR コードをスキャンします。
TOTP アプリによって提供された確認コードを、[確認コード] テキスト ボックスに入力します。
[確認] を選択します。
検証が成功すると、[Your authenticator app has been verified](認証アプリが確認されました) というバナーといくつかの復旧コードが、ページに表示されます。
VS Code の [SQL Server] タブで、RazorPagesPizza データベースを右クリックし、[新しいクエリ] を選択します。 次のクエリを入力し、Ctrl+Shift+E を押して実行します。
SELECT FirstName, LastName, Email, TwoFactorEnabled FROM dbo.AspNetUsers
サインインしているユーザーの場合、
TwoFactorEnabled
列が1
と等しいことが出力で示されます。 他の登録済みユーザーに対しては多要素認証が有効になっていないため、レコードの列の値は0
です。Web アプリで、[ログアウト] を選び、同じユーザーでもう一度サインインします。
TOTP 認証アプリからの確認コードを、[Authenticator code](認証コード) テキスト ボックスに入力します。 [ログイン] ボタンを選択します。
[こんにちは、<名> <姓>!] を選択します。 その後、[Two-factor authentication](2 要素認証) タブを選択します。
Microsoft Authenticator が設定されているため、次のボタンが表示されます。
- Disable 2FA (2FA を無効にする)
- Reset recovery codes (復旧コードをリセットする)
- Set up authenticator app (認証アプリを設定する)
- Reset authenticator app (認証アプリをリセットする)
VS Code のターミナル ペインで、Ctrl+C を押してアプリを停止します。
まとめ
このユニットでは、認証アプリ構成フォームに QR コードを生成する機能を追加しました。 次のユニットでは、Identity を使って要求を格納し、認可ポリシーを適用する方法について説明します。