Using Keycloak behind a reverse proxy: Could not open Admin loginpage because mixed Content

Viewed 74646

so I have a problem getting keycloak 3.2.1 to work behind kong (0.10.3), a reverse proxy based on nginx.

Scenario is:

I call keycloak via my gateway-route via https://{gateway}/auth and it shows me the entrypoint with keycloak logo, link to admin console etc. - so far so good.

But when clicking on administration console -> calling https://{gateway}/auth/admin/master/console/ , keycloak tries to load its css/js via http (see screenie below), which my browser blocks because mixed content.

I searched around and found this thread: keycloak apache server configuration with 'Mixed Content' problems which lead to this github repo: https://github.com/dukecon/keycloak_postgres_https

From there on, I tried to integrate its' cli into my dockerfile with success (did not change the files' contents, just copied them into my repo and add/run them from dockerfile). This is my dockerfile right now:

FROM jboss/keycloak-postgres:3.2.1.Final

USER root

ADD config.sh /tmp/
ADD batch.cli /tmp/

RUN bash /tmp/config.sh

#Give correct permissions when used in an OpenShift environment.
RUN chown -R jboss:0 $JBOSS_HOME/standalone && \
    chmod -R g+rw $JBOSS_HOME/standalone

USER jboss
EXPOSE 8080

Sadly, my problem still exists: error

So I am out of ideas for now and hope you could help me out:

  • How do I tell keycloak to call its' css-files via https here?

  • do I have to change something in the cli script?

Here's the content of the script:

config.sh:

#!/bin/bash -x

set -e

JBOSS_HOME=/opt/jboss/keycloak
JBOSS_CLI=$JBOSS_HOME/bin/jboss-cli.sh
JBOSS_MODE=${1:-"standalone"}
JBOSS_CONFIG=${2:-"$JBOSS_MODE.xml"}

echo "==> Executing..."
cd /tmp

$JBOSS_CLI --file=`dirname "$0"`/batch.cli

# cf. http://stackoverflow.com/questions/34494022/permissions-error-when-using-cli-in-jboss-wildfly-and-docker
/bin/rm -rf ${JBOSS_HOME}/${JBOSS_MODE}/configuration/${JBOSS_MODE}_xml_history/current

and batch.cli:

embed-server --std-out=echo

# http://keycloak.github.io/docs/userguide/keycloak-server/html/server-installation.html
# 3.2.7.2. Enable SSL on a Reverse Proxy
# First add proxy-address-forwarding and redirect-socket to the http-listener element.
# Then add a new socket-binding element to the socket-binding-group element.

batch

/subsystem=undertow/server=default-server/http-listener=default:write-attribute(name=proxy-address-forwarding,value=true)

/subsystem=undertow/server=default-server/http-listener=default:write-attribute(name=redirect-socket,value=proxy-https)

/socket-binding-group=standard-sockets/socket-binding=proxy-https:add(port=443)

run-batch

stop-embedded-server

It may be of interest too, that kong is deployed on openshift with a route using a redirect from http to https ( "insecureEdgeTerminationPolicy": "Redirect" ).

7 Answers

This sounds somehow like a duplicate of Keycloak Docker behind loadbalancer with https fails

Set the request headers X-Forwarded-For and X-Forwarded-Proto in nginx. Then you have to configure Keycloak (Wildfly, Undertow) to work together with the SSL terminating reverse proxy (aka load balancer). See http://www.keycloak.org/docs/latest/server_installation/index.html#_setting-up-a-load-balancer-or-proxy for a detailed description.

The point is that nginx is terminating SSL and is forwarding the requests to Keycloak as pure http. Therefore Keycloak/Wildfly must be told that the incoming http requests from nginx must be handled like they were https.

Add the X-Forwarded-For and X-Forwarded-Proto headers (as Boomer said) in all upstream load balancers and make sure those reach Keycloak server. X-Forwarded-For should be the domain of your Keycloak which routes to the LB and X-Forwarded-Proto should be the protocol (most of the cases https).

As a final step you need to modify standalone.xml or standalone-ha.xml file and add the proxy-address-forwarding="true" attribute to <http-listener> element under <server>.

If you are using Docker you can use PROXY_ADDRESS_FORWARDING environment var from the original Keycloak container to set this attribute.

To elaborate on the reply from @MattBianco. In modern Keycloak variables you need to set KEYCLOAK_FRONTEND_URL to https:///auth. Using docker you can set this as an environment variable e.g. KEYCLOAK_FRONTEND_URL=https://auth.foo.com/auth

I have the same problem with you, now it fixed, This is my method.

First, I setup reverse proxy with cloak at a clean env, confirm that the proxy and cloak was configured rightly.

Next, with test and gusess, I found when setup keycloak use the image you pull from dockerhub whith docker. There is some difference set it up with binary on server, from the standalone.xml, you will find the key point is this 2:

1. You should set PROXY_ADDRESS_FORWARDING=true for docker env.

2. You should set jboss.https.port 443 for docker env.

If your standalone.xml also configured rightly, you will get it work for admin page. Good lucks ;)

Two tips :

If you use a docker-compose.yml, add the following env variable to the keycloak container:

environment:
  PROXY_ADDRESS_FORWARDING: "true"

Restart the stack, check if the variable is there (sometimes you have to restart several times the container)

docker-compose exec keycloak bash -c 'echo $PROXY_ADDRESS_FORWARDING'

If you use an Apache container as a proxy (with mod_proxy) you should add manually the X-Forwarded-Proto and X-Forwarded-Port headers:

<IfModule mod_ssl.c>

# Proxy pass for keycloak
<VirtualHost *:443>
    ServerName auth.myproject_url.tld
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/apache-selfsigned.crt
    SSLCertificateKeyFile /etc/ssl/certs/apache-selfsigned.key
    <IfModule mod_proxy.c>
        SSLProxyEngine on
        <Location "/">
            ProxyPass  "http://keycloak:8080/"
            ProxyPassReverse "http://keycloak:8080/"
            RequestHeader set X-Forwarded-Proto "https"
            RequestHeader set X-Forwarded-Port "443"
            #  ProxyPreserveHost On
        </Location>
    </IfModule>
    </IfModule>
</VirtualHost>

After much struggle I found alternative solution using X-Forwarded-Host in addition to other headers. This is undocumented however it works, and seems to be working quite long time ago already. Check this pull request https://github.com/wildfly/wildfly/pull/5593

Keycloak documentation at https://www.keycloak.org/docs/latest/server_installation mentions that for proxy forwarding you need to set PROXY_ADDRESS_FORWARDING=true as docker arg plus X-Forwarded-For, X-Forwarded-Proto and original Host (host of internet facing proxy in my case).

But setting original Host was not possible in my case, because I'm hosting Keycloak in Azure app service. Actually the main issue it was not working because proxy sent requests with keycloak internal Host header, which is the only way it will work in my case.

Azure app gateway is using X-ORIGINAL-HOST, but X-Forwarded-Host seems to be more widely used header for original host name. I've tried setting X-Forwarded-Host at my proxy and finally it worked, although this approach is not mentioned in documentation. Check also this discussion https://keycloak.discourse.group/t/x-forwarded-host-proxy-header-support/10730

Related