Auth0 RBAC Reference
Quick reference guide for managing authentication and role-based access control (RBAC) in My Health Portal.
Overview
The platform uses Auth0 for authentication with client-side integration (Single Page Application). Users are assigned roles that control what content they can access.
Auth0 Domain: auth.jmdaling.co.za (Custom Domain)
Tenant: dev-80t8a4t7gbp2h55c.eu.auth0.com (Management API only)
Application Type: Single Page Application (SPA)
Integration: Client-side JavaScript SDK (auth0-spa-js)
Roles & Permissions
Available Roles
| Role | Description | Access |
|---|---|---|
| admin | Full system access | Everything - bypasses all restrictions |
| patient | Patient/personal use | Home, Medical Data, Research, Supplements, Treatments, Analysis |
| clinician | Medical professional | Home, Medical Data, Medical Reports (no Research or Technical) |
Access Matrix
| Section | Admin | Patient | Clinician | Patient + Clinician |
|---|---|---|---|---|
| Home | ✅ | ✅ | ✅ | ✅ |
| Medical Summary | ✅ | ✅ | ✅ | ✅ |
| Care Team | ✅ | ✅ | ✅ | ✅ |
| Medical Intelligence | ✅ | ✅ | ✅ | ✅ |
| Health Data | ✅ | ✅ | ✅ | ✅ |
| Medical Reports | ✅ | ✅ | ✅ | ✅ |
| Treatments | ✅ | ✅ | ❌ | ✅ |
| Supplements | ✅ | ✅ | ❌ | ✅ |
| Research | ✅ | ✅ | ❌ | ✅ |
| Analysis | ✅ | ✅ | ❌ | ✅ |
| Technical | ✅ | ❌ | ❌ | ❌ |
| My Account | ✅ | ✅ | ✅ | ✅ |
Auth0 Configuration
Application Settings
Basic Settings:
- Name: My Health Portal
- Application Type: Single Page Application
- Domain (Custom): auth.jmdaling.co.za
- Domain (Tenant): dev-80t8a4t7gbp2h55c.eu.auth0.com (Management API only)
- Client ID: 51vX1kTQOAAeOARHyDXVKKMVvc72d64Y
Application URIs:
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
Allowed Origins (CORS):
http://localhost:8002, https://health.jmdaling.co.za
Advanced Settings → Grant Types: - ✅ Authorization Code - ✅ Refresh Token - ❌ Implicit (not needed with PKCE)
Advanced Settings → OAuth: - Token Endpoint Authentication Method: None (SPA requirement) - Skip User Consent: ON (first-party application)
Custom Claims Configuration
Auth0 Action: "Add Roles to Token"
Location: Actions → Flows → Login
Code:
exports.onExecutePostLogin = async (event, api) => {
const namespace = 'https://health.jmdaling.co.za';
if (event.authorization) {
// Add roles to ID token
api.idToken.setCustomClaim(`${namespace}/roles`, event.authorization.roles);
// Add roles to access token (if using API)
api.accessToken.setCustomClaim(`${namespace}/roles`, event.authorization.roles);
}
};
Important: The namespace (https://health.jmdaling.co.za) must match the rolesClaimNamespace in docs/javascripts/auth0-config.js.
Role Management
Creating a New Role
- Go to User Management → Roles
- Click "Create Role"
- Enter role name (lowercase:
admin,patient,clinician) - Add description
- Click "Create"
Assigning Roles to Users
- Go to User Management → Users
- Find and click on the user
- Go to Roles tab
- Click "Assign Roles"
- Select role(s) from dropdown
- Click "Assign"
User Can Have Multiple Roles
Users can have multiple roles simultaneously:
- patient + clinician = Full access to everything
- admin alone = Full access (no need for other roles)
Local Configuration
Configuration Files
Auth0 Config: docs/javascripts/auth0-config.js (gitignored)
const AUTH0_CONFIG = {
domain: 'auth.jmdaling.co.za', // Custom domain
clientId: '51vX1kTQOAAeOARHyDXVKKMVvc72d64Y',
audience: '', // Not needed for basic auth
rolesClaimNamespace: 'https://health.jmdaling.co.za/roles'
};
Template: docs/javascripts/auth0-config.template.js (in git)
Key Files
| File | Purpose |
|---|---|
docs/javascripts/auth0-config.js |
Auth0 credentials (GITIGNORED) |
docs/javascripts/auth0-init.js |
Auth initialization & RBAC logic |
docs/javascripts/view-switcher.js |
"My Account" button in header |
docs/account.md |
Account page showing user info & roles |
overrides/main.html |
Loads Auth0 SPA SDK |
mkdocs.yml |
JavaScript loading configuration |
Authentication Flow
1. User visits site
↓
2. auth0-init.js checks authentication
↓
3. Not authenticated? → Redirect to Auth0 login
↓
4. User logs in at Auth0
↓
5. Auth0 redirects back with code
↓
6. SDK exchanges code for tokens
↓
7. Roles extracted from ID token
↓
8. RBAC rules applied (hide/show content)
↓
9. Page reloads to show content
↓
10. Session maintained in localStorage
RBAC Implementation
JavaScript Logic
Location: docs/javascripts/auth0-init.js
Function: applyRoleBasedAccess(roles)
Key Logic:
const isAdmin = roles.includes('admin');
const isClinician = roles.includes('clinician') || isAdmin;
const isPatient = roles.includes('patient') || isAdmin;
// Admin bypasses all restrictions
if (isAdmin) {
console.log('Admin access: All content visible');
return;
}
// Hide Technical section from ALL non-admins (admin-only)
// This runs for everyone except admins
const techDocsLinks = document.querySelectorAll('a[href*="/technical/"]');
techDocsLinks.forEach(link => {
link.closest('li').style.display = 'none';
});
// Hide research from clinician-only users
if (isClinician && !isPatient) {
// Hide research links
}
CSS Classes
The body element gets classes based on roles for CSS targeting:
body.is-admin { /* Admin-specific styling */ }
body.is-patient { /* Patient-specific styling */ }
body.is-clinician { /* Clinician-specific styling */ }
body.role-admin { /* For single role */ }
body.role-patient-clinician { /* For multiple roles */ }
User Interface
Header Components (Left to Right)
- Logo & Navigation (left)
- Search (center-left)
- My Account button (right)
- User email (right)
- Logout button (far right)
My Account Page
URL: /account/
Shows: - Profile picture - Name and email - Role badges (colored pills) - Account details (User ID, Email verification, Last updated) - Logout button
Styling: - Centered content (80% viewport width) - No sidebars - No git revision dates - Centered title
Testing & Debugging
Browser Console Commands
// Get current user object
window.auth0App.getCurrentUser()
// Get user roles array
window.auth0App.getUserRoles()
// Check authentication status
sessionStorage.getItem('auth0_authenticated')
// View stored roles
JSON.parse(sessionStorage.getItem('user_roles'))
Common Console Messages
// Successful authentication
"✓ Authentication successful"
"Authenticated user: {email: ...}"
"User roles: ['patient', 'clinician']"
// Admin access
"Admin access: All content visible"
// Duplicate prevention
"Account button already exists, skipping"
"Logout button already exists, skipping"
Troubleshooting
Issue: 401 Unauthorized Error
Symptoms: Login fails with "Unauthorized" error
Solutions: 1. Check Application Type = "Single Page Application" 2. Verify Grant Types: Authorization Code + Refresh Token enabled 3. Ensure Token Endpoint Authentication Method = "None" 4. Confirm Callback URLs include current origin
Issue: Roles Not Appearing
Symptoms: User roles: [] in console
Solutions: 1. Verify user has roles assigned in Auth0 dashboard 2. Check Auth0 Action is deployed and in Login flow 3. Confirm namespace matches in Action and auth0-config.js 4. Log out and log back in (roles are in token, not updated live)
Issue: Buttons Duplicating
Symptoms: Multiple "My Account" or "Logout" buttons
Solutions: - This is fixed with duplicate prevention checks - Clear browser cache and reload
Issue: Content Not Hidden
Symptoms: Clinicians see Research or Patients see Technical
Solutions:
1. Check roles with window.auth0App.getUserRoles()
2. Verify RBAC logic in browser console
3. Check for JavaScript errors in console
Security Notes
What's Protected
✅ Client-side navigation - Content hidden based on roles
✅ User authentication - Must log in to access site
✅ Session management - Tokens stored securely in localStorage
What's NOT Protected (Yet)
❌ Direct URL access - Users can manually type URLs to restricted pages
❌ API endpoints - Backend semantic search API (port 8003) not protected
❌ Data files - PDFs and data accessible if URL is known
Future Enhancements
- Server-side route protection
- API endpoint authentication with JWT validation
- File access control with signed URLs
Deployment
Production URL
Live Site: https://health.jmdaling.co.za
Deployment Checklist
- [ ] Update Allowed Callback URLs in Auth0 with production domain
- [ ] Update Allowed Logout URLs in Auth0 with production domain
- [ ] Update Allowed Web Origins in Auth0 with production domain
- [ ] Verify
rolesClaimNamespacematches production domain - [ ] Test authentication flow on production
- [ ] Verify roles appear correctly
- [ ] Test RBAC content hiding/showing
Quick Commands
Restart Docker (Apply Changes)
docker compose restart
Clear Browser Auth State
# In browser console
localStorage.clear()
sessionStorage.clear()
location.reload()
Check Auth0 Token Claims
- Log in
- Open browser DevTools → Application → Local Storage
- Look for keys starting with
@@auth0spajs@@ - Decode JWT tokens at https://jwt.io
Support
Auth0 Resources
- Dashboard: https://manage.auth0.com/dashboard/
- Documentation: https://auth0.com/docs
- SPA Quickstart: https://auth0.com/docs/quickstart/spa/vanillajs
Project-Specific Help
- Check browser console for error messages
- Review
docs/javascripts/auth0-init.jsfor RBAC logic - See Git history for recent changes:
git log --oneline docs/javascripts/
Last Updated: December 4, 2025
Auth0 Configuration Version: v1.0
Branch: feature/auth0-integration