using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Bit.Core.Models.Table; using Bit.Core.Enums; #if NET461 using YubicoDotNetClient; #endif using System.Linq; namespace Bit.Core.Identity { public class YubicoOtpTokenProvider : IUserTwoFactorTokenProvider { private readonly GlobalSettings _globalSettings; public YubicoOtpTokenProvider(GlobalSettings globalSettings) { _globalSettings = globalSettings; } public Task CanGenerateTwoFactorTokenAsync(UserManager manager, User user) { if(!user.Premium) { return Task.FromResult(false); } var provider = user.GetTwoFactorProvider(TwoFactorProviderType.YubiKey); var canGenerate = user.TwoFactorProviderIsEnabled(TwoFactorProviderType.YubiKey) && (provider?.MetaData.Values.Any(v => !string.IsNullOrWhiteSpace((string)v)) ?? false); return Task.FromResult(canGenerate); } public Task GenerateAsync(string purpose, UserManager manager, User user) { return Task.FromResult(null); } public Task ValidateAsync(string purpose, string token, UserManager manager, User user) { if(!user.Premium) { return Task.FromResult(false); } if(string.IsNullOrWhiteSpace(token) || token.Length != 44) { return Task.FromResult(false); } var id = token.Substring(0, 12); var provider = user.GetTwoFactorProvider(TwoFactorProviderType.YubiKey); if(!provider.MetaData.ContainsValue(id)) { return Task.FromResult(false); } #if NET461 var client = new YubicoClient(_globalSettings.Yubico.ClientId, _globalSettings.Yubico.Key); var response = client.Verify(token); return Task.FromResult(response.Status == YubicoResponseStatus.Ok); #else return Task.FromResult(false); #endif } } }