Authentication
The advanced setup uses Keycloak as the identity provider. DIAL Chat authenticates users via OIDC, and DIAL Core validates JWT tokens against Keycloak's JWKS endpoint.
Keycloak
From docker-compose-base.yml:
keycloak:
image: keycloak/keycloak:26.7
user: root
command: ["start-dev", "--import-realm", "--http-port=${KC_PORT}"]
environment:
KC_BOOTSTRAP_ADMIN_USERNAME: admin
KC_BOOTSTRAP_ADMIN_PASSWORD: ${KC_ADMIN_PASSWORD}
KC_HOSTNAME: http://${COMMON_HOST}:${KC_PORT}
KC_HOSTNAME_STRICT: true
KC_HTTP_ENABLED: true
QUARKUS_HTTP_LIMITS_MAX_HEADER_SIZE: 64k
KC_INITIALIZE_EMPTY: 'true'
KC_CACHE: local
KC_HEALTH_ENABLED: 'true'
ports:
- "${KC_PORT}:${KC_PORT}"
- "${DIAL_CHAT_HOST_PORT}:${DIAL_CHAT_HOST_PORT}"
- "${DIAL_ADMIN_FRONTEND_HOST_PORT}:3000"
volumes:
- ./keycloak/data:/opt/keycloak/data
- ./keycloak/import/realm-config.json:/opt/keycloak/data/import/realm-config.json
restart: always
healthcheck:
test: ["CMD-SHELL", "bash -c 'exec 3<>/dev/tcp/127.0.0.1/${KC_PORT}'"]
interval: 5s
timeout: 5s
retries: 30
start_period: 20s
Environment variables
| Variable | Description |
|---|---|
KC_BOOTSTRAP_ADMIN_USERNAME | Initial admin username. Hardcoded to admin. |
KC_BOOTSTRAP_ADMIN_PASSWORD | Initial admin password. Injected from .env via ${KC_ADMIN_PASSWORD}. |
KC_HOSTNAME | Public URL of the Keycloak server, built from ${COMMON_HOST} so browser redirects and container-internal calls agree. |
KC_HOSTNAME_STRICT | When true, Keycloak issues URLs using KC_HOSTNAME only. |
KC_HTTP_ENABLED | Enable plain HTTP. Required when running behind a reverse proxy or in development. |
QUARKUS_HTTP_LIMITS_MAX_HEADER_SIZE | Maximum HTTP header size. Set to 64k to accommodate large JWT tokens. |
KC_INITIALIZE_EMPTY | Initialize an empty database on first startup. |
KC_CACHE | Cache mode. local for a single-node development instance. |
KC_HEALTH_ENABLED | Expose health endpoints, used by the healthcheck that gates Chat and Admin startup. |
The start-dev command runs Keycloak in development mode. For production deployments, use start with a properly configured database and TLS.
Realm import
Keycloak imports the realm configuration at startup from ./keycloak/import/realm-config.json. This file defines the dial realm, clients, roles, and default users. See realm-config.json for the realm file structure.
Volumes
| Mount | Purpose |
|---|---|
./keycloak/data | Keycloak data directory (embedded H2 database in dev mode) |
./keycloak/import/realm-config.json | Realm configuration for automatic import |
Chat (authenticated)
In the advanced setup, Chat uses Keycloak OIDC instead of API key authentication:
chat:
image: epam/ai-dial-chat:1.0.15
platform: linux/amd64
environment:
PORT: ${DIAL_CHAT_HOST_PORT}
API_PREFIX: "api"
AUTH_SESSION_SECRET: "${AUTH_SESSION_SECRET}"
AUTH_CALLBACK_BASE_URL: "http://${COMMON_HOST}:${DIAL_CHAT_HOST_PORT}"
AUTH_POST_LOGOUT_REDIRECT_URI: "http://${COMMON_HOST}:${DIAL_CHAT_HOST_PORT}"
AUTH_KEYCLOAK_CLIENT_ID: "dial-chat"
AUTH_KEYCLOAK_SECRET: "${AUTH_KEYCLOAK_SECRET}"
AUTH_KEYCLOAK_HOST: "http://${COMMON_HOST}:${KC_PORT}/realms/dial"
AUTH_KEYCLOAK_DIAL_ROLES_FIELD: "resource_access.dial-chat.roles"
AUTH_COOKIE_SECURE: "false"
DIAL_CORE_URL: "http://core:8080"
THEMES_CONFIG_URL: "http://themes:8080"
ENABLED_UI_FEATURES: "code-apps,schema-apps,custom-apps,chat-settings,..."
LIVE_CHAT_INTERACTION_ENABLED: "true"
RESPONSES_API_ENABLED: "true"
network_mode: "service:keycloak"
depends_on:
themes:
condition: service_started
core:
condition: service_started
keycloak:
condition: service_healthy
restart: always
Chat no longer publishes its own port — it shares Keycloak's network namespace (see the note above), and PORT tells Chat to listen on ${DIAL_CHAT_HOST_PORT} directly so the published mapping lines up. AUTH_COOKIE_SECURE: "false" is required because this stack serves plain HTTP.
Environment variables
| Variable | Description |
|---|---|
AUTH_KEYCLOAK_CLIENT_ID | Keycloak client ID for DIAL Chat. Must match the client configured in realm-config.json. |
AUTH_KEYCLOAK_DIAL_ROLES_FIELD | Path to the roles claim in the Keycloak token. Uses resource_access.dial-chat.roles for client-scoped roles. |
AUTH_KEYCLOAK_HOST | Keycloak realm URL for OIDC discovery. |
AUTH_KEYCLOAK_SECRET | Keycloak client secret. Injected from .env. |
AUTH_SESSION_SECRET | Session encryption key. Injected from .env. Replaces NEXTAUTH_SECRET. |
AUTH_CALLBACK_BASE_URL | Public base URL used to build the OIDC callback. Replaces NEXTAUTH_URL. |
AUTH_POST_LOGOUT_REDIRECT_URI | Where Keycloak sends the browser after sign-out. |
AUTH_COOKIE_SECURE | When false, session cookies are sent over plain HTTP. Required for this local stack. |
PORT | Port Chat listens on. Set to ${DIAL_CHAT_HOST_PORT} because Chat shares Keycloak's network namespace. |
API_PREFIX | Path prefix for the Chat API routes. |
DIAL_CORE_URL | DIAL Core internal URL. Replaces DIAL_API_HOST. |
THEMES_CONFIG_URL | Themes service internal URL. Replaces THEMES_CONFIG_HOST. |
ENABLED_UI_FEATURES | Comma-separated list of enabled Chat UI features. Replaces ENABLED_FEATURES. |
LIVE_CHAT_INTERACTION_ENABLED | Enable live chat interaction. |
RESPONSES_API_ENABLED | Enable the Responses API. |
Comparison with quick start Chat
| Aspect | Quick Start | Advanced |
|---|---|---|
| Authentication | DIAL_API_KEY (static key) | Keycloak OIDC (AUTH_KEYCLOAK_*) |
| Session encryption | Hardcoded "secret" | ${AUTH_SESSION_SECRET} from .env |
| Dependencies | Core, Themes | Core, Themes, Keycloak (gated on its healthcheck) |
| Networking | Own port mapping 3000 | Shares Keycloak's namespace; Keycloak publishes ${DIAL_CHAT_HOST_PORT} |
See DIAL Chat configuration for all Chat environment variables.
Further reading
- Core, Redis & Themes — Core identity provider and encryption settings
- Admin Panel — Admin Backend and Frontend (also Keycloak-authenticated)
- realm-config.json — Keycloak realm file structure
- .env reference — secret and port variable definitions
- Configure Keycloak — connect DIAL to a Keycloak realm
- How DIAL Chat is configured — how Chat reads environment variables and where each group is documented