Skip to main content

Authentication and Permissions

Source: equa-server/modules/auth/src/

Authentication Methods

Equa supports three authentication methods, all resulting in a server-side session.

1. Password Login

Source: equa-server/modules/auth/src/authentication.ts
  • Password hashing: bcryptjs (10 rounds)
  • Two-factor authentication: Supported via twoFactorToken
  • Email verification: Required before login
  • Temporary passwords: Supported via checkTempPassword()
  • On success: session.user = result.user.id (line 72)

2. Google OAuth

Source: equa-server/modules/auth/src/google-auth.ts, equa-server/modules/api/src/server.ts
  • Supports both ID tokens and access tokens
  • Validates email verification status
  • Checks audience (aud) matches client ID
  • Validates g_csrf_token cookie/body consistency in API middleware before Google auth endpoint execution
  • Auto-registration: Creates user if email not found (random password assigned)
  • On success: session.user = user.id (line 88)
Source: equa-server/modules/auth/src/magic-link.ts
Note: magic-link.ts is currently an untracked file in the equa-server repo. It imports a MagicLinks entity from persistence that has not yet been added to schema.ts. This feature is in development but not yet integrated into the database schema.
PropertyValue
Token32-byte random hex
Expiry15 minutes (MAGIC_LINK_EXPIRY_MINUTES)
Anti-enumerationGenerates token even if user doesn’t exist
Dev modeReturns token in response when EMAIL_TRANSPORTER=dev
Functions:
  • sendMagicLink() — Creates magic link record and sends email
  • verifyMagicLink() — Validates token, checks expiry, marks as used
  • magicLinkLogin() — Creates session after verification
  • cleanupExpiredMagicLinks() — Cleanup for expired links

Session Management

Source: equa-server/modules/auth/src/sessions.ts
PropertyValue
Libraryexpress-session
StoreCustom TypeORMSessionStore (Sessions entity)
SecretAPI_SESSION_SECRET env var
Max ageAPI_SESSION_MAX_AGE (default: 604,800,000ms / 7 days)
SameSitelax
HttpOnlytrue
Cookie secureWhen SSL enabled
Proxytrue
Rollingtrue (extends session on each request)
Resavefalse
Save uninitializedfalse
Sessions are persisted in the sessions table with columns: id, expires (indexed), user (indexed), json.

Authorization Model (RBAC)

Source: equa-server/modules/auth/src/authorization.ts, equa-server/docs/cascading-permission.puml

Entities

Permission Check Flow

  1. Endpoint declares requires?: PermissionCheck property
  2. vineyard-lawn calls the permission check function before the handler
  3. Check verifies:
    • User is logged in (requireLoggedInSync())
    • User has required role/permission for the target organization
  4. If check fails, returns 403 Forbidden

Key Authorization Functions

Source: equa-server/modules/auth/src/authorization.ts
FunctionLinesPurpose
requirePermissions()21-26Wraps endpoints with permission checks
canWriteSite()43-47Checks site-level write permissions
canReadSite()49-50Checks site-level read permissions
defineRelationalAuthorizationEndpoints()33-36Applies permission checks to endpoint arrays

Cascading Permission Model

Source: equa-server/docs/cascading-permission.puml The cascading permission model supports nested organizations with permission inheritance:
  • Direct permissions: User has a role directly assigned in the organization
  • Indirect permissions: User inherits permissions from a parent organization
  • Union: For read operations, permissions from parent and child are combined
  • Intersection: For write operations, only overlapping permissions apply

Role Tables

TablePurposeKey Columns
rolesRole definitionsid, name, description, owner, isShared
permissionsPermission definitionsid, name
permissions_rolesRole-to-permission mappingpermission, role
members_rolesMember-to-role assignment (org-scoped)member, role
organizations_rolesOrganization-to-role bindingorganization, role
global_roles_usersGlobal role assignmentuser, role (GlobalRole enum)

Permission Enumeration

Source: Confluence KnowledgeBase — Equa App Permissions (by Christopher Johnson)

Organization Permissions (15)

PermissionDescription
View OrganizationView organization details and dashboard
View Cap TableView capitalization table, shareholdings, securities
View Governing DocumentsView agreements, operating agreements
View MembersView team member list and details
View SelfView own holdings and member page (may be deprecated)
View DocumentsView data room documents
View Incentive PlanView ESOP plans, option pools, vesting schedules
Edit MembersAdd, invite, modify, remove team members
Edit DocumentsUpload, modify, delete data room documents
Edit Organization DetailsModify organization settings, securities, legends
Edit Cap TableCreate/modify shareholdings, transfers, certificates
Edit Incentive PlanCreate/modify ESOP plans, pools, grant options
Delete DocumentsRemove documents from data rooms
SigningDigital signature capability for agreements
Edit BillingManage subscriptions, payment profiles, billing

Site Permissions (2, for site admins only)

PermissionDescription
Write SiteFull site-level write access (admin operations)
Read SiteFull site-level read access (admin view all organizations)
The authorization module maps these to endpoint-level checks:
  • requirePermissions() — generic permission check
  • canWriteSite() / canReadSite() — site-level admin access
  • canEditCapTable, canViewOrganization, canEditMembers, canEditOrganizationBilling, etc. — organization-level checks used in endpoint definitions

Security Notes

  • No explicit rate limiting middleware found in the codebase
  • Registration IP limit: REGISTRATION_IP_LIMIT (default: 20; applied in modules/referral/src/referral.ts)
  • Domain blacklist: domain_blacklists table
  • Email blacklist: email_blacklists table
  • Email verification required before login
  • Two-factor authentication supported but optional