Fix passkey registration: use correct py_webauthn credential parsers

RegistrationCredential and AuthenticationCredential are plain dataclasses,
not Pydantic models — model_validate_json() does not exist on them.
Replace with parse_registration_credential_json() and
parse_authentication_credential_json() from webauthn.helpers, which
correctly parse the camelCase JSON from @simplewebauthn/browser and
convert base64url fields to bytes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kyle 2026-03-17 23:40:26 +08:00
parent 57d400c6de
commit fc1f8d5514
2 changed files with 17 additions and 7 deletions

View File

@ -21,6 +21,15 @@ ENVIRONMENT=development
# Timezone (applied to backend + db containers via env_file)
TZ=Australia/Perth
# ──────────────────────────────────────
# WebAuthn / Passkeys
# ──────────────────────────────────────
# REQUIRED for passkeys to work. Must match the domain users access UMBRA on.
# RP_ID = eTLD+1 (no scheme, no port). ORIGIN = full origin with scheme.
WEBAUTHN_RP_ID=umbra.example.com
WEBAUTHN_RP_NAME=UMBRA
WEBAUTHN_ORIGIN=https://umbra.example.com
# ──────────────────────────────────────
# Integrations
# ──────────────────────────────────────

View File

@ -28,7 +28,12 @@ from webauthn.helpers.structs import (
UserVerificationRequirement,
AttestationConveyancePreference,
)
from webauthn.helpers import bytes_to_base64url, base64url_to_bytes
from webauthn.helpers import (
bytes_to_base64url,
base64url_to_bytes,
parse_registration_credential_json,
parse_authentication_credential_json,
)
from app.config import settings as app_settings
@ -148,9 +153,7 @@ def verify_registration(
Returns VerifiedRegistration on success, raises on failure.
"""
from webauthn.helpers.structs import RegistrationCredential
credential = RegistrationCredential.model_validate_json(credential_json)
credential = parse_registration_credential_json(credential_json)
return verify_registration_response(
credential=credential,
expected_challenge=challenge,
@ -209,9 +212,7 @@ def verify_authentication(
Returns VerifiedAuthentication on success, raises on failure.
Sign count anomalies are NOT hard-failed caller should log and continue.
"""
from webauthn.helpers.structs import AuthenticationCredential
credential = AuthenticationCredential.model_validate_json(credential_json)
credential = parse_authentication_credential_json(credential_json)
return verify_authentication_response(
credential=credential,
expected_challenge=challenge,