Reputation: 2252
I am trying to understand how Google Two Factor Authenticator process works in order to incorporate it into my site. Its my understanding that there are two different part to the process
Now, the following code, generate the QR Image and the setup-code to enable the 2FA and link the account to Google Authenticate.
TwoFactorAuthenticator tfa = new TwoFactorAuthenticator();
string accountSecretKey = Guid.NewGuid();
var setupInfo = tfa.GenerateSetupCode("Dotnet Awesome", login.Username, accountSecretKey, 300, 300);
ViewBag.BarcodeImageUrl = setupInfo.QrCodeSetupImageUrl;
ViewBag.SetupCode = setupInfo.ManualEntryKey;
Now on every request, I would authenticate the user using the following code
TwoFactorAuthenticator tfa = new TwoFactorAuthenticator();
tfa.ValidateTwoFactorPIN(accountSecretKey, "Six Digit Code");
Question
In the above code, will the accountSecretKey
code something I would have to save into my database so I can pass it every-time I want to validate? Or, the accountSecretKey
something I would have to re-create on every login attempt? If this code something I would store into my database, should it be encrypted like a password as well?
Upvotes: 2
Views: 1296
Reputation: 74635
When I set it up I tend to:
Have a G2FAEnabled column in the db, and one for the user's SecretKey
Generate a unique secret key and use it to generate the barcode for the page the user is using the set up G2FA, remember it in the server side (put it in the db) but don't set the enabled column
Ask the user to scan or type the code their device shows after they add your site to authenticator. This proves their device is set up correctly, their device clock is correct etc
If the number they type is correct, set the enabled column to true and lock things in so that the secretkey is not now changeable (changing it will kill their 2FA)
From then on the user must supply a correct time-based pin for the current server time and the secret key stored on the server. Their device clock must remain synchronized with the server. You can achieve tolerance of clock drift by checking e.g 6 times either side of current time trying to find a match (it means the device clock can be plusminus 3 minutes relative to server time and still match).
Any attempt to deactivate 2FA (set the enabled column to false) should require a valid 2FA code too, but an alternative process for your customer service department (eg look at the user's passport) should allow reset without knowing it
You don't have to encrypt the secretkey in the db - you'll have to decrypt it to use it, and it's not like a faux pas such as storing plaintext passwords (which is an issue if your db is stolen because users reuse passwords all the time so a theft of your db might mean you reveal a user's password for all their other services) because it should be random data that doesn't mean anything outside your organization, so it won't help a hacker break into another of the user's sites that uses the same 2FA device.
Usually if someone gets as far as being able to steal your db they already reached a point where they could steal the necessary bits to decrypt anything you stored encrypted but if you're certain that your db is likely to be stolen but your web server will remain secure then by all means encrypt the db data
Upvotes: 3