Skip to main content

SPEC 001 — Authentication

FieldValue
StatusDRAFT
PriorityP0 — Launch-Critical
Backendequa-server/modules/auth/src/
Frontendequa-web/src/modules/auth/, equa-web/src/modules/landing/

1. Feature Purpose

Authentication gates every action in the Equa platform. It provides three sign-in methods (password, Google OAuth, magic link), enforces email verification before access, supports optional two-factor authentication, and maintains rolling server-side sessions. Authorization is layered on top via RBAC with per-site read/write permission checks.

2. Current State (Verified)

2.1 Password Login

DetailValue
Fileequa-server/modules/auth/src/authentication.ts
Hash algorithmbcryptjs, 10 salt rounds
2FASupported (TOTP via twoFactorSecret)
Email verificationRequired before login succeeds
Session bindingsession.user = result.user.id (line 72)

2.2 Google OAuth

DetailValue
Fileequa-server/modules/auth/src/google-auth.ts
Token typesGoogle ID tokens + access tokens
Auto-registrationYes — creates user on first Google sign-in
Email verificationValidated from Google profile
Session bindingsession.user = user.id (line 88)
DetailValue
Fileequa-server/modules/auth/src/magic-link.ts
Token32-byte random hex
Expiry15 minutes
Anti-enumerationToken is generated even when user does not exist
Dev modeReturns token directly for testing
Exported functionssendMagicLink(), verifyMagicLink(), magicLinkLogin(), cleanupExpiredMagicLinks()

2.4 Sessions

DetailValue
Fileequa-server/modules/auth/src/sessions.ts
Libraryexpress-session + TypeORMSessionStore
SecretAPI_SESSION_SECRET environment variable
Max age2 520 000 ms (~42 minutes)
Cookie flagssecure when SSL is active, proxy: true, rolling: true

2.5 Authorization (RBAC)

DetailValue
Fileequa-server/modules/auth/src/authorization.ts
GuardrequirePermissions() (lines 21–26)
Site write checkcanWriteSite() (lines 43–47)
Site read checkcanReadSite() (lines 49–50)

3. Data Model

Users

ColumnTypeConstraints
iduuidPK
emailcitextUNIQUE, NOT NULL
usernamevarchar
passwordHashvarchar
twoFactorSecretvarcharnullable
enabledboolean
twoFactorEnabledboolean
emailVerifiedboolean
acceptedTermsboolean

Sessions

ColumnTypeConstraints
idvarcharPK
expirestimestampINDEXED
useruuidINDEXED, FK → Users
jsonjsonb

TempPasswords

ColumnTypeConstraints
useruuidFK → Users
passwordHashvarchar

EmailVerifications

ColumnTypeConstraints
useruuidFK → Users
codevarchar

Onetimecodes

ColumnTypeConstraints
useruuidFK → Users
codevarchar
availableboolean

4. API Endpoints

MethodPathAuthDescription
POST/api/v1/auth/loginNoPassword login (returns session cookie)
POST/api/v1/auth/registerNoCreate account with email + password
POST/api/v1/auth/googleNoGoogle OAuth sign-in / auto-register
POST/api/v1/auth/magic-linkNoRequest magic link email
POST/api/v1/auth/magic-link/verifyNoVerify magic link token and create session
POST/api/v1/auth/logoutYesDestroy session
GET/api/v1/user/currentYesReturn authenticated user profile
POST/api/v1/auth/verify-emailNoConfirm email verification code
POST/api/v1/auth/2fa/enableYesEnable TOTP two-factor auth
POST/api/v1/auth/2fa/verifyYesVerify TOTP code

5. Frontend Components

ComponentFileDescription
Login pageequa-web/src/modules/auth/pages/login.tsxEmail + password form, Google button, magic-link option
Register pageequa-web/src/modules/auth/pages/register.tsxNew account creation form
Google auth buttonequa-web/src/modules/auth/components/google-auth-button.tsxInitiates Google OAuth flow
Auth modalequa-web/src/modules/landing/components/auth-modal.tsxLogin/register modal on landing page

Frontend Session Handling

  • Cookies sent with credentials: 'include' on every fetch.
  • 401 responses trigger automatic logout and redirect to login.
  • Current user loaded from GET /api/v1/user/current.

6. Business Rules

  1. Email verification required — Users cannot access protected routes until emailVerified = true.
  2. Rolling sessions — Every authenticated request refreshes the session expiry (rolling: true), so active users stay logged in as long as they make a request within every 42-minute window.
  3. Anti-enumeration on magic linkssendMagicLink() always returns success, even for unknown emails, to prevent email harvesting.
  4. Secure cookies — The secure flag is set automatically when SSL is detected, preventing cookie transmission over plain HTTP.
  5. Google auto-registration — First-time Google OAuth users are created automatically; email is pre-verified from Google’s claim.
  6. RBAC enforcementrequirePermissions() middleware runs before every protected endpoint; canWriteSite() and canReadSite() gate organization-level access.
  7. Password hashing — bcryptjs with 10 salt rounds; raw passwords are never stored or logged.
  8. Magic link expiry — Tokens expire after 15 minutes; cleanupExpiredMagicLinks() removes stale rows.

7. Acceptance Criteria

  • User can register with email + password and receive a verification email
  • User cannot access protected routes until email is verified
  • User can log in with verified email + correct password
  • User can enable and verify TOTP two-factor authentication
  • User can sign in with Google OAuth and is auto-registered on first use
  • User can request a magic link and log in via the emailed token
  • Magic link tokens expire after 15 minutes
  • Session persists for up to 42 minutes with rolling refresh
  • 401 response on frontend triggers automatic logout
  • RBAC guards block unauthorized access to organization resources
  • Anti-enumeration: magic link request returns success for non-existent emails

8. Risks

RiskImpactMitigation
Session secret leak (API_SESSION_SECRET)Full session forgeryRotate secret; store in vault; restrict env access
bcrypt cost factor (10) may become insufficientBrute-force of leaked hashesMonitor OWASP guidance; plan migration to higher rounds or argon2
Magic link token interception (email)Account takeover15-min expiry limits window; consider rate-limiting requests per email
Sessions expire after 42 minutes of inactivityUsers logged out unexpectedly during long workflowsConsider increasing API_SESSION_MAX_AGE; implement session revocation on password change / 2FA reset
Google OAuth token validation bypassUnauthorized account creationValidate ID token signature server-side against Google JWKS
No account lockout on failed password attemptsBrute-force attacksAdd rate limiting / progressive lockout on login endpoint