Chapter 6. Using a reverse proxy Distributed environments frequently require the use of a reverse proxy. For Red Hat build of Keycloak, your choice of proxy modes depends on the TLS termination in your environment. 6.1. Proxy modes The following proxy modes are available: edge Enables communication through HTTP between the proxy and Red Hat build of Keycloak. This mode is suitable for deployments with a highly secure internal network where the reverse proxy keeps a secure connection (HTTP over TLS) with clients while communicating with Red Hat build of Keycloak using HTTP. reencrypt Requires communication through HTTPS between the proxy and Red Hat build of Keycloak. This mode is suitable for deployments where internal communication between the reverse proxy and Red Hat build of Keycloak should also be protected. Different keys and certificates are used on the reverse proxy as well as on Red Hat build of Keycloak. passthrough The proxy forwards the HTTPS connection to Red Hat build of Keycloak without terminating TLS. The secure connections between the server and clients are based on the keys and certificates used by the Red Hat build of Keycloak server. 6.2. Configure the proxy mode in Red Hat build of Keycloak To select the proxy mode, enter this command: bin/kc.[sh|bat] start --proxy <mode> 6.3. Configure the reverse proxy Some Red Hat build of Keycloak features rely on the assumption that the remote address of the HTTP request connecting to Red Hat build of Keycloak is the real IP address of the clients machine. When in edge or reencrypt proxy mode, Red Hat build of Keycloak will parse the following headers and expects the reverse proxy to set them: Forwarded as per RFC7239 Non-standard X-Forwarded Non-standard X-Forwarded-* , such as X-Forwarded-For , X-Forwarded-Proto , X-Forwarded-Host , and X-Forwarded-Port To set these headers, consult the documentation for your reverse proxy. Take extra precautions to ensure that the client address is properly set by your reverse proxy via the Forwarded or X-Forwarded-For headers. If this header is incorrectly configured, rogue clients can set this header and trick Red Hat build of Keycloak into thinking the client is connected from a different IP address than the actual address. This precaution can be more critical if you do any deny or allow listing of IP addresses. 6.4. Different context-path on reverse proxy Red Hat build of Keycloak assumes it is exposed through the reverse proxy under the same context path as Red Hat build of Keycloak is configured for. By default Red Hat build of Keycloak is exposed through the root ( / ), which means it expects to be exposed through the reverse proxy on / as well. You can use hostname-path or hostname-url in these cases, for example using --hostname-path=/auth if Red Hat build of Keycloak is exposed through the reverse proxy on /auth . Alternatively you can also change the context path of Red Hat build of Keycloak itself to match the context path for the reverse proxy using the http-relative-path option, which will change the context-path of Red Hat build of Keycloak itself to match the context path used by the reverse proxy. 6.5. Trust the proxy to set hostname By default, Red Hat build of Keycloak needs to know under which hostname it will be called. If your reverse proxy is configured to check for the correct hostname, you can set Red Hat build of Keycloak to accept any hostname. bin/kc.[sh|bat] start --proxy <mode> --hostname-strict=false 6.6. Enable sticky sessions Typical cluster deployment consists of the load balancer (reverse proxy) and 2 or more Red Hat build of Keycloak servers on private network. For performance purposes, it may be useful if load balancer forwards all requests related to particular browser session to the same Red Hat build of Keycloak backend node. The reason is, that Red Hat build of Keycloak is using Infinispan distributed cache under the covers for save data related to current authentication session and user session. The Infinispan distributed caches are configured with two owners by default. That means that particular session is primarily stored on two cluster nodes and the other nodes need to lookup the session remotely if they want to access it. For example if authentication session with ID 123 is saved in the Infinispan cache on node1, and then node2 needs to lookup this session, it needs to send the request to node1 over the network to return the particular session entity. It is beneficial if particular session entity is always available locally, which can be done with the help of sticky sessions. The workflow in the cluster environment with the public frontend load balancer and two backend Red Hat build of Keycloak nodes can be like this: User sends initial request to see the Red Hat build of Keycloak login screen This request is served by the frontend load balancer, which forwards it to some random node (eg. node1). Strictly said, the node doesn't need to be random, but can be chosen according to some other criterias (client IP address etc). It all depends on the implementation and configuration of underlying load balancer (reverse proxy). Red Hat build of Keycloak creates authentication session with random ID (eg. 123) and saves it to the Infinispan cache. Infinispan distributed cache assigns the primary owner of the session based on the hash of session ID. See Infinispan documentation for more details around this. Let's assume that Infinispan assigned node2 to be the owner of this session. Red Hat build of Keycloak creates the cookie AUTH_SESSION_ID with the format like <session-id>.<owner-node-id> . In our example case, it will be 123.node2 . Response is returned to the user with the Red Hat build of Keycloak login screen and the AUTH_SESSION_ID cookie in the browser From this point, it is beneficial if load balancer forwards all the requests to the node2 as this is the node, who is owner of the authentication session with ID 123 and hence Infinispan can lookup this session locally. After authentication is finished, the authentication session is converted to user session, which will be also saved on node2 because it has same ID 123 . The sticky session is not mandatory for the cluster setup, however it is good for performance for the reasons mentioned above. You need to configure your loadbalancer to sticky over the AUTH_SESSION_ID cookie. How exactly do this is dependent on your loadbalancer. If your proxy supports session affinity without processing cookies from backend nodes, you should set the spi-sticky-session-encoder-infinispan-should-attach-route option to false in order to avoid attaching the node to cookies and just rely on the reverse proxy capabilities. bin/kc.[sh|bat] start --spi-sticky-session-encoder-infinispan-should-attach-route=false By default, the spi-sticky-session-encoder-infinispan-should-attach-route option value is true so that the node name is attached to cookies to indicate to the reverse proxy the node that subsequent requests should be sent to. 6.6.1. Exposing the administration console By default, the administration console URLs are created solely based on the requests to resolve the proper scheme, host name, and port. For instance, if you are using the edge proxy mode and your proxy is misconfigured, backend requests from your TLS termination proxy are going to use plain HTTP and potentially cause the administration console from being accessible because URLs are going to be created using the http scheme and the proxy does not support plain HTTP. In order to proper expose the administration console, you should make sure that your proxy is setting the X-Forwarded-* headers herein mentioned in order to create URLs using the scheme, host name, and port, being exposed by your proxy. 6.6.2. Exposed path recommendations When using a reverse proxy, Red Hat build of Keycloak only requires certain paths need to be exposed. The following table shows the recommended paths to expose. Red Hat build of Keycloak Path Reverse Proxy Path Exposed Reason / - No When exposing all paths, admin paths are exposed unnecessarily. /admin/ - No Exposed admin paths lead to an unnecessary attack vector. /js/ - Yes (see note below) Access to keycloak.js needed for "internal" clients, e.g. the account console /welcome/ - No No need exists to expose the welcome page after initial installation. /realms/ /realms/ Yes This path is needed to work correctly, for example, for OIDC endpoints. /resources/ /resources/ Yes This path is needed to serve assets correctly. It may be served from a CDN instead of the Red Hat build of Keycloak path. /robots.txt /robots.txt Yes Search engine rules /metrics - No Exposed metrics lead to an unnecessary attack vector. /health - No Exposed health checks lead to an unnecessary attack vector. Note As it's true that the js path is needed for internal clients like the account console, it's good practice to use keycloak.js from a JavaScript package manager like npm or yarn for your external clients. We assume you run Red Hat build of Keycloak on the root path / on your reverse proxy/gateway's public API. If not, prefix the path with your desired one. 6.6.3. Enabling client certificate lookup When the proxy is configured as a TLS termination proxy the client certificate information can be forwarded to the server through specific HTTP request headers and then used to authenticate clients. You are able to configure how the server is going to retrieve client certificate information depending on the proxy you are using. The server supports some of the most commons TLS termination proxies such as: Proxy Provider Apache HTTP Server apache HAProxy haproxy NGINX nginx To configure how client certificates are retrieved from the requests you need to: Enable the corresponding proxy provider bin/kc.[sh|bat] build --spi-x509cert-lookup-provider=<provider> Configure the HTTP headers bin/kc.[sh|bat] start --spi-x509cert-lookup-<provider>-ssl-client-cert=SSL_CLIENT_CERT --spi-x509cert-lookup-<provider>-ssl-cert-chain-prefix=CERT_CHAIN --spi-x509cert-lookup-<provider>-certificate-chain-length=10 When configuring the HTTP headers, you need to make sure the values you are using correspond to the name of the headers forwarded by the proxy with the client certificate information. The available options for configuring a provider are: Option Description ssl-client-cert The name of the header holding the client certificate ssl-cert-chain-prefix The prefix of the headers holding additional certificates in the chain and used to retrieve individual certificates accordingly to the length of the chain. For instance, a value CERT_CHAIN will tell the server to load additional certificates from headers CERT_CHAIN_0 to CERT_CHAIN_9 if certificate-chain-length is set to 10 . certificate-chain-length The maximum length of the certificate chain. trust-proxy-verification Enable trusting NGINX proxy certificate verification, instead of forwarding the certificate to Red Hat build of Keycloak and verifying it in Red Hat build of Keycloak. 6.6.3.1. Configuring the NGINX provider The NGINX SSL/TLS module does not expose the client certificate chain. Red Hat build of Keycloak's NGINX certificate lookup provider rebuilds it by using the Red Hat build of Keycloak truststore. If you are using this provider, see Configuring trusted certificates for outgoing requests for how to configure a Red Hat build of Keycloak Truststore. 6.7. Relevant options Value hostname-path This should be set if proxy uses a different context-path for Keycloak. CLI: --hostname-path Env: KC_HOSTNAME_PATH hostname-url Set the base URL for frontend URLs, including scheme, host, port and path. CLI: --hostname-url Env: KC_HOSTNAME_URL http-relative-path 🛠 Set the path relative to / for serving resources. The path must start with a / . CLI: --http-relative-path Env: KC_HTTP_RELATIVE_PATH / (default) proxy The proxy address forwarding mode if the server is behind a reverse proxy. CLI: --proxy Env: KC_PROXY none (default), edge , reencrypt , passthrough

Commands:
bin/kc.[sh|bat] start --proxy <mode>
bin/kc.[sh|bat] start --proxy <mode> --hostname-strict=false
bin/kc.[sh|bat] start --spi-sticky-session-encoder-infinispan-should-attach-route=false
bin/kc.[sh|bat] build --spi-x509cert-lookup-provider=<provider>
bin/kc.[sh|bat] start --spi-x509cert-lookup-<provider>-ssl-client-cert=SSL_CLIENT_CERT --spi-x509cert-lookup-<provider>-ssl-cert-chain-prefix=CERT_CHAIN --spi-x509cert-lookup-<provider>-certificate-chain-length=10