Add 2fa authenticator to user
Asked Answered
H

1

6

I have been trying to work out how to enable 2f login with Google Authentication in my Identity server 4 application.

2fa works fine with both email and phone.

if i check

var userFactors = await _userManager.GetValidTwoFactorProvidersAsync(user);

it has two email and phone. I am assuming that this would be the two factor providers that have been set up for this user.

Now if i check _usermanager again there is a field called tokenproviders. Which appears to contain default, email, phone, and authenticator. I assume these are the ones that Asp .net identity is configured to deal with.

enter image description here

I have worked out how to create the secret needed to genreate the QR code for the authecator app. As well has how to build the QR code and to test the code

 var code = _userManager.GenerateNewAuthenticatorKey();      

 var qr = AuthencatorHelper.GetQrCodeGoogleUrl("bob", code, "My Company");

 var user = await _signInManager.TwoFactorAuthenticatorSignInAsync(codeFromAppToTestWith, true, false);
        if (user == null)
        {
            return View("Error");
        }

Now the problem. I have gone though every method I can find on the user trying to work out how to add another token provider to the user.

How do I assign a new token provider to the user and supply the secret code needed to create the authentication codes?? I am not even seeing any tables in the database setup to handle this information. email and phone number are there and there is a column for 2faenabled. But nothing about authenticator.

I am currently looking into creating a custom usermanager and adding a field onto the application user. I was really hoping someone had a better idea.

Hammock answered 12/7, 2018 at 12:20 Comment(2)
It should be enough to use ResetAuthenticatorKeyAsync on the UserManager for a specific user to enable the authenticator provider for 2fa.Strainer
Going to give that a try thanks for the sugestionHammock
S
3

From what I can see, you are generating a new authenticator key each time the user needs to configure an authenticator app:

var code = _userManager.GenerateNewAuthenticatorKey(); 

You should be aware that using GenerateNewAuthenticatorCodeAsync will not persist the key, and thus will not be useful for 2FA.

Instead, you need to generate and persist the key in the underlying storage, if it not already created:

var key = await _userManager.GetAuthenticatorKeyAsync(user); // get the key
if (string.IsNullOrEmpty(key))
{ 
    // if no key exists, generate one and persist it
    await _userManager.ResetAuthenticatorKeyAsync(user);
    // get the key we just created
    key = await _userManager.GetAuthenticatorKeyAsync(user);
}

Which will generate the key if not already done and persist it in the database (or any storage configured for Identity).

Without persisting the key inside the storage, the AuthenticatorTokenProvider will never be able to generate tokens, and will not be available when calling GetValidTwoFactorProvidersAsync.

Strainer answered 12/7, 2018 at 13:11 Comment(3)
do you know where in the database this data is stored off hand? I am going to set it up in user edit now.Hammock
If you are using Entity Framework Core for the underlying storage (with the default mappings for entities), it should be persistent inside AspNetUserTokens table with LoginProvider = [AspNetUserStore] and Name = AuthenticatorKey.Strainer
For me I was wondering where the 'AspNetUserStore' value came from, the value is a private constant: github.com/dotnet/aspnetcore/blob/…Thorr

© 2022 - 2024 — McMap. All rights reserved.