I have used Vue 3 and vuetify with webpack.config for buidling keycloak theme. When user enters asn invalid url, I expect that error page rendered, but the following error appears:
Internal Server Error , Error id 9b20c47f-d0d6-4b7d-ab92-1f107c5b5c9e-45
I also have defined my template.ftl as follows:
<#macro registrationLayout bodyClass="" displayInfo=false displayMessage=true displayRequiredFields=false showAnotherWayIfPresent=true>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" class="${properties.kcHtmlClass!}">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="icon" href="${url.resourcesPath}/img/kando.ico" />
<meta name="robots" content="noindex, nofollow">
<link href='${url.resourcesPath}/css/index.css' rel='stylesheet'/>
<#nested "styles">
</head>
<body>
<div id="app"></div>
<script id="environment" type="application/json">
{
"urls": {
"project":"${url.resourcesPath}",
"loginResetCredentials": "${url.loginResetCredentialsUrl}",
"login": "${url.loginUrl}",
"registration": "${url.registrationUrl}",
"loginAction": "${url.loginAction}",
"registrationAction": "${url.registrationAction}",
"loginRestartFlowUrl":"${url.loginRestartFlowUrl}"
},
"titles": {
"loginProfileTitle": "${msg("loginProfileTitle")}",
"loginAccountTitle": "${msg("loginAccountTitle")}",
"registerTitle": "${msg("registerTitle")}",
"emailForgotTitle": "${msg("emailForgotTitle")}",
"confirmLinkIdpTitle": "${msg("confirmLinkIdpTitle")}",
"emailLinkIdpTitle": "${msg("emailLinkIdpTitle", idpDisplayName)}"
},
"permissions": {
"usernameEditDisabled": <#if usernameEditDisabled??>true<#else>false</#if>,
"loginWithEmailAllowed": <#if realm.loginWithEmailAllowed>true<#else>false</#if>,
"registrationEmailAsUsername": <#if realm.registrationEmailAsUsername>true<#else>false</#if>,
"rememberMe": <#if realm.rememberMe>true<#else>false</#if>,
"resetPasswordAllowed": <#if realm.resetPasswordAllowed>true<#else>false</#if>,
"password": <#if realm.password>true<#else>false</#if>,
"registrationAllowed": <#if realm.registrationAllowed>true<#else>false</#if>,
"registrationDisabled": <#if registrationDisabled??>true<#else>false</#if>,
"passwordRequired": <#if passwordRequired??>true<#else>false</#if>,
"phoneNumberIsRequired": <#if phoneNumberRequired??>true<#else>false</#if>,
"verifyPhoneIsRequired": <#if verifyPhone??>true<#else>false</#if>,
"supportPhone": <#if supportPhone??>true<#else>false</#if>
},
"error":{
"errorCondition": <#if !(auth?has_content && auth.showUsername() && !auth.showResetCredentials())>true<#else>false</#if>,
"requiredField": <#if displayRequiredFields>true<#else>false</#if>
},
"labels": {
"firstName": "${msg("firstName")}",
"lastName": "${msg("lastName")}",
"username": "${msg("username")}",
"usernameOrEmail": "${msg("usernameOrEmail")}",
"email": "${msg("email")}",
"password": "${msg("password")}",
"passwordConfirm": "${msg("passwordConfirm")}",
"rememberMe": "${msg("rememberMe")}",
"doForgotPassword": "${msg("doForgotPassword")}",
"doLogIn": "${msg("doLogIn")}",
"doSubmit": "${msg("doSubmit")}",
"noAccount": "${msg("noAccount")}",
"doRegister": "${msg("doRegister")}",
"backToLogin": "${kcSanitize(msg("backToLogin"))?no_esc}",
"confirmLinkIdpContinue": "${msg("confirmLinkIdpContinue")}",
"doClickHere": "${msg("doClickHere")}"
},
"totp":{
"totpTopSecret": <#if totp??>"${(totp.totpSecret!'')}"<#else>""</#if>,
"totpQrCode": <#if totp??>"${(totp.totpSecretQrCode)}"<#else>""</#if>,
"totpError": <#if messagesPerField.existsError('totp')>true<#else>false</#if>
},
"forms": {
"loginUsername": "${(login.username!'')}",
"loginRememberMe": <#if login.rememberMe??>true<#else>false</#if>,
"selectedCredential": "${(auth.selectedCredential!'')}",
"registerFirstName": <#if register??>"${(register.formData.firstName!'')}"<#else>""</#if>,
"registerLastName": <#if register??>"${(register.formData.lastName!'')}"<#else>""</#if>,
"registerEmail": <#if register??>"${(register.formData.email!'')}"<#else>""</#if>,
"registerUsername": <#if register??>"${(register.formData.username!'')}"<#else>""</#if>
},
"user": {
"username": <#if user??>"${(user.username!'')}"<#else>""</#if>,
"email": <#if user??>"${(user.email!'')}"<#else>""</#if>,
"firstName": <#if user??>"${(user.firstName!'')}"<#else>""</#if>,
"lastName": <#if user??>"${(user.lastName!'')}"<#else>""</#if>
},
"validations": {
"firstName": <#if messagesPerField.existsError('firstName')>"${kcSanitize(messagesPerField.get('firstName'))?no_esc}"<#else>""</#if>,
"lastName": <#if messagesPerField.existsError('lastName')>"${kcSanitize(messagesPerField.get('lastName'))?no_esc}"<#else>""</#if>,
"email": <#if messagesPerField.existsError('email')>"${kcSanitize(messagesPerField.get('email'))?no_esc}"<#else>""</#if>,
"usernameOrPassword": <#if messagesPerField.existsError('username','password')>"${kcSanitize(messagesPerField.getFirstError('username','password'))?no_esc}"<#else>""</#if>,
"username": <#if messagesPerField.existsError('username')>"${kcSanitize(messagesPerField.get('username'))?no_esc}"<#else>""</#if>,
"password": <#if messagesPerField.existsError('password')>"${kcSanitize(messagesPerField.get('password'))?no_esc}"<#else>""</#if>,
"passwordConfirm": <#if messagesPerField.existsError('password-confirm')>"${kcSanitize(messagesPerField.get('password-confirm'))?no_esc}"<#else>""</#if>,
"PhoneOrCode": <#if messagesPerField.existsError('code','phoneNumber')>"${kcSanitize(messagesPerField.getFirstError('phoneNumber','code'))?no_esc}"<#else>""</#if>,
"RegisterCode": <#if messagesPerField.existsError('registerCode')>"${kcSanitize(messagesPerField.get('registerCode'))?no_esc}"<#else>""</#if>
},
"message": {
"type": <#if displayMessage && message?has_content && (message.type != 'warning' || !isAppInitiatedAction??)>"${message.type}"<#else>""</#if>,
"summary": <#if displayMessage && message?has_content && (message.type != 'warning' || !isAppInitiatedAction??)>"${kcSanitize(message.summary)?no_esc}"<#else>""</#if>
},
"instruction": {
"title": "${msg("appRealmName",realm.displayName)}",
"realmTitle":"${msg("realName",realm.name)}",
"emailLinkIdp1": "${msg("emailLinkIdp1", idpDisplayName, realm.username, realm.displayName)}",
"emailLinkIdp2": "${msg("emailLinkIdp2")}",
"emailLinkIdp3": "${msg("emailLinkIdp3")}",
"emailLinkIdp4": "${msg("emailLinkIdp4")}",
"emailLinkIdp5": "${msg("emailLinkIdp5")}"
},
"social": [
<#if realm.password && social.providers??>
<#list social.providers as p>
{
"alias": "${p.alias}",
"displayName": "${p.displayName!}",
"loginUrl": "${p.loginUrl}"
}<#sep>, </#sep>
</#list>
</#if>
]
}
</script>
<#nested "scripts">
</body>
</html>
</#macro>
and each page built by webpack.config as the following structure: for example my error.ftl page:
<#import "template.ftl" as layout>
<@layout.registrationLayout; section>
<#if section = "scripts">
<script typo="module" src="${url.resourcesPath}/js/error.js"></script>
</#if>
</@layout.registrationLayout>
, when user enters an invalid url, i expect that the error page appears, but the following error is shown by keycloak:
FTL stack trace (“~” means nesting-related):
idp | - Failed at: ${url.loginAction} [in template “template.ftl” in macro “registrationLayout” at line 28, column 25]
idp | - Reached through: @layout.registrationLayout displayMes… [in template “error.ftl” at line 2, column 1]