Skip to main content

Descope Authentication Setup

Complete guide to integrating and managing Descope authentication with Traefik.

Overview

Descope is an enterprise authentication platform providing:
  • Single Sign-On (SSO)
  • Magic links
  • Passkeys
  • Multi-factor authentication (MFA)
  • OAuth/OpenID Connect
  • User management

Architecture

Authentication Flow

User Request

    ├─→ Traefik (reverse proxy)
    │   - Checks route
    │   - Applies descope-verify middleware

    ├─→ Descope Auth Service
    │   - Verifies session
    │   - Returns 200 (authorized) or 307 (redirect)

    ├─→ Descope Verify Endpoint
    │   - Checks for valid session
    │   - If no session: redirect to login
    │   - If valid: allow request

    └─→ Backend Service
        - Process authenticated request
        - Return response

Session Management

Login Flow:
1. User visits protected service
2. Descope service redirects to login page
3. User authenticates (method varies)
4. Descope creates session
5. Sets cookie for .starfleet-command.dev
6. Redirects back to original service
7. Traefik verifies session → allows access

Logout Flow:
1. User clicks logout
2. Descope service destroys session
3. Clears authentication cookie
4. User redirected to login page

Setup Instructions

Step 1: Create Descope Account

  1. Visit https://descope.com
  2. Sign up for a free account
  3. Create a new project
  4. Copy your Project ID

Step 2: Configure Project ID

Update .env file:
DESCOPE_PROJECT_ID=your-project-id-here
Or set in docker-compose.yml:
services:
  descope-auth:
    environment:
      - DESCOPE_PROJECT_ID=your-project-id

Step 3: Set Session Secret

Generate a random secret:
# Generate 32-byte random secret
openssl rand -base64 32
Set in environment:
SESSION_SECRET=your-generated-secret-here

Step 4: Configure Descope Redirect

In Descope console:
  1. Go to Project Settings
  2. Set redirect URI to: https://auth.starfleet-command.dev/auth/callback
  3. Save settings

Step 5: Deploy Service

# SSH to VPS
ssh root@your-vps-ip

# Navigate to project
cd /opt/ProjectSpecter

# Deploy Descope auth
docker compose up -d descope-auth

# Verify running
docker ps | grep descope-auth

# Check logs
docker logs descope-auth

Configuration Files

Docker Compose

services:
  descope-auth:
    image: node:18-alpine
    container_name: descope-auth
    restart: unless-stopped
    working_dir: /app
    command: sh -c "npm install && node server.js"
    networks:
      - traefik-proxy
    volumes:
      - ./server.js:/app/server.js:ro
      - ./package.json:/app/package.json:ro
      - ./public:/app/public:ro
    environment:
      - DESCOPE_PROJECT_ID=${DESCOPE_PROJECT_ID}
      - SESSION_SECRET=${SESSION_SECRET}
      - NODE_ENV=production
    labels:
      - "traefik.enable=true"
      
      # Auth login page
      - "traefik.http.routers.descope-auth.rule=Host(`auth.starfleet-command.dev`)"
      - "traefik.http.routers.descope-auth.entrypoints=websecure"
      - "traefik.http.routers.descope-auth.tls.certresolver=cloudflare"
      
      # Service port
      - "traefik.http.services.descope-auth.loadbalancer.server.port=3000"
      
      # Forward Auth Middleware definition
      - "traefik.http.middlewares.descope-verify.forwardauth.address=http://descope-auth:3000/verify"
      - "traefik.http.middlewares.descope-verify.forwardauth.authResponseHeaders=X-Forwarded-User,X-Auth-User"
      - "traefik.http.middlewares.descope-verify.forwardauth.trustForwardHeader=true"

networks:
  traefik-proxy:
    external: true

Environment Variables

# Descope Configuration
DESCOPE_PROJECT_ID=P39rEbfc3CqsjuYOV6rq3pu29x7r
SESSION_SECRET=generated-random-secret
NODE_ENV=production

Using Descope Middleware

Adding Authentication to Services

To protect a service with Descope authentication:
services:
  myapp:
    image: myapp:latest
    networks:
      - traefik-proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.myapp.rule=Host(`myapp.starfleet-command.dev`)"
      - "traefik.http.routers.myapp.entrypoints=websecure"
      - "traefik.http.routers.myapp.tls.certresolver=cloudflare"
      
      # Add Descope authentication
      - "traefik.http.routers.myapp.middlewares=descope-verify@docker"
      
      - "traefik.http.services.myapp.loadbalancer.server.port=8080"

Service Without Authentication

To skip authentication for certain services:
services:
  public-api:
    image: public-api:latest
    networks:
      - traefik-proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.public.rule=Host(`api.starfleet-command.dev`) && Path(`/public`)"
      - "traefik.http.routers.public.entrypoints=websecure"
      - "traefik.http.routers.public.tls.certresolver=cloudflare"
      # NO middleware = no authentication required
      - "traefik.http.services.public.loadbalancer.server.port=8080"

Authentication Methods

Users receive an email with a magic link to log in:
1. User enters email
2. Receives email with link
3. Clicks link to authenticate
4. Session created

Passkeys

Users can register and use passkeys (biometric/hardware):
1. User registers passkey
2. Stored securely
3. Uses passkey to login
4. Biometric/hardware authentication

Multi-Factor Authentication

Add additional security layer:
1. User enters password
2. Receives MFA code (SMS/Email/App)
3. Enters MFA code
4. Session created

Session Management

Sessions stored in HTTP-only secure cookies:
// Domain: .starfleet-command.dev
// Path: /
// HttpOnly: true (not accessible via JavaScript)
// Secure: true (HTTPS only)
// SameSite: Lax (prevent CSRF)
// MaxAge: 24 hours

Cross-Domain Sessions

The authentication cookie works across all subdomains:
✓ traefik.starfleet-command.dev
✓ auth.starfleet-command.dev
✓ api.starfleet-command.dev
✓ any-service.starfleet-command.dev

Session Validation

Each request is validated:
1. Browser sends request with session cookie
2. Traefik applies descope-verify middleware
3. Middleware calls Descope verify endpoint
4. Descope checks session validity
5. Returns 200 (valid) or 307 (redirect)
6. Traefik allows/denies access

Troubleshooting

Service Not Starting

# Check logs
docker logs descope-auth

# Verify environment variables
docker inspect descope-auth | grep -A 10 "Env"

# Check network
docker network inspect traefik-proxy

Login Not Working

Symptoms: Stuck on login page after submitting credentials Causes:
  • PROJECT_ID incorrect
  • Redirect URI not configured in Descope console
  • SESSION_SECRET not set
Fix:
  1. Verify PROJECT_ID in Descope console
  2. Check redirect URI: https://auth.starfleet-command.dev/auth/callback
  3. Generate new SESSION_SECRET: openssl rand -base64 32
  4. Restart service: docker compose restart descope-auth

Redirect Loop

Symptoms: Continuously redirected to login page Causes:
  • Middleware configuration error
  • Session not being created properly
  • Cookie domain incorrect
Fix:
# Check service logs
docker logs descope-auth | grep -i error

# Verify cookie configuration
# Should show: domain: '.starfleet-command.dev'

# Restart all services
docker compose down
docker compose up -d

Can’t Access Protected Service

Symptoms: 403 Forbidden or 401 Unauthorized Causes:
  • Not authenticated
  • Session expired
  • Invalid middleware configuration
Fix:
# 1. Log out and log back in
# 2. Clear browser cookies
# 3. Check middleware is applied to route
# 4. Verify service is on traefik-proxy network

User Management

In Descope Console

  1. Go to Users section
  2. View all users
  3. Manage user permissions
  4. Reset user sessions
  5. Export user data

Programmatically

Descope provides SDKs for:
  • JavaScript/TypeScript
  • Python
  • Go
  • Node.js
  • Java

Custom Login Page

To customize the login page, modify public/index.html:
<!DOCTYPE html>
<html>
<head>
    <title>Login - ProjectSpecter</title>
    <script async defer src="https://cdn.descope.com/latest/descope.js"></script>
</head>
<body>
    <div id="descope-container"></div>
    
    <script>
        Descope.useFlow({
            projectId: 'YOUR_PROJECT_ID',
            flowId: 'YOUR_FLOW_ID'
        });
    </script>
</body>
</html>

Best Practices

  1. Always use HTTPS
    • Sessions only work over HTTPS
    • Set secure: true on cookies
  2. Secure Session Secret
    • Generate strong random secret
    • Never commit to Git
    • Rotate periodically
  3. Monitor Sessions
    • Review login logs
    • Monitor for failed attempts
    • Alert on suspicious activity
  4. Test Authentication
    • Test login flow
    • Test logout flow
    • Test session expiration
    • Test on multiple devices/browsers
  5. User Communication
    • Clear login instructions
    • Help for forgotten passwords
    • Support contact information

API Endpoints

Verify Endpoint

Used by Traefik middleware:
GET /verify
Headers:
  X-Forwarded-URI: /original-path
  X-Forwarded-Proto: https
  X-Forwarded-Host: example.com

Response:
  200: Session valid
  307: Redirect to login

Callback Endpoint

Used after user authenticates:
POST /auth/callback
Body:
  {
    "sessionToken": "token...",
    "user": {
      "loginIds": ["[email protected]"]
    }
  }

Response:
  { "success": true }

Logout Endpoint

Used to end session:
POST /logout

Response:
  { "success": true }

Next: Troubleshooting Guide