Keycloak ui_locales is ignored on requesting password reset link

Viewed 613

I am passing a chosen language from my web app into the keycloak login ui with keyCloakClient.createLoginUrl({locale: locale}) which correctly redirects me to: https://localhost/auth/realms/../protocol/openid-connect/auth?....&ui_locales=it. This shows me the content correctly in locale it.

For the password-reset link shown in the login form, I also added ui_locales=it to the url, which redirects me to: https://localhost/auth/realms/../login-actions/reset-credentials?....&ui_locales=it. This also shows me the content correctly in locale it.

Problem:

When I add ui_locales=it to the submission url for submitting the reset-password-request (${url.loginAction?no_esc} in login-reset-password.ftl, that generates the url https://localhost/auth/realms/../login-actions/reset-credentials?..), and I submit the form, I land on: https://localhost/auth/realms/../login-actions/authenticate?execution=.... This suddenly has no ui_locales in the url, and the content is therefore not translated in locale it.

To test if there are any magic redirections, i logged the network with preserve-log enabled. It shows only one new entry after clicking the reset-password-request button: https://localhost/auth/realms/../login-actions/reset-credentials?...&ui_locales=it.

Any ideas?

EDIT:

The same issue happens when submitting the login form with wrong credentials, to the action url (${url.loginAction?no_esc}) with appended &ui_locales=it.

It seems that locale query parameter is buggy since a while see Why are kc_locale and UI lang switch not working?. According to https://www.keycloak.org/docs/latest/release_notes/, in 9.0 was a change for locale, and was reverted in 9.0.1. Since then, there was no new change for locale. I am using 12.0.4.

Cookie approach:

I created the Cookie KEYCLOAK_LOCALE with JS on my React Login GUI, passing the locale value from the URL. It works only until a user logs in the very first time. Because then, Keycloak somehow sets the same Cookie with httpOnly, so that I can't read/write the Cookie value anymore with JS. So I can't overwrite the Cookie value on a new login, and I can't read the Cookie value to sync it with the React GUI localization.

  • Working usecase: Choose language in App -> redirect to Keycloak login -> set KEYCLOAK_LOCALE Cookie with value from the url (Keycloak & GUI language stay in sync now) -> go back to App -> change language in App -> redirect to Keycloak login -> Keycloak language can be updated over the Cookie with js because Cookie is not httpOnly.
  • Not working usecase: Choose language in App -> redirect to Keycloak login -> set KEYCLOAK_LOCALE Cookie with value from the url (Keycloak & GUI language stay in sync now) -> login -> Keycloak updates the Cookie to be httpOnly -> redirect back to App happens -> logout -> change language in App -> redirect to Keycloak login -> Keycloak language can't be updated over the Cookie with js because Cookie is httpOnly.
2 Answers

I've added this snippet to my code:

        <script type="text/javascript">
            (function() {
                if ('URLSearchParams' in window) {
                    let parameters = new URLSearchParams(location.search);
                    let locale = parameters.get('ui_locales');
                    if (locale != null) {
                        let [language, country] = locale.split('-');
                        document.cookie = "KEYCLOAK_LOCALE=" + language + "; path=/;";
                    }
                }
            })();
        </script>

Now on login page load i set KEYCLOAK_LOCALE from ui_locales parameter

I fix it by setting the cookie in template.ftl manually before reloading the page.

let me know if you need more support.

document.addEventListener("DOMContentLoaded", function() {
        let locales = 'ui_locales';

        document.getElementById("lang-link").addEventListener("click", function() {
            let switchTo = ...
            document.cookie = 'KEYCLOAK_LOCALE=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;'
            document.cookie = 'KEYCLOAK_LOCALE='+ switchTo;
            // change the language
            const currentUrl = new URL(window.location.href);
            currentUrl.searchParams.set(locales, switchTo);
            document.location.href = currentUrl;
        });
    });
    ```
Related