Passkey bug fix in gunicorn

This commit is contained in:
喆OvO
2026-08-13 12:50:18 +08:00
parent 15b54f204e
commit 530b8a8269
4 changed files with 131 additions and 16 deletions
+23 -12
View File
@@ -153,32 +153,43 @@ def begin_registration(request, user_id: int, display_name: str = "",
return _serialize_options(options)
def complete_registration(request, credential: dict) -> dict:
def complete_registration(request, credential: dict, user_id: int = None) -> dict:
"""Complete WebAuthn registration.
Returns {'ok': True, 'user_id': int, 'credential_id': str, 'public_key': str}
or raises an exception on failure.
user_id: explicit target user. Always pass it from the route when known —
admin provisioning runs inside the ADMIN's session (its uid differs from
the target user, so deriving the challenge key from the session would never
match). When omitted, it is derived from credential.user_name ("user_5" → 5),
then from the authenticated request context.
"""
rp_id = _get_rp_id(request)
origin = _get_origin(request)
user_name = credential.get("user_name", "")
# Derive the target user id from the registration challenge key.
expected_challenge = pop_webauthn_challenge(f"reg_{user_name}", db_path=_challenge_db())
if not expected_challenge:
# Self-registration fallback: the browser may not echo the user handle,
# so resolve the target from the authenticated request context.
uid = user_id
if uid is None:
uname = credential.get("user_name", "")
if isinstance(uname, str) and uname.startswith("user_"):
try:
uid = int(uname.split("_")[-1])
except (ValueError, IndexError):
uid = None
if uid is None:
try:
from backend.auth import current_user_id
uid = current_user_id()
if uid is not None:
expected_challenge = pop_webauthn_challenge(f"reg_{uid}", db_path=_challenge_db())
user_name = f"user_{uid}"
except Exception:
pass
uid = None
if uid is None:
raise ValueError("No registration challenge found. Please restart registration.")
# Challenge key must match begin_registration's f"reg_{user_id}" exactly.
expected_challenge = pop_webauthn_challenge(f"reg_{uid}", db_path=_challenge_db())
if not expected_challenge:
raise ValueError("No registration challenge found. Please restart registration.")
user_id = int(user_name.split("_")[-1])
user_id = uid
try:
# Library expects rawId field (browser-native camelCase, base64url string)