Visual Studio 2019 のテンプレートで作成した ASP.NET Core 3.1 以降のアプリには TOTP ベースの認証アプリを用いて 2 要素認証を行うコードが実装されています。なので、開発の際プログラマは何も実装しなくても、Google Authenticator App などの認証アプリを用いた 2 要素認証を有効にできます。
実は、最初、自分は Microsoft のドキュメント「ASP.NET Core での多要素認証」にいろいろ書いてあるのを見て惑わされて、一体何をどのように実装すればいいのか分からなかったです。(汗)
実際に試してみると、そのドキュメントの「MFA TOTP (時間ベースのワンタイム パスワード アルゴリズム)」セクションの 2 要素認証のコードは実装済みで、何も手を加える必要はなかったです。
唯一、認証アプリに秘密キーを共有させる画面(Manage/EnableAuthenticator 画面)には QR コードが表示されないのが難点でしたが、そこは別のドキュメント「ASP.NET Core での TOTP authenticator アプリの QR コード生成を有効にする」に qrcode.js という JavaScript ライブラリを使って表示できるようにする方法が書いてありました。
この記事の一番上の画像が、そのドキュメントに従って QR コードを表示できるようにした Manage/EnableAuthenticator 画面です。そうするだけで、テンプレートで実装済みの 2 要素認証は十分実用になると思います。
という訳で、実際にいろいろやってみましたので、その結果を備忘録として残しておきます。
(1) プロジェクトの作成
Visual Studio 2019 16.11.5 のテンプレートで、認証は「なし」にして .NET 5.0 の ASP.NET Core MVC アプリのプロジェクトを作成しました。
その後、スキャフォールディング機能を利用して ASP.NET Core Identity 関係のソースコードを一式全て実装します。(認証を「個別のユーザー」にすると、認証関係の機能は Razor Class Library (RCL) として提供され、ソースコードはプロジェクトには含まれません。後で必要な部分のみソースコードに差し替えることができますが、いろいろ面倒です)
(2) ユーザーの登録
新規ユーザーとして oz@mail.example.com (以下、oz と書きます) というユーザーを登録します。
ユーザー登録しただけの状態ですと、ASP.NET Core Identity が使う SQL Server データベースの AspNetUsers テーブルの当該ユーザーの TwoFactorEnabled 列は False となっています。
TOTP 用の秘密キー等は AspNetUserTokens テーブルに格納されますが、この時点ではユーザー oz のデータはありません。
(2) TOTP 秘密キーの生成
ログインして Manage/Index 画面に進み、[Two-factor authentication]をクリックして Manage/TwoFactorAuthentication 画面を表示して、そこで [Add authenticator app]をクリックします。
この記事の一番上の画像の Manage/EnableAuthenticator 画面に遷移しますので、そこで認証アプリに秘密キーを渡すことができます。
ユーザー oz の TOTP 用の秘密キーが生成され、SQL Server データベースの AspNetUserTokens テーブルに格納されます。
ちなみに、もしここで認証アプリには秘密キーは渡さずログオフした場合、次回ログインして Manage/TwoFactorAuthentication 画面を表示すると上の Manage/TwoFactorAuthentication 画面とは違って以下のようになります。
[Setup authnticator app]をクリックすると、この記事の一番上の画像の Manage/EnableAuthenticator 画面に遷移します。
[Reset authentication app] をクリックすると Manage/ResetAuthenticator 画面に遷移します。
上の画面で[Reset authenticator key]をクリックすると、秘密キーが変更されてから、この記事の一番上の画像の Manage/EnableAuthenticator 画面に遷移します。
(3) TOTP 秘密キーの共有
この記事の一番上の画像の Manage/EnableAuthenticator 画面に表示された QR コードを認証アプリでスキャンすると 6 桁の数字のパスワードをが認証アプリに表示されますので、それを[Verification Code]欄に入力し[verify]ボタンをクリックすると以下の Manage/ShowRecoveryCodes 画面に遷移します。
認証アプリをインストールしたデバイスを紛失するとアクセスできなくなるので、それに備えてリカバリーコードは記録しておいた方が良いとのことです。リカバリーコードは秘密キーと共に AspNetUserTokens テーブルに保存されます。
以上の操作により、ASP.NET Core アプリと認証アプリで秘密キーが共有され、AspNetUsers テーブルの TwoFactorEnabled は True に設定されて、認証アプリを利用しての 2 要素認証が可能になります。
(4) 2 要素認証でのログイン
一旦ログアウトしてから、まずログイン画面でのメールとパスワードによるログイン操作を行います。成功すると以下の Account/LoginWith2fa 画面に遷移しますので、認証アプリを起動してパスワードを取得し、[Authenticator code]欄に入力して[Log in]ボタンをクリックすれば 2 要素認証機能が働いでログインできます。
(5) その他
2 要素認証が有効になった後 Manage/TwoFactorAuthentication 画面を表示すると以下のようになります。
そこで[Disable 2FA]ボタンをクリックすると Manage/Disable2fa 画面に遷移します。
上の画面で[Disable2fa]ボタンをクリックすると AspNetUsers テーブルの当該ユーザーの TwoFactorEnabled 列は False となり、ログイン画面でメールとパスワードでログイン操作を行うだけでログインできるようになります(2 要素認証は無効になります)。
再度 2 要素認証を有効にするには、ログイン画面でメールとパスワードでログイン操作を行ってログインしてから Manage/TwoFactorAuthentication 画面に進み、[Setup authenticator app]ボタンをクリックして Manage/EnableAuthenticator 画面を表示し、上のステップ (3) と同じ操作を行います。
[Reset recovery codes]ボタンをクリックすると Manage/GenerateRecoveryCodes 画面に遷移します。
そこで[Generate Recovery Codes]ボタンをクリックすると、上のステップ (3) にあるのと同様な Manage/ShowRecoveryCodes 画面に遷移し、再発行されたリカバリーコードが表示されます。同時に AspNetUserTokens テーブルの既存のリカバリーコードは画面に表示されたものに書き換えられます。
なお、MVC5 プロジェクトのテンプレートに標準で実装されていた SMS を用いた 2 要素認証は非推奨だそうです。上に紹介した記事には "SMS を使用する方法は推奨されなくなりました。 この種の実装には、既知の攻撃ベクトルが多すぎます" と書いてあります。
Core 1.1 用には「SMS を使用した 2 要素認証 (ASP.NET Core)」というチュートリアルがありますが、.NET Core 3.1 とか .NET 5.0 の新しいバージョンのテンプレートで作ったプロジェクトにはそのチュートリアルのコードは実装されていません。