feat: require discoverable credentials and prefer user verification in WebAuthnService

This commit is contained in:
Johan Lundberg 2026-02-17 13:18:46 +01:00
parent 8aebd04d2a
commit 2ffe968342
No known key found for this signature in database
GPG key ID: A6C152738D03C7D1
2 changed files with 44 additions and 1 deletions

View file

@ -134,6 +134,23 @@ def test_complete_registration_returns_credential_data() -> None:
assert result.credential_data.credential_id == credential_id
def test_begin_registration_requires_resident_key() -> None:
service = _make_service()
options, _state = service.begin_registration(user_id=b"user-123", username="alice")
pub_key = options["publicKey"]
auth_sel = pub_key["authenticatorSelection"]
assert auth_sel["residentKey"] == "required"
assert auth_sel["requireResidentKey"] is True
def test_begin_registration_prefers_user_verification() -> None:
service = _make_service()
options, _state = service.begin_registration(user_id=b"user-123", username="alice")
pub_key = options["publicKey"]
auth_sel = pub_key["authenticatorSelection"]
assert auth_sel["userVerification"] == "preferred"
def test_begin_registration_with_existing_credentials() -> None:
service = _make_service()
_, cred_id, _attested = _generate_credential()
@ -157,6 +174,25 @@ def test_begin_registration_with_existing_credentials() -> None:
# --- Authentication tests ---
def test_begin_authentication_without_credentials() -> None:
"""Usernameless flow: no allowCredentials, browser shows passkey picker."""
service = _make_service()
options, state = service.begin_authentication()
assert "publicKey" in options
assert "challenge" in state
pub_key = options["publicKey"]
# allowCredentials should be absent or empty
allow = pub_key.get("allowCredentials", [])
assert allow is None or len(allow) == 0
def test_begin_authentication_prefers_user_verification() -> None:
service = _make_service()
options, _state = service.begin_authentication()
pub_key = options["publicKey"]
assert pub_key["userVerification"] == "preferred"
def test_begin_authentication_returns_options_and_state() -> None:
service = _make_service()
_, cred_id, _attested = _generate_credential()