Authentication & Authorization
UniPulse implements a multi-layered auth system with JWT tokens, OAuth providers, OTP verification, and workspace-scoped RBAC.
Authentication Methods
| Method | Provider | Endpoint | Use Case |
|---|---|---|---|
| Email + Password | Local | POST /api/v1/auth/register, POST /api/v1/auth/login | Standard sign-up/login |
| Phone + OTP | Local | POST /api/v1/auth/login/phone | Phone-based login |
| Google OAuth | Passport.js | GET /api/v1/auth/oauth/google | Social login |
| Microsoft OAuth | MSAL | GET /api/v1/auth/oauth/microsoft | Enterprise login |
| OTP Verification | Local | POST /api/v1/auth/otp/send, POST /api/v1/auth/otp/verify | Email/phone verification |
JWT Token Flow
Token Configuration
| Token | Secret | Lifetime | Storage |
|---|---|---|---|
| Access Token | JWT_SECRET | Short-lived | Memory / httpOnly cookie |
| Refresh Token | JWT_REFRESH_SECRET | Long-lived | httpOnly cookie |
Auth API Endpoints
| Endpoint | Method | Description |
|---|---|---|
/api/v1/auth/register | POST | Create new account |
/api/v1/auth/login | POST | Email + password login |
/api/v1/auth/login/phone | POST | Phone number login |
/api/v1/auth/oauth/:provider | GET | Initiate OAuth flow (google, microsoft) |
/api/v1/auth/otp/send | POST | Send OTP to email/phone |
/api/v1/auth/otp/verify | POST | Verify OTP code |
/api/v1/auth/onboarding | POST | Complete onboarding flow |
/api/v1/auth/refresh | POST | Refresh access token |
/api/v1/auth/logout | POST | Invalidate refresh token |
/api/v1/auth/me | GET | Get current user profile |
/api/v1/auth/change-password | POST | Change password (authenticated) |
/api/v1/auth/forgot-password | POST | Request password reset email |
/api/v1/auth/reset-password | POST | Reset password with token |
RBAC (Role-Based Access Control)
5-Tier Role Hierarchy
| Role | Manage Members | Manage Settings | Create Content | View Analytics | View Content |
|---|---|---|---|---|---|
| OWNER | Yes | Yes | Yes | Yes | Yes |
| ADMIN | Yes | Yes | Yes | Yes | Yes |
| EDITOR | No | No | Yes | Yes | Yes |
| VIEWER | No | No | No | Yes | Yes |
| CLIENT | No | No | No | Limited | Limited |
Middleware Enforcement
Authorization is enforced at the middleware level using requireWorkspace.ts:
// Route requiring at least EDITOR role
router.post('/posts',
authenticate, // auth.ts: Verify JWT, attach user to req
requireWorkspace('EDITOR'), // requireWorkspace.ts: Load workspace, check role
requireFeature('publishing'), // requireFeature.ts: Check plan feature flag
requireQuota('posts'), // requireQuota.ts: Check usage quota
validate(createPostSchema), // validate.ts: Zod validation
postController.create
);
// Route requiring ADMIN role
router.delete('/members/:memberId',
authenticate,
requireWorkspace('ADMIN'),
workspaceController.removeMember
);
// Route requiring super admin (platform-level)
router.get('/admin/users',
authenticate,
requireSuperAdmin, // requireSuperAdmin.ts: Check isSuperAdmin flag
adminController.listUsers
);
Workspace Isolation (Multi-Tenancy)
All data is scoped to workspaces. The requireWorkspace middleware attaches the current workspace to the request context, and every database query filters by workspaceId.
Key database models with workspace scoping:
| Model | Scoped By |
|---|---|
Post, PostPublication, PostMetric | workspaceId |
SocialAccount | workspaceId |
Workflow, WorkflowRun | workspaceId |
ConversationThread, ConversationMessage | workspaceId |
EcommerceStore, CommerceOrder | workspaceId |
AudienceNode, AudienceSegment | workspaceId |
Competitor, CompetitorSnapshot | workspaceId |
ABTest, EngagementPrediction | workspaceId |
WorkspaceUsage, Subscription | workspaceId |
Feature Flags & Usage Quotas
Feature Flags (requireFeature.ts)
Features are gated by the workspace's subscription plan. The Plan model defines available features through PlanFeature records, and the Feature model lists all gatable features.
// Only allow access if workspace plan includes 'ai_suggestions' feature
router.get('/ai/suggestions',
authenticate,
requireWorkspace('VIEWER'),
requireFeature('ai_suggestions'),
aiController.getSuggestions
);
Usage Quotas (requireQuota.ts)
The WorkspaceUsage model tracks monthly usage. Quotas are defined per plan and enforced before allowing resource-consuming operations.
// Check that workspace hasn't exceeded their monthly AI generation quota
router.post('/ai/caption/generate',
authenticate,
requireWorkspace('EDITOR'),
requireQuota('ai_generations'),
validate(generateCaptionSchema),
aiController.generateCaption
);
Social Platform OAuth
Connecting social accounts (Facebook, Instagram, TikTok) uses OAuth 2.0 flows. Tokens are encrypted at rest using ENCRYPTION_KEY (64-character hex string) and refreshed automatically via the token-refresh queue.
| Platform | OAuth Type | Callback URL Env |
|---|---|---|
| OAuth 2.0 (Meta Login) | FACEBOOK_APP_ID, FACEBOOK_APP_SECRET | |
| OAuth 2.0 (via Facebook) | INSTAGRAM_CALLBACK_URL | |
| TikTok | OAuth 2.0 (Login Kit) | TIKTOK_CLIENT_KEY, TIKTOK_CLIENT_SECRET |
Social platform tokens are encrypted before storage using AES-256 with the ENCRYPTION_KEY environment variable. This key must be exactly 64 hexadecimal characters. Never commit this key to version control.
Environment Variables for Auth
| Variable | Purpose | Required |
|---|---|---|
JWT_SECRET | Signs access tokens | Yes |
JWT_REFRESH_SECRET | Signs refresh tokens | Yes |
ENCRYPTION_KEY | Encrypts social tokens (64 hex chars) | Yes |
GOOGLE_CLIENT_ID | Google OAuth | For Google login |
MICROSOFT_CLIENT_ID | Microsoft OAuth | For Microsoft login |
MICROSOFT_TENANT_ID | Microsoft tenant | For Microsoft login |
FACEBOOK_APP_ID | Facebook OAuth | For social account connection |
FACEBOOK_APP_SECRET | Facebook OAuth | For social account connection |
TIKTOK_CLIENT_KEY | TikTok OAuth | For social account connection |
TIKTOK_CLIENT_SECRET | TikTok OAuth | For social account connection |
- Middleware -- full middleware stack
- Environment Variables -- all environment configuration
- API Reference -- complete route listing
- Key Relations -- WorkspaceMember and role models