Harden auth failure handling and registration logging
This commit is contained in:
@@ -5,6 +5,7 @@ from __future__ import annotations
|
||||
from dataclasses import dataclass
|
||||
import hashlib
|
||||
import hmac
|
||||
import logging
|
||||
from pathlib import Path
|
||||
import re
|
||||
import secrets
|
||||
@@ -23,6 +24,7 @@ ARGON2_PARALLELISM = 1
|
||||
ARGON2_HASH_LEN = 32
|
||||
ARGON2_SALT_LEN = 16
|
||||
USERNAME_PATTERN = re.compile(r"^[a-z0-9_-]+$")
|
||||
LOGGER = logging.getLogger("chgrid.server.auth")
|
||||
|
||||
|
||||
def _build_dummy_password_hash(password_hasher: PasswordHasher) -> str:
|
||||
@@ -127,14 +129,14 @@ class AuthService:
|
||||
|
||||
with self._conn_lock:
|
||||
normalized_username = self._normalize_username(username)
|
||||
self._validate_username(normalized_username)
|
||||
self._validate_password(password)
|
||||
normalized_email = self._normalize_email(email)
|
||||
if role not in {"user", "admin"}:
|
||||
raise AuthError("role must be user or admin.")
|
||||
now_ms = self.now_ms()
|
||||
password_hash = self._hash_password(password)
|
||||
try:
|
||||
self._validate_username(normalized_username)
|
||||
self._validate_password(password)
|
||||
normalized_email = self._normalize_email(email)
|
||||
if role not in {"user", "admin"}:
|
||||
raise AuthError("role must be user or admin.")
|
||||
now_ms = self.now_ms()
|
||||
password_hash = self._hash_password(password)
|
||||
self._db_execute(
|
||||
"""
|
||||
INSERT INTO users (
|
||||
@@ -147,12 +149,22 @@ class AuthService:
|
||||
except sqlite3.IntegrityError as exc:
|
||||
message = str(exc).lower()
|
||||
if "users.username" in message:
|
||||
LOGGER.warning("register rejected username_taken username=%s", normalized_username)
|
||||
raise AuthError("Username is already taken.") from exc
|
||||
if "users.email" in message:
|
||||
LOGGER.warning("register rejected email_taken username=%s", normalized_username)
|
||||
raise AuthError("Email is already in use.") from exc
|
||||
LOGGER.exception("register sqlite integrity failure username=%s", normalized_username)
|
||||
raise AuthError("Registration failed due to a database constraint.") from exc
|
||||
except AuthError as exc:
|
||||
LOGGER.warning("register rejected username=%s reason=%s", normalized_username, str(exc))
|
||||
raise
|
||||
except Exception as exc:
|
||||
LOGGER.exception("register unexpected failure username=%s", normalized_username)
|
||||
raise AuthError("Registration failed due to a server error.") from exc
|
||||
user = self._get_user_by_username(normalized_username)
|
||||
if user is None:
|
||||
LOGGER.error("register created user missing username=%s", normalized_username)
|
||||
raise AuthError("Failed to load newly created user.")
|
||||
self._db_execute(
|
||||
"""
|
||||
|
||||
@@ -968,6 +968,8 @@ class SignalingServer:
|
||||
)
|
||||
async for raw_message in websocket:
|
||||
await self._handle_message(client, raw_message)
|
||||
except Exception:
|
||||
LOGGER.exception("client message loop error id=%s ip=%s", client.id, self._client_ip(client))
|
||||
finally:
|
||||
if websocket in self.clients:
|
||||
disconnected = self.clients.pop(websocket)
|
||||
@@ -1172,6 +1174,26 @@ class SignalingServer:
|
||||
),
|
||||
)
|
||||
return True
|
||||
except Exception:
|
||||
if isinstance(packet, (AuthLoginPacket, AuthRegisterPacket, AuthResumePacket)):
|
||||
self._record_auth_failure(client, packet)
|
||||
await self._sleep_auth_failure_jitter()
|
||||
LOGGER.exception(
|
||||
"auth unexpected error id=%s ip=%s packet=%s",
|
||||
client.id,
|
||||
self._client_ip(client),
|
||||
packet.type,
|
||||
)
|
||||
await self._send(
|
||||
client.websocket,
|
||||
AuthResultPacket(
|
||||
type="auth_result",
|
||||
ok=False,
|
||||
message="Authentication failed due to a server error. Please try again.",
|
||||
authPolicy=self._auth_policy(),
|
||||
),
|
||||
)
|
||||
return True
|
||||
|
||||
if isinstance(packet, (AuthLoginPacket, AuthRegisterPacket, AuthResumePacket)):
|
||||
self._clear_auth_failures(client, packet)
|
||||
|
||||
Reference in New Issue
Block a user