I am getting a not verified using the TOTP method I have found on the following link.
OTP code generation and validation with otp.net
!My! code is below.
The _2FAValue line at the top is embedded into the QR barcode that Microsoft Authenticator attaches too.
The _Check... Function is the server ajax call to the server which implements OTP.Net library exposing TOTP calculation.
MakeTOTPSecret creates an SHA1 version of a Guid which is applied to the User profile and stored in _gTOTPSecret. NB: This IS populated in the places it is used.
I think I must have missed something obvious to get a result, here.
loSetup2FAData._s2FAValue = $@"otpauth://totp/{loUser.UserName}?secret={loUser.MakeTOTPSecret()}&digits=6&issuer={Booking.Library.Classes.Constants._sCompanyName}&period=60&algorithm=SHA1";
[AllowAnonymous] public JsonResult _CheckTOTPCodeOnServer([FromBody] Booking.Site.Models.Shared.CheckTotpData loCheckTotpData) { string lsMessage = "<ul>"; try { string lsEmail = this.Request.HttpContext.Session.GetString("Buku_sEmail"); Booking.Data.DB.Extensions.IdentityExtend.User loUser = this._oDbContext.Users.Where(U => U.UserName.ToLower() == lsEmail.ToLower() || U.Email == lsEmail).FirstOrDefault(); if (loUser != null && loUser.Load(this._oDbContext) && loUser._gTOTPSecret != Guid.Empty) { OtpNet.Totp loTotp = new Totp(Booking.Library.Classes.Utility.StringToBytes(loUser.MakeTOTPSecret()), 60, OtpHashMode.Sha1, 6); loTotp.ComputeTotp(DateTime.Now); long lnTimeStepMatched = 0; bool lbVerify = loTotp.VerifyTotp(loCheckTotpData._nTotp.ToString("000000"), out lnTimeStepMatched, new VerificationWindow(2, 2)); if (lbVerify) { lsMessage += "<li>Successfully validated Totp code</li>"; lsMessage += "<li>Save is now activated</li>"; return this.Json(new { bResult = true, sMessage = lsMessage + "</ul>" }); } } } catch (Exception loException) { lsMessage += "<li>" + Booking.Library.Classes.Utility.MakeExceptionMessage(true, loException, "\r\n", "_CheckTOTPCodeOnServer") + "</li>"; } lsMessage += "<li>Unsuccessfully validated Totp code</li>"; return this.Json(new { bResult = false, sMessage = lsMessage + "</ul>" }); } public string MakeTOTPSecret() { string lsReturn = String.Empty; try { using (SHA1Managed loSha1 = new SHA1Managed()) { var loHash = loSha1.ComputeHash(Encoding.UTF8.GetBytes(this._gTOTPSecret.ToString())); var loSb = new StringBuilder(loHash.Length * 2); foreach (byte b in loHash) { loSb.Append(b.ToString("X2")); } lsReturn = loSb.ToString(); } } catch (Exception loException) { Booking.Library.Classes.Utility.MakeExceptionMessage(true, loException, "\r\n", "Identity.MakeSHA1Secret"); } return lsReturn; }