I tried creating a new project from VS 2017 (.Net Core v2.0) and for authentication, I chose 'Individual User Accounts'. I put QRCode from (https://davidshimjs.github.io/qrcodejs/). I put javascript code in EnableAuthenticator.cshtml
<script src="~/lib/qcrcode.js/qrcode.js"></script><script> new QRCode(document.getElementById("qrCode"), { text: "@Html.Raw(Model.AuthenticatorUri)", width: 200, height: 200 } );</script>
In ManageController.cs, action method EnableAuthenticator doesn't change at all.
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> EnableAuthenticator (EnableAuthenticatorViewModel model) { var user = await _userManager.GetUserAsync(User); if ( user == null ) { throw new ApplicationException ($"Unable to load user with ID '{_userManager.GetUserId (User)}'."); } if ( !ModelState.IsValid ) { await LoadSharedKeyAndQrCodeUriAsync (user, model); return View (model); } // Strip spaces and hypens var verificationCode = model.Code.Replace(" ", string.Empty).Replace("-", string.Empty); //AuthenticatorTokenProvider var is2faTokenValid = await _userManager.VerifyTwoFactorTokenAsync( user, _userManager.Options.Tokens.EmailConfirmationTokenProvider, verificationCode); if ( !is2faTokenValid ) { ModelState.AddModelError ("Code", "Verification code is invalid."); await LoadSharedKeyAndQrCodeUriAsync (user, model); return View (model); } await _userManager.SetTwoFactorEnabledAsync (user, true); _logger.LogInformation ("User with ID {UserId} has enabled 2FA with an authenticator app.", user.Id); var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10); TempData[RecoveryCodesKey] = recoveryCodes.ToArray (); return RedirectToAction (nameof (ShowRecoveryCodes)); }
and this is QRCode generator
private async Task LoadSharedKeyAndQrCodeUriAsync (ApplicationUser user, EnableAuthenticatorViewModel model) { var unformattedKey = await _userManager.GetAuthenticatorKeyAsync(user); if ( string.IsNullOrEmpty (unformattedKey) ) { await _userManager.ResetAuthenticatorKeyAsync (user); unformattedKey = await _userManager.GetAuthenticatorKeyAsync (user); } model.SharedKey = FormatKey (unformattedKey); model.AuthenticatorUri = GenerateQrCodeUri (user.Email, unformattedKey); }
I run and register user, I get notification to 'update-database' to be executed in Package manager console, done. I register again and login successfully. In the 'Two-factors Authentication' menu, I clicked 'configure authentication app', go to 'enable authenticator' page scan QRCode through google/microsoft authenticator and always get fail with this error message:Verification code is valid.
I tried to debug, I found VerifyTwoFactorTokenAsync() always return false. I don't know why this happen ? I tried to changed AuthenticatorTokenProvider became EmailConfirmationTokenProvider and still return false.
but I found something interesting that [TwoFactorEnabled] and [EmailConfirmed] columns in the dbo.AspNetUsers is false.
are there any relation between value in the [TwoFactorEnabled] and [EmailConfirmed] columns and VerifyTwoFactorTokenAsync(), because one of the parameter is ApplicationUser ?
how to solve this problem ?