Merge pull request #3889 from alphagov/webauthn-errors

Handle errors when registration fails
This commit is contained in:
Ben Thorner
2021-05-19 11:22:05 +01:00
committed by GitHub
8 changed files with 152 additions and 64 deletions

View File

@@ -27,7 +27,16 @@
})
.then((response) => {
if (!response.ok) {
throw Error(response.statusText);
return response.arrayBuffer()
.then((cbor) => {
return Promise.resolve(window.CBOR.decode(cbor));
})
.catch(() => {
throw Error(response.statusText);
})
.then((text) => {
throw Error(text);
});
}
window.location.reload();

View File

@@ -3,7 +3,7 @@ from flask import current_app, request, session
from flask_login import current_user
from app.main import main
from app.models.webauthn_credential import WebAuthnCredential
from app.models.webauthn_credential import RegistrationError, WebAuthnCredential
from app.notify_client.user_api_client import user_api_client
from app.utils import user_is_platform_admin
@@ -34,13 +34,19 @@ def webauthn_begin_register():
@main.route('/webauthn/register', methods=['POST'])
@user_is_platform_admin
def webauthn_complete_register():
credential = WebAuthnCredential.from_registration(
session.pop("webauthn_registration_state"),
cbor.decode(request.get_data()),
)
if 'webauthn_registration_state' not in session:
return cbor.encode("No registration in progress"), 400
try:
credential = WebAuthnCredential.from_registration(
session.pop("webauthn_registration_state"),
cbor.decode(request.get_data()),
)
except RegistrationError as e:
return cbor.encode(str(e)), 400
user_api_client.create_webauthn_credential_for_user(
current_user.id, credential
)
return ''
return cbor.encode('')

View File

@@ -2,12 +2,17 @@ import base64
from fido2 import cbor
from fido2.client import ClientData
from fido2.cose import UnsupportedKey
from fido2.ctap2 import AttestationObject, AttestedCredentialData
from flask import current_app
from app.models import JSONModel
class RegistrationError(Exception):
pass
class WebAuthnCredential(JSONModel):
ALLOWED_PROPERTIES = {
'id',
@@ -22,11 +27,17 @@ class WebAuthnCredential(JSONModel):
def from_registration(cls, state, response):
server = current_app.webauthn_server
auth_data = server.register_complete(
state,
ClientData(response["clientDataJSON"]),
AttestationObject(response["attestationObject"]),
)
try:
auth_data = server.register_complete(
state,
ClientData(response["clientDataJSON"]),
AttestationObject(response["attestationObject"]),
)
except ValueError as e:
raise RegistrationError(e)
if isinstance(auth_data.credential_data.public_key, UnsupportedKey):
raise RegistrationError("Encryption algorithm not supported")
return cls({
'name': 'Unnamed key',