334 lines
9.0 KiB
Markdown
334 lines
9.0 KiB
Markdown
# 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 = `
|
|
<strong>Signing up for: ${tenantName}</strong><br>
|
|
<small>Your account will require admin approval before you can access the system.</small>
|
|
`;
|
|
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<any> => {
|
|
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.
|