Проблема: аутентификация отлично работает во всех настольных браузерах. Однако при использовании мобильного браузера (Chrome или Safari на iOS/Android) метод ValidateTwoFactorPIN постоянно возвращает false, даже если введенный код соответствует именно тому, что отображается в приложении Google Authenticator.
Что я пробовал:
- Подтвердил, что строка пароля правильно доходит до контроллера на мобильном устройстве (ровно 6 цифр)
- Подтверждено, что UserUniqueKey (секрет) единообразен во всех сеансах настольного компьютера и мобильного устройства.
- Проверено, что браузеры настольных компьютеров работают в 100 % случаев, а мобильные устройства не работают в 100 % случаев.
Почему эта проверка может завершиться неудачно именно в мобильных браузерах? Существует ли известная проблема с тем, как аутентификатор Google обрабатывает временные окна или как мобильные браузеры могут отправлять запросы?
Моя настройка: представление (ввод OTP): я использую шесть отдельных полей ввода для лучшего взаимодействия с пользователем. Я использую JavaScript, чтобы объединить их в одну строку перед отправкой через AJAX.
Enter OTP
Enter OTP from the Google Authenticator App...
Verify
Сценарий на стороне клиента: я очищаю ввод, чтобы гарантировать отправку только цифр.
$("#btnVerify").on("click", function () {
const passcodeDigits = [];
for (let i = 1; i 0)
passcodeDigits.push(value.charAt(0));
}
const passcode = passcodeDigits.join("");
const UserUniqueKey = $("#HfUserUniqueKey").val();
$.ajax({
type: "POST",
url: "/Login/Verify2FA",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ passcode: passcode, UserUniqueKey: UserUniqueKey }),
success: function (d) {
if (d === "Y") window.location.href = "/Home/Index";
else alert("Enter correct OTP...");
}
});
});
onKeyUpEvent и onFocusEvent
function onKeyUpEvent(index, event) {
const $element = getCodeBoxElement(index);
let value = $element.val();
value = value.replace(/\D/g, ''); // Remove all non-digits
if (value.length > 1) {
value = value.charAt(0);
}
$element.val(value);
if (event.which === 8 || event.keyCode === 8) {
if (value.length === 0 && index !== 1) {
getCodeBoxElement(index - 1).focus();
}
}
else if (value.length === 1) {
if (index !== 6) {
getCodeBoxElement(index + 1).focus();
} else {
$element.blur();
}
}
}
function onFocusEvent(index) {
for (let i = 1; i < index; i++) {
const $current = getCodeBoxElement(i);
if (!$current.val()) {
$current.focus();
break;
}
}
}
Контроллер на стороне сервера:
[HttpPost]
public JsonResult Verify2FA(string passcode, string UserUniqueKey)
{
if (string.IsNullOrWhiteSpace(passcode) || UserUniqueKey == null)
return Json("N");
TwoFactorAuthenticator tfa = new TwoFactorAuthenticator();
// UserUniqueKey is the secret saved in the DB
bool isValid = tfa.ValidateTwoFactorPIN(UserUniqueKey, passcode.Trim());
if (isValid)
{
FormsAuthentication.SetAuthCookie(Session["UserID_Temp"].ToString(), false);
return Json("Y");
}
return Json("N");
}
Подробнее здесь: https://stackoverflow.com/questions/798 ... s-on-deskt
Мобильная версия