Auth0 Setup Guide
Complete guide for configuring Auth0 authentication with the NoETL Gateway.
- UI Config:
tests/fixtures/gateway_ui/config.js - Auth Playbooks:
tests/fixtures/playbooks/api_integration/auth0/
Overview
The NoETL Gateway uses Auth0 for user authentication via the OAuth2/OIDC implicit flow, with NATS K/V providing fast session caching:
Authentication Flow
- User clicks "Login with Auth0" on the gateway UI
- Browser redirects to Auth0 Universal Login
- User authenticates (email/password, social, etc.)
- Auth0 redirects back with an ID token
- Gateway calls
auth0_loginplaybook via NoETL - Playbook validates token, creates user/session in PostgreSQL
- Playbook caches session in NATS K/V (
sessionsbucket) - User receives a session token for subsequent API calls
Session Validation (Subsequent Requests)
Gateway Request → Check NATS K/V → Cache Hit? → Use cached session (sub-ms)
→ Cache Miss? → Call playbook → Refresh cache
- Gateway checks NATS K/V for cached session (sub-millisecond lookup)
- Cache hit: Use cached session data immediately
- Cache miss: Call
auth0_validate_sessionplaybook - Playbook validates from PostgreSQL (source of truth) and refreshes cache
Benefits:
- Sub-millisecond session lookups from NATS K/V
- Reduced load on NoETL server and PostgreSQL
- PostgreSQL remains source of truth
- Automatic cache refresh on validation
Auth0 Account Setup
Create Auth0 Account
- Go to auth0.com
- Sign up for a free account
- Create a new tenant (e.g.,
mycompany-dev)
Create Application
- Navigate to Applications > Applications
- Click + Create Application
- Enter name:
NoETL Gateway - Select Single Page Application
- Click Create
Configure Application Settings
In your application's Settings tab:
Basic Information
- Name: NoETL Gateway
- Application Type: Single Page Application
Application URIs
Allowed Callback URLs (comma-separated):
http://localhost:8090/login.html,
https://gateway.yourdomain.com/login.html
Allowed Logout URLs:
http://localhost:8090/login.html,
https://gateway.yourdomain.com/login.html
Allowed Web Origins:
http://localhost:8090,
https://gateway.yourdomain.com
ID Token Configuration
Scroll to ID Token section:
- ID Token Expiration: 36000 (10 hours)
Advanced Settings
Click Show Advanced Settings:
Grant Types tab:
- Implicit
- Authorization Code
Endpoints tab - note these values:
- OAuth Authorization URL
- OAuth Token URL
- OpenID Configuration
Save Credentials
Note these values from your application settings:
- Domain:
your-tenant.us.auth0.com - Client ID:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Important: Never commit the Client Secret. For SPAs using implicit flow, you don't need the Client Secret.
Gateway UI Configuration
config.js
Update tests/fixtures/gateway_ui/config.js:
// Auth0 Configuration
const isLocalDev = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1';
const auth0Config = {
domain: 'your-tenant.us.auth0.com', // Your Auth0 domain
clientId: 'YOUR_CLIENT_ID', // Your Client ID
// Redirect back to login.html - use port 8090 for local dev
redirectUri: isLocalDev
? 'http://localhost:8090/login.html'
: window.location.origin + '/login.html'
};
login.html
The login flow is handled in tests/fixtures/gateway_ui/login.html:
// Auth0 Universal Login redirect
function loginWithAuth0() {
const auth0Domain = auth0Config.domain;
const clientId = auth0Config.clientId;
const redirectUri = auth0Config.redirectUri;
// Build Auth0 authorization URL
const authUrl = `https://${auth0Domain}/authorize?` +
`response_type=id_token token&` +
`client_id=${clientId}&` +
`redirect_uri=${encodeURIComponent(redirectUri)}&` +
`scope=openid profile email&` +
`nonce=${Math.random().toString(36).substring(7)}`;
// Redirect to Auth0
window.location.href = authUrl;
}
NoETL Playbook Configuration
Register the Auth0 Login Playbook
noetl register playbook -f tests/fixtures/playbooks/api_integration/auth0/auth0_login.yaml
Playbook Overview
The auth0_login.yaml playbook:
- Validates Auth0 Token: Fetches user info from Auth0
- Upserts User: Creates or updates user in the auth.users table
- Creates Session: Generates a session token with expiration
- Returns Result: Returns session token and user info
Required Database Schema
Ensure the auth schema exists:
CREATE SCHEMA IF NOT EXISTS auth;
CREATE TABLE IF NOT EXISTS auth.users (
user_id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
auth0_sub VARCHAR(255) UNIQUE,
display_name VARCHAR(255),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS auth.sessions (
session_id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES auth.users(user_id),
session_token VARCHAR(64) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
expires_at TIMESTAMP NOT NULL,
client_ip VARCHAR(45),
user_agent TEXT
);
Required Credentials
PostgreSQL Credential
Create a PostgreSQL credential for the auth schema:
# Create credential file
cat > tests/fixtures/credentials/pg_auth.json << 'EOF'
{
"name": "pg_auth",
"type": "postgres",
"data": {
"host": "postgres.postgres.svc.cluster.local",
"port": 5432,
"user": "your_user",
"password": "your_password",
"database": "your_database"
}
}
EOF
# Register credential
noetl register credential -f tests/fixtures/credentials/pg_auth.json
NATS Credential (for Session Caching)
Create a NATS credential for K/V session storage:
# Create credential file
cat > tests/fixtures/credentials/nats_credential.json << 'EOF'
{
"name": "nats_credential",
"type": "nats",
"description": "NATS JetStream credential for K/V Store session management",
"tags": ["nats", "jetstream", "kv", "sessions", "auth0"],
"data": {
"nats_url": "nats://nats.nats.svc.cluster.local:4222",
"nats_user": "noetl",
"nats_password": "noetl"
}
}
EOF
# Register credential
noetl register credential -f tests/fixtures/credentials/nats_credential.json
The auth0 playbooks use nats_credential to cache sessions in the NATS K/V sessions bucket for fast gateway lookups.
Auth0 Customization
Universal Login Branding
- Go to Branding > Universal Login
- Customize:
- Logo
- Colors
- Background
Social Connections
- Go to Authentication > Social
- Enable desired providers:
- GitHub
- Microsoft
- etc.
Custom Database Connection
For enterprise users with existing user databases:
- Go to Authentication > Database
- Create custom database connection
- Configure login/signup scripts
Security Best Practices
Token Handling
- Never log tokens: Ensure tokens aren't written to logs
- Use HTTPS: Always use HTTPS in production
- Token expiration: Set reasonable token expiration times
- Secure storage: Store session tokens in HttpOnly cookies when possible
Auth0 Security Settings
- Brute Force Protection: Enable in Security > Attack Protection
- Bot Detection: Enable in Security > Attack Protection
- Breached Password Detection: Enable in Security > Attack Protection
CORS Configuration
Ensure CORS is properly configured in the gateway:
# values.yaml
env:
corsAllowedOrigins: "https://your-app.com" # Only allow your domain
Testing Authentication
Local Testing
- Start the gateway (port-forwarded or local):
kubectl port-forward -n gateway svc/gateway 8091:80
- Start the UI server:
cd tests/fixtures/gateway_ui
python3 -m http.server 8090
-
Click "Login with Auth0"
-
Authenticate with your Auth0 credentials
-
Verify redirect back to login.html with session established
Debug Authentication
Check gateway logs:
kubectl logs -n gateway deployment/gateway -f | grep -i auth
Expected log sequence:
INFO Auth login request for domain: your-tenant.us.auth0.com
INFO Auth login execution_id: 123456789
INFO Auth login successful for user: [email protected]
Test API Directly
# Get an ID token from Auth0 (use browser dev tools after login)
TOKEN="eyJhbGciOiJSUzI1NiIs..."
# Call gateway auth endpoint
curl -X POST http://localhost:8091/api/auth/login \
-H "Content-Type: application/json" \
-d "{
\"auth0_token\": \"$TOKEN\",
\"auth0_domain\": \"your-tenant.us.auth0.com\"
}"
Expected response:
{
"status": "authenticated",
"session_token": "abc123...",
"user": {
"user_id": 1,
"email": "[email protected]",
"display_name": "[email protected]"
},
"expires_at": "2026-01-28T20:00:00Z",
"message": "Authentication successful"
}
Troubleshooting
"Callback URL mismatch"
Cause: Redirect URI doesn't match Auth0 settings
Solution:
- Check
redirectUriin config.js - Verify exact match in Auth0 Allowed Callback URLs
- Ensure protocol (http/https) matches
"Invalid state"
Cause: State parameter mismatch (usually from browser back button)
Solution: Clear browser cache and try again
"No output from login playbook"
Cause: Gateway can't parse playbook response
Solution:
- Check playbook is registered
- Verify credential exists and has correct permissions
- Check NoETL logs for playbook execution errors
"User not found in Auth0"
Cause: Auth0 token expired or invalid
Solution:
- Check token expiration
- Verify token is ID token (not access token)
- Try logging in again
CORS Errors
Cause: Origin not in allowed list
Solution:
- Add your origin to
corsAllowedOrigins - Redeploy gateway
- Check Cloudflare isn't caching preflight responses