Switching locale results in error: Missing parameter: response_type

Hello,

I have a custom theme that uses buttons to select the language instead of a dropdown:

<#if realm.internationalizationEnabled  && locale.supported?size gt 1>
    <div id="kc-locale">
        <div id="kc-locale-wrapper" class="${properties.kcLocaleWrapperClass!}">
            <div class="kc-dropdown lang-selection" id="kc-locale-dropdown">
                <#list locale.supported as l>
                    <span class="lang-option"><a href="${l.url}">${l.label}</a></span>
                </#list>
            </div>
        </div>
    </div>
</#if>

When I click the button to switch language, an error occurs:

KC-SERVICES0092: Missing parameter: response_type

Although the same ${l.url} is used in the base theme.
This issue started after upgrading from Keycloak 5 to 12. Is this a bug in Keycloak?

Regards

Update: it looks like the issue is not related to the custom theme, but rather to a custom authenticator.
When I bind the browser flow to the default browser flow, I can change language without problem.

I’ll keep you guys updated

I don’t understand why it is required to have a response_type in the URL with my custom authenticator set, but with the default UsernamePasswordForm it isn’t. I’d love to hear if someone can explain.

I solved my particular problem in an ugly but effective way:
<span class="lang-option"><a href="${l.url}&response_type=code">${l.label}</a></span>

Regardless of the flow, the Keycloak adapter redirects the user to /auth/realms/.../protocol/openid-connect/auth?... for login.

The value of {l.url} depends on the flow:

  • default flow: /auth/realms/.../login-actions/authenticate?...
  • flow with custom authenticator: /auth/realms/.../protocol/openid-connect/auth?...

It looks like the latter URL doesn’t recognize the kc_locale parameter and requires the response_type parameter.

The reason is the following: my custom authenticator uses a custom FTL form:

authenticationFlowContext.forceChallenge(authenticationFlowContext.form().createForm("customPage.ftl"));

This means that there is no LoginFormsPages defined in FreeMarkerLoginsFormsProvider::createCommonAttributes, resulting in the /protocol/openid-connect path.

I don’t see another solution than this ugly workaround in my custom FTL:

<span class="lang-option"><a href="${l.url?replace('protocol/openid-connect/auth','login-actions/authenticate')}">${l.label}</a></span>

I am surprised that this hasn’t been reported yet by other developers that use custom FTL pages in combination with internationalization.