ASP.NET Core での SMS を使用した 2 要素認証
作成者: Rick Anderson、Swiss-Devs
警告
時間ベースのワンタイム パスワード アルゴリズム (TOTP) を使用した 2 要素認証 (2FA) 認証アプリは、業界で推奨される 2FA のアプローチです。 SMS 2FA には、TOTP を使用した 2FA が推奨されます。 詳細については、ASP.NET Core 2.0 以降用の「ASP.NET Core での TOTP authenticator アプリの QR コード生成を有効にする」を参照してください。
このチュートリアルでは、SMS を使用して 2 要素認証 (2FA) を設定する方法について示します。 twilio と ASPSMS の手順が示されますが、他の SMS プロバイダーも使用できます。 このチュートリアルを開始する前に、アカウントの確認とパスワードの復元を完了することをお勧めします。
サンプル コードを表示またはダウンロードします。 ダウンロード方法。
新しい ASP.NET Core プロジェクトを作成する
個々のユーザー アカウントを使用して Web2FA
という名前の ASP.NET Core Web アプリを作成します。 「ASP.NET Core で HTTPS を適用する」の手順に従って、HTTPS を設定して要求します。
SMS アカウントを作成する
たとえば、twilio や ASPSMS から SMS アカウントを作成します。 認証資格情報を記録します (twilio の場合は accountSid と authToken、ASPSMS の場合は Userkey と Password)。
SMS プロバイダーの資格情報を確認する
Twilio:
Twilio アカウントの [ダッシュボード] タブの [Account SID](アカウント SID) と [Auth token](セキュリティ トークン) をコピーします。
ASPSMS:
アカウント設定から [Userkey] に移動し、それをパスワードと共にコピーします。
これらの値は、後で secret-manager ツールを使用して、SMSAccountIdentification
と SMSAccountPassword
のキー内に格納されます。
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 ツールを使用して、SMSAccountIdentification
、SMSAccountPassword
、SMSAccountFrom
を設定します。 次に例を示します。
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.cs
の ConfigureServices
メソッドでサービス コンテナーに SMSoptions
を追加します。
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
services.Configure<SMSoptions>(Configuration);
}
2 要素認証を有効にする
Views/Manage/Index.cshtml
Razor ビュー ファイルを開いて、コメント文字を削除します (そのため、マークアップはコメントアウトされません)。
2 要素認証でログインする
- アプリを実行して新しいユーザーを登録します
- Manage コントローラーで
Index
アクション メソッドをアクティブにするユーザー名をタップします。 次に、電話番号の [追加] リンクをタップします。
- 確認コードを受け取る電話番号を追加し、 [確認コードの送信] をタップします。
- 確認コードを含むテキスト メッセージが表示されます。 それを入力し、 [送信] をタップします
テキスト メッセージが表示されない場合は、twilio のログ ページを参照してください。
- 管理ビューには、電話番号が正常に追加されたと表示されます。
- [有効にする] をタップして、2 要素認証を有効にします。
2 要素認証をテストする
ログオフします。
ログインします。
ユーザー アカウントは 2 要素認証を有効にしているため、2 番目の認証要素を指定する必要があります。 このチュートリアルでは、電話による確認を有効にしました。 組み込みのテンプレートを使用すると、電子メールを 2 番目の要素として設定することもできます。 認証用に QR コードなどの 2 番目の追加要素を設定できます。 [送信] をタップします。
SMS メッセージに表示されるコードを入力します。
[このブラウザーを記憶する] チェック ボックスをオンにすると、同じデバイスとブラウザーを使用するときに 2FA を使用してログオンする必要がなくなります。 2FA を有効にし、 [このブラウザーを記憶する] をクリックすると、悪意のあるユーザーにお客様のデバイスへのアクセス権がない限り、アカウントにアクセスしようとしているものからの強力な 2FA 保護が提供されます。 これは、定期的に使用するすべてのプライベート デバイスで実行できます。 [このブラウザーを記憶する] を設定すると、通常使用しないデバイスから 2FA のセキュリティが強化され、独自のデバイスで 2FA を行う必要がなくなるため、便利になります。
ブルート フォース攻撃から保護するためのアカウント ロックアウト
2FA と共に、アカウント ロックアウトをお勧めします。 ユーザーがローカル アカウントまたはソーシャル アカウントを使用してサインインすると、2FA で失敗した各試行が格納されます。 失敗したアクセス試行の最大数に達すると、ユーザーはロックアウトされます (既定値: アクセス試行が 5 回失敗した後、5 分ロックアウトされます)。 認証が成功すると、失敗したアクセス試行回数がリセットされ、クロックがリセットされます。 失敗したアクセス試行の最大数とロックアウト時間は、MaxFailedAccessAttempts と DefaultLockoutTimeSpan で設定できます。 次の例では、アクセス試行が 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);
}
PasswordSignInAsync で lockoutOnFailure
が true
に設定されていることを確認します。
var result = await _signInManager.PasswordSignInAsync(
Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true);
ASP.NET Core