Authentication

Multi-strategy authentication system supporting local credentials, SSO, magic links, and 2FA.

Authentication Strategies

StrategyFlowBackend Entry
Local (email/password)JWT token pair (access + refresh)backend/src/routes/auth.ts
Azure Entra ID SSOOAuth2/OIDC redirectbackend/src/routes/entra-auth.ts
Magic LinkEmail link with one-time tokenbackend/src/routes/auth.ts
Portal TokenSeparate token-based auth for customersbackend/src/middleware/portal-auth.ts

Password Security

  • Hashed with argon2id via Bun.password.hash() (no separate argon2 package)
  • Minimum 12 characters enforced
  • Rate limited: 5 attempts per 15 minutes on auth endpoints

Optional TOTP 2FA

Users can enable time-based one-time passwords for second-factor authentication. Managed through the user settings interface.

Backend Sources

FilePurpose
backend/src/routes/auth.tsAuth route handlers (login, signup, refresh, magic link)
backend/src/services/auth-service.tsAuth business logic
backend/src/lib/auth.tsPassword hashing, token verification utilities
backend/src/lib/tokens.tsJWT creation and validation
backend/src/middleware/auth.tsJWT verification middleware for protected routes
backend/src/routes/entra-auth.tsAzure Entra ID SSO routes
backend/src/services/entra/Entra ID service layer

Frontend Pages

PagePurpose
LoginEmail/password + SSO entry
SignupNew account registration
ForgotPasswordPassword reset request
ResetPasswordPassword reset with token
MagicLinkRequestRequest passwordless login link
MagicLinkVerifyVerify magic link token
PhoneNumberInputPhone number entry for SMS auth
PhoneVerificationSMS code verification
AuthCallbackOAuth redirect handler

State Management

Auth state is managed via a Zustand store at frontend/src/store/auth.ts. The store provides RBAC helpers like isTeamAdmin(), isTeamLead(), canCreateUsers(), and canDeactivateUsers().

Portal Authentication

The Portal uses a separate token-based authentication system (not session-based). Middleware at backend/src/middleware/portal-auth.ts validates portal tokens independently from the main auth flow.