Hello everyone,
We are trying to implement a custom Authenticator which will be eventually used within the password reset flow. This custom authenticator will be in general responsible to integrate with an external service.
At some point we will need to move the FE control to this external service provider (meaning that at that point we are going to switch from rendering keycloak page to rendering FE of the provider).
As soon as the flow of the external service is completed we will be redirected back to keycloak FE and should continue our flow from the point where we remained (we will have to provide the redirect URL right before switching the FE control to this external service).
Here is the tricky part. We are providing as redirect URL the current keycloak URL including the parameters client_id, tab_id, execution and client_data
We are not including the session_code since the redirection from the external service will be a GET request and not a POST.
The thing is that this actually works most of the time, but in some cases the execution stored in cookie has changed for some unknown reason. So when it’s compared with the execution provided as parameter (SessionCodeChecks.java of keycloak source) it ends up sending us to keycloak’s “expired page”.
So the general question is whether keycloak supports staying in the current flow step by performing a GET request including these parameters (either by manually refreshing the browser page, or in our case as a consequence of a redirection from an external service page back to this URL). In most cases it works but there are cases where we are being redirected to the “expired page”.
You should not create the URL yourself. Dealing manually with tab_id and execution will lead sooner or later to errors, as you already experienced.
Instead, you should use the methods, Keycloak is already providing to you for getting, e.g. in this case, a refreshURL from the authentication context. See also my example of a magic-link authenticator, where the link will be used to „continue“ the started authentication.
Wow thank you for your prompt response! Thanks for letting me know about the existence of context.getRefreshExecutionUrl()! To be more precise in our implementation we didn’t use a custom solution to construct the current URL but instead we used the method context.getActionUrl(String code). But the method that you just highlighted is indeed the ideal one!
In our case we constructed the URL using context.getActionUrl(String code) with a dummy code which we later removed (since the action URL which includes a session_code is intended to be used for POST requests as a response to a challenge). We see that the internal implementation of those methods is the same with the only difference in the session_code inclusion. However for sure we will use your suggestion as we will avoid using a dummy session_code and clearing it later!
So this means that keycloak indeed supports the logic to stay on the same step using such a URL (We just wanted to be sure that we are not trying to do something which is not supported by Keycloak).
I have got one more question though because this might explain why we get errors even if we construct the URL using an existing method provided by context. What if we try to refresh this page again a couple of times (instead of just using it once)? Is there a chance that keycloak might end up generating internally a new execution (different than the initial one) on one of the upcoming refreshes that could lead us to the expiration page?
So in other words each time this page is refreshed should we calculate again this URL (for the subsequent refresh ) in order to be sure that we are always getting the correct parameters?
I am mentioning that scenario because in our solution we have implemented a custom theme implementation that would try to automatically refresh the page using a specific interval (this will happen as soon as we get back from the FE of this external service back to keycloak FE) . Each time a refresh is performed, our custom Authenticator will try to call an endpoint of the external service until we get a terminal response. As soon as we get a positive response from this external service the flow will be continued and we will proceed to the password reset page. So do you think that on each refresh we should always re-calculate the next refresh URL?
It’s also worth mentioning that each time this refresh is performed we are keeping an AuthenticationSession Note to track the number of the automatic refresh attempts performed. If the number of refreshes exceeds a given limit, the flow will be marked as failed (we will not keep refreshing forever).
We have got an update on that problem! It seems that the problem in our case was the way our custom theme implementation was polling the endpoint. It turned out that it was performing an additional unnecessary poll request although the flow had already progressed to the next step (which means that the execution parameter was new as it was now referring to the next step). This way the previous URL was no longer valid that’s why it ended up redirecting us to the expired page of keycloak.