Authentication Guide¶
This guide covers the dual authentication system and user management for AUP Learning Cloud.
Table of Contents¶
Overview¶
AUP Learning Cloud supports dual authentication to accommodate different user types:
GitHub OAuth: For technical teams and organization members
Native Authenticator: For students and external users (admin-managed accounts)
Key Features¶
Auto-admin on install: Initial admin created automatically with random password
No self-registration: Only admins can create native accounts
Individual passwords: Each user has their own password (can be changed)
Unified admin panel: All users managed in
/hub/adminBatch operations: CSV/Excel-based bulk user management
Script-based admin management: Use
set-admincommand
Authentication Methods¶
Comparison¶
Feature |
GitHub OAuth |
Native Authenticator |
|---|---|---|
User Type |
Technical teams, org members |
Students, external users |
Account Creation |
GitHub organization invite |
Admin creates manually |
Password |
Managed by GitHub |
User-defined (changeable) |
Access Control |
Based on GitHub teams |
Based on username patterns or groups |
Best For |
Staff, developers, researchers |
Course students, temporary users |
Login Flow¶
Users see a combined login page with GitHub OAuth button and native login form:
┌─────────────────────────────────┐
│ JupyterHub Login │
├─────────────────────────────────┤
│ [ Sign in with GitHub ] │ ← GitHub OAuth
│ │
│ ─── Or use local account ─── │
│ │
│ Username: [____________] │
│ Password: [____________] │ ← Native Auth
│ [ Sign In ] │
└─────────────────────────────────┘
Configuration¶
Enable Auto-Admin (Recommended)¶
In runtime/values.yaml or runtime/values-local.yaml:
custom:
adminUser:
enabled: true # Auto-create admin on helm install
This automatically:
Generates random API token and admin password
Creates
jupyterhub-admin-credentialssecretConfigures
adminuser with admin privileges on hub startup
The API token is associated with the admin user for script operations.
Get Credentials After Install¶
# Get admin password
kubectl -n jupyterhub get secret jupyterhub-admin-credentials \
-o go-template='{{index .data "admin-password" | base64decode}}'
# Get API token for scripts
export JUPYTERHUB_TOKEN=$(kubectl -n jupyterhub get secret jupyterhub-admin-credentials \
-o go-template='{{index .data "api-token" | base64decode}}')
Resource Access Mapping¶
Configure which resources different user groups can access in jupyterhub_config.py:
TEAM_RESOURCE_MAPPING = {
"cpu": ["cpu"],
"gpu": ["Course-CV","Course-DL","Course-LLM"],
"official": ["cpu", "Course-CV","Course-DL","Course-LLM"],
"AUP": ["Course-CV","Course-DL","Course-LLM"],
"native-users": ["Course-CV","Course-DL","Course-LLM"]
}
Native Authenticator Settings¶
The CustomFirstUseAuthenticator class settings:
class CustomFirstUseAuthenticator(FirstUseAuthenticator):
service_name = "Native"
create_users = False # Only admin-created users can login
Important: create_users = False prevents users from creating accounts themselves. Users must be created by an admin first.
Admin Management¶
Initial Admin¶
Created automatically on helm install when custom.adminUser.enabled: true.
Adding More Admins¶
Use the set-admin command (NOT config files):
# Grant admin to users
python scripts/manage_users.py set-admin teacher01 teacher02
# Grant admin from file
python scripts/manage_users.py set-admin -f new_admins.csv
# Revoke admin
python scripts/manage_users.py set-admin --revoke student01
Or via Admin Panel (/hub/admin):
Click username
Check “Admin” checkbox
Save
Admin Users Summary¶
Method |
When to Use |
|---|---|
|
Initial admin on install |
|
Add/remove admins later |
Admin Panel |
Quick single-user changes |
User Management¶
Prerequisites¶
Install required dependencies:
pip install pandas openpyxl requests
Set environment variables:
export JUPYTERHUB_URL="http://localhost:30890" # Or your hub URL
export JUPYTERHUB_TOKEN=$(kubectl -n jupyterhub get secret jupyterhub-admin-credentials \
-o go-template='{{index .data "api-token" | base64decode}}')
Batch User Operations¶
For detailed batch user management, see User Management Guide.
Quick Reference:
# Generate user template
python scripts/generate_users_template.py --prefix student --count 50 --output users.csv
# Create users from file
python scripts/manage_users.py create users.csv
# List all users
python scripts/manage_users.py list
# Grant admin privileges
python scripts/manage_users.py set-admin teacher01 teacher02
# Revoke admin privileges
python scripts/manage_users.py set-admin --revoke student01
# Export/backup users
python scripts/manage_users.py export backup.xlsx
# Delete users
python scripts/manage_users.py delete remove_list.csv
Manual User Management¶
Via JupyterHub Admin Panel (/hub/admin):
Add single user: Click “Add Users” button
Delete user: Click username → “Delete User”
Make admin: Click username → Check “Admin” → “Save”
Stop user server: Click “Stop Server” button
Deployment¶
1. Update Hub Image¶
The Hub Docker image must include the jupyterhub-nativeauthenticator dependency.
File: dockerfiles/Hub/Dockerfile
RUN pip install jupyterhub-multiauthenticator jupyterhub-nativeauthenticator
2. Rebuild Hub Image¶
cd dockerfiles/Hub
./build.sh
# Or manually:
docker build -t ghcr.io/amdresearch/aup-jupyterhub-hub:v1.4.0-dual-auth .
docker push ghcr.io/amdresearch/aup-jupyterhub-hub:v1.4.0-dual-auth
3. Update Helm Values¶
File: runtime/values.yaml
custom:
adminUser:
enabled: true
hub:
image:
name: ghcr.io/amdresearch/aup-jupyterhub-hub
tag: v1.4.0-dual-auth
4. Deploy or Upgrade¶
Production (K3s):
cd runtime
bash scripts/helm_upgrade.bash
Local Development (Docker Desktop):
cd runtime
helm upgrade jupyterhub ./jupyterhub --namespace jupyterhub -f values-local.yaml
5. Verify Deployment¶
# Check hub pod is running
kubectl --namespace=jupyterhub get pods
# Check hub logs for admin setup
kubectl --namespace=jupyterhub logs deployment/hub | grep -i admin
# Get admin password
kubectl -n jupyterhub get secret jupyterhub-admin-credentials \
-o jsonpath='{.data.admin-password}' | base64 -d && echo
Troubleshooting¶
Issue: “Module ‘nativeauthenticator’ not found”¶
Cause: Hub image doesn’t have jupyterhub-nativeauthenticator installed.
Solution:
# Rebuild Hub image with updated Dockerfile
cd dockerfiles/Hub
./build.sh
Issue: Users can self-register¶
Cause: create_users is not set to False.
Solution: Verify in jupyterhub_config.py:
class CustomFirstUseAuthenticator(FirstUseAuthenticator):
create_users = False
Issue: API token authentication fails¶
Symptoms:
❌ Connection failed with status 403
Solutions:
Verify secret exists:
kubectl -n jupyterhub get secret jupyterhub-admin-credentials
Check token is loaded:
kubectl -n jupyterhub logs deployment/hub | grep "API token"
Regenerate credentials:
kubectl -n jupyterhub delete secret jupyterhub-admin-credentials helm upgrade jupyterhub ./jupyterhub -n jupyterhub -f values-local.yaml
Issue: Admin not created on install¶
Symptoms: No admin user after helm install.
Solutions:
Verify config:
custom: adminUser: enabled: true # Must be true
Check hub logs:
kubectl -n jupyterhub logs deployment/hub | grep -i "admin"
Restart hub:
kubectl -n jupyterhub rollout restart deployment/hub
Issue: Wrong resource permissions¶
Symptoms: User sees courses they shouldn’t access, or missing expected courses.
Solution: Check resource mapping in jupyterhub_config.py:
# Verify user's group assignment in CustomFirstUseAuthenticator
async def authenticate(self, handler, data):
result = await super().authenticate(handler, data)
if result:
username = result.get("name", "").strip().upper()
if "AUP" in username:
result["group"] = "AUP"
# ...
# Verify group has correct resources
TEAM_RESOURCE_MAPPING = {
"AUP": ["Course-CV","Course-DL","Course-LLM"],
# ...
}
Issue: Users created but can’t login¶
Cause: Native users must set password on first login.
Solution:
User should go to login page
Enter username created by admin
Enter desired password
Password is saved for future logins
Alternative: Set passwords via script:
python scripts/manage_users.py set-passwords users.csv --generate
Issue: Batch script fails to connect¶
Symptoms:
❌ Connection error: Connection refused
Solutions:
Verify JupyterHub URL:
# For local dev export JUPYTERHUB_URL="http://localhost:30890" # For production export JUPYTERHUB_URL="https://your-domain.com"
Check if hub is accessible:
curl $JUPYTERHUB_URL/hub/api/
Verify namespace and port forwarding (if using kubectl):
kubectl --namespace=jupyterhub port-forward service/hub 8081:8081 export JUPYTERHUB_URL="http://localhost:8081"
Security Best Practices¶
Protect API tokens:
Tokens are stored in Kubernetes secrets
Never commit tokens to git
Rotate tokens by deleting and recreating the secret
User password policy:
Encourage strong passwords
Consider adding password complexity requirements
Admin accounts:
Limit number of admin users
Use
set-admincommand to manage (auditable)Review admin list regularly
GitHub OAuth:
Keep GitHub organization membership updated
Review team permissions regularly
Use GitHub organization SSO if available
Additional Resources¶
User Management Guide - Batch user operations and scripts