I'm trying to migrate a custom template from pre-Quarkus to Keycloak Quarkus (24.0.1).
It is located at <KEYCLOAK_HOME>/themes/base/login/consent-required-action.ftl
.
The template looks as follows:
<#import "template.ftl" as layout>
<@layout.registrationLayout; section>
<#if section = "title">
${msg("loginTitle",realm.name)}
<#elseif section = "header">
${msg("loginTitleHtml",realm.name)}
<#elseif section = "form">
<form id="kc-totp-login-form" class="${properties.kcFormClass!}" action="${url.loginAction}" method="post">
<div class="${properties.kcFormGroupClass!}">
<div class="${properties.kcLabelWrapperClass!}">
<label for="totp" class="${properties.kcLabelClass!}">
In order to proceed we need permission to load information about your username to our servers. Otherwise you won't be able to use our IT services.
</label>
</div>
</div>
<div class="${properties.kcFormGroupClass!}">
<div id="kc-form-options" class="${properties.kcFormOptionsClass!}">
<div class="${properties.kcFormOptionsWrapperClass!}">
</div>
</div>
<div id="kc-form-buttons" class="${properties.kcFormButtonsClass!}">
<div class="${properties.kcFormButtonsWrapperClass!}">
<input class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!}" name="accept" id="kc-accept" type="submit" value="${msg("doAccept")}"/>
<input class="${properties.kcButtonClass!} ${properties.kcButtonDefaultClass!} ${properties.kcButtonLargeClass!}" name="decline" id="kc-decline" type="submit" value="${msg("doDecline")}"/>
</div>
</div>
</div>
</form>
</#if>
</@layout.registrationLayout>
As soon as this template is uploaded and the web-interface is accessed it gives an "Internal Server Error" on the website and the keycloak-service logs the following error:
2024-03-27 18:46:36,383 ERROR [org.keycloak.forms.login.freemarker.FreeMarkerLoginFormsProvider] (executor-thread-2) Failed to process template: org.keycloak.theme.FreeMarkerException: Failed to process template login.ftl
at org.keycloak.theme.freemarker.DefaultFreeMarkerProvider.processTemplate(DefaultFreeMarkerProvider.java:52)
at org.keycloak.forms.login.freemarker.FreeMarkerLoginFormsProvider.processTemplate(FreeMarkerLoginFormsProvider.java:544)
at org.keycloak.forms.login.freemarker.FreeMarkerLoginFormsProvider.createResponse(FreeMarkerLoginFormsProvider.java:316)
at org.keycloak.forms.login.freemarker.FreeMarkerLoginFormsProvider.createLoginUsernamePassword(FreeMarkerLoginFormsProvider.java:558)
at org.keycloak.authentication.authenticators.browser.UsernamePasswordForm.challenge(UsernamePasswordForm.java:95)
at org.keycloak.authentication.authenticators.browser.UsernamePasswordForm.authenticate(UsernamePasswordForm.java:81)
at org.keycloak.authentication.DefaultAuthenticationFlow.processSingleFlowExecutionModel(DefaultAuthenticationFlow.java:442)
at org.keycloak.authentication.DefaultAuthenticationFlow.processFlow(DefaultAuthenticationFlow.java:246)
at org.keycloak.authentication.DefaultAuthenticationFlow.processSingleFlowExecutionModel(DefaultAuthenticationFlow.java:377)
at org.keycloak.authentication.DefaultAuthenticationFlow.processFlow(DefaultAuthenticationFlow.java:268)
at org.keycloak.authentication.AuthenticationProcessor.authenticateOnly(AuthenticationProcessor.java:1027)
at org.keycloak.protocol.AuthorizationEndpointBase.handleBrowserAuthenticationRequest(AuthorizationEndpointBase.java:116)
at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.buildAuthorizationCodeAuthorizationResponse(AuthorizationEndpoint.java:337)
at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.process(AuthorizationEndpoint.java:202)
at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.buildGet(AuthorizationEndpoint.java:113)
at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint$quarkusrestinvoker$buildGet_4b690b27439f19dd29733dc5fd4004f24de0adb6.invoke(Unknown Source)
at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:582)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:840)
Caused by: freemarker.template.TemplateNotFoundException: Template not found for name "login.ftl".
The name was interpreted by this TemplateLoader: org.keycloak.theme.freemarker.DefaultFreeMarkerProvider$ThemeTemplateLoader@4579404f.
at freemarker.template.Configuration.getTemplate(Configuration.java:2957)
at freemarker.template.Configuration.getTemplate(Configuration.java:2777)
at org.keycloak.theme.freemarker.DefaultFreeMarkerProvider.getTemplate(DefaultFreeMarkerProvider.java:66)
at org.keycloak.theme.freemarker.DefaultFreeMarkerProvider.processTemplate(DefaultFreeMarkerProvider.java:45)
... 25 more
2024-03-27 18:46:36,922 ERROR [org.keycloak.forms.login.freemarker.FreeMarkerLoginFormsProvider] (executor-thread-2) Failed to process template: org.keycloak.theme.FreeMarkerException: Failed to process template login.ftl
at org.keycloak.theme.freemarker.DefaultFreeMarkerProvider.processTemplate(DefaultFreeMarkerProvider.java:52)
at org.keycloak.forms.login.freemarker.FreeMarkerLoginFormsProvider.processTemplate(FreeMarkerLoginFormsProvider.java:544)
at org.keycloak.forms.login.freemarker.FreeMarkerLoginFormsProvider.createResponse(FreeMarkerLoginFormsProvider.java:316)
at org.keycloak.forms.login.freemarker.FreeMarkerLoginFormsProvider.createLoginUsernamePassword(FreeMarkerLoginFormsProvider.java:558)
at org.keycloak.authentication.authenticators.browser.UsernamePasswordForm.challenge(UsernamePasswordForm.java:95)
at org.keycloak.authentication.authenticators.browser.UsernamePasswordForm.authenticate(UsernamePasswordForm.java:81)
at org.keycloak.authentication.DefaultAuthenticationFlow.processSingleFlowExecutionModel(DefaultAuthenticationFlow.java:442)
at org.keycloak.authentication.DefaultAuthenticationFlow.processFlow(DefaultAuthenticationFlow.java:246)
at org.keycloak.authentication.DefaultAuthenticationFlow.processSingleFlowExecutionModel(DefaultAuthenticationFlow.java:377)
at org.keycloak.authentication.DefaultAuthenticationFlow.processFlow(DefaultAuthenticationFlow.java:268)
at org.keycloak.authentication.AuthenticationProcessor.authenticateOnly(AuthenticationProcessor.java:1027)
at org.keycloak.authentication.AuthenticationProcessor.authenticate(AuthenticationProcessor.java:884)
at org.keycloak.protocol.AuthorizationEndpointBase.handleBrowserAuthenticationRequest(AuthorizationEndpointBase.java:152)
at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.buildAuthorizationCodeAuthorizationResponse(AuthorizationEndpoint.java:337)
at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.process(AuthorizationEndpoint.java:202)
at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.buildGet(AuthorizationEndpoint.java:113)
at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint$quarkusrestinvoker$buildGet_4b690b27439f19dd29733dc5fd4004f24de0adb6.invoke(Unknown Source)
at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:582)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:840)
Caused by: freemarker.template.TemplateNotFoundException: Template not found for name "login.ftl".
The name was interpreted by this TemplateLoader: org.keycloak.theme.freemarker.DefaultFreeMarkerProvider$ThemeTemplateLoader@29e1cb6d.
at freemarker.template.Configuration.getTemplate(Configuration.java:2957)
at freemarker.template.Configuration.getTemplate(Configuration.java:2777)
at org.keycloak.theme.freemarker.DefaultFreeMarkerProvider.getTemplate(DefaultFreeMarkerProvider.java:66)
at org.keycloak.theme.freemarker.DefaultFreeMarkerProvider.processTemplate(DefaultFreeMarkerProvider.java:45)
... 26 more
2024-03-27 18:46:36,923 ERROR [org.keycloak.headers.DefaultSecurityHeadersProvider] (executor-thread-2) MediaType not set on path /auth/realms/master/protocol/openid-connect/auth, with response status 500
2024-03-27 18:46:36,924 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-2) Uncaught server error: jakarta.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error
at org.keycloak.headers.DefaultSecurityHeadersProvider.addHeaders(DefaultSecurityHeadersProvider.java:75)
at org.keycloak.services.filters.KeycloakSecurityHeadersFilter.filter(KeycloakSecurityHeadersFilter.java:43)
at org.jboss.resteasy.reactive.server.handlers.ResourceResponseFilterHandler.handle(ResourceResponseFilterHandler.java:25)
at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:150)
at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:582)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:840)
2024-03-27 18:46:36,927 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-2) Failed to create error page: org.keycloak.theme.FreeMarkerException: Failed to process template error.ftl
at org.keycloak.theme.freemarker.DefaultFreeMarkerProvider.processTemplate(DefaultFreeMarkerProvider.java:52)
at org.keycloak.services.error.KeycloakErrorHandler.getResponse(KeycloakErrorHandler.java:108)
at org.keycloak.services.error.KeycloakErrorHandler.toResponse(KeycloakErrorHandler.java:67)
at org.jboss.resteasy.reactive.server.core.RuntimeExceptionMapper.mapException(RuntimeExceptionMapper.java:100)
at org.jboss.resteasy.reactive.server.core.ResteasyReactiveRequestContext.mapExceptionIfPresent(ResteasyReactiveRequestContext.java:346)
at org.jboss.resteasy.reactive.server.handlers.ExceptionHandler.handle(ExceptionHandler.java:15)
at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:150)
at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:582)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:840)
Caused by: freemarker.template.TemplateNotFoundException: Template not found for name "error.ftl".
The name was interpreted by this TemplateLoader: org.keycloak.theme.freemarker.DefaultFreeMarkerProvider$ThemeTemplateLoader@74524fda.
at freemarker.template.Configuration.getTemplate(Configuration.java:2957)
at freemarker.template.Configuration.getTemplate(Configuration.java:2777)
at org.keycloak.theme.freemarker.DefaultFreeMarkerProvider.getTemplate(DefaultFreeMarkerProvider.java:66)
at org.keycloak.theme.freemarker.DefaultFreeMarkerProvider.processTemplate(DefaultFreeMarkerProvider.java:45)
... 14 more
2024-03-27 18:46:36,927 ERROR [org.keycloak.headers.DefaultSecurityHeadersProvider] (executor-thread-2) MediaType not set on path /auth/realms/master/protocol/openid-connect/auth, with response status 500
2024-03-27 18:46:36,930 ERROR [io.quarkus.vertx.http.runtime.QuarkusErrorHandler] (executor-thread-2) HTTP Request to /auth/realms/master/protocol/openid-connect/auth?client_id=<redacted>&redirect_uri=<redacted>&response_mode=fragment&response_type=code&scope=openid&nonce=<redacted>1&code_challenge=<redacted>&code_challenge_method=S256 failed, error id: 92f86fe9-2438-4a5b-9741-3a95fb53103b-1: jakarta.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error
at org.keycloak.headers.DefaultSecurityHeadersProvider.addHeaders(DefaultSecurityHeadersProvider.java:75)
at org.keycloak.services.filters.KeycloakSecurityHeadersFilter.filter(KeycloakSecurityHeadersFilter.java:43)
at org.jboss.resteasy.reactive.server.handlers.ResourceResponseFilterHandler.handle(ResourceResponseFilterHandler.java:25)
at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:150)
at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:582)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:840)
What is strange is that this happens without any provider uploaded that uses this template, nor the template being selected in the web-interface.
Also the error fails to process, not the template consent-required-action.ftl
or template.ftl
which is imported in the first, but rather it fails to process login.ftl
which is seemingly unrelated (Not imported in consent-required-action.ftl
nor in template.ftl
).
I checked if the referenced theme template.ftl
is also available in the Quarkus version, and while it has been moved from <KEYCLOAK_HOME>/themes/base/login/template.ftl
to the jar located at <KEYCLOAK_HOME>/lib/lib/main/org.keycloak.keycloak-themes-24.0.1.jar
in which it has the path theme/base/login/template.ftl
, it does still exist and has no notable changes.
Bundling the template with the jar solved the issue. Instead of placing the template within the <KEYCLOAK_HOME>/themes/
directory, I added the ftl
template in the jar under theme-resources/templates/
. It can now be used by custom providers.