Skip to content

Latest commit

 

History

History
81 lines (74 loc) · 3.27 KB

README.md

File metadata and controls

81 lines (74 loc) · 3.27 KB

You can generate Totp code based on time, UserSecurityStamp and UserIdentifier and ExpirationTime.

You can use this package instead of Rfc6238AuthenticationService class for generating totp code with identity.

NuGet:

<PackageReference Include="TotpGenerator" Version="1.0.2" />

image

Usage:

//Generate totp code
var totpCode = TotpService.GenerateCode(user.SecurityStamp.ToString(), modifier);
//Verify totp code
var isValid = TotpService.ValidateCode(
    user.SecurityStamp.ToString(), 
    totpCode, 
    modifier, 
    _userOption.TwoFactorTotpExpiration);

If you want to modify the TOTP code method generated by Identity, you need to follow these steps:

First, create a class that inherits from the TotpSecurityStampBasedTokenProvider class. Then, you should override the GenerateAsync and ValidateAsync methods and use TotpService instead of Rfc6238AuthenticationService.

GenerateAsync method:

public override async Task<string> GenerateAsync(
    string purpose,
    UserManager<ApplicationUser> manager,
    ApplicationUser user)
{
    if (manager == null)
    {
        throw new ArgumentNullException(nameof(manager));
    }
    var token = await manager.CreateSecurityTokenAsync(user);
    var modifier = await GetUserModifierAsync(purpose, manager, user);

    return TotpService.GenerateCode(token, modifier).ToString("D6", CultureInfo.InvariantCulture);
}

ValidateAsync method:

public override async Task<bool> ValidateAsync(
    string purpose,
    string token,
    UserManager<ApplicationUser> manager,
    ApplicationUser user)
{
    if (manager == null)
    {
        throw new ArgumentNullException(nameof(manager));
    }
    int code;
    if (!int.TryParse(token, out code))
    {
        return false;
    }
    var securityToken = await manager.CreateSecurityTokenAsync(user);
    var modifier = await GetUserModifierAsync(purpose, manager, user);

    return securityToken != null && TotpService.ValidateCode(securityToken, code, modifier, _userOption.TwoFactorTotpExpiration);
}

Then, introduce the created class to Identity:

services.AddIdentity<ApplicationUser, ApplicationRole>()
    .AddEntityFrameworkStores<IdentityContext>()
    .AddDefaultTokenProviders()
    .AddTokenProvider<CustomTotpSecurityStampBasedTokenProvider >("CustomTotp");

And when generating and validating the code, you should send its provider name to the UserManager:

var verificationCode = await _userManager.GenerateTwoFactorTokenAsync(user, "CustomTotp");
var verify = await _userManager.VerifyTwoFactorTokenAsync(user, "CustomTotp", request.VerificationCode);