Add login lockout and encrypt Player.totp_secret/auth_token at rest

Per-username lockout (5 failed TOTP attempts / 5 min) stops account-targeted
brute force regardless of source IP. Player.totp_secret is now Fernet-
encrypted (ENCRYPTION_KEY env, db/crypto.py) instead of stored in plaintext,
and auth_token is stored as a SHA-256 hash rather than the raw session token.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
tim
2026-07-01 19:49:56 +02:00
co-authored by Claude Sonnet 5
parent 0845562a21
commit fbe0c3aa18
7 changed files with 177 additions and 12 deletions
+3 -1
View File
@@ -20,10 +20,12 @@ class Player(Base):
id: Mapped[int] = mapped_column(primary_key=True)
username: Mapped[str] = mapped_column(String(40), unique=True, index=True)
totp_secret: Mapped[str] = mapped_column(String(32))
# Sifrovany cez db/crypto.py (Fernet) -- nikdy neuklada plaintext secret.
totp_secret: Mapped[str] = mapped_column(String(255))
# Posledny pouzity TOTP casovy krok -- ochrana proti replay v ramci okna.
totp_last_step: Mapped[int] = mapped_column(Integer, default=0)
# Session token pre auto-reconnect (poslany v Socket.IO `auth`).
# Uklada sa SHA-256 hash (db/crypto.hash_token), nie surovy token.
auth_token: Mapped[str | None] = mapped_column(
String(64), unique=True, nullable=True
)