Auth Module
🎯 Overview
The internal Auth module wires together authentication flows for the Internal API (/v1/* routes). It accepts login credentials, manages session lifecycles, performs password recovery, and supports account discovery for multi-account users. The module proxies minimal work inside controllers and concentrates business logic inside service layers so the rest of the platform can trust a single source of truth for auth behavior.
The services operate against first-party MongoDB collections and several shared utilities (email delivery, Stripe, Wasabi, Intercom, and Queue Manager hooks). They also enforce complex SSO and impersonation rules that protect main accounts while still allowing support and partner workflows.
📁 Directory Structure
internal/api/v1/auth/
├── 📄 index.js
├── 📄 README.md
├── 📂 controllers/
│ ├── account.controller.js
│ ├── index.js
│ ├── password.controller.js
│ └── session.controller.js
├── 📂 routes/
│ ├── account.routes.js
│ ├── password.routes.js
│ └── session.routes.js
├── 📂 schemas/
│ ├── password.js
│ └── session.js
├── 📂 services/
│ ├── account.service.js
│ ├── index.js
│ ├── password.service.js
│ └── session.service.js
├── 📂 tests/
│ ├── account.test.js
│ ├── fixtures/
│ │ └── session.js
│ ├── password.test.js
│ └── session.test.js
└── 📂 utils/
└── processShared.js
🗄️ MongoDB Collections
Collection: _accounts
- Purpose: Stores account metadata, affiliate details, branding, and subscription state.
- Model Reference:
shared/models/account.js - Key Fields:
parent_account,domain,branding.colors,stripe_customer,affiliate - Indexes: Compound indexes on
_id,parent_account
Collection: _users
- Purpose: Contains user credentials, roles, and security preferences per account.
- Model Reference:
shared/models/user.js - Key Fields:
email,password,scope,is_owner,metadata
Collection: _projects.dashboard.preferences
- Purpose: Stores per-user dashboard access flags used to filter sub-accounts.
- Model Reference:
shared/models/projects-dashboard-preferences.js - Key Fields:
users,sub_account_id,allow_client_dashboard
Collection: _api.sessions
- Purpose: Persists API session payloads, token expirations, and metadata.
- Model Reference:
shared/models/api-session.js - Key Fields:
token.access_token,session_expiration,metadata.platform
Collection: _api.refresh.tokens
- Purpose: Stores refresh tokens that are removed during logout.
- Model Reference:
shared/models/api-refresh-token.js - Key Fields:
refresh_token
Collection: _api.grants
- Purpose: Temporarily caches OAuth grants generated during login/SSO token exchange.
- Model Reference:
shared/models/api-grant.js - Key Fields:
grant
Collection: _api.scopes
- Purpose: Lists OAuth scopes used to build session access envelopes.
- Model Reference:
shared/models/api-scope.js - Key Fields:
scope
Collection: _funnels
- Purpose: Funnels metadata used when cloning shared funnels after login.
- Model Reference:
shared/models/funnels.js - Key Fields:
original_funnel_id,account_id,pending
📚 Note: See Database Collections Documentation for schema diagrams and index definitions.
🏗️ Architecture Overview
- Pattern: Classic MVC with thin controllers → services → shared utilities. Services encapsulate business rules and call Mongo models directly.
- Key Dependencies:
shared/utilities/authfor hashing, session verification, OAuth helper functions.shared/utilities/stripe,stripeSDK, andaxiosfor billing lookups and OAuth exchange.shared/utilities/loggerfor structured logging and security breadcrumbs.shared/utilities/send-email,Wasabiwrapper, and Queue Manager conventions for transactional email.
- External Services: Stripe, SendGrid, Twilio, Wasabi Object Storage, Intercom hashing, Axios-based OAuth endpoint on the Router service.
🔗 Submodules
- 📘 Account Service – Account discovery helpers exposed to internal portals.
- 📗 Password Service – Password reset, change, and email workflows.
- 📙 Session Service – Login, logout, session status enrichment, and SSO flows.
- 📒 Process Shared Utility – Clones shared funnels when a login carries
sharedmetadata.
🚀 Quick Start
Authenticate against the Internal API using the login endpoint:
POST /v1/v1/auth/login HTTP/1.1
Content-Type: application/json
X-Client-Id: <public-app-id>
{
"account": "64fa...",
"email": "user@example.com",
"password": "••••••••",
"remember": true,
"platform": "client_dashboard"
}
- ✅ On success, the controller forwards to
sessionService.login, writes a session document, and returnsSUCCESSin a subsequent call toGET /v1/v1/auth/status. - ❌ On failure (invalid credentials, banned account, unauthorized scope), a
400/403is raised by the service.
🔐 Required Environment Variables
| Variable | Description | Required |
|---|---|---|
APP_SECRET | JWT secret for password tokens and SSO verification payloads | ✅ Yes |
APP_MISC_SECRET | Short-lived OAuth grant signing secret | ✅ Yes |
PORT | Router port used when exchanging OAuth grants | ✅ Yes |
CLIENT_REDIRECT_URI | Router URL used during SSO token exchange | ✅ Yes |
STRIPE_SECRET_KEY | Stripe API key for account billing lookups | ✅ Yes |
INTRO_COUPON_ID | Coupon template ID used when generating promo codes | ❌ Optional |
BOT_BYPASS_KEY | Optional header that bypasses bot detection logic | ❌ Optional |
📊 Key Metrics & Performance
- Session status responses aggregate ~15 Mongo collections and several Stripe/Twilio calls. Cache repeated lookups (scope, Stripe keys) in upstream services when possible.
- Login requests perform synchronous OAuth grant exchange with the Router service; ensure Router is reachable (
PORT) to avoid 502s. - Password reset email sends rely on Wasabi public URLs and SendGrid transactional templates; transient failures bubble up as
400with logged context.