mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-09-11 10:28:41 -04:00
Handle errors when registration fails
Previously we would raise a 500 error in a variety of cases: - If a second key was being registered simultaneously (e.g. in a separate tab), which means the registration state could be missing after the first registration completes. That smells like an attack. - If the server-side verification failed e.g. origin verification, challenge verification, etc. The library seems to use 'ValueError' for all such errors [1] (after auditing its 'raise' statements, and excluding AttestationError [2], since we're not doing that). - If a key is used that attempts to sign with an unsupported algorithm. This would normally raise a NotImplemented error as part of verifying attestation [3], but we don't do that, so we need to verify the algorithm is supported by the library manually. This adds error handling to return a 400 response and error message in these cases, since the error is not unexpected (i.e. not a 500). A 400 seems more appropriate than a 403, since in many cases it's not clear if the request data is valid. I've used CBOR for the transport encoding, to match the successful request / response encoding. Note that the ordering of then/catch matters in JS - we don't want to catch our own throws! [1]: https://github.com/Yubico/python-fido2/blob/142587b3e698ca0e253c78d75758fda635cac51a/fido2/server.py#L255 [2]: https://github.com/Yubico/python-fido2/blob/c42d9628a4f33d20c4401096fa8d3fc466d5b77f/fido2/attestation/base.py#L39 [3]: https://github.com/Yubico/python-fido2/blob/c42d9628a4f33d20c4401096fa8d3fc466d5b77f/fido2/cose.py#L92
This commit is contained in:
@@ -3,6 +3,7 @@ from fido2 import cbor
|
||||
from flask import url_for
|
||||
|
||||
from app import webauthn_server
|
||||
from app.models.webauthn_credential import RegistrationError
|
||||
|
||||
|
||||
@pytest.mark.parametrize('endpoint', [
|
||||
@@ -132,3 +133,37 @@ def test_complete_register_clears_session(
|
||||
|
||||
with platform_admin_client.session_transaction() as session:
|
||||
assert 'webauthn_registration_state' not in session
|
||||
|
||||
|
||||
def test_complete_register_handles_library_errors(
|
||||
platform_admin_client,
|
||||
mocker,
|
||||
):
|
||||
with platform_admin_client.session_transaction() as session:
|
||||
session['webauthn_registration_state'] = 'state'
|
||||
|
||||
mocker.patch(
|
||||
'app.models.webauthn_credential.WebAuthnCredential.from_registration',
|
||||
side_effect=RegistrationError('error')
|
||||
)
|
||||
|
||||
response = platform_admin_client.post(
|
||||
url_for('main.webauthn_complete_register'),
|
||||
data=cbor.encode('public_key_credential'),
|
||||
)
|
||||
|
||||
assert response.status_code == 400
|
||||
assert cbor.decode(response.data) == 'error'
|
||||
|
||||
|
||||
def test_complete_register_handles_missing_state(
|
||||
platform_admin_client,
|
||||
mocker,
|
||||
):
|
||||
response = platform_admin_client.post(
|
||||
url_for('main.webauthn_complete_register'),
|
||||
data=cbor.encode('public_key_credential'),
|
||||
)
|
||||
|
||||
assert response.status_code == 400
|
||||
assert cbor.decode(response.data) == 'No registration in progress'
|
||||
|
||||
Reference in New Issue
Block a user