public void GenerateTwoFactorCodeFor(string subject) { const string dummyCode = "123"; var twoFactorCode = new TwoFactorCode(dummyCode); TwoFactorCodeDictionary[subject] = twoFactorCode; }
public bool HasVerifiedTwoFactorCode(string subject) { TwoFactorCode twoFactorCodeFromDictionary = null; // find subject in dictionary if (TwoFactorTokenService._twoFactorCodeDictionary .TryGetValue(subject, out twoFactorCodeFromDictionary)) { return(twoFactorCodeFromDictionary.IsVerified); } return(false); }
public void GenerateTwoFactorCodeFor(string subject) { // create random code & notify the user // (via sms, mail, or another mechanism) // for the demo, we'll use a dummy code var code = "123"; var twoFactorCode = new TwoFactorCode(code); // add or overwrite code TwoFactorTokenService._twoFactorCodeDictionary[subject] = twoFactorCode; }
public async Task VerifyCodeTest() { using var testDb = new DbContextOptionsBuilder <TwoFactorDbContext>().UseInMemoryDatabase("UnitTest").CreateDbContext(); var principal = PrincipalUser.Personate(1, "TestUser", null); var row = new TwoFactorCode { Code = "123456", UserId = principal.Id, SentTo = "17751283521" }; testDb.Add(row); testDb.SaveChanges(); Result verifyResult = null; var twoFactorManager = new TwoFactorManager(testDb, principal, new AliyunSmsSender(new AliyunSmsOptions()), null); for (var i = 0; i < 12; i++) { verifyResult = await twoFactorManager.VerifyCodeAsync(row.SentTo, "WRONG!", true); Assert.IsFalse(verifyResult.Ok); } row = testDb.TwoFactorCodes.First(); Assert.IsFalse(row.IsUsed); Assert.IsTrue(row.ErrorTimes > 10); //it still fails even the code is correct this time, because it has already failed for more than 10 times verifyResult = await twoFactorManager.VerifyCodeAsync(row.SentTo, row.Code, true); Assert.IsFalse(verifyResult.Ok); //reset then try a good one row.ErrorTimes = 0; testDb.SaveChanges(); verifyResult = await twoFactorManager.VerifyCodeAsync(row.SentTo, row.Code, true); row = testDb.TwoFactorCodes.First(); Assert.IsTrue(verifyResult.Ok); Assert.IsTrue(row.IsUsed); //if try one more time, it should fail because the code is used verifyResult = await twoFactorManager.VerifyCodeAsync(row.SentTo, row.Code, true); Assert.IsFalse(verifyResult.Ok); testDb.Database.EnsureDeleted(); }
public bool VerifyTwoFactorCodeFor(string subject, string code) { TwoFactorCode twoFactorCodeFromDictionary = null; // find subject in dictionary if (TwoFactorTokenService._twoFactorCodeDictionary .TryGetValue(subject, out twoFactorCodeFromDictionary)) { if (twoFactorCodeFromDictionary.CanBeVerifiedUntil > DateTime.Now && twoFactorCodeFromDictionary.Code == code) { twoFactorCodeFromDictionary.IsVerified = true; return(true); } } return(false); }
public static async Task <bool> VerifyTwoFactorCode(TwoFactorCode twoFactorCode, string code, IDataContext context) { if (twoFactorCode == null) { return(false); } var key = new seamoonapi(); var result = key.passwordsyn(twoFactorCode.CurrentData ?? twoFactorCode.OriginalData, code); if (result.Length <= 3) { return(false); } twoFactorCode.CurrentData = result; await context.SaveChangesAsync(); return(true); }
public async Task <IActionResult> OnPostAsync(bool rememberMe, string?returnUrl = null) { if (ModelState.IsValid) { ApplicationUser?user = await signInManager.GetTwoFactorAuthenticationUserAsync(); if (user is null) { throw new InvalidOperationException($"Unable to load two-factor authentication user."); } var authenticatorCode = TwoFactorCode .Replace(" ", string.Empty, StringComparison.OrdinalIgnoreCase) .Replace("-", string.Empty, StringComparison.OrdinalIgnoreCase); Microsoft.AspNetCore.Identity.SignInResult?result = await signInManager.TwoFactorAuthenticatorSignInAsync( authenticatorCode, rememberMe, RememberMachine); if (result.Succeeded) { logger.LogInformation("User with ID '{UserId}' logged in with 2fa.", user.Id); return(LocalRedirect(returnUrl)); } else if (result.IsLockedOut) { logger.LogWarning("User with ID '{UserId}' account locked out.", user.Id); return(RedirectToPage("./Lockout")); } else { logger.LogWarning("Invalid authenticator code entered for user with ID '{UserId}'.", user.Id); ModelState.AddModelError(string.Empty, "Invalid authenticator code."); return(Page()); } } return(Page()); }
public async Task <IActionResult> OnPostAsync(bool rememberMe, string returnUrl = null) { if (!ModelState.IsValid) { return(Page()); } returnUrl = returnUrl ?? Url.Content("~/"); User user = await userService.SignInManager.GetTwoFactorAuthenticationUserAsync(); if (user is null) { throw new InvalidOperationException(EXCEPTION_2FA); } string authenticatorCode = TwoFactorCode.Replace(" ", string.Empty).Replace("-", string.Empty); Microsoft.AspNetCore.Identity.SignInResult result = await userService.SignInManager.TwoFactorAuthenticatorSignInAsync(authenticatorCode, rememberMe, RememberMachine); if (result.Succeeded) { logger.LogInformation(LOGGER_INFO_2FA_LOGIN, user.Id); return(LocalRedirect(returnUrl)); } else if (result.IsLockedOut) { logger.LogWarning(LOGGER_WARNING_USER_LOCKEDOUT, user.Id); return(RedirectToPage("./Lockout")); } else { logger.LogWarning(LOGGER_WARNING_USER_2FA_INVALIDATTEMPT, user.Id); ModelState.AddModelError(string.Empty, MESSAGE_ERROR_INVALID_2FACODE); return(Page()); } }
private async Task <Result> SendCodeAsync(string mobileNumberOrEmailAddress, string?overrideMessageTemplateWithCodeArg0 = null, string?overrideSmsTemplateAlias = null, string?overrideSmsSignName = null) { if (mobileNumberOrEmailAddress == null) { throw new ArgumentNullException(nameof(mobileNumberOrEmailAddress)); } var isEmail = mobileNumberOrEmailAddress.IsEmail(); var isMobile = mobileNumberOrEmailAddress.IsMobileNumber(); if (!isEmail && !isMobile) { return(new Failure($"无法送达 '{mobileNumberOrEmailAddress}'")); } var justSentWithinMinute = await _twoFactorDb.TwoFactorCodes .AsNoTracking() .Where(x => x.SentTo == mobileNumberOrEmailAddress) .Where(x => x.CreatedTime > DateTime.Now.AddMinutes(-1)) .AnyAsync(); if (justSentWithinMinute) { return(new Failure("过于频繁,请1分钟后再试")); } var code = new TwoFactorCode { UserId = _me.Id, AnonymousId = _me.AnonymousId, Code = new Random().Next(0, 1000000).ToString("D6"), SentTo = mobileNumberOrEmailAddress }; _twoFactorDb.TwoFactorCodes.Add(code); await _twoFactorDb.Normalize().SaveChangesAsync(); if (isEmail) { if (_mailSender == null) { throw new Exception($"Required to inject service {nameof(IMailSender)}"); } var wrappedSignName = overrideSmsSignName == null ? null : $"【{overrideSmsSignName}】 "; var content = string.Format(overrideMessageTemplateWithCodeArg0 ?? "{wrappedSignName}验证码: {0}", code.Code); await _mailSender.SendAsync($"{wrappedSignName}动态验证码", content, mobileNumberOrEmailAddress); } else if (isMobile) { if (_smsSender == null) { throw new Exception($"Required to inject service {nameof(IMailSender)}"); } var shortMessage = new SmsBody { SignName = overrideSmsSignName, Template = overrideMessageTemplateWithCodeArg0, TemplateAlias = overrideSmsTemplateAlias, Parameters = new Dictionary <string, string> { ["code"] = code.Code } }; await _smsSender.SendAsync(shortMessage, mobileNumberOrEmailAddress); } return(new Success()); }