Keycloak not working with HAProxy

I’ve seen similar issues reported but nothing I’ve seen documented seems to help. The error in log is as follows along with constant redirects in the browser:

keycloak-1 | 2024-05-06 22:47:39,036 WARN [org.keycloak.events] (executor-thread-9) type=“REFRESH_TOKEN_ERROR”, realmId=“<realm_id>”, clientId=“security-admin-console”, userId=“null”, ipAddress=“<my_remote_server_ip>”, error=“invalid_token”, grant_type=“refresh_token”, client_auth_method=“client-secret”

my docker-compose is as follows:

version: ‘3’

services:
postgres_kc:
image: postgres:latest
environment:
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
ports:
- “5435:5432”
networks:
- keycloak-network
volumes:
- /etc/postgresql/14/main/postgresql.conf:/etc/postgresql/postgresql.conf
- /etc/keycloak/data:/var/lib/postgresql/data

keycloak:
image: Quay
restart: always
command: start-dev
environment:
- DB_VENDOR=POSTGRES
- DB_ADDR=postgres_kc
- DB_DATABASE=${POSTGRES_DB}
- DB_USER=${POSTGRES_USER}
- DB_PASSWORD=${POSTGRES_PASSWORD}
- KEYCLOAK_ADMIN=${KEYCLOAK_ADMIN}
- KEYCLOAK_ADMIN_PASSWORD=${KEYCLOAK_ADMIN_PASSWORD}
- QUARKUS_TRANSACTION_MANAGER_ENABLE_RECOVERY=true
- KC_CACHE=ispn
- PROXY_ADDRESS_FORWARDING=true
- REDIRECT_SOCKET=proxy-https
- KC_PROXY_ADDRESS_FORWARDING=true
- KC_PROXY_HEADERS=xforwarded
- KC_HTTP_ENABLED=true
- KC_HOSTNAME_STRICT=false
- KC_HOSTNAME=<my_domain>
- KC_HTTP_PORT=8081
- KC_HTTPS_CLIENT_AUTH=request
- KC_HTTPS_PROTOCOLS=TLSv1.3,TLSv1.2
# - KC_LOG_LEVEL=DEBUG
depends_on:
- postgres_kc
ports:
- “8443:8081”
networks:
- keycloak-network
volumes:
- /etc/keycloak/realms:/opt/keycloak/data

networks:
keycloak-network:
driver: bridge

haproxy:

http front

frontend http_front
bind *:80
timeout client 60000ms
# redirect HTTP to HTTPS
redirect scheme https code 301 if { hdr_sub(host) <my_domain> } !{ ssl_fc }

https front

frontend https_front
mode http
bind *:443 ssl crt /etc/haproxy/ssl/<my_cert>
timeout client 60000ms

# pass ssl to end host
http-request set-header X-Forwarded-Proto https if { ssl_fc }
http-request add-header X-Forwarded-Port %[dst_port] if { ssl_fc }
http-request add-header X-Forwarded-Host %[req.hdr(Host)]
http-request set-header X-Forwarded-For %[src] if { ssl_fc }

# sets secure cookie flag, and httponly cookie flag
http-after-response replace-header Set-Cookie '(^((?!(?i)httponly).)*$)' "\1; HttpOnly"
http-after-response replace-header Set-Cookie '(^((?!(?i)secure).)*$)' "\1; Secure"

# capture header for logging
http-request capture req.hdr(Content-Length) len 10

acl host_keycloak ssl_fc_sni -i <mydomain>
use_backend https_back_keycloak if host_keycloak

https back

backend https_back_keycloak
mode http
option forwardfor header X-Client
balance roundrobin
server nkc1 <my_remote_server_ip>:8443
timeout connect 60000ms
timeout server 60000ms
compression algo gzip
compression offload

been at this for several days now, any help is appreciated!

I finally gave up and switched to nginx and its working fine now. I’ll leave this thread up in case someone spots a misconfiguration? My only guess was that haproxy was blocking a header or a cookie so that the refresh token could not be read. Another difference I noted when going through haproxy was that it was making a token POST request an extra time before fetching serverinfo :man_shrugging:

I figured it out, its this line here in my above haproxy configuration:

http-after-response replace-header Set-Cookie ‘(^((?!(?i)httponly).)*$)’ “\1; HttpOnly”

I see when inspecting the cookies for keycloak that a couple are not set to HttpOnly, and I suppose that this is necessary, so after commenting that then I can log into the admin console without issue. If this thread can save a headache for someone else then my suffering will have been worth it!