Auth0 Custom Domain Setup Guide
Overview
This guide walks through configuring My Health Portal to use the Auth0 custom domain: auth.jmdaling.co.za
Using a custom domain provides: - Better branding (users see your domain instead of Auth0's) - Enhanced security (prevents phishing attacks using Auth0 domains) - Improved trust (consistent domain across your platform) - Required for some enterprise SSO configurations
Prerequisites
Before starting, ensure you have:
1. DNS Access: Ability to add CNAME records to jmdaling.co.za
2. Auth0 Dashboard Access: Admin access to your Auth0 tenant
3. SSL Certificate: Auth0 will provision this automatically via Let's Encrypt
Step 1: Configure Custom Domain in Auth0
1.1 Add Custom Domain
- Go to Auth0 Dashboard
- Navigate to Branding → Custom Domains
- Click + Set Up a Custom Domain
- Enter:
auth.jmdaling.co.za - Select Auth0 Managed Certificates (recommended)
- Click Continue
1.2 Add DNS Record
Auth0 will provide a CNAME record to add:
Type: CNAME
Name: auth
Value: [provided-by-auth0].edge.tenants.auth0.com
TTL: 3600 (or default)
To add this record:
- Log into your DNS provider (where
jmdaling.co.zais hosted) - Add the CNAME record exactly as shown
- Wait for DNS propagation (usually 5-15 minutes, can take up to 24 hours)
1.3 Verify Domain
- Return to Auth0 Dashboard → Branding → Custom Domains
- Click Verify (may need to wait for DNS propagation)
- Once verified, Auth0 will provision an SSL certificate
- Status should change to Ready
1.4 Customize Universal Login Branding
Make the login page match your platform's branding:
- Go to Auth0 Dashboard → Branding → Universal Login
- Click Settings tab
- Logo URL: Enter the full URL to your logo
- Production:
https://health.jmdaling.co.za/images/logo.png - Local:
http://localhost:8002/images/logo.png(for testing) - Primary Color:
#009485(teal, matches your theme) - Page Background Color:
#ffffff(white) or#121212(dark mode) - Company Name:
My Health Portal(optional) - Click Save Changes
Preview Your Login Page: - Click Preview button to see how it looks - Test with both light and dark themes
Note: The logo should be: - Format: PNG, SVG, or JPG - Size: Recommended 150x150px to 400x400px - Transparent background (PNG) works best - Publicly accessible URL (must be HTTPS for production)
Step 2: Update Application Configuration
2.1 Update Environment Variables
Local Development (.env file):
# Use custom domain for all Auth0 operations
AUTH0_DOMAIN=auth.jmdaling.co.za
AUTH0_API_AUDIENCE=https://remission-api
# Management API uses tenant domain (backend only)
# These stay the same - Management API always uses tenant domain
AUTH0_MANAGEMENT_CLIENT_ID=your_m2m_client_id
AUTH0_MANAGEMENT_CLIENT_SECRET=your_m2m_client_secret
Production Server (.env file):
AUTH0_DOMAIN=auth.jmdaling.co.za
AUTH0_API_AUDIENCE=https://remission-api
AUTH0_MANAGEMENT_CLIENT_ID=your_prod_m2m_client_id
AUTH0_MANAGEMENT_CLIENT_SECRET=your_prod_m2m_client_secret
2.2 Update Frontend Configuration
File: docs/javascripts/auth0-config.js
const AUTH0_CONFIG = {
domain: 'auth.jmdaling.co.za', // ✅ Custom domain
clientId: '51vX1kTQOAAeOARHyDXVKKMVvc72d64Y',
audience: 'https://health.jmdaling.co.za',
rolesClaimNamespace: 'https://health.jmdaling.co.za/roles'
};
Step 3: Feature-Specific Setup
3.1 Universal Login (Already Works)
The Auth0 Universal Login will automatically use your custom domain once configured. No additional changes needed.
3.2 Management API (Important!)
⚠️ Critical: The Auth0 Management API always uses the tenant domain, not the custom domain.
Backend Code: src/auth/auth0_management.py
The Management API client should continue using the tenant domain:
# Management API must use tenant domain
MANAGEMENT_DOMAIN = "dev-80t8a4t7gbp2h55c.eu.auth0.com"
# User-facing auth uses custom domain
AUTH0_DOMAIN = os.getenv("AUTH0_DOMAIN", "auth.jmdaling.co.za")
Current Implementation:
- ✅ Backend JWT verification uses AUTH0_DOMAIN (custom domain)
- ✅ Management API operations use hardcoded tenant domain
- ✅ Frontend uses custom domain for login/logout
3.3 Social Connections (If Used)
If you use social login (Google, GitHub, etc.), update callback URLs in each provider:
Old Callback: https://dev-80t8a4t7gbp2h55c.eu.auth0.com/login/callback
New Callback: https://auth.jmdaling.co.za/login/callback
Update in: 1. Google Cloud Console (OAuth 2.0 Client) 2. GitHub OAuth Apps 3. Any other social providers
3.4 Email Templates
Auth0 email templates may reference the tenant domain. Update these in Auth0 Dashboard → Branding → Email Templates:
- Verification emails
- Password reset emails
- Welcome emails
Replace dev-80t8a4t7gbp2h55c.eu.auth0.com with auth.jmdaling.co.za
Step 4: Testing & Verification
4.1 Test Login Flow
# Restart Docker containers
docker compose restart
# Open documentation site
open http://localhost:8002
# Click "My Account" → should redirect to auth.jmdaling.co.za
Verify:
- ✅ Login redirects to https://auth.jmdaling.co.za/...
- ✅ Your logo appears on the Auth0 login page
- ✅ Login page uses your brand colors (teal primary color)
- ✅ After login, returns to your site with valid token
- ✅ User info displays correctly
- ✅ No mixed content warnings (all HTTPS)
4.2 Test Backend JWT Verification
# Check backend logs
docker logs remission-search-web --tail 50
# Should see JWT verification using custom domain
# Look for: "Verifying JWT from https://auth.jmdaling.co.za/"
4.3 Test API Calls
# Test semantic search with authentication
curl -X POST http://localhost:8003/ask \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{"question":"What was my latest β-HCG result?"}'
Step 5: Production Deployment
5.1 Update Production Environment
On your production server:
ssh hetzner
cd ~/remission
# Update .env file
nano .env
# Change AUTH0_DOMAIN=dev-80t8a4t7gbp2h55c.eu.auth0.com
# To: AUTH0_DOMAIN=auth.jmdaling.co.za
# Update frontend config
nano docs/javascripts/auth0-config.js
# Update domain to: 'auth.jmdaling.co.za'
# Restart containers
docker compose restart
# Test login
open https://health.jmdaling.co.za
5.2 Update Auth0 Application Settings
In Auth0 Dashboard, ensure your SPA application has correct URLs:
Allowed Callback URLs:
http://localhost:8002,
https://health.jmdaling.co.za
Allowed Logout URLs:
http://localhost:8002,
https://health.jmdaling.co.za
Allowed Web Origins:
http://localhost:8002,
https://health.jmdaling.co.za
Troubleshooting
Issue: "Invalid domain" error
Cause: Custom domain not fully verified or SSL not provisioned
Solution:
1. Check Auth0 Dashboard → Branding → Custom Domains
2. Status should be "Ready"
3. Wait for DNS propagation (can take up to 24 hours)
4. Use dig auth.jmdaling.co.za to verify CNAME exists
Issue: JWT verification fails
Cause: JWKS endpoint using wrong domain
Solution:
1. Verify AUTH0_DOMAIN environment variable is set to custom domain
2. Restart containers: docker compose restart
3. Check backend logs: docker logs remission-search-web --tail 100
Issue: Login works but API calls fail
Cause: Token issuer (iss claim) doesn't match custom domain
Solution:
1. Decode your JWT token at jwt.io
2. Check iss claim - should be https://auth.jmdaling.co.za/
3. If it shows tenant domain, clear browser cache and login again
Issue: Management API calls fail
Cause: Trying to use custom domain for Management API
Solution:
Management API always uses tenant domain. Verify auth0_management.py:
# This should stay as tenant domain
base_url = f"https://dev-80t8a4t7gbp2h55c.eu.auth0.com"
Key Differences: Custom vs Tenant Domain
| Feature | Tenant Domain | Custom Domain |
|---|---|---|
| User Login | dev-80t8a4t7gbp2h55c.eu.auth0.com |
auth.jmdaling.co.za ✅ |
| JWT Issuer | https://dev-80t8a4t7gbp2h55c.eu.auth0.com/ |
https://auth.jmdaling.co.za/ ✅ |
| JWKS Endpoint | Tenant domain URL | Custom domain URL ✅ |
| Management API | Uses tenant domain ⚠️ | Uses tenant domain ⚠️ |
| Social Login Callbacks | Tenant domain | Custom domain ✅ |
| Branding | Shows Auth0 domain | Shows your domain ✅ |
References
- Auth0 Custom Domains Documentation
- Feature-Specific Custom Domain Setup
- Auth0 Management API Reference
Last Updated: 2025-12-05