Files
reflector/docs/docs/installation/auth-setup.md
Igor Monadical 407c15299f docs: docs website + installation (#778)
* feat: WIP doc (vibe started and iterated)

* install from scratch docs

* caddyfile.example

* gitignore

* authentik script

* authentik script

* authentik script

* llm doc

* authentik ongoing

* more daily setup logs

* doc website

* gpu self hosted setup guide (no-mistakes)

* doc review round

* doc review round

* doc review round

* update doc site sidebars

* feat(docs): add mermaid diagram support

* docs polishing

* live pipeline doc

* move pipeline dev docs to dev docs location

* doc pr review iteration

* dockerfile healthcheck

* docs/pr-comments

* remove jwt comment

* llm suggestion

* pr comments

* pr comments

* document auto migrations

* cleanup docs

---------

Co-authored-by: Mathieu Virbel <mat@meltingrocks.com>
Co-authored-by: Igor Loskutov <igor.loskutoff@gmail.com>
2026-01-06 17:25:02 -05:00

8.4 KiB

sidebar_position, title
sidebar_position title
5 Authentication Setup

Authentication Setup

This page covers authentication setup in detail. For the complete deployment guide, see Deployment Guide.

Reflector uses Authentik for OAuth/OIDC authentication. This guide walks you through setting up Authentik and connecting it to Reflector.

The guide simplistically sets Authentic on the same server as Reflector. You can use your own Authentic instance instead.

Overview

Reflector's authentication flow:

  1. User clicks "Sign In" on frontend
  2. Frontend redirects to Authentik login page
  3. User authenticates with Authentik
  4. Authentik redirects back with OAuth tokens
  5. Frontend stores tokens, backends verify JWT signature

Option 1: Self-Hosted Authentik (Same Server)

This setup runs Authentik on the same server as Reflector, with Caddy proxying to both.

Deploy Authentik

# Create directory for Authentik
mkdir -p ~/authentik && cd ~/authentik

# Download docker-compose file
curl -O https://goauthentik.io/docker-compose.yml

# Generate secrets and bootstrap credentials
cat > .env << 'EOF'
PG_PASS=$(openssl rand -base64 36 | tr -d '\n')
AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60 | tr -d '\n')
# Privacy-focused choice for self-hosted deployments
AUTHENTIK_ERROR_REPORTING__ENABLED=false
AUTHENTIK_BOOTSTRAP_PASSWORD=YourSecurePassword123
AUTHENTIK_BOOTSTRAP_EMAIL=admin@example.com
EOF

# Start Authentik
sudo docker compose up -d

Authentik takes ~2 minutes to run migrations and apply blueprints on first start.

Connect Authentik to Reflector's Network

If Authentik runs in a separate Docker Compose project, connect it to Reflector's network so Caddy can proxy to it:

# Wait for Authentik to be healthy
# Connect Authentik server to Reflector's network
sudo docker network connect reflector_default authentik-server-1

Important: This step must be repeated if you restart Authentik with docker compose down. Add it to your deployment scripts or use docker compose up -d (which preserves containers) instead of down/up.

Add Authentik to Caddy

Uncomment the Authentik section in your Caddyfile and set your domain:

nano Caddyfile

Uncomment and edit:

{$AUTHENTIK_DOMAIN:authentik.example.com} {
    reverse_proxy authentik-server-1:9000
}

Reload Caddy:

docker compose -f docker-compose.prod.yml exec caddy caddy reload --config /etc/caddy/Caddyfile

Create OAuth2 Provider in Authentik

Option A: Automated Setup (Recommended)

Location: Reflector server

Run the setup script from the Reflector repository:

ssh user@your-server-ip
cd ~/reflector
./scripts/setup-authentik-oauth.sh https://authentik.example.com YourSecurePassword123 https://app.example.com

Important: The script must be run from the ~/reflector directory on your server, as it creates files using relative paths.

The script will output the configuration values to add to your .env files. Skip to "Update docker-compose.prod.yml".

Option B: Manual Setup

  1. Login to Authentik Admin at https://authentik.example.com/

    • Username: akadmin
    • Password: The AUTHENTIK_BOOTSTRAP_PASSWORD you set in .env
  2. Create OAuth2 Provider:

    • Go to Applications > Providers > Create
    • Select OAuth2/OpenID Provider
    • Configure:
      • Name: Reflector
      • Authorization flow: default-provider-authorization-implicit-consent
      • Client type: Confidential
      • Client ID: Note this value (auto-generated)
      • Client Secret: Note this value (auto-generated)
      • Redirect URIs: Add entry with:
        https://app.example.com/api/auth/callback/authentik
        
    • Scroll down to Advanced protocol settings
    • In Scopes, add these three mappings:
      • authentik default OAuth Mapping: OpenID 'email'
      • authentik default OAuth Mapping: OpenID 'openid'
      • authentik default OAuth Mapping: OpenID 'profile'
    • Click Finish
  3. Create Application:

    • Go to Applications > Applications > Create
    • Configure:
      • Name: Reflector
      • Slug: reflector (auto-filled)
      • Provider: Select the Reflector provider you just created
    • Click Create

Get Public Key for JWT Verification

Location: Reflector server

Extract the public key from Authentik's JWKS endpoint:

mkdir -p ~/reflector/server/reflector/auth/jwt/keys
curl -s https://authentik.example.com/application/o/reflector/jwks/ | \
  jq -r '.keys[0].x5c[0]' | base64 -d | openssl x509 -pubkey -noout \
  > ~/reflector/server/reflector/auth/jwt/keys/authentik_public.pem

Update docker-compose.prod.yml

Location: Reflector server

Note: This step is already done in the current docker-compose.prod.yml. Verify the volume mounts exist:

server:
  image: monadicalsas/reflector-backend:latest
  # ... other config ...
  volumes:
    - server_data:/app/data
    - ./server/reflector/auth/jwt/keys:/app/reflector/auth/jwt/keys:ro

worker:
  image: monadicalsas/reflector-backend:latest
  # ... other config ...
  volumes:
    - server_data:/app/data
    - ./server/reflector/auth/jwt/keys:/app/reflector/auth/jwt/keys:ro

Configure Reflector Backend

Location: Reflector server

Update server/.env:

# Authentication
AUTH_BACKEND=jwt
AUTH_JWT_PUBLIC_KEY=authentik_public.pem
AUTH_JWT_AUDIENCE=<your-client-id>
CORS_ALLOW_CREDENTIALS=true

Replace <your-client-id> with the Client ID from previous steps.

Configure Reflector Frontend

Location: Reflector server

Update www/.env:

# Authentication
FEATURE_REQUIRE_LOGIN=true

# Authentik OAuth
AUTHENTIK_ISSUER=https://authentik.example.com/application/o/reflector
AUTHENTIK_REFRESH_TOKEN_URL=https://authentik.example.com/application/o/token/
AUTHENTIK_CLIENT_ID=<your-client-id>
AUTHENTIK_CLIENT_SECRET=<your-client-secret>

# NextAuth
NEXTAUTH_SECRET=<generate-with-openssl-rand-hex-32>

Restart Services

Location: Reflector server

cd ~/reflector
sudo docker compose -f docker-compose.prod.yml up -d --force-recreate server worker web

Verify Authentication

  1. Visit https://app.example.com
  2. Click "Log in" or navigate to /api/auth/signin
  3. Click "Sign in with Authentik"
  4. Login with your Authentik credentials
  5. You should be redirected back and see "Log out" in the header

Option 2: Disable Authentication

For testing or internal deployments where authentication isn't needed:

Backend server/.env:

AUTH_BACKEND=none

Frontend www/.env:

FEATURE_REQUIRE_LOGIN=false

Note: The pre-built Docker images have FEATURE_REQUIRE_LOGIN=true baked in. To disable auth, you'll need to rebuild the frontend image with the env var set at build time, or set up Authentik.

Troubleshooting

"Invalid redirect URI" error

  • Verify the redirect URI in Authentik matches exactly:
    https://app.example.com/api/auth/callback/authentik
    
  • Check for trailing slashes - they must match exactly

"Invalid audience" JWT error

  • Ensure AUTH_JWT_AUDIENCE in server/.env matches the Client ID from Authentik
  • The audience value is the OAuth Client ID, not the issuer URL

"JWT verification failed" error

  • Verify the public key file is mounted in the container
  • Check AUTH_JWT_PUBLIC_KEY points to the correct filename
  • Ensure the key was extracted from the correct provider's JWKS endpoint

Caddy returns 503 for Authentik

  • Verify Authentik container is connected to Reflector's network:
    sudo docker network connect reflector_default authentik-server-1
    
  • Check Authentik is healthy: cd ~/authentik && sudo docker compose ps

Users can't access protected pages

  • Verify FEATURE_REQUIRE_LOGIN=true in frontend
  • Check AUTH_BACKEND=jwt in backend
  • Verify CORS settings allow credentials

Token refresh errors

  • Ensure Redis is running (frontend uses Redis for token caching)
  • Verify KV_URL is set correctly in frontend env
  • Check AUTHENTIK_REFRESH_TOKEN_URL is correct

API Key Authentication

For programmatic access (scripts, integrations), users can generate API keys:

  1. Login to Reflector
  2. Go to Settings > API Keys
  3. Click "Generate New Key"
  4. Use the key in requests:
    curl -H "X-API-Key: your-api-key" https://api.example.com/v1/transcripts
    

API keys are stored hashed and can be revoked at any time.