Lachlan B's Blog

ASP.NET Two Factor Auth with Google's Authenticator App part 1

So you want to add two factor authentication to your site?

auth 1 screenshot

I have created a NuGet package that will get it running in 10 minutes. Alternatively, I have also written an article on how you can implement it manually without using the NuGet package.

This method is using ASP.NET’s Identity and Google’s “Authenticator” app. The authenticator app is simple, very widely used (GitHub and Slack, to name two) and works very well.

If you are adding two-factor authentication to an existing site or codebase, I would suggest that you start by creating a brand new project and adding the already-prepared NuGet package that I have prepared. This will add all of the neccesary code, web pages, references and dependencies. You can step through the code and see how it all works and holds together. Once you are happy with it you can then add the package to your existing solution.

Alternatively, you can add all of the code manually, which is a lot more involved, but will give you a better overall picture on how it holds together. That part will be covered in part two.

Create your sample application

The first step is to create a new ASP.NET MVC web application, making sure to set authentication to none:

auth 2 screenshot

From this screen you can click “Ok” – and then on the next screen turn off authentication by clicking “Change Authentication” and selecting “No Authentication”:

auth 3 screenshot auth 4 screenshot

You should now have a very basic MVC app:

auth 5 screenshot

Adding the NuGet package

You can now add the NuGet package “AddTwoFactorToMvc” by running:

install-package AddTwoFactorToMvc


in the package manager console, like so:

auth 6 screenshot

Files Added by NuGet Package

File Description
Content\authenticator-iphone-sample.png Example image showing how to use the authenticator app
Controllers\AccountController.cs Controller for managing all the account pages like registration, login, logout etc
Controllers\ManageController.cs Controller for managing all of the “manage my account” pages
Scripts\qrcode.js Javascript library for generating QR codes
TwoFactor\database-scripts\twofactor.sql SQL script for creating tables in the DB
TwoFactor\readme.txt Instructions for installing TwoFactor
Views\Account\*.cshtml Pages handling registration, login, logout etc
Views\Manage\*.cshtml Pages for the user to manage their account
Views\Shared\_LoginPartial.cshtml Partial control used to display Registration/Login links

Directories Added

Directory Description
TwoFactor\classes\auth Contains the code for two factor authentication
TwoFactor\classes\common Common code used across multiple pages
TwoFactor\classes\models ApplicationDb and ApplicationUser models
TwoFactor\classes\viewmodels Viewmodels for Account and Manage pages

All of these files should be added to your source control system.

You should also see an installation/configuration page that will tell you how to get started. There are just three steps needed:

  1. Database Configuration
  2. SMTP Configuration
  3. Adding the Login Bar to your master page

Database Configuration

The first step will be to create a SQL Server DB that will be used to store the member’s credentials. You can do this very simply by using the following script:


CREATE DATABASE [moviemanager]
GO

you will also need to create a user that your ASP.NET application uses to connect to the DB as:

USE [master]
GO
CREATE LOGIN [moviemanageruser] WITH PASSWORD=N'moviemanagerpassword', 
    DEFAULT_DATABASE=[moviemanager], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
GO
USE [moviemanager]
GO
CREATE USER [moviemanageruser] FOR LOGIN [moviemanageruser]
GO
ALTER ROLE [db_owner] ADD MEMBER [moviemanager]
GO

You will need to add a connection string to your web.config:
<configuration>

  ...

<connectionStrings>

    <add name="DefaultConnection"
	 connectionString="Server=localhost;database=moviemanager;
	     User Id=moviemanageruser;password=moviemanagerpassword"
	 providerName="System.Data.SqlClient" />

</connectionStrings>

Once the tables have been created, we need to add the columns necessary for two factor authentication by running the following script:


TwoFactor\database-scripts\update-existing-db.sql 

Db Owner?

You may have noticed that I have added the db_owner role to the moviemanageruser account. This is a very bad practice when it comes to security, as it means that if someone can find a way to execute SQL via a security hole on your website, they will have full access to your entire DB. They can read your data, update your data, or worse of all, delete your entire database.

We need to give the user account full access so that the entity framework can do its thing and create all of the tables necessary. Once they have been set up, we can lower the permissions level needed. I will write another post on this soon.

Configuring SMTP

Whenever a user registers on your site, you need to send them an email so they can confirm that they own that email address. You’ll need to enter your SMTP server’s details so that this email can be sent. If you open this file you can edit the following file:

TwoFactor\classes\common\SendEmail.cs

With these contents:

namespace MovieManager
{
    public class Emailer
    {
        const string smtpServerName = "localhost";
        const string replyToEmail = "donotreply@yourcompany.com";

        public void sendEmail(string email, string subject, string body)
        {
            MailMessage mail = new MailMessage(
                replyToEmail, 
                email, 
                subject, 
                body);

            mail.IsBodyHtml = true;

            SmtpClient client = new SmtpClient();

            client.Port = 25;
            client.DeliveryMethod = SmtpDeliveryMethod.Network;
            client.Host = smtpServerName;

            client.Send(mail);
        }
    }
}

( I would suggest moving the smtpServerName and replyToEmail to your web.config and use the ConfigurationManager.Appsettings object to retrieve them. ) For development purposes you can simply comment out the client.send(mail), as you will be able to approve the registered email address manually.

Adding the Login Bar to your site

You will also need to add the “Register / Login / Manage My Account” links to your site:

auth 7 screenshot

these have been bundled into a partial view named:

 Views\Shared\LoginPartial.cshtml 

which has been added to your project by the NuGet package. You’ll need to add a call to @Html.Partial() to render it, which I suggest putting into your Views\Shared\_Layout.cshtml page:

<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                ...
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">   
     ...  
  </ul>
  @Html.Partial("_LoginPartial")

Let's go!

You can now go ahead and test your two factor authentication! Simply register on your site:

auth 8 screenshot

After you click “Register”, you will need to verify your email. If you are working on a Debug build, you can just click on the link provided which will verify your email automatically:

auth 9 screenshot

Your email should now be confirmed:

auth 10 screenshot

And you can now login:

auth 11 screenshot

voila!

auth 12 screenshot

but hang on... WHERE’S MY TWO FACTOR AUTHENTICATION??

You need to enable it!

Click on your user account:

auth 13 screenshot

and click “Enable” for google’s authenticator:

auth 14 screenshot

you will now need to scan the QR code using Google’s Authenticator app, and enter the 6 digits provided:

auth 15 screenshot

now log out, and log back in again, this time you should see the following:

auth 16 screenshot

enter the verification code shown on your mobile and you have successfully logged in!

A few other points to note...

  • Yes, your database user probably still has db_owner permission. You need to lower this.

  • At no point is any data (password or otherwise) transferred to or from google’s servers. The joy of the authenticator app is that you are (essentially) storing a password on your mobile, and your application knows how to work out if the one-time 30 second code is currently valid. There is no need to transmit the password over the wire.

  • You need to encourage your users to use a complex password. You can add a “password strength meter”, using something like JQuery Password Stregth, or you can add links to KeePass & LastPass.

  • Calling it “two factor authentication” is bad. You know why? Most users see that phrase and go “I don’t know what that is, I’m not interested”. Calling it something like “Login Approvals" like facebook have is a much friendlier approach and will probably see much higher adoption!

  • Adding functionality that says “you recently logged in from a new/unknown device, if you don’t recognise it let us know” would be a great extra layer. A free system like MaxMind might be useful, or a paid system like IpInfo might help.

  • If you are developing an enterprise system, training your users on basic security principles is definitely necessary. No sharing of passwords, lock your computer when you leave your desk, don’t plug in random USB sticks etc.

  • Protecting yourself from the top 10 most common security vulnerabilities will go a long way to making your app more secure. No point in adding 2FA if your site is very easily hacked.