ASP.NET Core での SMS を使用した 2 要素認証

作成者: Rick AndersonSwiss-Devs

警告

時間ベースのワンタイム パスワード アルゴリズム (TOTP) を使用した 2 要素認証 (2FA) 認証アプリは、業界で推奨される 2FA のアプローチです。 SMS 2FA には、TOTP を使用した 2FA が推奨されます。 詳細については、ASP.NET Core 2.0 以降用の「ASP.NET Core での TOTP authenticator アプリの QR コード生成を有効にする」を参照してください。

このチュートリアルでは、SMS を使用して 2 要素認証 (2FA) を設定する方法について示します。 twilioASPSMS の手順が示されますが、他の SMS プロバイダーも使用できます。 このチュートリアルを開始する前に、アカウントの確認とパスワードの復元を完了することをお勧めします。

サンプル コードを表示またはダウンロードします。 ダウンロード方法

新しい ASP.NET Core プロジェクトを作成する

個々のユーザー アカウントを使用して Web2FA という名前の ASP.NET Core Web アプリを作成します。 「ASP.NET Core で HTTPS を適用する」の手順に従って、HTTPS を設定して要求します。

SMS アカウントを作成する

たとえば、twilioASPSMS から SMS アカウントを作成します。 認証資格情報を記録します (twilio の場合は accountSid と authToken、ASPSMS の場合は Userkey と Password)。

SMS プロバイダーの資格情報を確認する

Twilio:

Twilio アカウントの [ダッシュボード] タブの [Account SID](アカウント SID)[Auth token](セキュリティ トークン) をコピーします。

ASPSMS:

アカウント設定から [Userkey] に移動し、それをパスワードと共にコピーします。

これらの値は、後で secret-manager ツールを使用して、SMSAccountIdentificationSMSAccountPassword のキー内に格納されます。

SenderID または Originator の指定

Twilio: [Numbers](数値) タブで、Twilio の電話番号をコピーします。

ASPSMS: [Unlock Originators](発信元のロック解除) メニューで、1 つまたは複数の発信元のロックを解除するか、英数字の発信元を選択します (すべてのネットワークではサポートされていません)。

この値は、後で secret-manager ツールを使用して SMSAccountFrom キー内に格納されます。

SMS サービスに資格情報を指定する

Options パターンを使用して、ユーザー アカウントとキーの設定にアクセスします。

  • セキュリティで保護された SMS キーをフェッチするためのクラスを作成します。 このサンプルでは、SMSoptions クラスは Services/SMSoptions.cs ファイルに作成されます。
namespace Web2FA.Services
{
    public class SMSoptions
    {
        public string SMSAccountIdentification { get; set; }
        public string SMSAccountPassword { get; set; }
        public string SMSAccountFrom { get; set; }
    }
}

secret-manager ツールを使用して、SMSAccountIdentificationSMSAccountPasswordSMSAccountFrom を設定します。 次に例を示します。

C:/Web2FA/src/WebApp1>dotnet user-secrets set SMSAccountIdentification 12345
info: Successfully saved SMSAccountIdentification = 12345 to the secret store.
  • SMS プロバイダー用の NuGet パッケージを追加します。 パッケージ マネージャー コンソール (PMC) から次が実行されます。

Twilio:

Install-Package Twilio

ASPSMS:

Install-Package ASPSMS

  • SMS を有効にするには、Services/MessageServices.cs ファイルにコードを追加します。 Twilio または ASPSMS セクションのいずれかを使用します。

Twilio:

using Microsoft.Extensions.Options;
using System.Threading.Tasks;
using Twilio;
using Twilio.Rest.Api.V2010.Account;
using Twilio.Types;

namespace Web2FA.Services
{
    // This class is used by the application to send Email and SMS
    // when you turn on two-factor authentication in ASP.NET Identity.
    // For more details see this link https://go.microsoft.com/fwlink/?LinkID=532713
    public class AuthMessageSender : IEmailSender, ISmsSender
    {
        public AuthMessageSender(IOptions<SMSoptions> optionsAccessor)
        {
            Options = optionsAccessor.Value;
        }

        public SMSoptions Options { get; }  // set only via Secret Manager

        public Task SendEmailAsync(string email, string subject, string message)
        {
            // Plug in your email service here to send an email.
            return Task.FromResult(0);
        }

        public Task SendSmsAsync(string number, string message)
        {
            // Plug in your SMS service here to send a text message.
            // Your Account SID from twilio.com/console
            var accountSid = Options.SMSAccountIdentification;
            // Your Auth Token from twilio.com/console
            var authToken = Options.SMSAccountPassword;

            TwilioClient.Init(accountSid, authToken);

            return MessageResource.CreateAsync(
              to: new PhoneNumber(number),
              from: new PhoneNumber(Options.SMSAccountFrom),
              body: message);
        }
    }
}

ASPSMS:

using Microsoft.Extensions.Options;
using System.Threading.Tasks;

namespace Web2FA.Services
{
    // This class is used by the application to send Email and SMS
    // when you turn on two-factor authentication in ASP.NET Identity.
    // For more details see this link https://go.microsoft.com/fwlink/?LinkID=532713
    public class AuthMessageSender : IEmailSender, ISmsSender
    {
        public AuthMessageSender(IOptions<SMSoptions> optionsAccessor)
        {
            Options = optionsAccessor.Value;
        }

        public SMSoptions Options { get; }  // set only via Secret Manager

        public Task SendEmailAsync(string email, string subject, string message)
        {
            // Plug in your email service here to send an email.
            return Task.FromResult(0);
        }

        public Task SendSmsAsync(string number, string message)
        {
            ASPSMS.SMS SMSSender = new ASPSMS.SMS();

            SMSSender.Userkey = Options.SMSAccountIdentification;
            SMSSender.Password = Options.SMSAccountPassword;
            SMSSender.Originator = Options.SMSAccountFrom;

            SMSSender.AddRecipient(number);
            SMSSender.MessageData = message;

            SMSSender.SendTextSMS();

            return Task.FromResult(0);
        }
    }
}

SMSoptions を使用するスタートアップを構成する

Startup.csConfigureServices メソッドでサービス コンテナーに SMSoptions を追加します。

    // Add application services.
    services.AddTransient<IEmailSender, AuthMessageSender>();
    services.AddTransient<ISmsSender, AuthMessageSender>();
    services.Configure<SMSoptions>(Configuration);
}

2 要素認証を有効にする

Views/Manage/Index.cshtmlRazor ビュー ファイルを開いて、コメント文字を削除します (そのため、マークアップはコメントアウトされません)。

2 要素認証でログインする

  • アプリを実行して新しいユーザーを登録します

Microsoft Edge で Web アプリケーションの登録ビューが開く

  • Manage コントローラーで Index アクション メソッドをアクティブにするユーザー名をタップします。 次に、電話番号の [追加] リンクをタップします。

管理ビュー - [追加] リンクをタップする

  • 確認コードを受け取る電話番号を追加し、 [確認コードの送信] をタップします。

[電話番号の追加] ページ

  • 確認コードを含むテキスト メッセージが表示されます。 それを入力し、 [送信] をタップします

[電話番号の確認] ページ

テキスト メッセージが表示されない場合は、twilio のログ ページを参照してください。

  • 管理ビューには、電話番号が正常に追加されたと表示されます。

管理ビュー - 電話番号が正常に追加されました

  • [有効にする] をタップして、2 要素認証を有効にします。

管理ビュー - 2 要素認証を有効にする

2 要素認証をテストする

  • ログオフします。

  • ログインします。

  • ユーザー アカウントは 2 要素認証を有効にしているため、2 番目の認証要素を指定する必要があります。 このチュートリアルでは、電話による確認を有効にしました。 組み込みのテンプレートを使用すると、電子メールを 2 番目の要素として設定することもできます。 認証用に QR コードなどの 2 番目の追加要素を設定できます。 [送信] をタップします。

確認コードの送信ビュー

  • SMS メッセージに表示されるコードを入力します。

  • [このブラウザーを記憶する] チェック ボックスをオンにすると、同じデバイスとブラウザーを使用するときに 2FA を使用してログオンする必要がなくなります。 2FA を有効にし、 [このブラウザーを記憶する] をクリックすると、悪意のあるユーザーにお客様のデバイスへのアクセス権がない限り、アカウントにアクセスしようとしているものからの強力な 2FA 保護が提供されます。 これは、定期的に使用するすべてのプライベート デバイスで実行できます。 [このブラウザーを記憶する] を設定すると、通常使用しないデバイスから 2FA のセキュリティが強化され、独自のデバイスで 2FA を行う必要がなくなるため、便利になります。

確認ビュー

ブルート フォース攻撃から保護するためのアカウント ロックアウト

2FA と共に、アカウント ロックアウトをお勧めします。 ユーザーがローカル アカウントまたはソーシャル アカウントを使用してサインインすると、2FA で失敗した各試行が格納されます。 失敗したアクセス試行の最大数に達すると、ユーザーはロックアウトされます (既定値: アクセス試行が 5 回失敗した後、5 分ロックアウトされます)。 認証が成功すると、失敗したアクセス試行回数がリセットされ、クロックがリセットされます。 失敗したアクセス試行の最大数とロックアウト時間は、MaxFailedAccessAttemptsDefaultLockoutTimeSpan で設定できます。 次の例では、アクセス試行が 10 回失敗した後、10 分間のアカウント ロックアウトが構成されます。

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.AddMvc();

    services.Configure<IdentityOptions>(options =>
    {
        options.Lockout.MaxFailedAccessAttempts = 10;
        options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(10);
    });

    // Add application services.
    services.AddTransient<IEmailSender, AuthMessageSender>();
    services.AddTransient<ISmsSender, AuthMessageSender>();
    services.Configure<SMSoptions>(Configuration);
}

PasswordSignInAsynclockoutOnFailuretrue に設定されていることを確認します。

var result = await _signInManager.PasswordSignInAsync(
                 Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true);