BrandonPotter / GoogleAuthenticator

Simple, easy to use server-side two-factor authentication library for .NET that works with Google Authenticator and Authy.
Apache License 2.0
369 stars 126 forks source link

Get or generate recovery code. #211

Closed micheletolve closed 4 months ago

micheletolve commented 4 months ago

Hi, how can I get or generate the recovery codes in case of problem with the Google Authenticator app? I would show this recovery codes only one time after have paired the app.

Thanks.

ahwm commented 4 months ago

Recovery codes are outside the scope of this library, but something like this should work to generate them (the code will need to adjust slightly between .NET versions).

    using var rng = RandomNumberGenerator.Create();
    List<uint> codes = [];
    while (codes.Count < 5)
    {
        var bytes = new byte[10];
        rng.GetBytes(bytes);
        UInt32 num = BitConverter.ToUInt32(bytes, 0);
        codes.Add(num);
    }

(based on answers from https://stackoverflow.com/questions/38668748/how-to-generate-random-int-value-using-system-security-cryptography)

This will create a list of 5 codes that look like this:

756967159 623057396 and so on.

If you want them alphanumeric, you could also hash them (for example, with HMACSHA256) and truncate to X characters long. Or you could just use the same method you used to generate the TOTP secret key in the first place (just however many times for how many codes you want to generate). Then save those to your database.

It's up to your application to contain the logic for validating/saving them.

micheletolve commented 4 months ago

And the codes generate in this way can be used to recover the login in case of problem with the OTP app?

ahwm commented 4 months ago

That logic is the responsibility of the developer and the application.

micheletolve commented 4 months ago

Ok that logic is my responsibility, but how to validate these recovery codes with the library’s ValidateTwoFactorPIN method? Or if someone uses one of these recovery codes does not this have to be validated by the library, but by an ad hoc method?

micheletolve commented 4 months ago

Can you consider adding this feature to the next realease?

ahwm commented 4 months ago

You wouldn't use this library to validate recovery codes. They are not time-based. You would validate them yourself (much like the user's password) such as

var tfa = new TwoFactorAuthenicator();
if (!tfa.ValidateTwoFactorPIN(Key, Request.Form["txtCode"]))
{
    List<string> recovery = GetRecoveryCodesForUserFromDb();
    if (recovery.Contains(Request.Form["txtCode"]))
    {
        // confirm login, set cookies, mark code as unusable
    }
}

Validating recovery codes is outside the scope of this library and can't be self-contained due to the nature of interacting with the rest of the application. As such, this feature really isn't even on the table for consideration.

micheletolve commented 4 months ago

Ok many thanks.