KEYCLOAK-16455 Solution to silent fails of JS adapter

5,572 views
Skip to first unread message

Michal Hajas

unread,
Jun 14, 2021, 11:29:21 AM6/14/21
to Keycloak Dev
Hello all,

Currently, init function in Keycloak JS adapter silently fails when Keycloak URL is unavailable or realm is wrongly configured.

The reason is how our 3rd party cookies support check works [1].
1. We create an iframe and a message callback that resolves a promise when a message is received from the iframe.
2. We return the promise and wait for it to be resolved
3. When promise is resolved successfully we continue with initialiation

The problem is, that when the message is never received in the callback (for example when Keycloak is not available or realm name is wrong), we never resolve the promise and hence the adapter is never initialized nor the error is reported.

Unfortunately, iframe doesn't have any onError callback, so we can't use it. We were considering 2 solutions to this:

1. Send a request before each 3rd party check which checks whether the Keycloak server is available and also whether specified realm exists. This works, however, sending a request with each init function call will cause a lot of useless network overhead especially in stable/production deployments where unavailability doesn't happen so often. See code for more details: https://github.com/keycloak/keycloak/pull/7901/files


2. The other solution is to use timeout for 3rd party cookies check. The timeout mechanism for promises can be reused also for other parts of code in the future. The disadvantage is that we don't know the exact reason of failure, we just know that we didn't receive the message in specified time. This can also cause false errors in some unstable environments like mobile networks. Code: https://github.com/keycloak/keycloak/pull/8161/files

WDYT? Which solution is better? Do you know about some better solution?

Best regards,
Michal

Jon Koops

unread,
Jun 14, 2021, 11:42:55 AM6/14/21
to Michal Hajas, Keycloak Dev
It takes advantage of the fact that the 'message' event is triggered before the 'load' event, and because the iframe is removed right away the 'load' event never triggers unless something goes wrong loading the iframe. It's not a beautiful solution, but seems to work as expected cross-browser. Iframes do not have an 'error' event, which makes these kinds of checks complicated.

I am personally not a big fan of a timeout solution, as there might be legitimate reasons why a request takes a long time (such as poor network conditions). For performance reasons it's also not great to make a preflight request, but still a better option than what is happening now. There is however no guarantee that the network conditions have not changed between the pre-flight request and the iframe loading in, so the error handling would still not be perfect.

--
You received this message because you are subscribed to the Google Groups "Keycloak Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to keycloak-dev...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/keycloak-dev/fbe1a23a-af40-4f21-8a25-ec2ad0afe85an%40googlegroups.com.

Michal Hajas

unread,
Jun 15, 2021, 3:28:26 AM6/15/21
to Jon Koops, Keycloak Dev
Hello Jon,

Thank you for sharing that. I played with your PR a little and it seems the solution doesn't work for me. I am not sure if I am doing something wrong, but I encountered two problems.

1. On PhantomJS, init sometimes fails even if keycloak is available, it seems that onload function is sometimes called when it shouldn't. This is not such a big problem, as we can replace PhantomJS with Chrome and it seems in Chrome this does not happen. But anyway, are you sure this solution will work in all browsers? I am a little bit concerned that this can cause false errors if the onload function is called when it shouldn't, like, for example, if there is some latency between iframe load and message receiving. 

2. The second problem is more serious though. The test you added is failing also on Chrome for me. I tried to debug the JS adapter and it seems the onload function is never called when keycloak is unavailable. Does it pass for you?

Michal Hajas

unread,
Jun 22, 2021, 7:23:30 AM6/22/21
to Jon Koops, Keycloak Dev
Hello everyone,

from the discussion here: https://github.com/keycloak/keycloak/pull/7901 it seems that PR: https://github.com/keycloak/keycloak/pull/8161 is the way to go. Thank you very much for all the answers!

Michal
Reply all
Reply to author
Forward
0 new messages