Login, 2FA and sessions

ZEUS protects console access with several layers. Understanding them helps you avoid the most common problems (e.g. a "login loop" caused by the wrong email address).

Step 1 — password

You log in with an email + password pair. The backend verifies:

  • the email via hmac.compare_digest (constant-time comparison),
  • the password via bcrypt (also constant-time),
  • and in on-prem/hybrid mode it additionally attempts an LDAP bind to Active Directory.

Tip: the email must match the specific deployment. admin@lsn.io is the admin of the lsn instance, and admin@z3us.io is the admin of the MVP. A mistake = wrong credentials and a bounce back to the login screen.

Login is protected by a rate limit: 10 failed attempts/IP in 5 minutes and 5 attempts/email in 15 minutes → 429 Too Many Requests. A successful login resets the counters.

Step 2 — 2FA via email

If 2FA is enabled, the backend does not issue a token right away. Instead it sends a 6-digit code by email (provider Resend) and returns a challenge_token. You redeem the code via 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→ resend the code (attempt limit)

Codes are single-use, have a short TTL and an attempt limit per challenge.

Domain allowlist

The ZEUS_ALLOWED_EMAIL_DOMAINS variable (e.g. professnet.pl) restricts whose accounts can authenticate — checked at login and on every request. An empty value = disabled (dev/test). Enforced "for everyone", with no break-glass exception.

Token and session

On success ZEUS issues a JWT HS256 (TTL 24 h by default) with the claims email · tenant · role · via · jti. The frontend (NextAuth) keeps it on the session and attaches it to every request as Authorization: Bearer <token>.

Who is logged in — active sessions

Each token has a unique jti, under which ZEUS registers the session in Redis (email · role · IP · user-agent · login time · last_seen). The admin can see who is currently logged in in the Roles & Theme → Active sessions studio: a list of online users (seen < 5 min ago), with the ability to revoke.

GET  /api/v1/admin/sessions            → who is online (admin only)
POST /api/v1/admin/sessions/{jti}/revoke
POST /auth/logout                      → revoke your own session

With the ZEUS_SESSION_ENFORCE=1 flag, revoke = immediate logout; by default it is a "visibility-only" view (the session disappears from the list, the token expires naturally).


In short: password → (2FA email) → JWT → session visible to the admin. If login "loops", first check the email and any lockout.