Skip to content

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

  1. Go to User ManagementRoles
  2. Click "Create Role"
  3. Enter role name (lowercase: admin, patient, clinician)
  4. Add description
  5. Click "Create"

Assigning Roles to Users

  1. Go to User ManagementUsers
  2. Find and click on the user
  3. Go to Roles tab
  4. Click "Assign Roles"
  5. Select role(s) from dropdown
  6. 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)

  1. Logo & Navigation (left)
  2. Search (center-left)
  3. My Account button (right)
  4. User email (right)
  5. 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 rolesClaimNamespace matches 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

  1. Log in
  2. Open browser DevTools → Application → Local Storage
  3. Look for keys starting with @@auth0spajs@@
  4. 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.js for 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