WebAuthn не работает на Chrome Android, но работает на настольных компьютерах и iOS.Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 WebAuthn не работает на Chrome Android, но работает на настольных компьютерах и iOS.

Сообщение Anonymous »

Недавно мы интегрировали WebAuthn в нашу систему с помощью Django 2.1.7. Что касается серверной части,
я не уверен, в чем может быть проблема. Он отлично работает на компьютерах и различных устройствах iOS, где мы его тестировали. У меня Samsung S23 с Android 14 и последней доступной версией Chrome. Он также был протестирован на POCO и дал тот же отрицательный результат.
Я использую WebAuthn 2.2.0, и вот как у меня есть конечные точки:Регистрация:
Принять вызов:

Код: Выделить всё

def get_challenge_authn(request):
try:
rp_id     = "localhost"

registration_options = generate_registration_options(
rp_id     = rp_id,
rp_name   = "MySite",
user_name = user.username,
user_display_name=user.username
)

if not registration_options:
return JsonResponse({'status': 'error', 'msg': 'Ocurrio un error.  Contacte a soporte'}, status=500)

# Almacena temporalmente el challenge en la sesión del usuario.
request.session['webauthn_challenge'] = base64.urlsafe_b64encode(registration_options.challenge).decode("utf-8").rstrip("=")
return JsonResponse(options_to_json(registration_options), safe=False)
except Exception as e:
return JsonResponse({'status': 'error', 'msg': e}, status=500)

Подтвердите и сохраните регистрацию:

Код: Выделить всё

def verificar_guardar_registro_authn(request):
body = json.loads(request.body)
try:

credential_data = {
"rawId": body['rawId'],
"response": {
"clientDataJSON": body['response']['clientDataJSON'],
"attestationObject": body['response']['attestationObject'],
},
"type": body["type"],
"id": body["id"],
}
stored_challenge = request.session.get('webauthn_challenge')

if not stored_challenge:
return JsonResponse({'status': 'error', 'msg': 'El challenge no se encuentra.'}, status=500)

expected_rp_id     = "localhost"
expected_origin    = "http://localhost:8000"

verification = verify_registration_response(
credential         = credential_data,
expected_challenge = base64url_to_bytes(stored_challenge),
expected_rp_id     = expected_rp_id,
expected_origin    = expected_origin,
require_user_verification = True
)

if verification.user_verified:
credential = webAuthnCredential.objects.create(
usuario       = request.user,
credential_id = base64.urlsafe_b64encode(verification.credential_id).decode("utf-8").rstrip("="),
public_key    = base64.urlsafe_b64encode(verification.credential_public_key).decode("utf-8").rstrip("="),
sign_count    = verification.sign_count
)

return JsonResponse({'status': 'ok'}, status=201)
else:
return JsonResponse({'status': 'error', 'msg': 'Registro invalido'}, status=400)
except Exception as e:
print(traceback.format_exc())
return JsonResponse({'status': 'error', 'msg': e}, status=500)
Это работает хорошо, поскольку ключи, которые я генерирую на своем телефоне Android, хранятся на моем сервере.
И вот как я использую эти услуги: Я использую библиотеку SimpleWebAuthn

Код: Выделить всё

const registrar_autentificacion = async () =>  {
try {
const url = "{% url 'autentificacion:get_challenge_authn' %}";

const response = await fetch(url);

const options  = await response.json();
const attResponse = await SimpleWebAuthnBrowser.startRegistration(JSON.parse(options));

const url_verificacion = "{% url 'autentificacion:verificar_guardar_registro_authn' %}";

const verificationResponse = await fetch(url_verificacion, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': '{{csrf_token}}'
},
body: JSON.stringify(attResponse)
});

if (verificationResponse.ok) {
$('#modal_aviso_upload').modal('show');
console.log('Registro exitoso.');
} else {
mensaje_error.innerText = "Ocurrio un error durante la verificación de la llave."
mensaje_error.style.display = ''
console.log('Error en la verificación.');
}
} catch (err) {
mensaje_error.innerText = `Ocurrio un error durante la verificación de la llave.\nError: ${err}`;
mensaje_error.style.display = ''
console.error('Error en el registro:', err);
}
}

Это мои коды для входа:
Получить вызов:

Код: Выделить всё

def get_challenge_authn_authentication(request):
try:
rp_id     = "localhost"

authentication_options = generate_authentication_options(
rp_id=rp_id,
user_verification=UserVerificationRequirement.REQUIRED
)
request.session['webauthn_challenge'] = base64.urlsafe_b64encode(authentication_options.challenge).decode("utf-8").rstrip("=")
return JsonResponse(options_to_json(authentication_options), safe=False)
except Exception as e:
print(e)
return JsonResponse({'error': 'Error', 'msg': e}, safe=False, status=400)

И проверка (хотя думаю до этой части кода уже не дошло):

Код: Выделить всё

def verificar_guardar_autenticacion(request):
auth_data = json.loads(request.body)

stored_challenge = request.session.get('webauthn_challenge')
if not stored_challenge:
return JsonResponse({"error": "Challenge no encontrado en sesión"}, status=500)

credential_id  = auth_data['id']
credential = webAuthnCredential.objects.filter(credential_id=credential_id).first()

if not credential:
return JsonResponse({"error": "No se a encontrado la credencial de llave"}, status=404)

expected_rp_id     = "localhost"
expected_origin    = "http://localhost:8000"
try:
verification = verify_authentication_response(
credential          = auth_data,
expected_rp_id      = expected_rp_id,
expected_origin     = expected_origin,
expected_challenge  = base64url_to_bytes(stored_challenge),
credential_public_key = base64url_to_bytes(credential.public_key),
credential_current_sign_count = credential.sign_count
)
if verification.new_sign_count > credential.sign_count:
credential.sign_count = verification.new_sign_count
credential.save()

# Login here
return JsonResponse({"status": "Autenticación exitosa", 'autenticado': True})

except Exception as e:
print(traceback.format_exc())
return JsonResponse({"error": "Fallo en la autenticación", "msg": str(e)}, status=400)
Вот код для входа:

Код: Выделить всё

btn_login?.addEventListener('click', async (e) =>  {
e.preventDefault();
try {
const url = "{% url 'autentificacion:get_challenge_authn_authentication' %}"

const response = await fetch(url);
const options = await response.json();

const assertionResponse = await SimpleWebAuthnBrowser.startAuthentication(JSON.parse(options));

const url_verificacion = "{% url 'autentificacion:verificar_guardar_autenticacion' %}";

const verificationResponse = await fetch(url_verificacion, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': '{{csrf_token}}'
},
body: JSON.stringify(assertionResponse)
});

const result = await verificationResponse.json();
const { autenticado = false, error = '', msg = '' } = result;
if (autenticado) {
window.location.href = "/";
} else {
mensaje_error.innerText     = `Ocurrio un error durante el inicio de sesión.\n${error}: ${msg}`;
mensaje_error.style.display = ''
console.log('Error en la verificación.');
}

} catch (error) {
mensaje_error.innerText     = `Ocurrio un error durante el inicio de sesión.\nError: ${error}`;
mensaje_error.style.display = ''
console.error('Error en la autenticación:', error);
}
});
При попытке войти в систему я ранее получал это сообщение напрямую:
[img]https:// i.sstatic.net/pBw43wjf.jpg[/img]

После того, как я изменил предпочитаемый сервис (первоначально у меня был Samsung Pass, а теперь я установил его на Google), я получаю сообщение, что зарегистрированных ключей нет (прописал ключ после смены сервиса).
Изображение


Подробнее здесь: https://stackoverflow.com/questions/791 ... op-and-ios
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»