Jay
Jay

Reputation: 2252

Should the "Google Two Factor Authenticator" accountSecretKey be stored into my database?

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

  1. A user on my site enable 2FA which created a link between my user and the app. This is a onetime step and does not happen on every login attempt.
  2. Every time the user logs in, he'll need to provide a six digit code from Google Authenticator app.

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

Answers (1)

Caius Jard
Caius Jard

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

Related Questions