# Auth0 Multi-Tenant Configuration Guide This document provides step-by-step instructions for configuring Auth0 for the multi-tenant MotoVaultPro platform. ## Overview The multi-tenant architecture requires: - **Landing Page**: `motovaultpro.com` - Entry point with tenant selection - **Admin Tenant**: `admin.motovaultpro.com` - Admin access to all tenants - **Regular Tenants**: `{tenant-id}.motovaultpro.com` - Isolated tenant access - **Signup Workflow**: Tenant-specific signup with admin approval ## Auth0 Application Configuration ### 1. Application Settings **Application Type**: Single Page Application (SPA) **Allowed Callback URLs**: ``` # Development URLs http://localhost:3002/callback http://admin.motovaultpro.local/callback http://demo-tenant.motovaultpro.local/callback # Production URLs https://motovaultpro.com/callback https://admin.motovaultpro.com/callback https://demo-tenant.motovaultpro.com/callback # Add additional tenant subdomains as needed: https://{tenant-id}.motovaultpro.com/callback ``` **Allowed Logout URLs**: ``` # Development http://localhost:3002 http://admin.motovaultpro.local http://demo-tenant.motovaultpro.local # Production https://motovaultpro.com https://admin.motovaultpro.com https://demo-tenant.motovaultpro.com https://{tenant-id}.motovaultpro.com ``` **Allowed Web Origins**: ``` # Development http://localhost:3002 http://admin.motovaultpro.local:3000 http://demo-tenant.motovaultpro.local:3000 # Production https://motovaultpro.com https://admin.motovaultpro.com https://demo-tenant.motovaultpro.com https://{tenant-id}.motovaultpro.com ``` ### 2. JWT Configuration **JWT Signature Algorithm**: RS256 **OIDC Conformant**: Enabled ### 3. Advanced Settings **Grant Types**: - Authorization Code - Refresh Token - Implicit (for development only) ## Auth0 Rules Configuration ### Rule 1: Add Tenant Context to JWT Create a new Rule in Auth0 Dashboard > Auth Pipeline > Rules: ```javascript function addTenantContext(user, context, callback) { const namespace = 'https://motovaultpro.com/'; // Extract tenant_id from user metadata (set during signup) let tenantId = user.user_metadata && user.user_metadata.tenant_id; // For existing users without tenant metadata, default to admin if (!tenantId) { tenantId = 'admin'; // Optionally update user metadata user.user_metadata = user.user_metadata || {}; user.user_metadata.tenant_id = tenantId; } // Check signup status for non-admin tenants const signupStatus = user.user_metadata && user.user_metadata.signup_status; if (tenantId !== 'admin' && signupStatus !== 'approved') { // Block login for unapproved users return callback(new UnauthorizedError('Account pending approval')); } // Add tenant context to tokens context.idToken[namespace + 'tenant_id'] = tenantId; context.accessToken[namespace + 'tenant_id'] = tenantId; context.idToken[namespace + 'signup_status'] = signupStatus || 'approved'; callback(null, user, context); } ``` ### Rule 2: Tenant-Specific User Metadata ```javascript function setTenantMetadata(user, context, callback) { const namespace = 'https://motovaultpro.com/'; // If this is a signup and connection is Username-Password-Authentication if (context.stats.loginsCount === 1 && context.connection === 'Username-Password-Authentication') { // Extract tenant from redirect_uri or state parameter const redirectUri = context.request.query.redirect_uri || ''; const tenantMatch = redirectUri.match(/([a-z0-9-]+)\.motovaultpro\.(com|local)/); if (tenantMatch) { const tenantId = tenantMatch[1]; // Set initial user metadata user.user_metadata = user.user_metadata || {}; user.user_metadata.tenant_id = tenantId; // Set signup status (pending for regular tenants, approved for admin) user.user_metadata.signup_status = tenantId === 'admin' ? 'approved' : 'pending'; // Update user metadata in Auth0 auth0.users.updateUserMetadata(user.user_id, user.user_metadata); } } callback(null, user, context); } ``` ## Tenant Signup Flow Configuration ### 1. Signup URLs **Tenant-Specific Signup**: ``` https://motovaultpro.com/signup/{tenant-id} ``` **Process**: 1. User visits tenant-specific signup URL 2. Landing page validates tenant exists 3. Redirects to Auth0 with tenant context 4. Auth0 Rule sets tenant_id in user metadata 5. User account created with status="pending" 6. Tenant admin receives notification 7. Admin approves/rejects via tenant management API ### 2. Auth0 Hosted Login Customization Add custom CSS and JavaScript to Auth0 Universal Login to support tenant context: **Custom CSS** (Dashboard > Universal Login > Advanced Options): ```css .tenant-signup-info { background: #f8f9fa; padding: 15px; border-radius: 5px; margin-bottom: 20px; border-left: 4px solid #007bff; } ``` **Custom JavaScript**: ```javascript // Extract tenant from URL parameters const urlParams = new URLSearchParams(window.location.search); const redirectUri = urlParams.get('redirect_uri') || ''; const tenantMatch = redirectUri.match(/([a-z0-9-]+)\.motovaultpro\.(com|local)/); if (tenantMatch && tenantMatch[1] !== 'admin') { const tenantName = tenantMatch[1].replace('-', ' ').toUpperCase(); // Add tenant information to signup form const container = document.querySelector('.auth0-lock-header'); if (container) { const info = document.createElement('div'); info.className = 'tenant-signup-info'; info.innerHTML = ` Signing up for: ${tenantName}
Your account will require admin approval before you can access the system. `; container.appendChild(info); } } ``` ## JWT Token Format After successful authentication, JWT tokens will include: **ID Token Claims**: ```json { "sub": "auth0|user-123", "email": "user@example.com", "https://motovaultpro.com/tenant_id": "demo-tenant", "https://motovaultpro.com/signup_status": "approved", "iat": 1699123456, "exp": 1699127056 } ``` **Access Token Claims**: ```json { "sub": "auth0|user-123", "https://motovaultpro.com/tenant_id": "demo-tenant", "scope": "openid profile email", "iat": 1699123456, "exp": 1699127056 } ``` ## Backend JWT Validation Services should validate JWT tokens and extract tenant context: ```typescript // Example JWT validation middleware import jwt from 'jsonwebtoken'; import jwksClient from 'jwks-rsa'; const client = jwksClient({ jwksUri: `https://${AUTH0_DOMAIN}/.well-known/jwks.json` }); function getKey(header: any, callback: any) { client.getSigningKey(header.kid, (err, key) => { if (err) return callback(err); const signingKey = key.getPublicKey(); callback(null, signingKey); }); } export const validateJWT = (token: string): Promise => { return new Promise((resolve, reject) => { jwt.verify(token, getKey, { audience: process.env.AUTH0_AUDIENCE, issuer: `https://${process.env.AUTH0_DOMAIN}/`, algorithms: ['RS256'] }, (err, decoded) => { if (err) return reject(err); resolve(decoded); }); }); }; // Extract tenant from validated JWT export const getTenantFromToken = (decodedToken: any): string => { return decodedToken['https://motovaultpro.com/tenant_id'] || 'admin'; }; ``` ## Environment Variables Configure the following environment variables for each service: **Platform Services**: ```env AUTH0_DOMAIN=your-domain.auth0.com AUTH0_AUDIENCE=https://api.motovaultpro.com ``` **Landing Page Service**: ```env VITE_AUTH0_DOMAIN=your-domain.auth0.com VITE_AUTH0_CLIENT_ID=your-client-id VITE_TENANTS_API_URL=http://mvp-platform-tenants:8000 ``` **Admin/Tenant Services**: ```env REACT_APP_AUTH0_DOMAIN=your-domain.auth0.com REACT_APP_AUTH0_CLIENT_ID=your-client-id REACT_APP_AUTH0_AUDIENCE=https://api.motovaultpro.com REACT_APP_TENANT_ID=admin # or specific tenant ID ``` ## Testing the Configuration ### 1. Test Admin Login ```bash # Visit admin tenant open http://admin.motovaultpro.local # Should redirect to Auth0, login, then return to admin app ``` ### 2. Test Tenant Signup ```bash # Visit tenant signup open http://motovaultpro.local/signup/demo-tenant # Complete signup, verify pending status curl -H "Authorization: Bearer admin-token" \ http://localhost:8001/api/v1/signups ``` ### 3. Test Approval Workflow ```bash # Approve signup curl -X PUT -H "Authorization: Bearer admin-token" \ http://localhost:8001/api/v1/signups/1/approve # User should now be able to login to tenant open http://demo-tenant.motovaultpro.local ``` ## Production Deployment Notes 1. **SSL Certificates**: Ensure wildcard SSL certificate for `*.motovaultpro.com` 2. **DNS Configuration**: Set up wildcard DNS or individual A records per tenant 3. **Auth0 Environment**: Use production Auth0 tenant with proper security settings 4. **Rate Limiting**: Configure Auth0 rate limiting for signup endpoints 5. **Monitoring**: Set up Auth0 logs monitoring for failed login attempts This configuration provides a secure, scalable multi-tenant authentication system with proper tenant isolation and admin approval workflows.