Во-первых, необходимо установить open source package под названием OTP Sharp для валидации TOTP кода.
Далее следует создать метод для вывода QR-кода на страницу:
[HttpGet] public async Task EnableGoogleAuthenticator() { byte[] secretKey = KeyGeneration.GenerateRandomKey(20); string userName = User.Identity.GetUserName(); string barcodeUrl = KeyUrl.GetTotpUrl(secretKey, userName) + "&issuer=MySuperApplication"; var model = new GoogleAuthenticatorViewModel { SecretKey = Base32Encoder.Encode(secretKey), BarcodeUrl = HttpUtility.UrlEncode(barcodeUrl) }; return View(model); }
Разметка для базового представления может быть следующей:
1\. Add MySuperApplication to Google Authenticator
Open Google Authenticator and add MySuperApplication by scanning the QR Code to the right.
2\. Enter the 6 digit code that Google Authenticator generates
Verify that MySuperApplication is added correctly in Google Authenticator by entering the 6 digit code which Google Authenticator generates for MySuperApplication below, and then click Enable.
@using (Html.BeginForm(“EnableGoogleAuthenticator”, “Manage”, FormMethod.Post, new { @class = “form-horizontal”, role = “form” })) { @Html.AntiForgeryToken() @Html.ValidationSummary(false) @Html.HiddenFor(m => m.SecretKey) @Html.HiddenFor(m => m.BarcodeUrl)
@Html.LabelFor(m => m.Code, new { @class = “col-md-2 control-label” })
}
Представление покажет QR-код, который следует считать пользователю с помощью приложения для мобильного Google AUTHENTICATOR. В результате будет получен код для валидации:
[HttpPost] public async Task EnableGoogleAuthenticator(GoogleAuthenticatorViewModel model) { if (ModelState.IsValid) { byte[] secretKey = Base32Encoder.Decode(model.SecretKey); long timeStepMatched = 0; var otp = new Totp(secretKey); if (otp.VerifyTotp(model.Code, out timeStepMatched, new VerificationWindow(2, 2))) { var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); user.IsGoogleAuthenticatorEnabled = true; user.GoogleAuthenticatorSecretKey = model.SecretKey; await UserManager.UpdateAsync(user); return RedirectToAction("Index", "Manage"); } else ModelState.AddModelError("Code", "The Code is not valid"); } return View(model); }