using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Bit.Core.Models.Table; using Bit.Core.Enums; using Bit.Core.Utilities.Duo; using Bit.Core.Models; using Bit.Core.Services; namespace Bit.Core.Identity { public class DuoWebTokenProvider : IUserTwoFactorTokenProvider { private readonly IUserService _userService; private readonly GlobalSettings _globalSettings; public DuoWebTokenProvider( IUserService userService, GlobalSettings globalSettings) { _userService = userService; _globalSettings = globalSettings; } public async Task CanGenerateTwoFactorTokenAsync(UserManager manager, User user) { if(!(await _userService.CanAccessPremium(user))) { return false; } var provider = user.GetTwoFactorProvider(TwoFactorProviderType.Duo); if(!HasProperMetaData(provider)) { return false; } return await user.TwoFactorProviderIsEnabledAsync(TwoFactorProviderType.Duo, _userService); } public async Task GenerateAsync(string purpose, UserManager manager, User user) { if(!(await _userService.CanAccessPremium(user))) { return null; } var provider = user.GetTwoFactorProvider(TwoFactorProviderType.Duo); if(!HasProperMetaData(provider)) { return null; } var signatureRequest = DuoWeb.SignRequest((string)provider.MetaData["IKey"], (string)provider.MetaData["SKey"], _globalSettings.Duo.AKey, user.Email); return signatureRequest; } public async Task ValidateAsync(string purpose, string token, UserManager manager, User user) { if(!(await _userService.CanAccessPremium(user))) { return false; } var provider = user.GetTwoFactorProvider(TwoFactorProviderType.Duo); if(!HasProperMetaData(provider)) { return false; } var response = DuoWeb.VerifyResponse((string)provider.MetaData["IKey"], (string)provider.MetaData["SKey"], _globalSettings.Duo.AKey, token); return response == user.Email; } private bool HasProperMetaData(TwoFactorProvider provider) { return provider?.MetaData != null && provider.MetaData.ContainsKey("IKey") && provider.MetaData.ContainsKey("SKey") && provider.MetaData.ContainsKey("Host"); } } }