public async Task <IActionResult> Register2FAAuthenticator(TwoFactorInputModel model, string redirectUrl = null)
        {
            var user = await _userManager.GetUserAsync(HttpContext.User);

            if (ModelState.IsValid)
            {
                model.OTP = model.OTP.Replace(" ", string.Empty).Replace("-", string.Empty);
                var is2FaTokenValid = await _userManager.VerifyTwoFactorTokenAsync(user, _userManager.Options.Tokens.AuthenticatorTokenProvider, model.OTP);

                if (is2FaTokenValid)
                {
                    await _userManager.SetTwoFactorEnabledAsync(user, true);

                    await _signInManager.SignInAsync(user, isPersistent : false);

                    await _userManager.SetAuthenticatorTokenVerifiedAsync(user);

                    return(RedirectToAction("Register2FAAuthenticatorComplete", new { redirectUrl = redirectUrl }));
                }
                else
                {
                    ModelState.AddModelError(string.Empty, "Token is invalid");
                }
            }

            return(View(await GetRegister2FAAuthenticatorViewModel(redirectUrl, user.Id, false)));
        }
        public async Task <IActionResult> Verify2FAAuthenticator(TwoFactorInputModel model, string button)
        {
            // the user clicked the "cancel" button
            if (button != "validate")
            {
                return(await CancelTokenRequest(model.RedirectUrl));
            }

            if (ModelState.IsValid)
            {
                model.OTP = model.OTP.Replace(" ", string.Empty).Replace("-", string.Empty);

                Microsoft.AspNetCore.Identity.SignInResult result;
                if (model.IsRecoveryCode)
                {
                    result = await _signInManager.TwoFactorRecoveryCodeSignInAsync(model.OTP);
                }
                else
                {
                    result = await _signInManager.TwoFactorAuthenticatorSignInAsync(model.OTP, false, false);
                }

                if (result.Succeeded)
                {
                    return(RedirectToAction("Index", "TermsOfService", new { returnUrl = model.RedirectUrl }));
                }

                if (result.IsLockedOut)
                {
                    ModelState.AddModelError(string.Empty, "Your account is locked out");
                }
                else
                {
                    ModelState.AddModelError(string.Empty, $"{(model.IsRecoveryCode ? "Recovery code" : "OTP")} is invalid");
                }

                ModelState.Remove("OTP");
            }

            // something went wrong, show form with error
            return(View(await GetTwoFactorViewModelAsync(model.RedirectUrl, model.Username)));
        }