Skip to content

Litmus Frontend Does Not Send Required OIDC Parameters When Starting Dex SSO Flow #5332

@periclesarch

Description

@periclesarch

🧪 LitmusChaos (ChaosCenter) + Authentik via Dex

💡 Goal: Integrate LitmusChaos with Authentik as an IdP using Dex as an OIDC broker, replicating the same working pattern already used by Argo CD.

⚙️ Environment Architecture

Main Components

flowchart TB
  %% EXTERNAL
  subgraph External
    direction TB
    User@{icon:"fa:user", form:"circle", label:"User"}
    F5@{icon:"fa:cloud", form:"circle", label:"F5 Load Balancer"}
    Authentik@{icon:"fa:lock", form:"circle", label:"Authentik IdP"}
  end

  %% KUBERNETES CLUSTER
  subgraph "Kubernetes Cluster"
    direction TB
    subgraph "Istio Service Mesh"
      direction TB
      VS@{icon:"fa:globe", form:"rounded", label:"VirtualService\nlitmus.example.com"}
      subgraph "Litmus Namespace"
        direction TB
        Frontend@{icon:"fa:desktop", form:"rect", label:"Litmus Frontend\n:9091"}
        AuthServer@{icon:"fa:key", form:"rect", label:"Auth Server\n:3000"}
        Dex@{icon:"fa:arrows-to-circle", form:"rect", label:"Dex\n:5556"}
      end
    end
  end

  %% FLUXO
  User -- HTTPS --> F5
  F5 -- Istio Gateway --> VS

  VS -- "/ (UI)" --> Frontend
  VS -- "/auth/dex/*" --> Dex
  VS -- "/auth/dex/callback" --> AuthServer

  Frontend -.->|SSO Button Click| Dex
  AuthServer -->|Validates Token| Dex
  Dex <--> Authentik

  %% ESTILOS
  classDef dexStyle fill:#f9f,stroke:#333,stroke-width:4px;
  classDef idpStyle fill:#bbf,stroke:#333,stroke-width:2px;
  classDef frontendStyle fill:#bfb,stroke:#333,stroke-width:2px;

  class Dex dexStyle;
  class Authentik idpStyle;
  class Frontend frontendStyle;
Loading

📦 Technology Stack
Component Version Port
Kubernetes 1.29 -
Istio - -
LitmusChaos 3.22.0 9091/3000
Dex 2.41.1 5556
Authentik - 443

📚 Two Operating Modes

The configuration has been organized into two distinct patterns:

1️⃣ Dedicated Dex Mode

ℹ️ Separate host: Dex has its own domain

sequenceDiagram
    participant U as User
    participant L as litmus.example.com
    participant D as dex.litmus.example.com
    participant A as Authentik
    
    U->>L: Clicks "Login with SSO"
    L->>D: Redirect to /auth
    D->>A: OIDC Authorization
    A->>U: Login Form
    U->>A: Credentials
    A->>D: Authorization Code
    D->>L: Callback with Code
    L->>U: Authenticated ✓

Loading

Configuration:

Dex Issuer: https://dex.litmus.example.com

Callback: https://litmus.example.com/auth/dex/callback

VirtualServices: Two separate ones (Litmus + Dex)

2️⃣ Embedded Dex Mode
:::warning

⚠️ Issue identified in this mode — Frontend does not initiate the OIDC flow correctly

sequenceDiagram
    participant U as User
    participant L as litmus.example.com
    participant D as litmus.example.com/auth/dex
    participant A as Authentik
    
    U->>L: Clicks "Login with SSO"
    L->>D: Redirect (same host)
    Note over L,D: :x: Frontend does not send<br/>client_id, redirect_uri, etc.
    D-->>L: Invalid client_id ("")

Loading

Configuration:

Dex Issuer: https://litmus.example.com/auth/dex

Callback: https://litmus.example.com/auth/dex/callback

VirtualService: Single resource routing all paths
:::

🔧 Detailed Implementation

1. Click to view full Dex configuration
apiVersion: apps/v1
kind: Deployment
metadata:
  name: litmus-dex
  namespace: litmus
spec:
  replicas: 1
  template:
    spec:
      serviceAccountName: dex-server-account
      initContainers:
      - name: wait-for-authentik
        image: curlimages/curl:latest
        command: ['/bin/sh', '-c']
        args:
          - |
            until curl -f https://authentik.example.com/application/o/httpslitmusexamplecom/.well-known/openid-configuration; do
              echo "Waiting for Authentik...";
              sleep 5;
            done
      containers:
      - name: dex
        image: ghcr.io/dexidp/dex:v2.41.1
        command: ["/usr/local/bin/dex"]
        args: ["serve", "/etc/dex/cfg/config.yaml"]
        ports:
        - containerPort: 5556
          name: http
        volumeMounts:
        - name: config
          mountPath: /etc/dex/cfg
        livenessProbe:
          tcpSocket:
            port: 5556
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          tcpSocket:
            port: 5556
          initialDelaySeconds: 20
          periodSeconds: 5
      volumes:
      - name: config
        configMap:
          name: litmus-dex-config

ConfigMap (litmus-dex-config)

apiVersion: v1
kind: ConfigMap
metadata:
  name: litmus-dex-config
  namespace: litmus
data:
  config.yaml: |
    # Embedded type
    issuer: https://litmus.example.com/auth/dex
    
    # Dedicated (alternative)
    # issuer: https://dex.litmus.example.com
    
    storage:
      type: memory
    
    web:
      http: 0.0.0.0:5556
    
    staticClients:
    - id: LitmusPortalAuthBackend
      redirectURIs:
        - https://litmus.example.com/auth/dex/callback
        - http://localhost:8080/auth/dex/callback
      name: 'Litmus Portal'
      secret: <your-secret>
    
    connectors:
    - type: oidc
      id: authentik
      name: Authentik
      config:
        issuer: https://authentik.example.com/application/o/httpslitmusexamplecom/
        clientID: <authentik-client-id>
        clientSecret: <authentik-client-secret>
        redirectURI: https://litmus.example.com/auth/dex/callback
        scopes:
          - openid
          - profile
          - email
          - groups
        claimMapping:
          email: email
          preferred_username: preferred_username
          groups: groups
2. Click to view full Auth Server Configuration

✅ Critical environment variables required to enable Dex

apiVersion: apps/v1
kind: Deployment
metadata:
  name: chaos-litmus-auth-server
spec:
  template:
    spec:
      containers:
      - name: auth-server
        env:
        # Habilitar Dex
        - name: DEX_ENABLED
          value: "true"
        
        # Embedded
        - name: OIDC_ISSUER
          value: "https://litmus.example.com/auth/dex"
        
        # Dedicated (alternative)
        # - name: OIDC_ISSUER
        #   value: "https://dex.litmus.example.com"
        
        # Callback (same for both methods)
        - name: DEX_OAUTH_CALLBACK_URL
          value: "https://litmus.example.com/auth/dex/callback"
        
        # Client Configuration
        - name: DEX_OAUTH_CLIENT_ID
          value: "LitmusPortalAuthBackend"
        - name: DEX_OAUTH_CLIENT_SECRET
          valueFrom:
            secretKeyRef:
              name: chaos-litmus-admin-secret
              key: OIDC_CLIENT_SECRET

3. Authentik Configuration

🔒OIDC Provider configured specifically for Dex/Litmus

Provider settings in Authentik:

Field Value
Name Litmus Dex Integration
Client Type Confidential
Redirect URIs https://litmus.example.com/auth/dex/callback
https://dex.litmus.example.com/callback (dedicated mode)
Scopes openid, email, profile, groups
Subject Mode Based on User’s Email

Claim Mappings:

email → User Email

preferred_username → User Username

groups → User Groups

4. Click to view Embedded Mode – Single VirtualService
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: litmus
  namespace: litmus
spec:
  hosts:
  - litmus.example.com
  gateways:
  - litmus-gateway
  http:
  # Temporary workaround for /auth/dex/login
  - match:
    - uri:
        exact: /auth/dex/login
    redirect:
      uri: /auth/dex/auth

  # Dex routes
  - match:
    - uri:
        prefix: /auth/dex/
    route:
    - destination:
        host: litmus-dex.litmus.svc.internal
        port:
          number: 5556

  # Litmus frontend
  - match:
    - uri:
        prefix: /
    route:
    - destination:
        host: chaos-litmus-frontend-service.litmus.svc.internal
        port:
          number: 9091

Click to view Dedicated Mode – Two VirtualServices
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: litmus
  namespace: litmus
spec:
  hosts:
  - litmus.example.com
  gateways:
  - litmus-gateway
  http:
  # Dex callback
  - match:
    - uri:
        prefix: /auth/dex/callback
    route:
    - destination:
        host: chaos-litmus-auth-server-service.litmus.internal.local
        port:
          number: 3000

  # Litmus frontend
  - match:
    - uri:
        prefix: /
    route:
    - destination:
        host: chaos-litmus-frontend-service.litmus.internal
        port:
          number: 9091

VirtualService for Dex:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: litmus-dex-vs
  namespace: litmus
spec:
  hosts:
  - dex.litmus.example.com
  gateways:
  - litmus-dex-gateway
  http:
  - match:
    - uri:
        prefix: /
    route:
    - destination:
        host: litmus-dex.litmus.internal
        port:
          number: 5556

🐛 Issues Found and Fixes

  1. Initial Dex CrashLoop

🔥 Error: Dex pod continuously restarting.

Root Cause:

storage.type: kubernetes without the required CRDs installed

Insufficient RBAC to access Kubernetes resources

Fix – ConfigMap change:



# Change in Dex config
storage:
  type: memory  # ✅ Instead of 'kubernetes'

Fix – Required RBAC:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: dex-server
rules:
- apiGroups: ["apiextensions.k8s.io"]
  resources: ["customresourcedefinitions"]
  verbs: ["list", "create"]
- apiGroups: [""]
  resources: ["secrets", "configmaps"]
  verbs: ["get", "list", "watch", "create", "update"]

2. HTTP Probes Failing (404)

⚠️ Symptom: Dex is running but the pod never becomes Ready.

Problem:

# Istio logs
no healthy upstream for /auth/dex/.well-known/openid-configuration

# Original probes (did not work)
livenessProbe:
  httpGet:
    path: /healthz/live
    port: 5556
  # Returned 404

Fix – Use TCP Socket instead of HTTP:

livenessProbe:
  tcpSocket:
    port: 5556
  initialDelaySeconds: 30  # ⏱️ Increased delay
  periodSeconds: 10

readinessProbe:
  tcpSocket:
    port: 5556
  initialDelaySeconds: 20
  periodSeconds: 5

  1. ConfigMap vs Secret Mismatch

🔥 Problem: Deployment mounting the wrong resource.

Cause:

Multiple ConfigMaps/Secrets with conflicting configurations

Deployment referencing the wrong resource

Fix – Single authoritative ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: litmus-dex-config  # Consistent name
  namespace: litmus
data:
  config.yaml: |
    # ... full Dex configuration here
---
# Deployment must reference exactly this ConfigMap
volumes:
- name: config
  configMap:
    name: litmus-dex-config  # ✅ Same name

  1. Endpoint Discovery Working

✅ After fixes, both endpoints return HTTP 200.

Embedded Mode:

curl https://litmus.example.com/auth/dex/.well-known/openid-configuration
# ✅ HTTP 200 OK

Dedicated Mode:

curl https://dex.litmus.example.com/.well-known/openid-configuration
# ✅ HTTP 200 OK

❌ Main Problem: Litmus Frontend
🔍 Behaviour Analysis
✅ Manual OIDC Flow (Works)

When we test the full OIDC flow manually:

# Correctly formed URL
curl -L "https://litmus.example.com/auth/dex/auth?\
client_id=LitmusPortalAuthBackend&\
redirect_uri=https://litmus.example.com/auth/dex/callback&\
response_type=code&\
scope=openid+profile+email+groups&\
state=random_state"

Result:

sequenceDiagram
    participant C as cURL/Browser
    participant D as Dex
    participant A as Authentik
    
    C->>D: GET /auth with OIDC params ✓
    D->>A: Redirect to Authentik
    A->>C: Login form
    C->>A: Credentials
    A->>D: Authorization Code ✓
    D->>C: Redirect to callback ✓
    
    Note over C,A: ✅ Full OIDC flow works

Loading

❌ Litmus Frontend Flow (Does NOT work)

When the user clicks "Login With Single Sign-On", the frontend does:

// What the Litmus frontend currently does (INCORRECT)
window.location = "https://litmus.example.com/auth/dex/auth/authentik";
// ❌ No client_id
// ❌ No redirect_uri
// ❌ No response_type
// ❌ No scope
// ❌ No state

Dex responds with:

{
  "error": "invalid_request",
  "error_description": "Not Found - Invalid client_id (\"\")"
}

Problem Diagram:

sequenceDiagram
    participant U as User
    participant F as Litmus Frontend
    participant D as Dex
    
    U->>F: Clicks "Login with SSO"
    
    rect rgb(255, 200, 200)
        Note over F: ❌ Builds incorrect URL
        F->>D: GET /auth/dex/auth/authentik<br/>(without OIDC params)
        D-->>F: Invalid client_id ("")
    end
    
    Note over U,D: Flow is interrupted

Loading

💡 Comparison with Argo CD

Argo CD, using the same infrastructure (Dex + Authentik), works correctly because its frontend builds the OIDC URL properly:

// Argo CD Frontend (CORRECT) ✅
const authUrl = new URL('https://argocd.example.com/auth/dex/auth');
authUrl.searchParams.set('client_id', 'argocd-client');
authUrl.searchParams.set('redirect_uri', 'https://argocd.example.com/auth/callback');
authUrl.searchParams.set('response_type', 'code');
authUrl.searchParams.set('scope', 'openid profile email groups');
authUrl.searchParams.set('state', generateRandomState());

window.location = authUrl.toString();

🚀 Improvement Proposal
For the Litmus Community

ℹ️ Validation: Dex, Authentik, Istio, callbacks, and issuer configuration are all correct and tested. The bottleneck is only how the Litmus frontend initiates the SSO flow.

  1. Required Changes in the Frontend

Option A: Frontend builds the OIDC URL correctly

// Suggested implementation in the frontend
function initiateSSO() {
  const authUrl = new URL(`${OIDC_ISSUER}/auth`);
  
  authUrl.searchParams.set('client_id', DEX_OAUTH_CLIENT_ID);
  authUrl.searchParams.set('redirect_uri', DEX_OAUTH_CALLBACK_URL);
  authUrl.searchParams.set('response_type', 'code');
  authUrl.searchParams.set('scope', 'openid profile email groups');
  authUrl.searchParams.set('state', generateSecureRandomString());
  
  window.location.href = authUrl.toString();
}

Option B: Backend exposes a “start SSO” endpoint

// Frontend just redirects to the backend
function initiateSSO() {
  window.location.href = '/auth/login/sso';
}

// Backend (auth-server) then returns the proper redirect
// with all required OIDC parameters

  1. Official Documentation Needed

📝 Missing: Official documentation for the “Litmus → Dex → external IdP” setup.

Suggested content for docs:

Full example of staticClients and connectors for Dex

Explanation of env vars: DEX_ENABLED, OIDC_ISSUER, DEX_OAUTH_*

Guide for embedded mode (Dex behind the Litmus host via Ingress/Istio)

Troubleshooting common problems (CrashLoop, probes, RBAC)

Comparison: when to use dedicated vs embedded mode

  1. Current Workaround

Until these frontend changes are implemented:

✅ Recommendation: Use Dedicated Dex Mode

graph LR
    A[Litmus Frontend<br/>litmus.example.com] -->|OIDC Flow| B[Dedicated Dex<br/>dex.litmus.example.com]
    B --> C[Authentik IdP]
    
    style B fill:#9f9,stroke:#333,stroke-width:3px
    style A fill:#bbf
    style C fill:#fbb

Loading

Advantages:

✅ Same pattern as Argo CD (already proven to work)

✅ Clear separation of responsibilities

✅ Easier debugging (isolated logs)

✅ Does not depend on Litmus frontend code changes

Configuration:

# Auth Server (example)
env:
- name: OIDC_ISSUER
  value: "https://dex.litmus.example.com"  # ← dedicated host

📋 Validation Checklist

Before reporting similar issues, check:

✅ Dex is running and the pod is Ready

✅ Probes are configured as tcpSocket (not HTTP)

✅ .well-known/openid-configuration returns HTTP 200

✅ A single, consistent ConfigMap is mounted in the Deployment

✅ RBAC allows access to secrets/configmaps

✅ storage.type: memory is configured

✅ Authentik has correct redirect URIs

✅ VirtualService correctly routes traffic to Dex

✅ Auth Server has DEX_ENABLED=true

✅ Callback URL is consistent everywhere

⬜ Frontend sends full OIDC parameters ← ❌ current problem

📚 References
Resource Link
Dex Documentation https://dexidp.io/docs/

OIDC Spec https://openid.net/specs/openid-connect-core-1_0.html

Argo CD + Dex https://argo-cd.readthedocs.io/en/stable/operator-manual/user-management/

Litmus Docs https://docs.litmuschaos.io/
💭 Conclusion

The Litmus ↔ Dex ↔ Authentik integration is completely viable from an infrastructure perspective. We have successfully validated:

✅ Full manual OIDC flow

✅ Dex endpoint discovery

✅ Authentication in Authentik

✅ Token generation

✅ Callbacks working

The only blocker is how the Litmus frontend starts the SSO flow. A relatively small change in the frontend (or an abstraction in the backend) would fully unlock the embedded mode.

In the meantime, the Dedicated Dex Mode works perfectly and is our recommendation for production environments.

Feedback and contributions are very welcome! 💬

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions