Keycloak behind reverse proxy sends expire_code

Hello every@ne,

I am having a strange behaviour that I am not sure how to solve.

As you can see in the picture I am trying to use a service that requires a logged user, so Keycloak redirect me to the login form. After that the user logged correctly and I get a " Your login attempt timed out. Login will start from the beginning. " and in the log we get the following message

type=LOGIN_ERROR, realmId=XXXX, clientId=null, userId=null, ipAddress=..., error=expired_code, restart_after_timeout=true, authSessionParentId=eb98f5b9-9132-4348-bee7-c5d8b6a39878, authSessionTabId=xlxPjp_ZCM8

This is only happening when I try to access the service through the reverse proxy but using the IP or the or an alias of the machine, and the reverse proxy has registered to be accessible through the hostname.

I mean if the reverse proxy uses the “myhostname” I need to use that hostname else if I use “” or the IP of the machine, I get that expire_code log message.

That doesnt happen to the admin since the keycloak.frontendUrl is set to the hostname and then when accessing the admin the redirect_url changes the value automatically from “…” to “myhostname/auth/admin…”, so after login in there is a redirect to the admin.

Do I have to force always to replace the redirect_url in the reverse proxy, like the keycloak is doing?

Kind regards and hope someone can help me :frowning:

1 Like


I’m facing the exact same behaviour, have found anything to avoid this annoying thing ?

1 Like

Are you setting this properties in your environment?

I’m using keycloak behind a reverse proxy without any issue like yours.


@klinux Not setting anything like this.
Is that an env variable you set on the keycloak host machine ?

Yes, or you can configure inside keycloak definition.

setting ```

@klinux thanks for your help

Actually i already have this configuration

   <subsystem xmlns="urn:jboss:domain:undertow:10.0" default-server="default-server" default-virtual-host="default-host" default-servlet-container="default" default-security-domain="other" statistics-enabled="${wildfly.undertow.statistics-enabled:${wildfly.statistics-enabled:false}}">
            <buffer-cache name="default"/>
            <server name="default-server">
                <ajp-listener name="ajp" socket-binding="ajp"/>
                <http-listener name="default" socket-binding="http" enable-http2="true" proxy-address-forwarding="true" redirect-socket="proxy-https"/>
                <!-- <https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/> -->
                <host name="default-host" alias="localhost">
                    <location name="/" handler="welcome-content"/>
                    <filter-ref name="proxy-peer"/>
                    <http-invoker security-realm="ApplicationRealm"/>

But still have the issue.

Any other idea ? maybe this conf is wrong ?

Are you specifying keycloak.frontendUrl in keycloak, correct?
Like: keycloak.frontendUrl=, which configuration is in your reverse proxy? Is

Can you show the reverse proxy configuration?

Are you deploying keycloak on kubernetes or baremetal installation?

When you speak, if you use a hostname or keylock ip address, the code works correctly?

Hi @klinux

Indeed I was missing this configuration, so I added :

<spi name="hostname">
                <provider name="default" enabled="true">
                        <property name="frontendUrl" value="https://sso***.****.com"/>
                        <property name="forceBackendUrlToFrontendUrl" value="true"/>

But now i can’t event get the login page anymore.

Can’t show my reverse proxy settings as I have no control myself but the archiecture is like

https://mysso -> WAF -> load balancing (physical Load balancer) -> 4 instances of keycloak on 2 nodes

What I noticed is that without frontendUrl ans if I stop one node, it works fine.
COuld it be possible that the issue is comming from sync of cache of something between the two node ?

Check this configuration
If you have 4 instance, check it owners=“2”, number of owners, the recommendation, if you have 4 instances, and owners definition is 2, only two instances have the cache, try to set it to 4, but, it don’t necessary can be the problem, you have to make your loadbalance persist sessions with stick sessions, but you can try this.

@klinux I added the sticky session on the load balancer, it seems to fix the issue.
Still it sounds strange as I was pretty sure, sticky session was only a performance tuning ans not mandatory at all (as it is explained in the doc).
So i’m ondering is there is not an hidden issue that prevent my cluster to work without it :confused:

Yes, to me, it’s show that you cache owner definition is incorrect, can you try to configure the owners cache to the same size of your instances?

And another point, check if your cluster is replicate the cache correctly, to me, it can be the problem.

I’ll give it a try.

But even if each data is only on one instance, isn’t keycloak suppose to go fetch the missing data ?

Yes, according to documentation, when a instance do not has the session, it ask to another member, I think is that, I agree with you point, stick session can not be the solution. Because this, I believe that problem is a bad configuration on replication or inside cluster, are you using multicast cluster? TCP_PING or UDP_PING? Check that, look at logs and check if cluster can see all members.

Look this post, it can be more simple to implement cluster

@klinux I’m indeed using udp ping cluster

It seems only the two instances on my node are discovered

even if I can see :
[] (Host Controller Service Threads - 11) WFLYHC0019: Registered remote slave host “slave”, JBoss Keycloak 11.0.0 (WildFly 12.0.3.Final)

I believe that your problem is your cluster, try to solve that, the cluster needs all instances discovered, otherwise it will be running as standalone instance.

Did you fix your cluster?

Hi @klinux

Yeah I finally did find what was wrong, I got strong network policies in the company that make this happen.

now I can clearly see all the 4 instances :
[slave:server-one(site-id=, rack-id=null, machine-id=null), slave:server-two(site-id=, rack-id=null, machine-id=null), master:server-one(site-id=, rack-id=null, machine-id=null), master:server-two(site-id=, rack-id=null, machine-id=null)]

thanks a lot for your advices !