public override async Task <bool> ValidateAsync(string purpose, string token, UserManager <AppUser> manager, AppUser user) { int code; if (!int.TryParse(token, out code)) { return(false); } List <UserTotpDevice> devices = await _authDbContext.UserTotpDevices .Where(u => u.User == user) .ToListAsync(); var unixTimestamp = Convert.ToInt64(Math.Round((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds)); var timestep = Convert.ToInt64(unixTimestamp / 30); foreach (UserTotpDevice device in devices) { var hash = new HMACSHA1(Base32.FromBase32(device.SharedSecret)); for (int i = -2; i <= 2; i++) { var expectedCode = Rfc6238AuthenticationService.ComputeTotp(hash, (ulong)(timestep + i), modifier: null); if (expectedCode == code) { device.LastUsedTime = SystemClock.Instance.GetCurrentInstant(); await _authDbContext.SaveChangesAsync(); return(true); } } } return(false); }
public override Task <NewAuthenticatorSecret> GetNewAuthenticatorSecret(Empty request, ServerCallContext context) { return(Task.FromResult(new NewAuthenticatorSecret { Secret = Base32.ToBase32(Rfc6238AuthenticationService.GenerateRandomKey()), })); }
public override async Task <bool> ValidateAsync(string purpose, string token, UserManager <AppUser> manager, AppUser user) { int code; if (!int.TryParse(token, out code)) { return(false); } List <string> keys = await _authDbContext.UserTotpDevices .AsNoTracking() .Where(u => u.User == user) .Select(t => t.SharedSecret) .ToListAsync(); var unixTimestamp = Convert.ToInt64(Math.Round((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds)); var timestep = Convert.ToInt64(unixTimestamp / 30); foreach (string key in keys) { var hash = new HMACSHA1(Base32.FromBase32(key)); for (int i = -2; i <= 2; i++) { var expectedCode = Rfc6238AuthenticationService.ComputeTotp(hash, (ulong)(timestep + i), modifier: null); if (expectedCode == code) { return(true); } } } return(false); }
/// <summary> /// /// </summary> /// <param name="purpose"></param> /// <param name="token"></param> /// <param name="manager"></param> /// <param name="user"></param> /// <returns></returns> public virtual async Task <bool> ValidateAsync(string purpose, string token, UserManager <TUser> manager, TUser user) { var key = await manager.GetAuthenticatorKeyAsync(user); int code; if (!int.TryParse(token, out code)) { return(false); } var hash = new HMACSHA1(Base32.FromBase32(key)); var unixTimestamp = Convert.ToInt64(Math.Round((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds)); var timestep = Convert.ToInt64(unixTimestamp / 30); // Allow codes from 90s in each direction (we could make this configurable?) for (int i = -2; i <= 2; i++) { var expectedCode = Rfc6238AuthenticationService.ComputeTotp(hash, (ulong)(timestep + i), modifier: null); if (expectedCode == code) { return(true); } } return(false); }
public static string ComputeCode(string key) { var hash = new HMACSHA1(Base32.FromBase32(key)); var unixTimestamp = Convert.ToInt64(Math.Round((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds)); var timestep = Convert.ToInt64(unixTimestamp / 30); var topt = Rfc6238AuthenticationService.ComputeTotp(hash, (ulong)timestep, modifier: null); return(topt.ToString("D6", CultureInfo.InvariantCulture)); }
public static string ComputeCode(string key) { var keyBytes = Base32.FromBase32(key); var unixTimestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); var timestep = Convert.ToInt64(unixTimestamp / 30); var topt = Rfc6238AuthenticationService.ComputeTotp(keyBytes, (ulong)timestep, modifier: null); return(topt.ToString("D6", CultureInfo.InvariantCulture)); }
/// <summary> /// Generates a token for the specified <paramref name="user"/> and <paramref name="purpose"/>. /// </summary> /// <param name="purpose">The purpose the token will be used for.</param> /// <param name="manager">The <see cref="UserManager{TUser}"/> that can be used to retrieve user properties.</param> /// <param name="user">The user a token should be generated for.</param> /// <returns> /// The <see cref="Task"/> that represents the asynchronous operation, containing the token for the specified /// <paramref name="user"/> and <paramref name="purpose"/>. /// </returns> /// <remarks> /// The <paramref name="purpose"/> parameter allows a token generator to be used for multiple types of token whilst /// insuring a token for one purpose cannot be used for another. For example if you specified a purpose of "Email" /// and validated it with the same purpose a token with the purpose of TOTP would not pass the check even if it was /// for the same user. /// /// Implementations of <see cref="IUserTwoFactorTokenProvider{TUser}"/> should validate that purpose is not null or empty to /// help with token separation. /// </remarks> public virtual async Task <string> GenerateAsync(string purpose, UserManager <TUser> manager, TUser user) { if (manager == null) { throw new ArgumentNullException(nameof(manager)); } var token = await manager.CreateSecurityTokenAsync(user).ConfigureAwait(false); var modifier = await GetUserModifierAsync(purpose, manager, user).ConfigureAwait(false); return(Rfc6238AuthenticationService.GenerateCode(token, modifier).ToString("D6", CultureInfo.InvariantCulture)); }
public User ValidateCode(int userId, int code, string newEmail) { var user = Find(userId); var securityToken = new SecurityToken(Encoding.Unicode.GetBytes(user.SecurityStamp)); if (Rfc6238AuthenticationService.ValidateCode(securityToken, code, newEmail)) { user.Email = newEmail; Update(user); return(user); } return(null); }
/// <summary> /// Creates a new instance of <see cref="OtpAuthenticateExtensionGrantValidator"/>. /// </summary> /// <param name="validator">Validates an access token.</param> /// <param name="userManager">Provides the APIs for managing user in a persistence store.</param> /// <param name="totpOptions">Configuration used in <see cref="System.Security.Rfc6238AuthenticationService"/> service.</param> /// <param name="identityMessageDescriber">Provides an extensibility point for altering localizing used inside the package.</param> /// <param name="totpService">Used to generate, send and verify time based one time passwords.</param> public OtpAuthenticateExtensionGrantValidator( ITokenValidator validator, UserManager <User> userManager, TotpOptions totpOptions, IdentityMessageDescriber identityMessageDescriber, ITotpService totpService ) { _tokenValidator = validator ?? throw new ArgumentNullException(nameof(validator)); _userManager = userManager ?? throw new ArgumentNullException(nameof(userManager)); _identityMessageDescriber = identityMessageDescriber ?? throw new ArgumentNullException(nameof(identityMessageDescriber)); _totpService = totpService ?? throw new ArgumentNullException(nameof(totpService)); _rfc6238AuthenticationService = new Rfc6238AuthenticationService(totpOptions.Timestep, totpOptions.CodeLength); }
public OperationResult <string> GenerateCode(int userId, string newEmail) { var user = Find(userId); if (Exist(newEmail)) { return(new OperationResult <string>(false, "该邮箱已注册")); } var securityToken = new SecurityToken(Encoding.Unicode.GetBytes(user.SecurityStamp)); int code = Rfc6238AuthenticationService.GenerateCode(securityToken, newEmail); EmailService.SendEmail(EmailType.ResetEmail, newEmail, user.UserName, "", code.ToString()); return(new OperationResult <string>(true, "验证码已发送至你的新邮箱")); }
/// <summary> /// Returns a flag indicating whether the specified <paramref name="token"/> is valid for the given /// <paramref name="user"/> and <paramref name="purpose"/>. /// </summary> /// <param name="purpose">The purpose the token will be used for.</param> /// <param name="token">The token to validate.</param> /// <param name="manager">The <see cref="UserManager{TUser}"/> that can be used to retrieve user properties.</param> /// <param name="user">The user a token should be validated for.</param> /// <returns> /// The <see cref="Task"/> that represents the asynchronous operation, containing the a flag indicating the result /// of validating the <paramref name="token"> for the specified </paramref><paramref name="user"/> and <paramref name="purpose"/>. /// The task will return true if the token is valid, otherwise false. /// </returns> public virtual async Task <bool> ValidateAsync(string purpose, string token, UserManager <TUser> manager, TUser 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).ConfigureAwait(false); var modifier = await GetUserModifierAsync(purpose, manager, user).ConfigureAwait(false); return(securityToken != null && Rfc6238AuthenticationService.ValidateCode(securityToken, code, modifier)); }
/// <summary> /// Constructs the <see cref="TotpService"/>. /// </summary> /// <param name="userManager">Provides the APIs for managing user in a persistence store.</param> /// <param name="smsServiceFactory">Sms Service Factory</param> /// <param name="pushNotificationService">Push Notification service</param> /// <param name="distributedCache">Represents a distributed cache of serialized values.</param> /// <param name="localizer">Represents a service that provides localized strings.</param> /// <param name="logger">Represents a type used to perform logging.</param> /// <param name="rfc6238AuthenticationService">Time-Based One-Time Password Algorithm service.</param> public TotpService( UserManager <User> userManager, ISmsServiceFactory smsServiceFactory, IPushNotificationService pushNotificationService, IDistributedCache distributedCache, IStringLocalizer <TotpService> localizer, ILogger <TotpService> logger, Rfc6238AuthenticationService rfc6238AuthenticationService ) { _userManager = userManager ?? throw new ArgumentNullException(nameof(userManager)); _smsServiceFactory = smsServiceFactory ?? throw new ArgumentNullException(nameof(smsServiceFactory)); _pushNotificationService = pushNotificationService; _cache = distributedCache ?? throw new ArgumentNullException(nameof(distributedCache)); _localizer = localizer ?? throw new ArgumentNullException(nameof(localizer)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _rfc6238AuthenticationService = rfc6238AuthenticationService ?? throw new ArgumentNullException(nameof(rfc6238AuthenticationService)); }
/// <summary> /// Creates a new instance of <see cref="ExtendedPhoneNumberTokenProvider{TUser}"/>. /// </summary> /// <param name="rfc6238AuthenticationService">Time-Based One-Time Password Algorithm service.</param> public ExtendedPhoneNumberTokenProvider(Rfc6238AuthenticationService rfc6238AuthenticationService) { Rfc6238AuthenticationService = rfc6238AuthenticationService ?? throw new ArgumentNullException(nameof(rfc6238AuthenticationService)); }
/// <summary> /// Creates a new instance of <see cref="ExtendedPhoneNumberTokenProvider{TUser}"/>. /// </summary> /// <param name="rfc6238AuthenticationService">Time-Based One-Time Password Algorithm service.</param> public DeveloperPhoneNumberTokenProvider(Rfc6238AuthenticationService rfc6238AuthenticationService) : base(rfc6238AuthenticationService) { }
/// <summary> /// Constructs the <see cref="TotpService"/>. /// </summary> /// <param name="userManager">Provides the APIs for managing user in a persistence store.</param> /// <param name="smsService">Sms service.</param> /// <param name="distributedCache">Represents a distributed cache of serialized values.</param> /// <param name="localizer">Represents a service that provides localized strings.</param> /// <param name="logger">Represents a type used to perform logging.</param> /// <param name="rfc6238AuthenticationService">Time-Based One-Time Password Algorithm service.</param> public TotpService(UserManager <User> userManager, ISmsService smsService, IDistributedCache distributedCache, IStringLocalizer <TotpService> localizer, ILogger <TotpService> logger, Rfc6238AuthenticationService rfc6238AuthenticationService) { UserManager = userManager ?? throw new ArgumentNullException(nameof(userManager)); SmsService = smsService ?? throw new ArgumentNullException(nameof(smsService)); Cache = distributedCache ?? throw new ArgumentNullException(nameof(distributedCache)); Localizer = localizer ?? throw new ArgumentNullException(nameof(localizer)); Logger = logger ?? throw new ArgumentNullException(nameof(logger)); Rfc6238AuthenticationService = rfc6238AuthenticationService ?? throw new ArgumentNullException(nameof(rfc6238AuthenticationService)); }