تخطَّ إلى المحتوى

Dex Cheat Sheet

Overview

Dex is an open-source OpenID Connect (OIDC) identity provider that acts as a portal to other identity sources. It serves as an identity federation hub, allowing applications to authenticate users against a variety of backends including LDAP, SAML 2.0, GitHub, GitLab, Google, Microsoft, and other OIDC providers through a single, standards-compliant OIDC interface.

Dex is commonly used with Kubernetes for cluster authentication, enabling kubectl and dashboard access through corporate identity providers. It is lightweight, written in Go, and designed for cloud-native deployments. Dex handles the complexity of integrating with multiple identity protocols while exposing a simple OIDC interface to client applications.

Installation

# Docker
docker pull ghcr.io/dexidp/dex

# Kubernetes Helm
helm repo add dex https://charts.dexidp.io
helm install dex dex/dex -f values.yaml

# Build from source
git clone https://github.com/dexidp/dex.git
cd dex
make build
./bin/dex serve config.yaml

# Verify
./bin/dex version

Core Configuration

# config.yaml
issuer: https://dex.example.com

storage:
  type: sqlite3
  config:
    file: /var/dex/dex.db

web:
  http: 0.0.0.0:5556

telemetry:
  http: 0.0.0.0:5558

oauth2:
  skipApprovalScreen: true
  responseTypes: ["code", "token", "id_token"]

staticClients:
  - id: my-app
    name: "My Application"
    redirectURIs:
      - "http://localhost:3000/callback"
    secret: ZXhhbXBsZS1hcHAtc2VjcmV0

  - id: kubernetes
    name: "Kubernetes"
    redirectURIs:
      - "http://localhost:8000"
    secret: a3ViZXJuZXRlcy1zZWNyZXQ=

connectors:
  - type: github
    id: github
    name: GitHub
    config:
      clientID: $GITHUB_CLIENT_ID
      clientSecret: $GITHUB_CLIENT_SECRET
      redirectURI: https://dex.example.com/callback
      orgs:
        - name: my-org
          teams:
            - developers
            - devops

enablePasswordDB: true
staticPasswords:
  - email: "admin@example.com"
    hash: "$2a$10$..."
    username: "admin"
    userID: "08a8684b-db88-4b73-90a9-3cd1661f5466"

Connector Types

LDAP Connector

connectors:
  - type: ldap
    id: ldap
    name: LDAP
    config:
      host: ldap.example.com:636
      insecureNoSSL: false
      insecureSkipVerify: false
      rootCA: /etc/dex/ldap-ca.crt
      bindDN: cn=admin,dc=example,dc=com
      bindPW: admin-password
      userSearch:
        baseDN: ou=users,dc=example,dc=com
        filter: "(objectClass=inetOrgPerson)"
        username: uid
        idAttr: uid
        emailAttr: mail
        nameAttr: displayName
      groupSearch:
        baseDN: ou=groups,dc=example,dc=com
        filter: "(objectClass=groupOfNames)"
        userMatchers:
          - userAttr: DN
            groupAttr: member
        nameAttr: cn

SAML 2.0 Connector

connectors:
  - type: saml
    id: corporate-sso
    name: "Corporate SSO"
    config:
      ssoURL: https://idp.example.com/saml/sso
      ca: /etc/dex/saml-ca.crt
      redirectURI: https://dex.example.com/callback
      usernameAttr: name
      emailAttr: email
      groupsAttr: groups
      entityIssuer: https://dex.example.com/callback
      ssoIssuer: https://idp.example.com
      nameIDPolicyFormat: emailAddress

Google Connector

connectors:
  - type: google
    id: google
    name: Google
    config:
      clientID: $GOOGLE_CLIENT_ID
      clientSecret: $GOOGLE_CLIENT_SECRET
      redirectURI: https://dex.example.com/callback
      hostedDomains:
        - example.com
      groups:
        - engineering@example.com
        - product@example.com
      serviceAccountFilePath: /etc/dex/google-sa.json
      adminEmail: admin@example.com

GitLab Connector

connectors:
  - type: gitlab
    id: gitlab
    name: GitLab
    config:
      clientID: $GITLAB_CLIENT_ID
      clientSecret: $GITLAB_CLIENT_SECRET
      redirectURI: https://dex.example.com/callback
      baseURL: https://gitlab.example.com
      groups:
        - my-group
        - my-group/subgroup
      useLoginAsID: false

OIDC Connector (Generic)

connectors:
  - type: oidc
    id: other-provider
    name: "Other OIDC Provider"
    config:
      issuer: https://accounts.provider.com
      clientID: $OIDC_CLIENT_ID
      clientSecret: $OIDC_CLIENT_SECRET
      redirectURI: https://dex.example.com/callback
      scopes:
        - openid
        - profile
        - email
        - groups
      getUserInfo: true
      insecureSkipEmailVerified: false
      claimMapping:
        groups: roles

Kubernetes Integration

# kube-apiserver flags
# --oidc-issuer-url=https://dex.example.com
# --oidc-client-id=kubernetes
# --oidc-username-claim=email
# --oidc-groups-claim=groups
# --oidc-ca-file=/etc/kubernetes/pki/dex-ca.crt

# RBAC for OIDC groups
# ClusterRoleBinding for devops group
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: oidc-devops-admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
  - kind: Group
    name: "devops"
    apiGroup: rbac.authorization.k8s.io
# Configure kubectl with OIDC
kubectl config set-credentials oidc-user \
  --auth-provider=oidc \
  --auth-provider-arg=idp-issuer-url=https://dex.example.com \
  --auth-provider-arg=client-id=kubernetes \
  --auth-provider-arg=client-secret=a3ViZXJuZXRlcy1zZWNyZXQ= \
  --auth-provider-arg=refresh-token=REFRESH_TOKEN \
  --auth-provider-arg=id-token=ID_TOKEN

Storage Backends

# SQLite (development)
storage:
  type: sqlite3
  config:
    file: /var/dex/dex.db

# PostgreSQL (production)
storage:
  type: postgres
  config:
    host: postgres.example.com
    port: 5432
    database: dex
    user: dex
    password: $DEX_DB_PASSWORD
    ssl:
      mode: verify-ca
      caFile: /etc/dex/db-ca.crt

# MySQL
storage:
  type: mysql
  config:
    host: mysql.example.com
    port: 3306
    database: dex
    user: dex
    password: $DEX_DB_PASSWORD

# Kubernetes CRDs
storage:
  type: kubernetes
  config:
    inCluster: true

Advanced Usage

Custom Claims and Scopes

oauth2:
  responseTypes: ["code", "token", "id_token"]
  skipApprovalScreen: true

  # Custom scopes
  passwordConnector: local

Expiration Settings

expiry:
  deviceRequests: 5m
  signingKeys: 6h
  idTokens: 24h
  refreshTokens:
    reuseInterval: 3s
    validIfNotUsedFor: 2160h  # 90 days
    absoluteLifetime: 3960h    # 165 days

High Availability

# Kubernetes Helm values for HA
replicaCount: 3

storage:
  type: postgres
  config:
    host: postgres-primary.example.com

ingress:
  enabled: true
  hosts:
    - host: dex.example.com
      paths:
        - path: /
          pathType: Prefix

Configuration

# Environment variables
export DEX_DB_PASSWORD="database-password"
export GITHUB_CLIENT_ID="github-oauth-client-id"
export GITHUB_CLIENT_SECRET="github-oauth-client-secret"
export GOOGLE_CLIENT_ID="google-oauth-client-id"
export GOOGLE_CLIENT_SECRET="google-oauth-client-secret"

# Start Dex
dex serve config.yaml

# Docker run
docker run -d \
  --name dex \
  -p 5556:5556 \
  -v $(pwd)/config.yaml:/etc/dex/config.yaml \
  -v $(pwd)/dex.db:/var/dex/dex.db \
  ghcr.io/dexidp/dex serve /etc/dex/config.yaml

Troubleshooting

IssueSolution
Discovery endpoint 404Verify issuer URL matches exactly what Dex serves
LDAP bind failedCheck bindDN and bindPW; test with ldapsearch directly
SAML redirect loopVerify entityIssuer and redirectURI in SAML connector config
No groups in tokenEnsure group search is configured; check groupsAttr mapping
Kubernetes auth failsVerify --oidc-issuer-url matches Dex issuer exactly
Token expiredAdjust expiry.idTokens and refreshTokens settings
Connector not showingCheck connector config syntax; look at Dex logs for errors
Database migration errorRun dex serve which auto-migrates; check DB permissions