Hello all! Hopefully someone here can help me with my current issue. I have a Keycloak instance inside of a rootless Docker container handling my authentication to Mattermost instance. The server has Nginx to handle the reverse proxy to Keycloak.
For my specific use case, I was able to configure x509 cards as a means to authenticate to Keycloak in order log into Mattermost. However, the problem I am having now is that my organization uses a VDI solution, specifically Azure Virtual Desktop (AVD) that requires a user to authenticate to the browser before accessing the internet with x509. When a user navigates to the Keycloak URL they are not prompted for their x509.
However, when not using the AVD and accessing the URL from any other means it prompts for the x509 card just fine. I have checked the browser flow and that doesn’t seem to be the issue, but am not sure how to fix this problem or where to start. Any help would be appreciated.
Ngnix conf:
server {
listen 80;
server_name ******.******* ******.*******;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
ssl_certificate /etc/nginx/******.*******/******.*******/tls.crt;
ssl_certificate_key /etc/nginx/******.*******/******.*******/tls.key;
server_name ******.******* ******.*******;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384';
ssl_prefer_server_ciphers on;
ssl_client_certificate /etc/nginx/******.*******/******.*******/nginx_ssl_bundle.pem;
ssl_verify_depth 4;
ssl_verify_client optional;
location / {
proxy_pass https://*.*.*.*:*****;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header SSL_CLIENT_CERT $ssl_client_escaped_cert;
proxy_buffer_size 64k;
proxy_buffers 8 64k;
}
}
Docker compose
services:
keycloak_web:
image: quay.io/keycloak/keycloak:26.1.2
container_name: keycloak
env_file: .env
ports:
- "*****:8443"
environment:
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://keycloakdb:5432/keycloak
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: ********************
KC_HOSTNAME: ********************
KC_HOSTNAME_STRICT: true
KC_HOSTNAME_STRICT_HTTPS: true
KC_HTTP_ENABLED: true
KC_HTTPS_CERTIFICATE_FILE: /opt/tls/tls.crt
KC_HTTPS_CERTIFICATE_KEY_FILE: /opt/tls/tls.key
KC_HTTPS_CLIENT_AUTH: request
KC_HTTPS_TRUST_STORE_FILE: /opt/x509/keycloak.truststore
KC_HTTPS_TRUST_STORE_PASSWORD: ********************
KC_HTTPS_KEY_STORE_TYPE: JKS
PROXY_ADDRESS_FORWARDING: true
KC_SPI_X509CERT_LOOKUP_PROVIDER: nginx
KC_SPI_X509CERT_LOOKUP_NGINX_SSL_CLIENT_CERT: SSL_CLIENT_CERT
KC_TRANSACTION_XA_ENABLED: false
KC_HTTP_RELATIVE_PATH: /auth
KC_METRICS_ENABLED: true
KC_HEALTH_ENABLED: true
volumes:
- /********/********/********/certs:/opt/tls
- /********/********/********/keycloak.truststore:/opt/x509/keycloak.truststore
command:
- start
- --spi-x509cert-lookup-provider=nginx
- --spi-x509cert-lookup-nginx-certificate-header=SSL_CLIENT_CERT
- --spi-x509cert-lookup-nginx-enable=true
depends_on:
keycloakdb:
condition: service_healthy
restart: always
healthcheck:
test: ["CMD", "curl", "--silent", "--fail", "https://localhost:8443/auth/health/ready"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
keycloakdb:
image: postgres:15.2
container_name: keycloakdb
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: ********************
POSTGRES_USER: ********************
POSTGRES_PASSWORD: ********************
POSTGRES_HOST_AUTH_METHOD: scram-sha-256
POSTGRES_INITDB_ARGS: --auth-host=scram-sha-256
restart: always
healthcheck:
test: ["CMD", "pg_isready", "-U", "keycloak"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
volumes:
postgres_data:
driver: local