Hello everyone!
I am deploying a Keycloak instance in production for the first time. I am using it behind an Apache reverse proxy in edge termination mode. The Keycloak’s KC_HOSTNAME is set to the DNS that accesses the reverse proxy, and KC_HOSTNAME_ADMIN is configured with the local address of the Keycloak instance. To demonstrate the issue, I manually added the address keycloak.example.com to my operating system’s DNS. This way, I can access the address in the browser and the OS will resolve it to the Apache reverse proxy.
These are the configurations I am using in Keycloak and the reverse proxy:
KC_DB=postgres
KC_DB_USERNAME=postgres
KC_DB_PASSWORD=postgres
KC_DB_URL=jdbc:postgresql://172.31.128.1:5432/keycloak
KC_HTTPS_CERTIFICATE_FILE=/opt/keycloak/conf/certs/cert.pem
KC_HTTPS_CERTIFICATE_KEY_FILE=/opt/keycloak/conf/certs/key.pem
KC_HOSTNAME=https://keycloak.example.com:1010
KC_HOSTNAME_ADMIN=http://172.31.142.178:8091
KC_BOOTSTRAP_ADMIN_USERNAME=temp-admin
KC_BOOTSTRAP_ADMIN_PASSWORD=temp-admin
KC_PROXY_HEADERS=xforwarded
KC_HTTP_ENABLED=true
services:
keycloak:
image: quay.io/keycloak/keycloak:26.4.5
env_file: .env
ports:
- “9090:8443”
- “8091:8080”
volumes:
- /home/user/keycloak/certs:/opt/keycloak/conf/certs
command: start
# Other stuff
RequestHeader set X-Forwarded-Proto “https”
RequestHeader set X-Forwarded-Host “keycloak.example.com:1010”
RequestHeader set X-Forwarded-For “%{REMOTE_ADDR}s”
ProxyPass “/” “http://172.31.142.178:8091/”
ProxyPassReverse “/” “http://172.31.142.178:8091/”
# Other stuff
The issue is as follows: When I access Keycloak via the address defined in KC_HOSTNAME_ADMIN, the redirects from / to /admin/ and to /admin/master/console/ happen normally, still using the address defined by KC_HOSTNAME_ADMIN. Then, I am redirected to the Keycloak login screen using the address defined in KC_HOSTNAME. At this stage, the redirect_uri parameter is correct, i.e., it points to the KC_HOSTNAME_ADMIN address. Here is an example of the URL:
https://keycloak.example.com:1010/realms/master/protocol/openid-connect/auth?client_id=security-admin-console&redirect_uri=http%3A%2F%2F172.31.142.178%3A8091%2Fadmin%2Fmaster%2Fconsole%2F&state=734f0052-4bc8-4c0a-8305-a6963574a3d1&response_mode=query&response_type=code&scope=openid&nonce=9c9b2ee6-bbf3-49ec-a494-15c4064a2093&code_challenge=Swm1kak6gtPFa4nnoijbH17Mpwqwo7Bkhs7p-PvZHJw&code_challenge_method=S256
However, even though the redirect_uri is correct, when I enter the admin credentials and click login, a POST request is made and, in the response headers, there is a redirect defined by the Location header pointing to the address defined by KC_HOSTNAME instead of KC_HOSTNAME_ADMIN. This redirect takes me to /admin/master/console/. Here is an example of the redirect defined by the Location header:
https://keycloak.example.com:1010/admin/master/console/?state=734f0052-4bc8-4c0a-8305-a6963574a3d1&session_state=73469140-f25c-6434-3751-3bf77960addf&iss=https%3A%2F%2Fkeycloak.example.com%3A1010%2Frealms%2Fmaster&code=189afcb5-6d9e-b9b9-532e-7455164c5f3e.73469140-f25c-6434-3751-3bf77960addf.4b6e8a0a-9ad3-4127-856c-5111d6490163
Notice that it does not match the redirect_uri parameter.
After that, a few more internal Keycloak redirects occur. The last one ends with a request that returns a 400 error with the following message: `Invalid parameter: redirect_uri`. This is the request URL:
https://keycloak.example.com:1010/realms/master/protocol/openid-connect/auth?client_id=security-admin-console&redirect_uri=https%3A%2F%2Fkeycloak.example.com%3A1010%2Fadmin%2Fmaster%2Fconsole%2F&state=817211c5-6871-4170-baaf-d4b3f82727d2&response_mode=query&response_type=code&scope=openid&nonce=a885f386-cf6b-4847-8986-a3731ff42cce&code_challenge=QBiDOCjnOcSyr6ktHyiLAHhCJS18fSoGxbgXMjoq98A&code_challenge_method=S256
I would like to know what I am configuring wrong or what I might have missed, as I have read the documentation and believe I am following the correct path.
Note: I know I don’t need the certificate since I am using edge termination, but I kept it in case I need to use HTTPS passthrough in the future.