Two-Step Authentication with MVC and Twilio

Two-Step authentication via SMS is easy to setup with MVC and Services like Twilio. Even better still most of the work has already been done if you load up a new MVC project in Visual Studio with the built in Identity providers.

First Setup an account with Twilio, they provide a trial account so you can start working straight away but if you want to use the service in a production capacity you will likely need to upgrade to a paid account. The trial gives you 1 allocated phone number for 45 days that can send only to a confirmed phone number, i.e your own phone number.

Confirm and Configure your Twilio account, once you have logged in you need to setup a new Number. To do this go to the Numbers menu at the side and request a new allocated number. This will be used to send the authentication text messages.

Back in your Visual Studio solution Install the NuGet package for the Twilio Rest API

PM> Install-Package Twilio

Update the web.config with your credentials, if you login to Twilio these are your main credentials found on the Dashboard page under Account Summary, note do not confuse these with API keys that you can request from Twilio.

    <add key="SMSAccountIdentification" value="[ACCOUNT SID]" />
    <add key="SMSAccountPassword" value="[AUTH TOKEN]" />
    <add key="SMSAccountFrom" value="[FROM PHONE NUMBER]" />

Un-comment the service methods in the IdentiityConfig.cs, also remember to include the using statement for Twilio.

public class SmsService : IIdentityMessageService 
{
    public Task SendAsync(IdentityMessage message)
    {
        var Twilio = new TwilioRestClient(
            System.Configuration.ConfigurationManager.AppSettings["SMSAccountIdentification"],
            System.Configuration.ConfigurationManager.AppSettings["SMSAccountPassword"]);

        var result = Twilio.SendMessage(
            System.Configuration.ConfigurationManager.AppSettings["SMSAccountFrom"],
            message.Destination, message.Body);

        return Task.FromResult(0);
     }
}

Un-comment the following form sections in Views\Manage\Index.cshtml these allow you to manage your phone number and enable two step authentication.

<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>

If you are using Unity for Dependency Injection then you will also need to add a few extra type registrations to the UnityConfig.cs as follows:

    container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(new InjectionConstructor(new ApplicationDbContext()));
    container.RegisterType<MyAccountController>(new InjectionConstructor());
    container.RegisterType<ManageController>(new InjectionConstructor());
    container.RegisterType<IAuthenticationManager>(new InjectionFactory(o => HttpContext.Current.GetOwinContext().Authentication));

Now when you login to your site under the manage section you should be able to add a phone number to your account.

When you save your phone number the site will send a code via Twilio to the phone number you enter allowing you to confirm authenticity. Once added you can enable Two-step authentication for your account.

Now the next time you login you will be prompted to enter the code sent to your mobile number. You also have the option to remember me so that you don't need to enter the code every time.