SMS や電子メールで 2 要素認証する ASP.NET MVC 5 アプリ

作成者: Rick Anderson

このチュートリアルでは、2 要素認証を使用して ASP.NET MVC 5 Web アプリを構築する方法について説明します。 次に進む前に、「ログイン、電子メール確認、パスワードのリセットを使用して、安全な ASP.NET MVC 5 Web アプリの作成」を完了する必要があります。 完成したアプリケーションはこちらからダウンロードできます。 このダウンロードには、電子メールまたは SMS プロバイダーを設定せずに電子メール確認と SMS をテストできるデバッグ ヘルパーが含まれています。

このチュートリアルは、Rick Anderson (Twitter: @RickAndMSFT) によって作成されました。

ASP.NET MVC アプリの作成

まず、Visual Studio Express 2013 for Web 以降をインストールして実行します。

Note

警告: 次に進む前に、「ログイン、電子メール確認、パスワードのリセットを使用して、安全な ASP.NET MVC 5 Web アプリの作成」を完了する必要があります。 このチュートリアルを完了するには、Visual Studio 2013 Update 3 以降をインストールする必要があります。

  1. 新しい ASP.NET Web プロジェクトを作成し、MVC テンプレートを選択します。 Web Forms も ASP.NET ID をサポートしているため、Web フォーム アプリでも同様の手順を実行できます。
    Screenshot that shows the New A S P dot NET Project window. The default authentication, Individual User Accounts, is highlighted.
  2. 既定の認証は個々のユーザー アカウントのままにします。 Azure でアプリをホストする場合は、チェック ボックスをオンのままにします。 チュートリアルの後半では、Azure にデプロイします。 Azure アカウントは無料で開設できます。
  3. SSL を使用するようにプロジェクトを設定します。

2 要素認証用に SMS を設定する

このチュートリアルでは、Twilio または ASPSMS のいずれかを使用する手順について説明しますが、他の SMS プロバイダーを使用することもできます。

  1. SMS プロバイダーを使用したユーザー アカウントの作成

    Twilio アカウントまたは ASPSMS アカウントを作成します。

  2. 追加パッケージのインストールまたはサービス参照の追加

    Twilio:
    パッケージ マネージャー コンソールで、次のコマンドを入力します。
    Install-Package Twilio

    ASPSMS:
    次のサービス参照を追加する必要があります。

    Screenshot that shows the Add Service Reference window. The Address and Namespace input bars are highlighted.

    [アドレス]:
    https://webservice.aspsms.com/aspsmsx2.asmx?WSDL

    名前空間:
    ASPSMSX2

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

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

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

    コピーした値は後で、"SMSAccountIdentification""SMSAccountPassword" キー内の web.config ファイルに格納されます。

  4. SenderID または Originator の指定

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

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

    コピーした値は後で、"SMSAccountFrom" キー内の web.config ファイルに格納されます。

  5. SMS プロバイダーの資格情報をアプリへ転送

    アプリで資格情報と送信者の電話番号を使用できるようにします。 シンプルにするために、この 2 つの値を web.config ファイルに格納します。 Azure にデプロイすると、Web サイトの [構成] タブの [アプリ設定] セクションに値を安全に格納できます。

    </connectionStrings>
       <appSettings>
          <add key="webpages:Version" value="3.0.0.0" />
          <!-- Markup removed for clarity. -->
          <!-- SendGrid-->
          <add key="mailAccount" value="account" />
          <add key="mailPassword" value="password" />
          <add key="SMSAccountIdentification" value="My Identification" />
          <add key="SMSAccountPassword" value="My Password" />
          <add key="SMSAccountFrom" value="+12065551234" />
       </appSettings>
      <system.web>
    

    警告

    セキュリティ - 機密データをソース コードに格納しないでください。 アカウントと資格情報は、サンプルをシンプルにするために上記のコードに追加されています。 「ASP.NET と Azure にパスワードやその他の機密データを配置するためのベスト プラクティス」を参照してください。

  6. SMS プロバイダーへのデータ転送の実装

    App_Start\IdentityConfig.cs ファイルで SmsService クラスを構成します。

    使用する SMS プロバイダーに応じて、Twilio または ASPSMS セクションをアクティブにします。

    public class SmsService : IIdentityMessageService
    {
        public Task SendAsync(IdentityMessage message)
        {
            // Twilio Begin
            //var accountSid = ConfigurationManager.AppSettings["SMSAccountIdentification"];
            //var authToken = ConfigurationManager.AppSettings["SMSAccountPassword"];
            //var fromNumber = ConfigurationManager.AppSettings["SMSAccountFrom"];
    
            //TwilioClient.Init(accountSid, authToken);
    
            //MessageResource result = MessageResource.Create(
                //new PhoneNumber(message.Destination),
                //from: new PhoneNumber(fromNumber),
               //body: message.Body
            //);
    
            ////Status is one of Queued, Sending, Sent, Failed or null if the number is not valid
             //Trace.TraceInformation(result.Status.ToString());
            ////Twilio doesn't currently have an async API, so return success.
             //return Task.FromResult(0);    
            // Twilio End
    
            // ASPSMS Begin 
            // var soapSms = new MvcPWx.ASPSMSX2.ASPSMSX2SoapClient("ASPSMSX2Soap");
            // soapSms.SendSimpleTextSMS(
            //   System.Configuration.ConfigurationManager.AppSettings["SMSAccountIdentification"],
            //   System.Configuration.ConfigurationManager.AppSettings["SMSAccountPassword"],
            //   message.Destination,
            //   System.Configuration.ConfigurationManager.AppSettings["SMSAccountFrom"],
            //   message.Body);
            // soapSms.Close();
            // return Task.FromResult(0);
            // ASPSMS End
        }
    }
    
  7. Views\Manage\Index.cshtml Razor ビューを更新します (注: 終了コードのコメントを削除するだけでなく、以下のコードを使用してください)。

    @model MvcPWy.Models.IndexViewModel
    @{
       ViewBag.Title = "Manage";
    }
    <h2>@ViewBag.Title.</h2>
    <p class="text-success">@ViewBag.StatusMessage</p>
    <div>
       <h4>Change your account settings</h4>
       <hr />
       <dl class="dl-horizontal">
          <dt>Password:</dt>
          <dd>
             [
             @if (Model.HasPassword)
             {
                @Html.ActionLink("Change your password", "ChangePassword")
             }
             else
             {
                @Html.ActionLink("Create", "SetPassword")
             }
             ]
          </dd>
          <dt>External Logins:</dt>
          <dd>
             @Model.Logins.Count [
             @Html.ActionLink("Manage", "ManageLogins") ]
          </dd>
            <dt>Phone Number:</dt>
          <dd>
             @(Model.PhoneNumber ?? "None") [
             @if (Model.PhoneNumber != null)
             {
                @Html.ActionLink("Change", "AddPhoneNumber")
                @: &nbsp;|&nbsp;
                @Html.ActionLink("Remove", "RemovePhoneNumber")
             }
             else
             {
                @Html.ActionLink("Add", "AddPhoneNumber")
             }
             ]
          </dd>
          <dt>Two-Factor Authentication:</dt> 
          <dd>
             @if (Model.TwoFactor)
             {
                using (Html.BeginForm("DisableTwoFactorAuthentication", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
                {
                   @Html.AntiForgeryToken()
                   <text>Enabled
                      <input type="submit" value="Disable" class="btn btn-link" />
                   </text>
                }
             }
             else
             {
                using (Html.BeginForm("EnableTwoFactorAuthentication", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
                {
                   @Html.AntiForgeryToken()
                   <text>Disabled
                      <input type="submit" value="Enable" class="btn btn-link" />
                   </text>
                }
             }
          </dd>
       </dl>
    </div>
    
  8. ManageControllerEnableTwoFactorAuthentication および DisableTwoFactorAuthentication アクション メソッドに [ValidateAntiForgeryToken] 属性が含まれていることを確認してください。

    //
    // POST: /Manage/EnableTwoFactorAuthentication
    [HttpPost,ValidateAntiForgeryToken]
    public async Task<ActionResult> EnableTwoFactorAuthentication()
    {
        await UserManager.SetTwoFactorEnabledAsync(User.Identity.GetUserId(), true);
        var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
        if (user != null)
        {
            await SignInAsync(user, isPersistent: false);
        }
        return RedirectToAction("Index", "Manage");
    }
    //
    // POST: /Manage/DisableTwoFactorAuthentication
    [HttpPost, ValidateAntiForgeryToken]
    public async Task<ActionResult> DisableTwoFactorAuthentication()
    {
        await UserManager.SetTwoFactorEnabledAsync(User.Identity.GetUserId(), false);
        var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
        if (user != null)
        {
            await SignInAsync(user, isPersistent: false);
        }
        return RedirectToAction("Index", "Manage");
    }
    
  9. アプリを実行し、以前に登録したアカウントでログインします。

  10. ユーザー ID をクリックすると、Manage コントローラーで Index アクション メソッドがアクティブになります。
    Screenshot that shows the A S P dot NET app Home page. A Sample USER I D is highlighted.

  11. 追加をクリックします。
    Screenshot that shows the A S P dot NET app Account Settings page. None Add next to Phone Number section is highlighted.

  12. AddPhoneNumber アクション メソッドは、SMS メッセージを受信できる電話番号を入力するダイアログ ボックスを表示します。

    // GET: /Account/AddPhoneNumber
    public ActionResult AddPhoneNumber()
    {
       return View();
    }
    

    Screenshot that shows the A S P dot NET app Add Phone Number page. A sample phone number is filled in with a Send Verification Code button below it.

  13. 電話番号を入力すると数秒後に、確認コードを含むテキスト メッセージが送信されます。 確認コードを入力し、[送信] を押します。
    Screenshot of the A S P dot NET app Add Phone Number page showing an input bar filled with a sample verification code and a Submit button below it.

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

2 要素認証を有効化する

テンプレートで生成されたアプリでは、UI を使用して 2 要素認証 (2FA) を有効にする必要があります。 2FA を有効にするには、ナビゲーション バーでユーザー ID (電子メール エイリアス) をクリックします。

Screenshot that displays the A S P dot NET app Home page. A sample USER I D is highlighted.

[2FA を有効にする] をクリックします。

Screenshot that shows the A S P dot NET app Account Settings page. Two-Factor Authentication: Disabled with an Enable link section is highlighted.

ログアウトしてから、もう一度ログインします。 メールを有効にしている場合 (前回のチュートリアルを参照)、2FA に使用する SMS またはメールを選択できます。

Screenshot that shows the A S P dot NET app Send Verification Code page. A dropdown menu showing Phone Code and Email Code is selected.

[コードの確認] ページが表示され、ここで (SMS またはメールから) コードを入力できます。

Screenshot that shows the A S P dot NET app Verify page for 2 FA. Beneath a sample code, a checkbox with Remember this browser is highlighted.

[このブラウザーを記憶する] チェック ボックスをクリックすると、チェック ボックスをオンにしたブラウザーとデバイスを使用するときに、2FA を使用してログインする必要がなくなります。 悪意のあるユーザーがデバイスにアクセスできない限り、2FAを有効にして [このブラウザーを記憶する] をクリックすると、信頼されていないデバイスからのすべてのアクセスに対して強固な 2FA 保護を維持しながら、便利なワンステップ パスワード アクセスが可能になります。 これは、定期的に使用するすべてのプライベート デバイスで実行できます。

このチュートリアルでは、新しい ASP.NET MVC アプリで 2FA を有効にする方法について簡単に説明します。 「ASP.NET ID での SMS とメールを 使用した 2 要素認証」のチュートリアルでは、サンプルの背後にあるコードについて詳しく説明します。

その他のリソース