keycloak: Admin console not loading and hostname related issues

Describe the bug

It seems the new admin console doesn’t load properly under some configurations, and this has been reported many times in different issues.

This is serving as an umbrella issue to collect all the reported issues.

When reporting issues please use the hostname-debug tool to help us figure out what’s going on:

  1. Start Keycloak with the --hostname-debug=true option
  2. After starting Keycloak open KEYCLOAK_BASE_URL/realms/master/hostname-debug
  3. Copy/paste the results to comments below, this will allow us to figure out your configuration, reverse proxy settings, and the results. If URLs are sensitive please replace with example URLs

Reported issues:

Follow-up:

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 7
  • Comments: 66 (11 by maintainers)

Most upvoted comments

Just because I spent hours trying get it to work, it may help others. I read most of the linked tickets above to find the cause. Thanks for summarising the issues here! Once I figured it out, migrating from 16 to 19 was super easy.

During the testing on staging I ran into 403 (redirect_uri) and 404 (/resources) errors, because of wrong URLs, so mostly because of my stupidity. I literally tried all ENV var combinations I could think of. In the end I had mistakenly added the /admin to the admin URL.

Using bitnami/keycloak chart, setting the following:

  • set env KC_HOSTNAME_URL and KC_HOSTNAME_ADMIN_URL to the same value, including port, like https://my.domain:8443/, include /auth/ for backwards compatibility. No other KC_HOSTNAME* variables used.
  • setting httpRelativePath: "/auth/" for backwards compatibility (mind the trailing /)
  • setting proxy: edge
  • setting cache.enabled: true for infinispan (if using replicaCount > 1)
  • removing proxyAddressForwarding, old cache and serviceDiscovery sections and env KEYCLOAK_FRONTEND_URL

Once I got my stage setup up and running, upgrading production worked like a charm from chart version 7 to 10.

I found the issue with my setup:

  • Keycloak: 23.0.0, 23.0.1, nightly
  • Proxy: edge, reencrypt

I tried every combinations of the above.

It’s a Bug present in all recent versions of KeyCloak.

KeyCloak can not handle default ports!

I had to specify hostname-admin-url and hostname-url without the port!

Do not follow the documentation! https://www.keycloak.org/server/all-config

hostname-url Set the base URL for frontend URLs, including scheme, host, port and path.

Adding the port to the URL, when using default ports (80 or 443), breaks KeyCloak.

Apparently, KeyCloak consider “https://domain.com:443” to be a different URL from “https://domain.com” and refuse the request without giving any error messages.

If the hostname-admin-url or the hostname-url is not specified in the config, KeyCloak craft one for you, and includes the port in the URL, breaking itself. Screenshot from 2023-12-06 20-27-00 Screenshot from 2023-12-06 20-27-46

To get everything working on Keycloak 22 behind a TLS-terminating ingress in a Kubernetes cluster, we had to set the following environment variables:

  • KC_HOSTNAME to the hostname
  • KC_HOSTNAME_STRICT_HTTPS = true
  • KEYCLOAK_PROXY = edge
  • KC_HOSTNAME_ADMIN_URL to the default https URL of the host (basically https://$KC_HOSTNAME/)

Setting KC_HOSTNAME_ADMIN to the same value as KC_HOSTNAME doesn’t help, as it seems like for the admin console the strict-https is ignored, and the hostname-debug tool also shows it failing as an http-URL.

Keycloak 21 was fully functional with just setting KC_HOSTNAME explicitly, after the update to 22 everything broke down without the above settings. The admin console complained about invalid redirect uris, issued tokens were invalid etc.

It seems like there were several hidden changes to how these settings are handled between 21 and 22, and they should have been documented in the release notes and migration guide.

facing the similar issue, I am using keycloak 21.1.1 and deploying in EKS. accessing through kong gateway. image image image image image image image

here is my kc.yaml

apiVersion: k8s.keycloak.org/v2alpha1
kind: Keycloak
metadata:
  name: example-kc
spec:
  instances: 1
  db:
    vendor: postgres
    host: keycloak-ha-primary.default.svc
    usernameSecret:
      name: keycloak-ha-kcdb
      key: user
    passwordSecret:
      name: keycloak-ha-kcdb
      key: password
    database: keycloak-kcdb0
    port: 5432
  hostname:
    hostname: keycloak.<my-url>.cloud
    admin: keycloak.<my-url>.cloud
    strictBackchannel: true
    strict: true
  additionalOptions:
    - name: proxy
      value: "edge"
    - name: override
      value: "true"
    - name: hostname-strict-https
      value: "true"
  ingress:
      enabled: false
  http:
    httpEnabled: true
    httpPort: 8080

here is my ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  labels:
    app: keycloak
    app.kubernetes.io/managed-by: keycloak-operator
  name: example-kc-ingress
spec:
  ingressClassName: kong
  rules:
  - host: keycloak.<my-url>.cloud
    http:
      paths:
      - path: /
        backend:
          service:
            name: example-kc-service
            port:
              number: 8080
        pathType: Prefix

can any one help me here.

Guys, for everyone using helm chart (from bitnami)

adding this to custom values yaml fixes the problem:

extraEnvVars:
  - name: KC_HEALTH_ENABLED
    value: "true"
  - name: KEYCLOAK_PRODUCTION
    value: "true"
  - name: KEYCLOAK_PROXY
    value: "edge"

Especially last variable KEYCLOAK_PROXY=edge, informs keycloack that its internally running on http (which is the case when behing ingress) and it fixes issue

Proxy edge doesn’t fix access to the admin console when you are behind a proxy and not using the default port. Our solution has been to manually specify the X-Forwared-Port to the externally used port rather than the internal port which normally gets forwarded. The admin console seems to use that port properly (where it ignore the hostname-port property).

In my case it wasn’t working, because I specified the hostname-port=443, but should have removed it at all.

In my setup, both Keycloak frontend and admin UI were behind a proxy (proxy=edge) and were both exposed under default port 443 (although they had different hostnames though this is irrelevant).

Keycloak’s frontend was configured to build URLs from incoming request, but they all had port 443 in them because of the hostname-port=443. Admin URL was configured via hostname-admin-url and didn’t have port in it. As I found out the hostname-admin-url was not used at all in admin UI.

Keycloak admin UI relies on the following code:

resources/libs/keycloak-js/dist/keycloak.mjs

        var messageCallback = function(event) {
            if ((event.origin !== loginIframe.iframeOrigin) || (loginIframe.iframe.contentWindow !== event.source)) {
                return;
            }

Because 443 is a default for HTTPS browser was ignoring it, and event.origin value was simply https://keyloak.example.com.

Value of loginIframe.iframeOrigin on the other hand was set from OpenID Configuration, and those URLs contained port 443, so the above if was evaluated to false, because:

"https://keycloak.example.com" !== "https://keycloak.example.com:443"

So nothing was happening.

As I already mentioned, OpenID Configuration was enforcing the port in URL because hostname-port was explicitly set to 443, removing this value (defaulting to -1), removed the port from URLs and things started working again.

I would expect that Keycloak could be a bit smarter here, even if it just means fixing the URL comparison, as these are effectively the same: https://example.com == https://example.com:443

But also it could omit port from OpenID Configuration if it matches default ports (80 for HTTP, and 443 for HTTPS).

Hope this helps somebody.

For people using load balancer -> nginx ingress controller, these configs worked for me without using dev mode, no other http or hostname environment variables were used.

Without /auth

KC_HOSTNAME_ADMIN_URL: 'https://keycloak.example.com'
KC_HOSTNAME_URL: 'https://keycloak.example.com'
KC_HTTP_ENABLED: 'true'
KC_PROXY: none

With /auth

KC_HOSTNAME_ADMIN_URL: 'https://keycloak.example.com/auth'
KC_HOSTNAME_URL: 'https://keycloak.example.com/auth'
KC_HTTP_ENABLED: 'true'
KC_HTTP_RELATIVE_PATH: /auth/
KC_PROXY: none

# add following to the ingress
annotations: 
  nginx.ingress.kubernetes.io/app-root: /auth

For deployment via Helm, from https://artifacthub.io/packages/helm/bitnami/keycloak/ , I had to add this to values.yml:

extraEnvVars:
  - name: KC_HOSTNAME_ADMIN_URL
    value: "https://example.com"
  - name: KC_HOSTNAME_URL
    value: "https://example.com"

to avoid this issue.

Keycloak’s frontend was configured to build URLs from incoming request, but they all had port 443 in them because of the hostname-port=443. Admin URL was configured via hostname-admin-url and didn’t have port in it. As I found out the hostname-admin-url was not used at all in admin UI.

Thank you so, so much!

In my case, I had configured everything explicitly in the Apache Webserver proxy configuration and in keycloak.conf. The latter had

hostname-url=https://fqdn:433/keycloak/
hostname-admin-url=https://fqdn:443/keycloak/

and the admin page was not working (only showed the loading message). The welcome page was working, though.

After removing the ports in the URLs, everything works!

After hours of trying and reading I got it working with this configuration:

hostname-port=443
hostname-strict-ssl=true
hostname-url=https://some.domain/auth/
hostname-admin-url=https://some.domain/auth/

http-enabled=true
http-relative-path=/auth/

Important to state here is: I removed the port from the URLs and set strict-ssl to true. Prior to this changes it wasn’t working, loading wheel was spinning endlessly.

I’m using the latest 22.0 behind an apache proxy and didn’t set PROXY_ADDRESS_FORWARDING=true!

Hope that helps.

I’m using Keycloak 22.0.5, in order to avoid having to change the endpoints of all the microservices I have to reuse the path “/auth”, to keep it works like this:

      - name: KC_HOSTNAME_URL
        value: https://your.domain/auth
      - name: KC_HOSTNAME_STRICT
        value: "false"
      - name:  KC_HTTP_RELATIVE_PATH
        value: /auth

I am not able to load the admin console when I specify the port, this is behind a nginx proxy. The admin page just spins foreever. When I don’t specify the port everything works perfectly, even though I am specifying the same port that I am using by defaul. Here is the debug hostname output. I realize I can just not specify the port at all for this case, but I am trying to run on a non-default port, like 444, which also doesn’t work, although in that case it does report that the admin console has failed on the debug page.

It seems like I need to get the port into the admin console route but I’m not sure how. I need to be able to access the page from different sites so I can’t hardcode the full admin url and port which does work.

With the configuration the admin page spins forever, no error reported. image

Admin page also spins in this configuration, Chrome does report a 403 error as well. image

So thats quiet interesting. When I start the Server with bin/kc.sh start --optimized --hostname-debug=true and after loggin in i get this: Screenshot 2023-09-13 160726 but when im starting the server with bin/kc.sh start-dev Screenshot 2023-09-13 161344 then suddenly i can access everything.

Results from hostname-debug Screenshot 2023-09-13 161526

Some extra information: OS; Debian 10.2.1 Webserver: Apache DB: Postgres Server: – CPU: i7-7700 4c 8t – RAM: 64GB

Idk why it isnt working, please help 😃

A stupid Idea later and I could fix it myself 😃 Problem was that the user I created couldnt read the files and I tried it with root and it worked without any problems.

@wajohancarlstedt did you try this #21758 (comment) already? Jeah but I also found it weird that the default setup doesn’t work well with an Ingress (In my case ingress-nginx).

Yes, the following is set in our keycloak yaml

  additionalOptions:
    - name: proxy
      value: edge

Like I mentioned, it works in Chrome for some reason. 😃

This worked for me using ArgoCD:

source:
  chart: keycloak
  repoURL: https://charts.bitnami.com/bitnami
  targetRevision: 16.0.3
  helm:
    parameters:
      - name: "proxy"
        value: "edge"
    # Values file as block file
    values: |
      ---
      auth:
        adminUser: admin
        adminPassword: admin123
        managementPassword: admin123
      extraEnvVars:
        - name: KEYCLOAK_PROXY_ADDRESS_FORWARDING
          value: "true"
        - name: KEYCLOAK_ENABLE_HTTPS
          value: "false"

Not sure if you want to file a separate issue for it, since it may either be documentation and/or enhancement already known, but I was not able to get the admin console loaded when Keycloak was set up using the operator and accessed via a kubectl port-forward --address=0.0.0.0 8080:8080 no-HTTPS without reading the source code and a handful of issues on GitHub. Multiple things needed to be set, with the thing that took the longest to find was fixing the step1.html iframe URL which was not using the same port number with which I used to connect to the page.

keycloak

Which can be seen in the document because authServerUrl is used to form the src for the iframe:

  <script id="environment" type="application/json">
    {
      "loginRealm": "master",
      "authServerUrl": "http://auth-myapp.local",
      "authUrl": "http://auth-myapp.local:8080",
      "consoleBaseUrl": "/admin/master/console/",
      "resourceUrl": "/resources/8bbtd/admin/keycloak.v2",
      "masterRealm": "master",
      "resourceVersion": "8bbtd",
      "isRunningAsTheme": true
    }
  </script>

If it is helpful to fix code/doc issues, or anyone else that comes across this issue, this is the config that appears to have gotten the admin page loaded:

apiVersion: k8s.keycloak.org/v2alpha1
kind: Keycloak
metadata:
  name: keycloak-myapp
spec:
  instances: 1
  http:
    httpEnabled: true
  hostname:
    hostname: auth-myapp.local
    strict: false
    strictBackchannel: false
  additionalOptions:
    - name: hostname-strict-https
      value: "false"
    - name: hostname-port
      value: "8080"
  ingress:
    enabled: false
  db:
    vendor: postgres
    host: myapp-primary.data-postgres.svc
    usernameSecret:
      name: keycloak-database
      key: username
    passwordSecret:
      name: keycloak-database
      key: password

Which yields these settings:

spec:
  containers:
  - args:
    - start
    env:
    - name: KC_CACHE
      value: ispn
    - name: KC_CACHE_STACK
      value: kubernetes
    - name: KC_PROXY
      value: passthrough
    - name: KC_HEALTH_ENABLED
      value: "true"
    - name: KC_HOSTNAME_STRICT_HTTPS
      value: "false"
    - name: KC_HOSTNAME_PORT
      value: "8080"
    - name: KEYCLOAK_ADMIN
      valueFrom:
        secretKeyRef:
          key: username
          name: keycloak-myapp-initial-admin
          optional: false
    - name: KEYCLOAK_ADMIN_PASSWORD
      valueFrom:
        secretKeyRef:
          key: password
          name: keycloak-myapp-initial-admin
          optional: false
    - name: jgroups.dns.query
      value: keycloak-myapp-discovery.auth-keycloak
    - name: KC_HOSTNAME
      value: auth-myapp.local
    - name: KC_HOSTNAME_STRICT
      value: "false"
    - name: KC_HOSTNAME_STRICT_BACKCHANNEL
      value: "false"
    - name: KC_HTTP_ENABLED
      value: "true"
    - name: KC_HTTP_PORT
      value: "8080"
    - name: KC_HTTPS_PORT
      value: "8443"
    - name: KC_DB
      value: postgres
    - name: KC_DB_USERNAME
      valueFrom:
        secretKeyRef:
          key: username
          name: keycloak-database
    - name: KC_DB_PASSWORD
      valueFrom:
        secretKeyRef:
          key: password
          name: keycloak-database
    - name: KC_DB_URL_HOST
      value: myapp-primary.data-postgres.svc

I am having the same issue with 21.0.2. The provided workaround is not working.

well, I just solved the issue by using the browser debug console and solve each error one by one, here are some VERY important things I learned in the process. This is my setup: frp tunnel as the TLS terminator -> traefik -> keycloak, all inside the same podman pod, so the ports I exposed to the host system is irrelevant, all traffic is passing through the frp tunnel. following the server guides, I have my keycloak.conf file like this:

proxy=passthrough
http-enabled=true
hostname=mydomain.com
hostname-port=myport
hostname-admin-url=https://mydomain.com:myport

I’ll explain each relevant settings:

  • proxy: my setup clearly fits the passthrough definition in the “using a reverse proxy” guide. upon testing, because SSL is terminated by the frp tunnel, everything after is plain HTTP, so I also need to set http-enabled to true to allow keycloak to use the HTTP scheme, otherwise you need a certificate to start the server.
    • alternative: set proxy=edge anyway and not worry about truth.
  • hostname: either this or hostname-strict=false, or keycloak won’t start.
  • hostname-port: because I use frp tunnel service, the remote address’ 443 port is not available to me, I’ll have to set this to my real port, otherwise step1.html will be requested through https://mydomain.com (over default 443 port) rather than https://mydomain.com:myport. This is the only page that does this, and it’s really weird.
  • hostname-admin-url: this is the most tricky part. because my reverse proxy communicates with keycloak with HTTP, the allowed login origin has a scheme of http. However, the request will be constructed automatically from request headers, so the request’s origin is set to https, like this: https://mydomain.com:myport/realms/master/protocol/openid-connect/login-status-iframe.html/init?client_id=security-admin-console&origin=https://mydomain.com:myport. This mismatch result in a 403 forbidden error when requesting the login endpoint. You’ll have to manually set hostname-admin-url’s scheme to https to make the system allow https origin.

The only time (and even then it is questionable) to use HTTP in production is when TLS is terminated in a proxy. It does not make sense to expose Keycloak over HTTP even to internal clients. That is a risky an inherently dangerous thing to do. Bear in mind that you are sending credentials and tokens in clear text between Keycloak an internal clients in these cases, and don’t believe your firewall will always protect you.

You can always only have a single frontend URL, and a single admin URL, for Keycloak. It is not possible to expose Keycloak over multiple URLs (external/internal) with the built-in hostname provider. If you need to be able to do this you need to either disable the hostname provider, and enforce host headers, etc. at the proxy level (ideally also for internal clients), or you can implement a custom hostname provider.

Hi!

I noticed that the official command to run a development Keycloak instance as a docker container also leads to an unreachable admin console.

docker run -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:latest start-dev

http://localhost:8080/admin shows a HTTPS required error message.

Hello, I have the same issue.

Note that my keycloak is the latest version (19.0.3).

My admin console is stuck at loading. My keycloak conf file is:

hostname=hostname_test.com (The blackbox in the image below)
spi-truststore-file-file=CA_TRUSTSTORE_FILE
spi-truststore-file-password=xxxxxxxx
spi-truststore-file-hostname-verification-policy=ANY
https-trust-store-file=CA_TRUSTSTORE_FILE
https-trust-store-password= xxxxxxxx
https-certificate-file=SERVER_CERT_FILE
https-certificate-key-file=server.key
https-client-auth=required

login keycloak2 As you see, the 8080 port is omitted in the console logs. I also change my hostname configuration to: hostname_url=http://hostname_test.com:8080 but the admin console is stuck as well.

Am I making any mistakes in my configuration?