I recently implemented two-factor authentication into a web app and since it was a new concept for me, I thought it would be good to explain the highest conceptual level of this process. As with a lot of new things, there’s some terminology to learn and there’s a need to understand how all the pieces fit together.
First, what’s it take to integrate this with an existing profile login? You need a new database field and a bit of extra code for opting in and out of the two-factor authentication. Ideally, you’ll need a library for generating a QR code, too.
Before I get too much into it, these are some of the elements of the process. There are three pieces of data involved:
- Shared Secret: This element is stored in the database with the user profile and is never exposed outside your application.
- Secret Key: This is an encoded version of the Shared Secret. It is given to the user by your application and the user enters it into their authenticator application.
- Code: The numeric value generated by the authenticator application. This changes every minute.
In brief, your application and the authenticator application both use the current time plus the Secret Key to generate a Code. If they match, the user is authenticated.
To implement this, you would modify your user profile page to provide a button to enable two-factor. When the button is clicked, you create a a random Shared Secret and save it to their profile. You use that Shared Secret to generate and return the Secret Key. The user puts that Secret Key in their authenticator app and the opt-in is complete.
When the user logs in to your application, if they have a Shared Secret set in their profile, they are prompted to enter the Code from their authenticator app. Your application compares that Code to the Code it generates itself, using the Secret Key (built from the Shared Secret). If it is the same, the user is logged in.
It really is simple. The only thing that isn’t clear, but can be found with some moderate Internet searching is the URL to embed in the QR code. That URL is: otpauth://totp/{0}?secret={1}, where {0} is the name of the profile to use (either your application or the user’s username or both) and {1} is the Secret Key. Authenticator apps allow manual entry of Secret Keys, so if you don’t provide a QR code, it’s still workable, just a bit tedious.
Some of the other pieces you’d need are functions to reset the Shared Secret or clear it, if the user wanted to opt-out. This is simple user account maintenance. With a simple implementation, you could blank out the Shared Secret on a “forgot password” action. With more sensitive data, you may want a second code to allow a password reset. The big concern is users who have lost their phone or wiped out their authenticator application entries.
Because two-factor authentication is so simple and is such a low-impact to existing user profile data structures (relative to oAuth), plus the fact it can be opt-in, it’s really a no-brainer to add it to your applications.