Using OWIN Security with MultiValue Data - Part 4: Two-Factor Login
In my previous articles in this series, I have explained how to implement a structurally sound OWIN identity Framework using a MultiValue database. For some shops, that's all you'll need. However, Two-Factor Authentication (2FA) has been moving from the nice-to-have to the need-to-have list for a lot of us. OWIN can help us here, too.
To be clear: Two-Factor can be accomplished in many different ways. OWIN is not required. Since we already have an OWIN connection, I figured that we should use what has already been provided for us. While this is simpler than building it all from scratch, you'll see that it takes more effort to implement Two-Factor logins than it does to implement a standard login process.
What is Two-Factor Login?
Two Factor Authentication [Figure 1], also known as Two-Step Verification, is an extra layer of security that requires not only a password and username but also something that only that user would know or be able to do. For example, if I provided you with a device that generates numbers in a sequence, I could ask for the current number on the device and match it to the output of my server-side copy of the same generator. Another example is having the person respond to a text message or an email, assuming that only they would have access to their phones and email.
Figure 1
The theory is that using a username and password together with a piece of information that only the user knows makes it harder for potential intruders to gain access and steal that person's personal data or identity.
Two-Factor Authentication is starting to become a requirement in many industries. While you can implement a from-scratch workflow yourself, it can be a little cumbersome. The OWIN framework provided in ASP.NET does much of the work for you. This article explains how to implement Two-Factor Authentication in Multivalue using OWIN identity information we have implemented in previous articles.
OWIN provides you a way to implement email and SMS components for two-factor authentication. The catch is that the developer has to create all the code for talking to the email server or to the SMS server. While this is not hard at all, it is a slight departure from the rest of the OWIN implementations we have done so far.
Startup.Auth
As we have talked about in the previous articles, the Startup Auth class does a lot of setup for the project. One of the things that you have to define in this class is how to handle the tokens used by two-factor authentication.[Figure 2]
Public Sub ConfigureAuth(app As IAppBuilder) ... ' Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process. app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5)) ' Enables the application to remember the second login verification factor such as phone or email. ' Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from. ' This is similar to the RememberMe option when you log in. app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie) ... End Sub
Figure 2
You have to implement the UseTwoFactorSignInCookie and UseTwoFactorRememberBrowserCookie routines in ConfigureAuth. Unless you have another reason, I would recommend just using the default process that OWIN uses for Two-Factor logins. You can always get fancier later.
ApplicationUserStore
You also have to implement the IUserTwoFactorStore interface in the ApplicationUserStore. This interface only implements two methods: SetTwoFactorEnabled and GetTwoFactorEnabled. This lets us determine, based on the user information, if we have enabled this feature for this user.
ApplicationUserManager
The last place you have to implement some code is in the ApplicationUserManager class. This class contains all the instructions on how to implement sending the two-factor token. [Figure 3]
Public Class ApplicationUserManager Inherits UserManager(Of ApplicationUser) Public Shared Function Create() As ApplicationUserManager ... ' Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user ' You can write your own provider and plug it in here. manager.RegisterTwoFactorProvider("Phone Code", New PhoneNumberTokenProvider(Of SpectrumUser) With { .MessageFormat = "Your security code is {0}" }) manager.RegisterTwoFactorProvider("Email Code", New EmailTokenProvider(Of SpectrumUser) With { .Subject = "Security Code", .BodyFormat = "Your security code is {0}" }) manager.EmailService = New EmailService() manager.SmsService = New SmsService() ... End Function End Class
Figure 3
You will also see that we are defining the EmailService and the SMSService. These classes will do all the work of sending the token to the needed two-factor devices. In other words, this is the part you'll have to build.
Two-Factor Authentication with Email
I'll make the assumption that all of our business systems already have a connection to sending out emails. If this is the case, I would recommend just using your existing business systems to send out the OWIN emails.
There are two advantages to doing it this way. First, you don't have to maintain code in two places. Secondly, you may want to integrate the login process with your CRM (Customer Relationship Manager) or CSM (Customer Service Manager) systems so that you can provide the needed phone support (and auditing) when people try to connect.
If you want to see more on how to send emails from your MultiValue system, please look under the "Email" keyword on the Spectrum website and see what your options are.
For OWIN to use the Email systems in your MultiValue application, you will have to create an EmailService class similar to Figure 4. You will notice that I'm using a MultiValue Stored Procedure (subroutine) to send the email.
Two-Factor Authentication with SMS
SMS message is a different story. Most business systems don't have a way to send text messages from within your system, but it is just as easy to send text messages as it is to send email. Again, if you want to see how to send SMS messages from your MultiValue system, please look under the "SMS" keyword on the Spectrum website to see what your options are.
As with the sending information through Email, you have to implement the SMSService class. The class basically matches the class created in Figure 4, but we replace "SEND.EMAIL" with "SEND.SMS".
Public Class EmailService Implements IIdentityMessageService Public ReadOnly Property DBContext As SpectrumDBContext Get If _DBContext Is Nothing Then Try _DBContext = HttpContext.Current.GetOwinContext.Get(Of SpectrumDBContext) Catch ex As Exception End Try If _DBContext Is Nothing Then _DBContext = SpectrumDBContext.Create End If End If Return _DBContext End Get End Property Private _DBContext As SpectrumDBContext Public Function SendAsync(message As IdentityMessage) As Task Implements IIdentityMessageService.SendAsync ' Plug in your email service here to send an email. Return Task.FromResult(0) Dim _RequestItem As String = "SEND.EMAIL" _RequestItem = _RequestItem & mvFunctions.AM & Message.Destination _RequestItem = _RequestItem & mvFunctions.AM & Message.Subject _RequestItem = _RequestItem & mvFunctions.AM & Message.Body Dim _DataItem As String = String.Empty Await DBContext.CallSubroutineAsync("SPECTRUM.OWIN.USER", _RequestItem, _DataItem) End Function End Class
Figure 4
If you don't want to use your business system to send SMS messages, you can use NuGet packages like Twillio, but I always like to have a record of when something like this is done. You never know when a user thinks they provided the required token but didn't press all the buttons.
Conclusion
If you need to have Two-Factor Authentication, it can be done with OWIN relatively easily, but it will require you to implement a bit of code to accomplish it.