Logowanie, 2FA i sesje

ZEUS chroni dostęp do konsoli kilkoma warstwami. Zrozumienie ich pozwala uniknąć najczęstszych problemów (np. „pętli logowania" z błędnym adresem e-mail).

Krok 1 — hasło

Logujesz się parą e-mail + hasło. Backend weryfikuje:

  • e-mail przez hmac.compare_digest (porównanie w stałym czasie),
  • hasło przez bcrypt (również w stałym czasie),
  • a w trybie on-prem/hybrid dodatkowo próbuje bind LDAP do Active Directory.

Wskazówka: e-mail musi pasować do konkretnego wdrożenia. admin@lsn.io to admin instancji lsn, a admin@z3us.io to admin MVP. Pomyłka = błędne dane i odbicie z powrotem na ekran logowania.

Logowanie jest chronione rate-limitem: 10 nieudanych prób/IP w 5 minut oraz 5 prób/e-mail w 15 minut → 429 Too Many Requests. Udane logowanie zeruje liczniki.

Krok 2 — 2FA przez e-mail

Jeśli 2FA jest włączone, backend nie wydaje od razu tokenu. Zamiast tego wysyła 6-cyfrowy kod e-mailem (provider Resend) i zwraca challenge_token. Kod redeemujesz przez POST /auth/verify-2fa:

POST /auth/login     → { requires_2fa: true, challenge_token, email_hint }
POST /auth/verify-2fa{ challenge_token, code } → { access_token (JWT) }
POST /auth/resend-2fa→ ponowna wysyłka kodu (limit prób)

Kody są jednorazowe, mają krótki TTL i limit prób na challenge.

Allowlista domen

Zmienna ZEUS_ALLOWED_EMAIL_DOMAINS (np. professnet.pl) ogranicza, czyje konta mogą się uwierzytelnić — sprawdzane przy logowaniu i na każdym żądaniu. Pusta wartość = wyłączone (dev/test). Egzekwowane „na wszystkich", bez wyjątku break-glass.

Token i sesja

Po sukcesie ZEUS wydaje JWT HS256 (TTL domyślnie 24 h) z claimami email · tenant · role · via · jti. Frontend (NextAuth) trzyma go na sesji i dokleja do każdego żądania jako Authorization: Bearer <token>.

Kto jest zalogowany — aktywne sesje

Każdy token ma unikalny jti, pod którym ZEUS rejestruje sesję w Redis (email · rola · IP · user-agent · czas logowania · last_seen). Admin widzi kto jest aktualnie zalogowany w studiu Roles & Theme → Active sessions: lista użytkowników online (widziani < 5 min), z możliwością revoke.

GET  /api/v1/admin/sessions            → kto online (admin only)
POST /api/v1/admin/sessions/{jti}/revoke
POST /auth/logout                      → revoke własnej sesji

Z flagą ZEUS_SESSION_ENFORCE=1 revoke = natychmiastowe wylogowanie; domyślnie to widok „visibility-only" (sesja znika z listy, token wygasa naturalnie).


W skrócie: hasło → (2FA e-mail) → JWT → sesja widoczna dla admina. Jeśli logowanie „się zapętla", najpierw sprawdź e-mail i ewentualny lockout.