Пример #1
0
        public void GenerateTwoFactorCodeFor(string subject)
        {
            const string dummyCode = "123";
            var twoFactorCode = new TwoFactorCode(dummyCode);

            TwoFactorCodeDictionary[subject] = twoFactorCode;
        }
Пример #2
0
        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;
        }
Пример #5
0
        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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        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());
        }
Пример #9
0
        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());
            }
        }
Пример #10
0
        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());
        }