Skip to content

Auth0 Authentication

Auth0 provides flexible identity platform services for BoilStream. This guide covers integrating with Auth0 for JWT authentication, custom claims, and universal login.

Overview

Auth0 integration provides:

  • Universal Login: Customizable login flows and social connections
  • Multi-provider Support: Integrate with Google, Microsoft, GitHub, and more
  • Custom Claims: Flexible namespaced claims for groups and roles
  • Rules and Actions: Custom authentication logic and user enrichment
  • High Availability: Auth0-managed service with enterprise SLA

Prerequisites

  • Auth0 account (free tier available)
  • Auth0 tenant configured
  • API resource registered in Auth0
  • Users and roles configured in Auth0

Auth0 Setup

1. Create API Resource

Register BoilStream as an API in Auth0:

bash
# Create API resource
auth0 apis create \
    --name "BoilStream Data Platform" \
    --identifier "https://api.boilstream.company.com" \
    --scopes "read:data,write:data,admin:system"
json
{
  "name": "BoilStream Data Platform",
  "identifier": "https://api.boilstream.company.com",
  "scopes": [
    {
      "value": "read:data",
      "description": "Read access to data streams"
    },
    {
      "value": "write:data", 
      "description": "Write access to data streams"
    },
    {
      "value": "admin:system",
      "description": "Administrative access to system"
    }
  ],
  "signing_alg": "RS256",
  "allow_offline_access": false
}

2. Configure Application

Create or configure an application in Auth0:

bash
# Create application
auth0 apps create \
    --name "BoilStream Client" \
    --type "spa" \
    --callbacks "https://boilstream.company.com/callback" \
    --allowed-origins "https://boilstream.company.com"
json
{
  "name": "BoilStream Client",
  "app_type": "spa",
  "callbacks": [
    "https://boilstream.company.com/callback"
  ],
  "allowed_origins": [
    "https://boilstream.company.com"
  ],
  "jwt_configuration": {
    "alg": "RS256"
  }
}

3. Setup Custom Claims (Optional)

For group and role mapping, configure custom claims using Auth0 Actions:

javascript
// Auth0 Action: Add Custom Claims
exports.onExecutePostLogin = async (event, api) => {
  const namespace = 'https://boilstream.company.com/';
  
  // Add user groups (from app_metadata or external source)
  if (event.user.app_metadata && event.user.app_metadata.groups) {
    api.accessToken.setCustomClaim(`${namespace}groups`, event.user.app_metadata.groups);
  }
  
  // Add user roles
  if (event.authorization && event.authorization.roles) {
    api.accessToken.setCustomClaim(`${namespace}roles`, event.authorization.roles);
  }
};

4. Configure User Roles

Set up roles in Auth0 Dashboard or via Management API:

bash
# Create roles via Management API
curl -X POST https://YOUR_DOMAIN.auth0.com/api/v2/roles \
  -H "Authorization: Bearer YOUR_MGMT_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "DataAdmin",
    "description": "Full access to data operations"
  }'

curl -X POST https://YOUR_DOMAIN.auth0.com/api/v2/roles \
  -H "Authorization: Bearer YOUR_MGMT_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "DataReader", 
    "description": "Read-only access to data"
  }'

BoilStream Configuration

Environment Variables

Configure BoilStream to use Auth0:

bash
# Required Auth0 settings
export AUTH_PROVIDERS="auth0"
export AUTH0_TENANT="your-tenant"  # e.g., "company" for company.auth0.com
export AUTH0_AUDIENCE="https://api.boilstream.company.com"

# Optional: Custom namespaces for claims
export AUTH0_GROUPS_NAMESPACE="https://boilstream.company.com/groups"
export AUTH0_ROLES_NAMESPACE="https://boilstream.company.com/roles"

# Authorization rules (optional)
export ADMIN_GROUPS="DataAdmin,SystemAdmin"
export READ_ONLY_GROUPS="DataReader,Analyst"
export WRITE_GROUPS="DataWriter,DataEngineer"

Docker Compose Example

yaml
version: '3.8'
services:
  boilstream:
    image: boilstream/ingestion-agent
    environment:
      # Auth0 Configuration
      AUTH_PROVIDERS: "auth0"
      AUTH0_TENANT: "company"
      AUTH0_AUDIENCE: "https://api.boilstream.company.com"
      AUTH0_GROUPS_NAMESPACE: "https://boilstream.company.com/groups"
      AUTH0_ROLES_NAMESPACE: "https://boilstream.company.com/roles"
      
      # Authorization
      ADMIN_GROUPS: "DataAdmin,SystemAdmin"
      READ_ONLY_GROUPS: "DataReader"
      WRITE_GROUPS: "DataWriter,DataEngineer"
      
      # Other configuration...
      S3_BUCKET: "my-data-bucket"
    ports:
      - "50051:50051"

Client Integration

JavaScript/Node.js

javascript
import { createAuth0Client } from '@auth0/auth0-spa-js';

// Initialize Auth0 client
const auth0 = await createAuth0Client({
  domain: 'company.auth0.com',
  clientId: 'YOUR_CLIENT_ID',
  authorizationParams: {
    redirect_uri: window.location.origin,
    audience: 'https://api.boilstream.company.com',
    scope: 'read:data write:data'
  }
});

// Get access token
const token = await auth0.getTokenSilently();

// Use with BoilStream
const headers = {
  'Authorization': `Bearer ${token}`
};

Python

python
import requests
from authlib.integrations.requests_client import OAuth2Session

# Auth0 configuration
AUTH0_DOMAIN = 'company.auth0.com'
CLIENT_ID = 'YOUR_CLIENT_ID'
CLIENT_SECRET = 'YOUR_CLIENT_SECRET'
AUDIENCE = 'https://api.boilstream.company.com'

# Get access token
client = OAuth2Session(CLIENT_ID, CLIENT_SECRET)
token = client.fetch_token(
    f'https://{AUTH0_DOMAIN}/oauth/token',
    audience=AUDIENCE,
    grant_type='client_credentials'
)

# Use with BoilStream
headers = {
    'Authorization': f"Bearer {token['access_token']}"
}

DuckDB with Authentication

sql
-- Set up authentication headers
SET VARIABLE auth_header = 'Bearer YOUR_JWT_TOKEN_HERE';

-- Connect with authentication
ATTACH 'boilstream' (
    TYPE AIRPORT, 
    location 'grpc+tls://localhost:50051/',
    headers (Authorization = getvariable('auth_header'))
);

-- Use authenticated connection
CREATE TABLE boilstream.s3.events (
    timestamp TIMESTAMPTZ,
    user_id VARCHAR,
    event_type VARCHAR,
    properties JSON
);

Claims Mapping

Standard Claims

Auth0 tokens include standard JWT claims:

  • sub: User ID (e.g., auth0|6123456789abcdef)
  • iss: Issuer (e.g., https://company.auth0.com/)
  • aud: Audience (API identifier)
  • exp: Expiration timestamp
  • iat: Issued at timestamp
  • scope: OAuth 2.0 scopes (space-separated)

Custom Claims

Configure custom namespaced claims for authorization:

json
{
  "sub": "auth0|6123456789abcdef",
  "iss": "https://company.auth0.com/",
  "aud": "https://api.boilstream.company.com",
  "scope": "read:data write:data",
  "https://boilstream.company.com/groups": [
    "data-engineers",
    "platform-users"
  ],
  "https://boilstream.company.com/roles": [
    "DataAdmin",
    "PlatformUser"
  ]
}

Security Considerations

Token Validation

BoilStream validates Auth0 tokens by:

  1. Signature Verification: RSA signature validation using Auth0 JWKS
  2. Issuer Validation: Ensures token comes from configured Auth0 tenant
  3. Audience Validation: Verifies token intended for BoilStream API
  4. Expiration Check: Ensures token hasn't expired

Best Practices

  • Use HTTPS: Always use TLS for token transmission
  • Short-lived Tokens: Configure reasonable token expiration times
  • Principle of Least Privilege: Grant minimal required scopes and roles
  • Regular Rotation: Rotate client secrets regularly
  • Monitor Access: Use Auth0 logs to monitor authentication events

JWKS Caching

BoilStream caches Auth0 JWKS keys for performance:

  • Cache Duration: 1 hour (3600 seconds)
  • Max Keys: 100 keys cached
  • Automatic Refresh: Keys refreshed on cache miss

Testing

Test JWT Generation

For testing, you can use Auth0's test tokens or create your own:

bash
# Get test token using Auth0 CLI
auth0 test token \
    --audience "https://api.boilstream.company.com" \
    --scopes "read:data write:data"

# Or use curl with client credentials
curl -X POST https://company.auth0.com/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET", 
    "audience": "https://api.boilstream.company.com",
    "grant_type": "client_credentials"
  }'

Integration Testing

bash
# Test authentication endpoint
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
     https://localhost:50051/flight/health

# Test with invalid token (should return 401)
curl -H "Authorization: Bearer invalid_token" \
     https://localhost:50051/flight/health

Troubleshooting

Common Issues

  1. "Invalid audience"

    • Verify AUTH0_AUDIENCE matches your API identifier
    • Check token aud claim contains correct audience
  2. "Invalid issuer"

    • Verify AUTH0_TENANT matches your Auth0 domain
    • Check token iss claim format: https://YOUR_TENANT.auth0.com/
  3. "Key not found"

    • Auth0 JWKS endpoint unreachable
    • Key rotation occurred, wait for cache refresh
  4. "Groups not extracted"

    • Verify custom claims Action is deployed
    • Check namespace configuration matches environment variables

Debug Commands

bash
# Verify Auth0 configuration
echo "Tenant: $AUTH0_TENANT"
echo "Audience: $AUTH0_AUDIENCE"
echo "Groups Namespace: $AUTH0_GROUPS_NAMESPACE"

# Test JWKS endpoint
curl https://$AUTH0_TENANT.auth0.com/.well-known/jwks.json

# Decode JWT token (base64)
echo "YOUR_JWT_TOKEN" | cut -d'.' -f2 | base64 -d | jq

Log Analysis

Look for these log messages:

INFO  boilstream::auth::manager: Added Auth0 authentication provider
DEBUG boilstream::auth::auth0: Fetching JWKS from Auth0: https://company.auth0.com/.well-known/jwks.json
DEBUG boilstream::auth::auth0: Successfully validated Auth0 token for user: auth0|6123456789abcdef

Migration from Other Providers

From Cognito

Auth0 can complement or replace Cognito:

bash
# Multi-provider setup
export AUTH_PROVIDERS="cognito,auth0"

# Auth0-only setup
export AUTH_PROVIDERS="auth0"
export AUTH0_TENANT="company"
export AUTH0_AUDIENCE="https://api.boilstream.company.com"

From Azure AD

Similar migration process:

bash
# Migrate from Azure AD
export AUTH_PROVIDERS="auth0"  # Replace "azure-ad"
export AUTH0_TENANT="company"
export AUTH0_AUDIENCE="https://api.boilstream.company.com"

Advanced Configuration

Multiple Audiences

Auth0 supports multiple audiences in JWT tokens:

bash
# BoilStream validates against this audience
export AUTH0_AUDIENCE="https://api.boilstream.company.com"

# Auth0 can issue tokens for multiple APIs
# Token will contain array: ["https://api.boilstream.company.com", "https://other-api.com"]

Custom Domains

Use Auth0 custom domains for branded authentication:

bash
# Custom domain setup
export AUTH0_TENANT="auth.company.com"  # Instead of "company.auth0.com"

This requires Auth0 custom domain configuration and SSL certificate setup.