using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Bit.Core.Models.Table; using Bit.Core.Enums; using OtpNet; using Bit.Core.Services; using Microsoft.Extensions.DependencyInjection; namespace Bit.Core.Identity { public class AuthenticatorTokenProvider : IUserTwoFactorTokenProvider { private readonly IServiceProvider _serviceProvider; public AuthenticatorTokenProvider(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public async Task CanGenerateTwoFactorTokenAsync(UserManager manager, User user) { var provider = user.GetTwoFactorProvider(TwoFactorProviderType.Authenticator); if(string.IsNullOrWhiteSpace((string)provider?.MetaData["Key"])) { return false; } return await user.TwoFactorProviderIsEnabledAsync(TwoFactorProviderType.Authenticator, _serviceProvider.GetRequiredService()); } public Task GenerateAsync(string purpose, UserManager manager, User user) { return Task.FromResult(null); } public Task ValidateAsync(string purpose, string token, UserManager manager, User user) { var provider = user.GetTwoFactorProvider(TwoFactorProviderType.Authenticator); var otp = new Totp(Base32Encoding.ToBytes((string)provider.MetaData["Key"])); long timeStepMatched; var valid = otp.VerifyTotp(token, out timeStepMatched, new VerificationWindow(1, 1)); return Task.FromResult(valid); } } }