Copy/pasta over login from the base theme
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
c215e7997f
commit
1134b4572b
@ -1,3 +1,5 @@
|
|||||||
# lumbung.space
|
# lumbung.space
|
||||||
|
|
||||||
Custom theme for [login.lumung.space](https://login.lumbung.space).
|
Custom theme for [login.lumung.space](https://login.lumbung.space).
|
||||||
|
|
||||||
|
- [login](./login) was copied from [default-themes/base/login](../default-themes/base/login)
|
||||||
|
7
lumbung.space/login/cli_splash.ftl
Normal file
7
lumbung.space/login/cli_splash.ftl
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
_ __ _ _
|
||||||
|
| |/ /___ _ _ ___| | ___ __ _| | __
|
||||||
|
| ' // _ \ | | |/ __| |/ _ \ / _` | |/ /
|
||||||
|
| . \ __/ |_| | (__| | (_) | (_| | <
|
||||||
|
|_|\_\___|\__, |\___|_|\___/ \__,_|_|\_\
|
||||||
|
|___/
|
||||||
|
|
19
lumbung.space/login/code.ftl
Executable file
19
lumbung.space/login/code.ftl
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout; section>
|
||||||
|
<#if section = "header">
|
||||||
|
<#if code.success>
|
||||||
|
${msg("codeSuccessTitle")}
|
||||||
|
<#else>
|
||||||
|
${msg("codeErrorTitle", code.error)}
|
||||||
|
</#if>
|
||||||
|
<#elseif section = "form">
|
||||||
|
<div id="kc-code">
|
||||||
|
<#if code.success>
|
||||||
|
<p>${msg("copyCodeInstruction")}</p>
|
||||||
|
<input id="code" class="${properties.kcTextareaClass!}" value="${code.code}"/>
|
||||||
|
<#else>
|
||||||
|
<p id="error">${code.error}</p>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
</@layout.registrationLayout>
|
33
lumbung.space/login/delete-account-confirm.ftl
Normal file
33
lumbung.space/login/delete-account-confirm.ftl
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout; section>
|
||||||
|
|
||||||
|
<#if section = "header">
|
||||||
|
${msg("deleteAccountConfirm")}
|
||||||
|
|
||||||
|
<#elseif section = "form">
|
||||||
|
|
||||||
|
<form action="${url.loginAction}" class="form-vertical" method="post">
|
||||||
|
|
||||||
|
<div class="alert alert-warning" style="margin-top:0 !important;margin-bottom:30px !important">
|
||||||
|
<span class="pficon pficon-warning-triangle-o"></span>
|
||||||
|
${msg("irreversibleAction")}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>${msg("deletingImplies")}</p>
|
||||||
|
<ul style="color: #72767b;list-style: disc;list-style-position: inside;">
|
||||||
|
<li>${msg("loggingOutImmediately")}</li>
|
||||||
|
<li>${msg("errasingData")}</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p class="delete-account-text">${msg("finalDeletionConfirmation")}</p>
|
||||||
|
|
||||||
|
<div id="kc-form-buttons">
|
||||||
|
<input class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!}" type="submit" value="${msg("doConfirmDelete")}" />
|
||||||
|
<#if triggered_from_aia>
|
||||||
|
<button class="${properties.kcButtonClass!} ${properties.kcButtonDefaultClass!} ${properties.kcButtonLargeClass!}" style="margin-left: calc(100% - 220px)" type="submit" name="cancel-aia" value="true" />${msg("doCancel")}</button>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
</@layout.registrationLayout>
|
13
lumbung.space/login/error.ftl
Executable file
13
lumbung.space/login/error.ftl
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout displayMessage=false; section>
|
||||||
|
<#if section = "header">
|
||||||
|
${msg("errorTitle")}
|
||||||
|
<#elseif section = "form">
|
||||||
|
<div id="kc-error-message">
|
||||||
|
<p class="instruction">${message.summary?no_esc}</p>
|
||||||
|
<#if client?? && client.baseUrl?has_content>
|
||||||
|
<p><a id="backToApplication" href="${client.baseUrl}">${kcSanitize(msg("backToApplication"))?no_esc}</a></p>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
</@layout.registrationLayout>
|
24
lumbung.space/login/info.ftl
Executable file
24
lumbung.space/login/info.ftl
Executable file
@ -0,0 +1,24 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout displayMessage=false; section>
|
||||||
|
<#if section = "header">
|
||||||
|
<#if messageHeader??>
|
||||||
|
${messageHeader}
|
||||||
|
<#else>
|
||||||
|
${message.summary}
|
||||||
|
</#if>
|
||||||
|
<#elseif section = "form">
|
||||||
|
<div id="kc-info-message">
|
||||||
|
<p class="instruction">${message.summary}<#if requiredActions??><#list requiredActions>: <b><#items as reqActionItem>${msg("requiredAction.${reqActionItem}")}<#sep>, </#items></b></#list><#else></#if></p>
|
||||||
|
<#if skipLink??>
|
||||||
|
<#else>
|
||||||
|
<#if pageRedirectUri?has_content>
|
||||||
|
<p><a href="${pageRedirectUri}">${kcSanitize(msg("backToApplication"))?no_esc}</a></p>
|
||||||
|
<#elseif actionUri?has_content>
|
||||||
|
<p><a href="${actionUri}">${kcSanitize(msg("proceedWithAction"))?no_esc}</a></p>
|
||||||
|
<#elseif (client.baseUrl)?has_content>
|
||||||
|
<p><a href="${client.baseUrl}">${kcSanitize(msg("backToApplication"))?no_esc}</a></p>
|
||||||
|
</#if>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
</@layout.registrationLayout>
|
31
lumbung.space/login/login-config-totp-text.ftl
Executable file
31
lumbung.space/login/login-config-totp-text.ftl
Executable file
@ -0,0 +1,31 @@
|
|||||||
|
<#ftl output_format="plainText">
|
||||||
|
${msg("loginTotpIntro")}
|
||||||
|
|
||||||
|
${msg("loginTotpStep1")}
|
||||||
|
|
||||||
|
<#list totp.policy.supportedApplications as app>
|
||||||
|
* ${app}
|
||||||
|
</#list>
|
||||||
|
|
||||||
|
${msg("loginTotpManualStep2")}
|
||||||
|
|
||||||
|
${totp.totpSecretEncoded}
|
||||||
|
|
||||||
|
|
||||||
|
${msg("loginTotpManualStep3")}
|
||||||
|
|
||||||
|
- ${msg("loginTotpType")}: ${msg("loginTotp." + totp.policy.type)}
|
||||||
|
- ${msg("loginTotpAlgorithm")}: ${totp.policy.getAlgorithmKey()}
|
||||||
|
- ${msg("loginTotpDigits")}: ${totp.policy.digits}
|
||||||
|
<#if totp.policy.type = "totp">
|
||||||
|
- ${msg("loginTotpInterval")}: ${totp.policy.period}
|
||||||
|
|
||||||
|
<#elseif totp.policy.type = "hotp">
|
||||||
|
- ${msg("loginTotpCounter")}: ${totp.policy.initialCounter}
|
||||||
|
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
Enter in your one time password so we can verify you have installed it correctly.
|
||||||
|
|
||||||
|
|
||||||
|
|
108
lumbung.space/login/login-config-totp.ftl
Executable file
108
lumbung.space/login/login-config-totp.ftl
Executable file
@ -0,0 +1,108 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout displayRequiredFields=false displayMessage=!messagesPerField.existsError('totp','userLabel'); section>
|
||||||
|
|
||||||
|
<#if section = "header">
|
||||||
|
${msg("loginTotpTitle")}
|
||||||
|
<#elseif section = "form">
|
||||||
|
<ol id="kc-totp-settings">
|
||||||
|
<li>
|
||||||
|
<p>${msg("loginTotpStep1")}</p>
|
||||||
|
|
||||||
|
<ul id="kc-totp-supported-apps">
|
||||||
|
<#list totp.policy.supportedApplications as app>
|
||||||
|
<li>${app}</li>
|
||||||
|
</#list>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<#if mode?? && mode = "manual">
|
||||||
|
<li>
|
||||||
|
<p>${msg("loginTotpManualStep2")}</p>
|
||||||
|
<p><span id="kc-totp-secret-key">${totp.totpSecretEncoded}</span></p>
|
||||||
|
<p><a href="${totp.qrUrl}" id="mode-barcode">${msg("loginTotpScanBarcode")}</a></p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>${msg("loginTotpManualStep3")}</p>
|
||||||
|
<p>
|
||||||
|
<ul>
|
||||||
|
<li id="kc-totp-type">${msg("loginTotpType")}: ${msg("loginTotp." + totp.policy.type)}</li>
|
||||||
|
<li id="kc-totp-algorithm">${msg("loginTotpAlgorithm")}: ${totp.policy.getAlgorithmKey()}</li>
|
||||||
|
<li id="kc-totp-digits">${msg("loginTotpDigits")}: ${totp.policy.digits}</li>
|
||||||
|
<#if totp.policy.type = "totp">
|
||||||
|
<li id="kc-totp-period">${msg("loginTotpInterval")}: ${totp.policy.period}</li>
|
||||||
|
<#elseif totp.policy.type = "hotp">
|
||||||
|
<li id="kc-totp-counter">${msg("loginTotpCounter")}: ${totp.policy.initialCounter}</li>
|
||||||
|
</#if>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<#else>
|
||||||
|
<li>
|
||||||
|
<p>${msg("loginTotpStep2")}</p>
|
||||||
|
<img id="kc-totp-secret-qr-code" src="data:image/png;base64, ${totp.totpSecretQrCode}" alt="Figure: Barcode"><br/>
|
||||||
|
<p><a href="${totp.manualUrl}" id="mode-manual">${msg("loginTotpUnableToScan")}</a></p>
|
||||||
|
</li>
|
||||||
|
</#if>
|
||||||
|
<li>
|
||||||
|
<p>${msg("loginTotpStep3")}</p>
|
||||||
|
<p>${msg("loginTotpStep3DeviceName")}</p>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<form action="${url.loginAction}" class="${properties.kcFormClass!}" id="kc-totp-settings-form" method="post">
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<div class="${properties.kcInputWrapperClass!}">
|
||||||
|
<label for="totp" class="control-label">${msg("authenticatorCode")}</label> <span class="required">*</span>
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcInputWrapperClass!}">
|
||||||
|
<input type="text" id="totp" name="totp" autocomplete="off" class="${properties.kcInputClass!}"
|
||||||
|
aria-invalid="<#if messagesPerField.existsError('totp')>true</#if>"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<#if messagesPerField.existsError('totp')>
|
||||||
|
<span id="input-error-otp-code" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
|
||||||
|
${kcSanitize(messagesPerField.get('totp'))?no_esc}
|
||||||
|
</span>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<input type="hidden" id="totpSecret" name="totpSecret" value="${totp.totpSecret}" />
|
||||||
|
<#if mode??><input type="hidden" id="mode" name="mode" value="${mode}"/></#if>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<div class="${properties.kcInputWrapperClass!}">
|
||||||
|
<label for="userLabel" class="control-label">${msg("loginTotpDeviceName")}</label> <#if totp.otpCredentials?size gte 1><span class="required">*</span></#if>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="${properties.kcInputWrapperClass!}">
|
||||||
|
<input type="text" class="${properties.kcInputClass!}" id="userLabel" name="userLabel" autocomplete="off"
|
||||||
|
aria-invalid="<#if messagesPerField.existsError('userLabel')>true</#if>"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<#if messagesPerField.existsError('userLabel')>
|
||||||
|
<span id="input-error-otp-label" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
|
||||||
|
${kcSanitize(messagesPerField.get('userLabel'))?no_esc}
|
||||||
|
</span>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<#if isAppInitiatedAction??>
|
||||||
|
<input type="submit"
|
||||||
|
class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!}"
|
||||||
|
id="saveTOTPBtn" value="${msg("doSubmit")}"
|
||||||
|
/>
|
||||||
|
<button type="submit"
|
||||||
|
class="${properties.kcButtonClass!} ${properties.kcButtonDefaultClass!} ${properties.kcButtonLargeClass!} ${properties.kcButtonLargeClass!}"
|
||||||
|
id="cancelTOTPBtn" name="cancel-aia" value="true" />${msg("doCancel")}
|
||||||
|
</button>
|
||||||
|
<#else>
|
||||||
|
<input type="submit"
|
||||||
|
class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!}"
|
||||||
|
id="saveTOTPBtn" value="${msg("doSubmit")}"
|
||||||
|
/>
|
||||||
|
</#if>
|
||||||
|
</form>
|
||||||
|
</#if>
|
||||||
|
</@layout.registrationLayout>
|
13
lumbung.space/login/login-idp-link-confirm.ftl
Normal file
13
lumbung.space/login/login-idp-link-confirm.ftl
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout; section>
|
||||||
|
<#if section = "header">
|
||||||
|
${msg("confirmLinkIdpTitle")}
|
||||||
|
<#elseif section = "form">
|
||||||
|
<form id="kc-register-form" action="${url.loginAction}" method="post">
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<button type="submit" class="${properties.kcButtonClass!} ${properties.kcButtonDefaultClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!}" name="submitAction" id="updateProfile" value="updateProfile">${msg("confirmLinkIdpReviewProfile")}</button>
|
||||||
|
<button type="submit" class="${properties.kcButtonClass!} ${properties.kcButtonDefaultClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!}" name="submitAction" id="linkAccount" value="linkAccount">${msg("confirmLinkIdpContinue", idpDisplayName)}</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</#if>
|
||||||
|
</@layout.registrationLayout>
|
16
lumbung.space/login/login-idp-link-email.ftl
Normal file
16
lumbung.space/login/login-idp-link-email.ftl
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout; section>
|
||||||
|
<#if section = "header">
|
||||||
|
${msg("emailLinkIdpTitle", idpDisplayName)}
|
||||||
|
<#elseif section = "form">
|
||||||
|
<p id="instruction1" class="instruction">
|
||||||
|
${msg("emailLinkIdp1", idpDisplayName, brokerContext.username, realm.displayName)}
|
||||||
|
</p>
|
||||||
|
<p id="instruction2" class="instruction">
|
||||||
|
${msg("emailLinkIdp2")} <a href="${url.loginAction}">${msg("doClickHere")}</a> ${msg("emailLinkIdp3")}
|
||||||
|
</p>
|
||||||
|
<p id="instruction3" class="instruction">
|
||||||
|
${msg("emailLinkIdp4")} <a href="${url.loginAction}">${msg("doClickHere")}</a> ${msg("emailLinkIdp5")}
|
||||||
|
</p>
|
||||||
|
</#if>
|
||||||
|
</@layout.registrationLayout>
|
41
lumbung.space/login/login-oauth-grant.ftl
Executable file
41
lumbung.space/login/login-oauth-grant.ftl
Executable file
@ -0,0 +1,41 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout bodyClass="oauth"; section>
|
||||||
|
<#if section = "header">
|
||||||
|
<#if client.name?has_content>
|
||||||
|
${msg("oauthGrantTitle",advancedMsg(client.name))}
|
||||||
|
<#else>
|
||||||
|
${msg("oauthGrantTitle",client.clientId)}
|
||||||
|
</#if>
|
||||||
|
<#elseif section = "form">
|
||||||
|
<div id="kc-oauth" class="content-area">
|
||||||
|
<h3>${msg("oauthGrantRequest")}</h3>
|
||||||
|
<ul>
|
||||||
|
<#if oauth.clientScopesRequested??>
|
||||||
|
<#list oauth.clientScopesRequested as clientScope>
|
||||||
|
<li>
|
||||||
|
<span>${advancedMsg(clientScope.consentScreenText)}</span>
|
||||||
|
</li>
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<form class="form-actions" action="${url.oauthAction}" method="POST">
|
||||||
|
<input type="hidden" name="code" value="${oauth.code}">
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<div id="kc-form-options">
|
||||||
|
<div class="${properties.kcFormOptionsWrapperClass!}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="kc-form-buttons">
|
||||||
|
<div class="${properties.kcFormButtonsWrapperClass!}">
|
||||||
|
<input class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!}" name="accept" id="kc-login" type="submit" value="${msg("doYes")}"/>
|
||||||
|
<input class="${properties.kcButtonClass!} ${properties.kcButtonDefaultClass!} ${properties.kcButtonLargeClass!}" name="cancel" id="kc-cancel" type="submit" value="${msg("doNo")}"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
</@layout.registrationLayout>
|
31
lumbung.space/login/login-oauth2-device-verify-user-code.ftl
Normal file
31
lumbung.space/login/login-oauth2-device-verify-user-code.ftl
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout; section>
|
||||||
|
<#if section = "header">
|
||||||
|
${msg("oauth2DeviceVerificationTitle")}
|
||||||
|
<#elseif section = "form">
|
||||||
|
<form id="kc-user-verify-device-user-code-form" class="${properties.kcFormClass!}" action="${url.oauth2DeviceVerificationAction}" method="post">
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<div class="${properties.kcLabelWrapperClass!}">
|
||||||
|
<label for="device-user-code" class="${properties.kcLabelClass!}">${msg("verifyOAuth2DeviceUserCode")}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="${properties.kcInputWrapperClass!}">
|
||||||
|
<input id="device-user-code" name="device_user_code" autocomplete="off" type="text" class="${properties.kcInputClass!}" autofocus />
|
||||||
|
</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!}" type="submit" value="${msg("doSubmit")}"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</#if>
|
||||||
|
</@layout.registrationLayout>
|
58
lumbung.space/login/login-otp.ftl
Executable file
58
lumbung.space/login/login-otp.ftl
Executable file
@ -0,0 +1,58 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout displayMessage=!messagesPerField.existsError('totp'); section>
|
||||||
|
<#if section="header">
|
||||||
|
${msg("doLogIn")}
|
||||||
|
<#elseif section="form">
|
||||||
|
<form id="kc-otp-login-form" class="${properties.kcFormClass!}" action="${url.loginAction}"
|
||||||
|
method="post">
|
||||||
|
<#if otpLogin.userOtpCredentials?size gt 1>
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<div class="${properties.kcInputWrapperClass!}">
|
||||||
|
<#list otpLogin.userOtpCredentials as otpCredential>
|
||||||
|
<input id="kc-otp-credential-${otpCredential?index}" class="${properties.kcLoginOTPListInputClass!}" type="radio" name="selectedCredentialId" value="${otpCredential.id}" <#if otpCredential.id == otpLogin.selectedCredentialId>checked="checked"</#if>>
|
||||||
|
<label for="kc-otp-credential-${otpCredential?index}" class="${properties.kcLoginOTPListClass!}" tabindex="${otpCredential?index}">
|
||||||
|
<span class="${properties.kcLoginOTPListItemHeaderClass!}">
|
||||||
|
<span class="${properties.kcLoginOTPListItemIconBodyClass!}">
|
||||||
|
<i class="${properties.kcLoginOTPListItemIconClass!}" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
<span class="${properties.kcLoginOTPListItemTitleClass!}">${otpCredential.userLabel}</span>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</#list>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<div class="${properties.kcLabelWrapperClass!}">
|
||||||
|
<label for="otp" class="${properties.kcLabelClass!}">${msg("loginOtpOneTime")}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="${properties.kcInputWrapperClass!}">
|
||||||
|
<input id="otp" name="otp" autocomplete="off" type="text" class="${properties.kcInputClass!}"
|
||||||
|
autofocus aria-invalid="<#if messagesPerField.existsError('totp')>true</#if>"/>
|
||||||
|
|
||||||
|
<#if messagesPerField.existsError('totp')>
|
||||||
|
<span id="input-error-otp-code" class="${properties.kcInputErrorMessageClass!}"
|
||||||
|
aria-live="polite">
|
||||||
|
${kcSanitize(messagesPerField.get('totp'))?no_esc}
|
||||||
|
</span>
|
||||||
|
</#if>
|
||||||
|
</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!}">
|
||||||
|
<input
|
||||||
|
class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!}"
|
||||||
|
name="login" id="kc-login" type="submit" value="${msg("doLogIn")}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</#if>
|
||||||
|
</@layout.registrationLayout>
|
11
lumbung.space/login/login-page-expired.ftl
Normal file
11
lumbung.space/login/login-page-expired.ftl
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout; section>
|
||||||
|
<#if section = "header">
|
||||||
|
${msg("pageExpiredTitle")}
|
||||||
|
<#elseif section = "form">
|
||||||
|
<p id="instruction1" class="instruction">
|
||||||
|
${msg("pageExpiredMsg1")} <a id="loginRestartLink" href="${url.loginRestartFlowUrl}">${msg("doClickHere")}</a> .<br/>
|
||||||
|
${msg("pageExpiredMsg2")} <a id="loginContinueLink" href="${url.loginAction}">${msg("doClickHere")}</a> .
|
||||||
|
</p>
|
||||||
|
</#if>
|
||||||
|
</@layout.registrationLayout>
|
43
lumbung.space/login/login-password.ftl
Executable file
43
lumbung.space/login/login-password.ftl
Executable file
@ -0,0 +1,43 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout displayMessage=!messagesPerField.existsError('password'); section>
|
||||||
|
<#if section = "header">
|
||||||
|
${msg("doLogIn")}
|
||||||
|
<#elseif section = "form">
|
||||||
|
<div id="kc-form">
|
||||||
|
<div id="kc-form-wrapper">
|
||||||
|
<form id="kc-form-login" onsubmit="login.disabled = true; return true;" action="${url.loginAction}"
|
||||||
|
method="post">
|
||||||
|
<div class="${properties.kcFormGroupClass!} no-bottom-margin">
|
||||||
|
<hr/>
|
||||||
|
<label for="password" class="${properties.kcLabelClass!}">${msg("password")}</label>
|
||||||
|
<input tabindex="2" id="password" class="${properties.kcInputClass!}" name="password"
|
||||||
|
type="password" autocomplete="on"
|
||||||
|
aria-invalid="<#if messagesPerField.existsError('password')>true</#if>"
|
||||||
|
/>
|
||||||
|
<#if messagesPerField.existsError('password')>
|
||||||
|
<span id="input-error-password" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
|
||||||
|
${kcSanitize(messagesPerField.get('password'))?no_esc}
|
||||||
|
</span>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="${properties.kcFormGroupClass!} ${properties.kcFormSettingClass!}">
|
||||||
|
<div id="kc-form-options">
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcFormOptionsWrapperClass!}">
|
||||||
|
<#if realm.resetPasswordAllowed>
|
||||||
|
<span><a tabindex="5"
|
||||||
|
href="${url.loginResetCredentialsUrl}">${msg("doForgotPassword")}</a></span>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="kc-form-buttons" class="${properties.kcFormGroupClass!}">
|
||||||
|
<input tabindex="4" class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!}" name="login" id="kc-login" type="submit" value="${msg("doLogIn")}"/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
</@layout.registrationLayout>
|
40
lumbung.space/login/login-reset-password.ftl
Executable file
40
lumbung.space/login/login-reset-password.ftl
Executable file
@ -0,0 +1,40 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout displayInfo=true displayMessage=!messagesPerField.existsError('username'); section>
|
||||||
|
<#if section = "header">
|
||||||
|
${msg("emailForgotTitle")}
|
||||||
|
<#elseif section = "form">
|
||||||
|
<form id="kc-reset-password-form" class="${properties.kcFormClass!}" action="${url.loginAction}" method="post">
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<div class="${properties.kcLabelWrapperClass!}">
|
||||||
|
<label for="username" class="${properties.kcLabelClass!}"><#if !realm.loginWithEmailAllowed>${msg("username")}<#elseif !realm.registrationEmailAsUsername>${msg("usernameOrEmail")}<#else>${msg("email")}</#if></label>
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcInputWrapperClass!}">
|
||||||
|
<#if auth?has_content && auth.showUsername()>
|
||||||
|
<input type="text" id="username" name="username" class="${properties.kcInputClass!}" autofocus value="${auth.attemptedUsername}" aria-invalid="<#if messagesPerField.existsError('username')>true</#if>"/>
|
||||||
|
<#else>
|
||||||
|
<input type="text" id="username" name="username" class="${properties.kcInputClass!}" autofocus aria-invalid="<#if messagesPerField.existsError('username')>true</#if>"/>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if messagesPerField.existsError('username')>
|
||||||
|
<span id="input-error-username" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
|
||||||
|
${kcSanitize(messagesPerField.get('username'))?no_esc}
|
||||||
|
</span>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcFormGroupClass!} ${properties.kcFormSettingClass!}">
|
||||||
|
<div id="kc-form-options" class="${properties.kcFormOptionsClass!}">
|
||||||
|
<div class="${properties.kcFormOptionsWrapperClass!}">
|
||||||
|
<span><a href="${url.loginUrl}">${kcSanitize(msg("backToLogin"))?no_esc}</a></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="kc-form-buttons" class="${properties.kcFormButtonsClass!}">
|
||||||
|
<input class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!}" type="submit" value="${msg("doSubmit")}"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<#elseif section = "info" >
|
||||||
|
${msg("emailInstruction")}
|
||||||
|
</#if>
|
||||||
|
</@layout.registrationLayout>
|
71
lumbung.space/login/login-update-password.ftl
Executable file
71
lumbung.space/login/login-update-password.ftl
Executable file
@ -0,0 +1,71 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout displayMessage=!messagesPerField.existsError('password','password-confirm'); section>
|
||||||
|
<#if section = "header">
|
||||||
|
${msg("updatePasswordTitle")}
|
||||||
|
<#elseif section = "form">
|
||||||
|
<form id="kc-passwd-update-form" class="${properties.kcFormClass!}" action="${url.loginAction}" method="post">
|
||||||
|
<input type="text" id="username" name="username" value="${username}" autocomplete="username"
|
||||||
|
readonly="readonly" style="display:none;"/>
|
||||||
|
<input type="password" id="password" name="password" autocomplete="current-password" style="display:none;"/>
|
||||||
|
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<div class="${properties.kcLabelWrapperClass!}">
|
||||||
|
<label for="password-new" class="${properties.kcLabelClass!}">${msg("passwordNew")}</label>
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcInputWrapperClass!}">
|
||||||
|
<input type="password" id="password-new" name="password-new" class="${properties.kcInputClass!}"
|
||||||
|
autofocus autocomplete="new-password"
|
||||||
|
aria-invalid="<#if messagesPerField.existsError('password','password-confirm')>true</#if>"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<#if messagesPerField.existsError('password')>
|
||||||
|
<span id="input-error-password" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
|
||||||
|
${kcSanitize(messagesPerField.get('password'))?no_esc}
|
||||||
|
</span>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<div class="${properties.kcLabelWrapperClass!}">
|
||||||
|
<label for="password-confirm" class="${properties.kcLabelClass!}">${msg("passwordConfirm")}</label>
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcInputWrapperClass!}">
|
||||||
|
<input type="password" id="password-confirm" name="password-confirm"
|
||||||
|
class="${properties.kcInputClass!}"
|
||||||
|
autocomplete="new-password"
|
||||||
|
aria-invalid="<#if messagesPerField.existsError('password-confirm')>true</#if>"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<#if messagesPerField.existsError('password-confirm')>
|
||||||
|
<span id="input-error-password-confirm" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
|
||||||
|
${kcSanitize(messagesPerField.get('password-confirm'))?no_esc}
|
||||||
|
</span>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<div id="kc-form-options" class="${properties.kcFormOptionsClass!}">
|
||||||
|
<div class="${properties.kcFormOptionsWrapperClass!}">
|
||||||
|
<#if isAppInitiatedAction??>
|
||||||
|
<div class="checkbox">
|
||||||
|
<label><input type="checkbox" id="logout-sessions" name="logout-sessions" value="on" checked> ${msg("logoutOtherSessions")}</label>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="kc-form-buttons" class="${properties.kcFormButtonsClass!}">
|
||||||
|
<#if isAppInitiatedAction??>
|
||||||
|
<input class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!}" type="submit" value="${msg("doSubmit")}" />
|
||||||
|
<button class="${properties.kcButtonClass!} ${properties.kcButtonDefaultClass!} ${properties.kcButtonLargeClass!}" type="submit" name="cancel-aia" value="true" />${msg("doCancel")}</button>
|
||||||
|
<#else>
|
||||||
|
<input class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!}" type="submit" value="${msg("doSubmit")}" />
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</#if>
|
||||||
|
</@layout.registrationLayout>
|
97
lumbung.space/login/login-update-profile.ftl
Executable file
97
lumbung.space/login/login-update-profile.ftl
Executable file
@ -0,0 +1,97 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout displayMessage=!messagesPerField.existsError('username','email','firstName','lastName'); section>
|
||||||
|
<#if section = "header">
|
||||||
|
${msg("loginProfileTitle")}
|
||||||
|
<#elseif section = "form">
|
||||||
|
<form id="kc-update-profile-form" class="${properties.kcFormClass!}" action="${url.loginAction}" method="post">
|
||||||
|
<#if user.editUsernameAllowed>
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<div class="${properties.kcLabelWrapperClass!}">
|
||||||
|
<label for="username" class="${properties.kcLabelClass!}">${msg("username")}</label>
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcInputWrapperClass!}">
|
||||||
|
<input type="text" id="username" name="username" value="${(user.username!'')}"
|
||||||
|
class="${properties.kcInputClass!}"
|
||||||
|
aria-invalid="<#if messagesPerField.existsError('username')>true</#if>"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<#if messagesPerField.existsError('username')>
|
||||||
|
<span id="input-error-username" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
|
||||||
|
${kcSanitize(messagesPerField.get('username'))?no_esc}
|
||||||
|
</span>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<div class="${properties.kcLabelWrapperClass!}">
|
||||||
|
<label for="email" class="${properties.kcLabelClass!}">${msg("email")}</label>
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcInputWrapperClass!}">
|
||||||
|
<input type="text" id="email" name="email" value="${(user.email!'')}"
|
||||||
|
class="${properties.kcInputClass!}"
|
||||||
|
aria-invalid="<#if messagesPerField.existsError('email')>true</#if>"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<#if messagesPerField.existsError('email')>
|
||||||
|
<span id="input-error-email" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
|
||||||
|
${kcSanitize(messagesPerField.get('email'))?no_esc}
|
||||||
|
</span>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<div class="${properties.kcLabelWrapperClass!}">
|
||||||
|
<label for="firstName" class="${properties.kcLabelClass!}">${msg("firstName")}</label>
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcInputWrapperClass!}">
|
||||||
|
<input type="text" id="firstName" name="firstName" value="${(user.firstName!'')}"
|
||||||
|
class="${properties.kcInputClass!}"
|
||||||
|
aria-invalid="<#if messagesPerField.existsError('firstName')>true</#if>"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<#if messagesPerField.existsError('firstName')>
|
||||||
|
<span id="input-error-firstname" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
|
||||||
|
${kcSanitize(messagesPerField.get('firstName'))?no_esc}
|
||||||
|
</span>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<div class="${properties.kcLabelWrapperClass!}">
|
||||||
|
<label for="lastName" class="${properties.kcLabelClass!}">${msg("lastName")}</label>
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcInputWrapperClass!}">
|
||||||
|
<input type="text" id="lastName" name="lastName" value="${(user.lastName!'')}"
|
||||||
|
class="${properties.kcInputClass!}"
|
||||||
|
aria-invalid="<#if messagesPerField.existsError('lastName')>true</#if>"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<#if messagesPerField.existsError('lastName')>
|
||||||
|
<span id="input-error-lastname" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
|
||||||
|
${kcSanitize(messagesPerField.get('lastName'))?no_esc}
|
||||||
|
</span>
|
||||||
|
</#if>
|
||||||
|
</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!}">
|
||||||
|
<#if isAppInitiatedAction??>
|
||||||
|
<input class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!}" type="submit" value="${msg("doSubmit")}" />
|
||||||
|
<button class="${properties.kcButtonClass!} ${properties.kcButtonDefaultClass!} ${properties.kcButtonLargeClass!}" type="submit" name="cancel-aia" value="true" />${msg("doCancel")}</button>
|
||||||
|
<#else>
|
||||||
|
<input class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!}" type="submit" value="${msg("doSubmit")}" />
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</#if>
|
||||||
|
</@layout.registrationLayout>
|
92
lumbung.space/login/login-username.ftl
Executable file
92
lumbung.space/login/login-username.ftl
Executable file
@ -0,0 +1,92 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout displayMessage=!messagesPerField.existsError('username') displayInfo=(realm.password && realm.registrationAllowed && !registrationDisabled??); section>
|
||||||
|
<#if section = "header">
|
||||||
|
${msg("loginAccountTitle")}
|
||||||
|
<#elseif section = "form">
|
||||||
|
<div id="kc-form">
|
||||||
|
<div id="kc-form-wrapper">
|
||||||
|
<#if realm.password>
|
||||||
|
<form id="kc-form-login" onsubmit="login.disabled = true; return true;" action="${url.loginAction}"
|
||||||
|
method="post">
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<label for="username"
|
||||||
|
class="${properties.kcLabelClass!}"><#if !realm.loginWithEmailAllowed>${msg("username")}<#elseif !realm.registrationEmailAsUsername>${msg("usernameOrEmail")}<#else>${msg("email")}</#if></label>
|
||||||
|
|
||||||
|
<#if usernameEditDisabled??>
|
||||||
|
<input tabindex="1" id="username"
|
||||||
|
aria-invalid="<#if message?has_content && message.type = 'error'>true</#if>"
|
||||||
|
class="${properties.kcInputClass!}" name="username"
|
||||||
|
value="${(login.username!'')}"
|
||||||
|
type="text" disabled/>
|
||||||
|
<#else>
|
||||||
|
<input tabindex="1" id="username"
|
||||||
|
aria-invalid="<#if messagesPerField.existsError('username')>true</#if>"
|
||||||
|
class="${properties.kcInputClass!}" name="username"
|
||||||
|
value="${(login.username!'')}"
|
||||||
|
type="text" autofocus autocomplete="off"/>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if messagesPerField.existsError('username')>
|
||||||
|
<span id="input-error-username" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
|
||||||
|
${kcSanitize(messagesPerField.get('username'))?no_esc}
|
||||||
|
</span>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="${properties.kcFormGroupClass!} ${properties.kcFormSettingClass!}">
|
||||||
|
<div id="kc-form-options">
|
||||||
|
<#if realm.rememberMe && !usernameEditDisabled??>
|
||||||
|
<div class="checkbox">
|
||||||
|
<label>
|
||||||
|
<#if login.rememberMe??>
|
||||||
|
<input tabindex="3" id="rememberMe" name="rememberMe" type="checkbox"
|
||||||
|
checked> ${msg("rememberMe")}
|
||||||
|
<#else>
|
||||||
|
<input tabindex="3" id="rememberMe" name="rememberMe"
|
||||||
|
type="checkbox"> ${msg("rememberMe")}
|
||||||
|
</#if>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="kc-form-buttons" class="${properties.kcFormGroupClass!}">
|
||||||
|
<input tabindex="4"
|
||||||
|
class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!}"
|
||||||
|
name="login" id="kc-login" type="submit" value="${msg("doLogIn")}"/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<#if realm.password && social.providers??>
|
||||||
|
<div id="kc-social-providers" class="${properties.kcFormSocialAccountSectionClass!}">
|
||||||
|
<hr/>
|
||||||
|
<h4>${msg("identity-provider-login-label")}</h4>
|
||||||
|
|
||||||
|
<ul class="${properties.kcFormSocialAccountListClass!} <#if social.providers?size gt 3>${properties.kcFormSocialAccountListGridClass!}</#if>">
|
||||||
|
<#list social.providers as p>
|
||||||
|
<a id="social-${p.alias}" class="${properties.kcFormSocialAccountListButtonClass!} <#if social.providers?size gt 3>${properties.kcFormSocialAccountGridItem!}</#if>"
|
||||||
|
type="button" href="${p.loginUrl}">
|
||||||
|
<#if p.iconClasses?has_content>
|
||||||
|
<i class="${properties.kcCommonLogoIdP!} ${p.iconClasses!}" aria-hidden="true"></i>
|
||||||
|
<span class="${properties.kcFormSocialAccountNameClass!} kc-social-icon-text">${p.displayName}</span>
|
||||||
|
<#else>
|
||||||
|
<span class="${properties.kcFormSocialAccountNameClass!}">${p.displayName}</span>
|
||||||
|
</#if>
|
||||||
|
</a>
|
||||||
|
</#list>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#elseif section = "info" >
|
||||||
|
<#if realm.password && realm.registrationAllowed && !registrationDisabled??>
|
||||||
|
<div id="kc-registration">
|
||||||
|
<span>${msg("noAccount")} <a tabindex="6" href="${url.registrationUrl}">${msg("doRegister")}</a></span>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
</@layout.registrationLayout>
|
2
lumbung.space/login/login-verify-email-code-text.ftl
Normal file
2
lumbung.space/login/login-verify-email-code-text.ftl
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<#ftl output_format="plainText">
|
||||||
|
${msg("console-verify-email",email, code)}
|
14
lumbung.space/login/login-verify-email.ftl
Executable file
14
lumbung.space/login/login-verify-email.ftl
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout displayInfo=true; section>
|
||||||
|
<#if section = "header">
|
||||||
|
${msg("emailVerifyTitle")}
|
||||||
|
<#elseif section = "form">
|
||||||
|
<p class="instruction">${msg("emailVerifyInstruction1")}</p>
|
||||||
|
<#elseif section = "info">
|
||||||
|
<p class="instruction">
|
||||||
|
${msg("emailVerifyInstruction2")}
|
||||||
|
<br/>
|
||||||
|
<a href="${url.loginAction}">${msg("doClickHere")}</a> ${msg("emailVerifyInstruction3")}
|
||||||
|
</p>
|
||||||
|
</#if>
|
||||||
|
</@layout.registrationLayout>
|
55
lumbung.space/login/login-x509-info.ftl
Normal file
55
lumbung.space/login/login-x509-info.ftl
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout; section>
|
||||||
|
<#if section = "header">
|
||||||
|
${msg("doLogIn")}
|
||||||
|
<#elseif section = "form">
|
||||||
|
|
||||||
|
<form id="kc-x509-login-info" class="${properties.kcFormClass!}" action="${url.loginAction}" method="post">
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
|
||||||
|
<div class="${properties.kcLabelWrapperClass!}">
|
||||||
|
<label for="certificate_subjectDN" class="${properties.kcLabelClass!}">${msg("clientCertificate")}</label>
|
||||||
|
</div>
|
||||||
|
<#if x509.formData.subjectDN??>
|
||||||
|
<div class="${properties.kcLabelWrapperClass!}">
|
||||||
|
<label id="certificate_subjectDN" class="${properties.kcLabelClass!}">${(x509.formData.subjectDN!"")}</label>
|
||||||
|
</div>
|
||||||
|
<#else>
|
||||||
|
<div class="${properties.kcLabelWrapperClass!}">
|
||||||
|
<label id="certificate_subjectDN" class="${properties.kcLabelClass!}">${msg("noCertificate")}</label>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
|
||||||
|
<#if x509.formData.isUserEnabled??>
|
||||||
|
<div class="${properties.kcLabelWrapperClass!}">
|
||||||
|
<label for="username" class="${properties.kcLabelClass!}">${msg("doX509Login")}</label>
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcLabelWrapperClass!}">
|
||||||
|
<label id="username" class="${properties.kcLabelClass!}">${(x509.formData.username!'')}</label>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
</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="login" id="kc-login" type="submit" value="${msg("doContinue")}"/>
|
||||||
|
<#if x509.formData.isUserEnabled??>
|
||||||
|
<input class="${properties.kcButtonClass!} ${properties.kcButtonDefaultClass!} ${properties.kcButtonLargeClass!}" name="cancel" id="kc-cancel" type="submit" value="${msg("doIgnore")}"/>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
</@layout.registrationLayout>
|
99
lumbung.space/login/login.ftl
Executable file
99
lumbung.space/login/login.ftl
Executable file
@ -0,0 +1,99 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout displayMessage=!messagesPerField.existsError('username','password') displayInfo=realm.password && realm.registrationAllowed && !registrationDisabled??; section>
|
||||||
|
<#if section = "header">
|
||||||
|
${msg("loginAccountTitle")}
|
||||||
|
<#elseif section = "form">
|
||||||
|
<div id="kc-form">
|
||||||
|
<div id="kc-form-wrapper">
|
||||||
|
<#if realm.password>
|
||||||
|
<form id="kc-form-login" onsubmit="login.disabled = true; return true;" action="${url.loginAction}" method="post">
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<label for="username" class="${properties.kcLabelClass!}"><#if !realm.loginWithEmailAllowed>${msg("username")}<#elseif !realm.registrationEmailAsUsername>${msg("usernameOrEmail")}<#else>${msg("email")}</#if></label>
|
||||||
|
|
||||||
|
<#if usernameEditDisabled??>
|
||||||
|
<input tabindex="1" id="username" class="${properties.kcInputClass!}" name="username" value="${(login.username!'')}" type="text" disabled />
|
||||||
|
<#else>
|
||||||
|
<input tabindex="1" id="username" class="${properties.kcInputClass!}" name="username" value="${(login.username!'')}" type="text" autofocus autocomplete="off"
|
||||||
|
aria-invalid="<#if messagesPerField.existsError('username','password')>true</#if>"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<#if messagesPerField.existsError('username','password')>
|
||||||
|
<span id="input-error" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
|
||||||
|
${kcSanitize(messagesPerField.getFirstError('username','password'))?no_esc}
|
||||||
|
</span>
|
||||||
|
</#if>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<label for="password" class="${properties.kcLabelClass!}">${msg("password")}</label>
|
||||||
|
|
||||||
|
<input tabindex="2" id="password" class="${properties.kcInputClass!}" name="password" type="password" autocomplete="off"
|
||||||
|
aria-invalid="<#if messagesPerField.existsError('username','password')>true</#if>"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="${properties.kcFormGroupClass!} ${properties.kcFormSettingClass!}">
|
||||||
|
<div id="kc-form-options">
|
||||||
|
<#if realm.rememberMe && !usernameEditDisabled??>
|
||||||
|
<div class="checkbox">
|
||||||
|
<label>
|
||||||
|
<#if login.rememberMe??>
|
||||||
|
<input tabindex="3" id="rememberMe" name="rememberMe" type="checkbox" checked> ${msg("rememberMe")}
|
||||||
|
<#else>
|
||||||
|
<input tabindex="3" id="rememberMe" name="rememberMe" type="checkbox"> ${msg("rememberMe")}
|
||||||
|
</#if>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcFormOptionsWrapperClass!}">
|
||||||
|
<#if realm.resetPasswordAllowed>
|
||||||
|
<span><a tabindex="5" href="${url.loginResetCredentialsUrl}">${msg("doForgotPassword")}</a></span>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="kc-form-buttons" class="${properties.kcFormGroupClass!}">
|
||||||
|
<input type="hidden" id="id-hidden-input" name="credentialId" <#if auth.selectedCredential?has_content>value="${auth.selectedCredential}"</#if>/>
|
||||||
|
<input tabindex="4" class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!}" name="login" id="kc-login" type="submit" value="${msg("doLogIn")}"/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<#if realm.password && social.providers??>
|
||||||
|
<div id="kc-social-providers" class="${properties.kcFormSocialAccountSectionClass!}">
|
||||||
|
<hr/>
|
||||||
|
<h4>${msg("identity-provider-login-label")}</h4>
|
||||||
|
|
||||||
|
<ul class="${properties.kcFormSocialAccountListClass!} <#if social.providers?size gt 3>${properties.kcFormSocialAccountListGridClass!}</#if>">
|
||||||
|
<#list social.providers as p>
|
||||||
|
<a id="social-${p.alias}" class="${properties.kcFormSocialAccountListButtonClass!} <#if social.providers?size gt 3>${properties.kcFormSocialAccountGridItem!}</#if>"
|
||||||
|
type="button" href="${p.loginUrl}">
|
||||||
|
<#if p.iconClasses?has_content>
|
||||||
|
<i class="${properties.kcCommonLogoIdP!} ${p.iconClasses!}" aria-hidden="true"></i>
|
||||||
|
<span class="${properties.kcFormSocialAccountNameClass!} kc-social-icon-text">${p.displayName!}</span>
|
||||||
|
<#else>
|
||||||
|
<span class="${properties.kcFormSocialAccountNameClass!}">${p.displayName!}</span>
|
||||||
|
</#if>
|
||||||
|
</a>
|
||||||
|
</#list>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<#elseif section = "info" >
|
||||||
|
<#if realm.password && realm.registrationAllowed && !registrationDisabled??>
|
||||||
|
<div id="kc-registration-container">
|
||||||
|
<div id="kc-registration">
|
||||||
|
<span>${msg("noAccount")} <a tabindex="6"
|
||||||
|
href="${url.registrationUrl}">${msg("doRegister")}</a></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
</@layout.registrationLayout>
|
415
lumbung.space/login/messages/messages_en.properties
Executable file
415
lumbung.space/login/messages/messages_en.properties
Executable file
@ -0,0 +1,415 @@
|
|||||||
|
doLogIn=Sign In
|
||||||
|
doRegister=Register
|
||||||
|
doCancel=Cancel
|
||||||
|
doSubmit=Submit
|
||||||
|
doBack=Back
|
||||||
|
doYes=Yes
|
||||||
|
doNo=No
|
||||||
|
doContinue=Continue
|
||||||
|
doIgnore=Ignore
|
||||||
|
doAccept=Accept
|
||||||
|
doDecline=Decline
|
||||||
|
doForgotPassword=Forgot Password?
|
||||||
|
doClickHere=Click here
|
||||||
|
doImpersonate=Impersonate
|
||||||
|
doTryAgain=Try again
|
||||||
|
doTryAnotherWay=Try Another Way
|
||||||
|
doConfirmDelete=Confirm deletion
|
||||||
|
errorDeletingAccount=Error happened while deleting account
|
||||||
|
deletingAccountForbidden=You do not have enough permissions to delete your own account, contact admin.
|
||||||
|
kerberosNotConfigured=Kerberos Not Configured
|
||||||
|
kerberosNotConfiguredTitle=Kerberos Not Configured
|
||||||
|
bypassKerberosDetail=Either you are not logged in by Kerberos or your browser is not set up for Kerberos login. Please click continue to login in through other means
|
||||||
|
kerberosNotSetUp=Kerberos is not set up. You cannot login.
|
||||||
|
registerTitle=Register
|
||||||
|
loginAccountTitle=Sign in to your account
|
||||||
|
loginTitle=Sign in to {0}
|
||||||
|
loginTitleHtml={0}
|
||||||
|
impersonateTitle={0} Impersonate User
|
||||||
|
impersonateTitleHtml=<strong>{0}</strong> Impersonate User
|
||||||
|
realmChoice=Realm
|
||||||
|
unknownUser=Unknown user
|
||||||
|
loginTotpTitle=Mobile Authenticator Setup
|
||||||
|
loginProfileTitle=Update Account Information
|
||||||
|
loginTimeout=Your login attempt timed out. Login will start from the beginning.
|
||||||
|
oauthGrantTitle=Grant Access to {0}
|
||||||
|
oauthGrantTitleHtml={0}
|
||||||
|
errorTitle=We are sorry...
|
||||||
|
errorTitleHtml=We are <strong>sorry</strong> ...
|
||||||
|
emailVerifyTitle=Email verification
|
||||||
|
emailForgotTitle=Forgot Your Password?
|
||||||
|
updatePasswordTitle=Update password
|
||||||
|
codeSuccessTitle=Success code
|
||||||
|
codeErrorTitle=Error code\: {0}
|
||||||
|
displayUnsupported=Requested display type unsupported
|
||||||
|
browserRequired=Browser required to login
|
||||||
|
browserContinue=Browser required to complete login
|
||||||
|
browserContinuePrompt=Open browser and continue login? [y/n]:
|
||||||
|
browserContinueAnswer=y
|
||||||
|
|
||||||
|
|
||||||
|
termsTitle=Terms and Conditions
|
||||||
|
termsText=<p>Terms and conditions to be defined</p>
|
||||||
|
termsPlainText=Terms and conditions to be defined.
|
||||||
|
|
||||||
|
recaptchaFailed=Invalid Recaptcha
|
||||||
|
recaptchaNotConfigured=Recaptcha is required, but not configured
|
||||||
|
consentDenied=Consent denied.
|
||||||
|
|
||||||
|
noAccount=New user?
|
||||||
|
username=Username
|
||||||
|
usernameOrEmail=Username or email
|
||||||
|
firstName=First name
|
||||||
|
givenName=Given name
|
||||||
|
fullName=Full name
|
||||||
|
lastName=Last name
|
||||||
|
familyName=Family name
|
||||||
|
email=Email
|
||||||
|
password=Password
|
||||||
|
passwordConfirm=Confirm password
|
||||||
|
passwordNew=New Password
|
||||||
|
passwordNewConfirm=New Password confirmation
|
||||||
|
rememberMe=Remember me
|
||||||
|
authenticatorCode=One-time code
|
||||||
|
address=Address
|
||||||
|
street=Street
|
||||||
|
locality=City or Locality
|
||||||
|
region=State, Province, or Region
|
||||||
|
postal_code=Zip or Postal code
|
||||||
|
country=Country
|
||||||
|
emailVerified=Email verified
|
||||||
|
website=Web page
|
||||||
|
phoneNumber=Phone number
|
||||||
|
phoneNumberVerified=Phone number verified
|
||||||
|
gender=Gender
|
||||||
|
birthday=Birthdate
|
||||||
|
zoneinfo=Time zone
|
||||||
|
gssDelegationCredential=GSS Delegation Credential
|
||||||
|
logoutOtherSessions=Sign out from other devices
|
||||||
|
|
||||||
|
profileScopeConsentText=User profile
|
||||||
|
emailScopeConsentText=Email address
|
||||||
|
addressScopeConsentText=Address
|
||||||
|
phoneScopeConsentText=Phone number
|
||||||
|
offlineAccessScopeConsentText=Offline Access
|
||||||
|
samlRoleListScopeConsentText=My Roles
|
||||||
|
rolesScopeConsentText=User roles
|
||||||
|
|
||||||
|
restartLoginTooltip=Restart login
|
||||||
|
|
||||||
|
loginTotpIntro=You need to set up a One Time Password generator to access this account
|
||||||
|
loginTotpStep1=Install one of the following applications on your mobile:
|
||||||
|
loginTotpStep2=Open the application and scan the barcode:
|
||||||
|
loginTotpStep3=Enter the one-time code provided by the application and click Submit to finish the setup.
|
||||||
|
loginTotpStep3DeviceName=Provide a Device Name to help you manage your OTP devices.
|
||||||
|
loginTotpManualStep2=Open the application and enter the key:
|
||||||
|
loginTotpManualStep3=Use the following configuration values if the application allows setting them:
|
||||||
|
loginTotpUnableToScan=Unable to scan?
|
||||||
|
loginTotpScanBarcode=Scan barcode?
|
||||||
|
loginCredential=Credential
|
||||||
|
loginOtpOneTime=One-time code
|
||||||
|
loginTotpType=Type
|
||||||
|
loginTotpAlgorithm=Algorithm
|
||||||
|
loginTotpDigits=Digits
|
||||||
|
loginTotpInterval=Interval
|
||||||
|
loginTotpCounter=Counter
|
||||||
|
loginTotpDeviceName=Device Name
|
||||||
|
|
||||||
|
loginTotp.totp=Time-based
|
||||||
|
loginTotp.hotp=Counter-based
|
||||||
|
|
||||||
|
loginChooseAuthenticator=Select login method
|
||||||
|
|
||||||
|
oauthGrantRequest=Do you grant these access privileges?
|
||||||
|
inResource=in
|
||||||
|
|
||||||
|
oauth2DeviceVerificationTitle=Device Login
|
||||||
|
verifyOAuth2DeviceUserCode=Enter the code provided by your device and click Submit
|
||||||
|
oauth2DeviceInvalidUserCodeMessage=Invalid code, please try again.
|
||||||
|
oauth2DeviceExpiredUserCodeMessage=The code has expired. Please go back to your device and try connecting again.
|
||||||
|
oauth2DeviceVerificationCompleteHeader=Device Login Successful
|
||||||
|
oauth2DeviceVerificationCompleteMessage=You may close this browser window and go back to your device.
|
||||||
|
oauth2DeviceVerificationFailedHeader=Device Login Failed
|
||||||
|
oauth2DeviceVerificationFailedMessage=You may close this browser window and go back to your device and try connecting again.
|
||||||
|
oauth2DeviceConsentDeniedMessage=Consent denied for connecting the device.
|
||||||
|
oauth2DeviceAuthorizationGrantDisabledMessage=Client is not allowed to initiate OAuth 2.0 Device Authorization Grant. The flow is disabled for the client.
|
||||||
|
|
||||||
|
emailVerifyInstruction1=An email with instructions to verify your email address has been sent to you.
|
||||||
|
emailVerifyInstruction2=Haven''t received a verification code in your email?
|
||||||
|
emailVerifyInstruction3=to re-send the email.
|
||||||
|
|
||||||
|
emailLinkIdpTitle=Link {0}
|
||||||
|
emailLinkIdp1=An email with instructions to link {0} account {1} with your {2} account has been sent to you.
|
||||||
|
emailLinkIdp2=Haven''t received a verification code in your email?
|
||||||
|
emailLinkIdp3=to re-send the email.
|
||||||
|
emailLinkIdp4=If you already verified the email in different browser
|
||||||
|
emailLinkIdp5=to continue.
|
||||||
|
|
||||||
|
backToLogin=« Back to Login
|
||||||
|
|
||||||
|
emailInstruction=Enter your username or email address and we will send you instructions on how to create a new password.
|
||||||
|
|
||||||
|
copyCodeInstruction=Please copy this code and paste it into your application:
|
||||||
|
|
||||||
|
pageExpiredTitle=Page has expired
|
||||||
|
pageExpiredMsg1=To restart the login process
|
||||||
|
pageExpiredMsg2=To continue the login process
|
||||||
|
|
||||||
|
personalInfo=Personal Info:
|
||||||
|
role_admin=Admin
|
||||||
|
role_realm-admin=Realm Admin
|
||||||
|
role_create-realm=Create realm
|
||||||
|
role_create-client=Create client
|
||||||
|
role_view-realm=View realm
|
||||||
|
role_view-users=View users
|
||||||
|
role_view-applications=View applications
|
||||||
|
role_view-clients=View clients
|
||||||
|
role_view-events=View events
|
||||||
|
role_view-identity-providers=View identity providers
|
||||||
|
role_manage-realm=Manage realm
|
||||||
|
role_manage-users=Manage users
|
||||||
|
role_manage-applications=Manage applications
|
||||||
|
role_manage-identity-providers=Manage identity providers
|
||||||
|
role_manage-clients=Manage clients
|
||||||
|
role_manage-events=Manage events
|
||||||
|
role_view-profile=View profile
|
||||||
|
role_manage-account=Manage account
|
||||||
|
role_manage-account-links=Manage account links
|
||||||
|
role_read-token=Read token
|
||||||
|
role_offline-access=Offline access
|
||||||
|
client_account=Account
|
||||||
|
client_account-console=Account Console
|
||||||
|
client_security-admin-console=Security Admin Console
|
||||||
|
client_admin-cli=Admin CLI
|
||||||
|
client_realm-management=Realm Management
|
||||||
|
client_broker=Broker
|
||||||
|
|
||||||
|
requiredFields=Required fields
|
||||||
|
|
||||||
|
invalidUserMessage=Invalid username or password.
|
||||||
|
invalidUsernameMessage=Invalid username.
|
||||||
|
invalidUsernameOrEmailMessage=Invalid username or email.
|
||||||
|
invalidPasswordMessage=Invalid password.
|
||||||
|
invalidEmailMessage=Invalid email address.
|
||||||
|
accountDisabledMessage=Account is disabled, contact your administrator.
|
||||||
|
accountTemporarilyDisabledMessage=Account is temporarily disabled; contact your administrator or retry later.
|
||||||
|
expiredCodeMessage=Login timeout. Please sign in again.
|
||||||
|
expiredActionMessage=Action expired. Please continue with login now.
|
||||||
|
expiredActionTokenNoSessionMessage=Action expired.
|
||||||
|
expiredActionTokenSessionExistsMessage=Action expired. Please start again.
|
||||||
|
|
||||||
|
missingFirstNameMessage=Please specify first name.
|
||||||
|
missingLastNameMessage=Please specify last name.
|
||||||
|
missingEmailMessage=Please specify email.
|
||||||
|
missingUsernameMessage=Please specify username.
|
||||||
|
missingPasswordMessage=Please specify password.
|
||||||
|
missingTotpMessage=Please specify authenticator code.
|
||||||
|
missingTotpDeviceNameMessage=Please specify device name.
|
||||||
|
notMatchPasswordMessage=Passwords don''t match.
|
||||||
|
|
||||||
|
invalidPasswordExistingMessage=Invalid existing password.
|
||||||
|
invalidPasswordBlacklistedMessage=Invalid password: password is blacklisted.
|
||||||
|
invalidPasswordConfirmMessage=Password confirmation doesn''t match.
|
||||||
|
invalidTotpMessage=Invalid authenticator code.
|
||||||
|
|
||||||
|
usernameExistsMessage=Username already exists.
|
||||||
|
emailExistsMessage=Email already exists.
|
||||||
|
|
||||||
|
federatedIdentityExistsMessage=User with {0} {1} already exists. Please login to account management to link the account.
|
||||||
|
federatedIdentityUnavailableMessage=User {0} authenticated with identity provider {1} does not exists. Please contact your administrator.
|
||||||
|
|
||||||
|
confirmLinkIdpTitle=Account already exists
|
||||||
|
federatedIdentityConfirmLinkMessage=User with {0} {1} already exists. How do you want to continue?
|
||||||
|
federatedIdentityConfirmReauthenticateMessage=Authenticate to link your account with {0}
|
||||||
|
nestedFirstBrokerFlowMessage=The {0} user {1} is not linked to any known user.
|
||||||
|
confirmLinkIdpReviewProfile=Review profile
|
||||||
|
confirmLinkIdpContinue=Add to existing account
|
||||||
|
|
||||||
|
configureTotpMessage=You need to set up Mobile Authenticator to activate your account.
|
||||||
|
updateProfileMessage=You need to update your user profile to activate your account.
|
||||||
|
updatePasswordMessage=You need to change your password to activate your account.
|
||||||
|
resetPasswordMessage=You need to change your password.
|
||||||
|
verifyEmailMessage=You need to verify your email address to activate your account.
|
||||||
|
linkIdpMessage=You need to verify your email address to link your account with {0}.
|
||||||
|
|
||||||
|
emailSentMessage=You should receive an email shortly with further instructions.
|
||||||
|
emailSendErrorMessage=Failed to send email, please try again later.
|
||||||
|
|
||||||
|
accountUpdatedMessage=Your account has been updated.
|
||||||
|
accountPasswordUpdatedMessage=Your password has been updated.
|
||||||
|
|
||||||
|
delegationCompleteHeader=Login Successful
|
||||||
|
delegationCompleteMessage=You may close this browser window and go back to your console application.
|
||||||
|
delegationFailedHeader=Login Failed
|
||||||
|
delegationFailedMessage=You may close this browser window and go back to your console application and try logging in again.
|
||||||
|
|
||||||
|
noAccessMessage=No access
|
||||||
|
|
||||||
|
invalidPasswordMinLengthMessage=Invalid password: minimum length {0}.
|
||||||
|
invalidPasswordMinDigitsMessage=Invalid password: must contain at least {0} numerical digits.
|
||||||
|
invalidPasswordMinLowerCaseCharsMessage=Invalid password: must contain at least {0} lower case characters.
|
||||||
|
invalidPasswordMinUpperCaseCharsMessage=Invalid password: must contain at least {0} upper case characters.
|
||||||
|
invalidPasswordMinSpecialCharsMessage=Invalid password: must contain at least {0} special characters.
|
||||||
|
invalidPasswordNotUsernameMessage=Invalid password: must not be equal to the username.
|
||||||
|
invalidPasswordNotEmailMessage=Invalid password: must not be equal to the email.
|
||||||
|
invalidPasswordRegexPatternMessage=Invalid password: fails to match regex pattern(s).
|
||||||
|
invalidPasswordHistoryMessage=Invalid password: must not be equal to any of last {0} passwords.
|
||||||
|
invalidPasswordGenericMessage=Invalid password: new password doesn''t match password policies.
|
||||||
|
|
||||||
|
failedToProcessResponseMessage=Failed to process response
|
||||||
|
httpsRequiredMessage=HTTPS required
|
||||||
|
realmNotEnabledMessage=Realm not enabled
|
||||||
|
invalidRequestMessage=Invalid Request
|
||||||
|
failedLogout=Logout failed
|
||||||
|
unknownLoginRequesterMessage=Unknown login requester
|
||||||
|
loginRequesterNotEnabledMessage=Login requester not enabled
|
||||||
|
bearerOnlyMessage=Bearer-only applications are not allowed to initiate browser login
|
||||||
|
standardFlowDisabledMessage=Client is not allowed to initiate browser login with given response_type. Standard flow is disabled for the client.
|
||||||
|
implicitFlowDisabledMessage=Client is not allowed to initiate browser login with given response_type. Implicit flow is disabled for the client.
|
||||||
|
invalidRedirectUriMessage=Invalid redirect uri
|
||||||
|
unsupportedNameIdFormatMessage=Unsupported NameIDFormat
|
||||||
|
invalidRequesterMessage=Invalid requester
|
||||||
|
registrationNotAllowedMessage=Registration not allowed
|
||||||
|
resetCredentialNotAllowedMessage=Reset Credential not allowed
|
||||||
|
|
||||||
|
permissionNotApprovedMessage=Permission not approved.
|
||||||
|
noRelayStateInResponseMessage=No relay state in response from identity provider.
|
||||||
|
insufficientPermissionMessage=Insufficient permissions to link identities.
|
||||||
|
couldNotProceedWithAuthenticationRequestMessage=Could not proceed with authentication request to identity provider.
|
||||||
|
couldNotObtainTokenMessage=Could not obtain token from identity provider.
|
||||||
|
unexpectedErrorRetrievingTokenMessage=Unexpected error when retrieving token from identity provider.
|
||||||
|
unexpectedErrorHandlingResponseMessage=Unexpected error when handling response from identity provider.
|
||||||
|
identityProviderAuthenticationFailedMessage=Authentication failed. Could not authenticate with identity provider.
|
||||||
|
couldNotSendAuthenticationRequestMessage=Could not send authentication request to identity provider.
|
||||||
|
unexpectedErrorHandlingRequestMessage=Unexpected error when handling authentication request to identity provider.
|
||||||
|
invalidAccessCodeMessage=Invalid access code.
|
||||||
|
sessionNotActiveMessage=Session not active.
|
||||||
|
invalidCodeMessage=An error occurred, please login again through your application.
|
||||||
|
identityProviderUnexpectedErrorMessage=Unexpected error when authenticating with identity provider
|
||||||
|
identityProviderMissingStateMessage=Missing state parameter in response from identity provider.
|
||||||
|
identityProviderNotFoundMessage=Could not find an identity provider with the identifier.
|
||||||
|
identityProviderLinkSuccess=You successfully verified your email. Please go back to your original browser and continue there with the login.
|
||||||
|
staleCodeMessage=This page is no longer valid, please go back to your application and sign in again
|
||||||
|
realmSupportsNoCredentialsMessage=Realm does not support any credential type.
|
||||||
|
credentialSetupRequired=Cannot login, credential setup required.
|
||||||
|
identityProviderNotUniqueMessage=Realm supports multiple identity providers. Could not determine which identity provider should be used to authenticate with.
|
||||||
|
emailVerifiedMessage=Your email address has been verified.
|
||||||
|
staleEmailVerificationLink=The link you clicked is an old stale link and is no longer valid. Maybe you have already verified your email.
|
||||||
|
identityProviderAlreadyLinkedMessage=Federated identity returned by {0} is already linked to another user.
|
||||||
|
confirmAccountLinking=Confirm linking the account {0} of identity provider {1} with your account.
|
||||||
|
confirmEmailAddressVerification=Confirm validity of e-mail address {0}.
|
||||||
|
confirmExecutionOfActions=Perform the following action(s)
|
||||||
|
|
||||||
|
locale_ca=Catal\u00E0
|
||||||
|
locale_cs=\u010Ce\u0161tina
|
||||||
|
locale_da=Dansk
|
||||||
|
locale_de=Deutsch
|
||||||
|
locale_en=English
|
||||||
|
locale_es=Espa\u00F1ol
|
||||||
|
locale_fr=Fran\u00E7ais
|
||||||
|
locale_hu=Magyar
|
||||||
|
locale_it=Italiano
|
||||||
|
locale_ja=\u65E5\u672C\u8A9E
|
||||||
|
locale_lt=Lietuvi\u0173
|
||||||
|
locale_nl=Nederlands
|
||||||
|
locale_no=Norsk
|
||||||
|
locale_pl=Polski
|
||||||
|
locale_pt_BR=Portugu\u00EAs (Brasil)
|
||||||
|
locale_pt-BR=Portugu\u00EAs (Brasil)
|
||||||
|
locale_ru=\u0420\u0443\u0441\u0441\u043A\u0438\u0439
|
||||||
|
locale_sk=Sloven\u010Dina
|
||||||
|
locale_sv=Svenska
|
||||||
|
locale_tr=T\u00FCrk\u00E7e
|
||||||
|
locale_zh-CN=\u4E2D\u6587\u7B80\u4F53
|
||||||
|
|
||||||
|
backToApplication=« Back to Application
|
||||||
|
missingParameterMessage=Missing parameters\: {0}
|
||||||
|
clientNotFoundMessage=Client not found.
|
||||||
|
clientDisabledMessage=Client disabled.
|
||||||
|
invalidParameterMessage=Invalid parameter\: {0}
|
||||||
|
alreadyLoggedIn=You are already logged in.
|
||||||
|
differentUserAuthenticated=You are already authenticated as different user ''{0}'' in this session. Please sign out first.
|
||||||
|
brokerLinkingSessionExpired=Requested broker account linking, but current session is no longer valid.
|
||||||
|
proceedWithAction=» Click here to proceed
|
||||||
|
|
||||||
|
requiredAction.CONFIGURE_TOTP=Configure OTP
|
||||||
|
requiredAction.terms_and_conditions=Terms and Conditions
|
||||||
|
requiredAction.UPDATE_PASSWORD=Update Password
|
||||||
|
requiredAction.UPDATE_PROFILE=Update Profile
|
||||||
|
requiredAction.VERIFY_EMAIL=Verify Email
|
||||||
|
|
||||||
|
doX509Login=You will be logged in as\:
|
||||||
|
clientCertificate=X509 client certificate\:
|
||||||
|
noCertificate=[No Certificate]
|
||||||
|
|
||||||
|
|
||||||
|
pageNotFound=Page not found
|
||||||
|
internalServerError=An internal server error has occurred
|
||||||
|
|
||||||
|
console-username=Username:
|
||||||
|
console-password=Password:
|
||||||
|
console-otp=One Time Password:
|
||||||
|
console-new-password=New Password:
|
||||||
|
console-confirm-password=Confirm Password:
|
||||||
|
console-update-password=Update of your password is required.
|
||||||
|
console-verify-email=You need to verify your email address. We sent an email to {0} that contains a verification code. Please enter this code into the input below.
|
||||||
|
console-email-code=Email Code:
|
||||||
|
console-accept-terms=Accept Terms? [y/n]:
|
||||||
|
console-accept=y
|
||||||
|
|
||||||
|
# Openshift messages
|
||||||
|
openshift.scope.user_info=User information
|
||||||
|
openshift.scope.user_check-access=User access information
|
||||||
|
openshift.scope.user_full=Full Access
|
||||||
|
openshift.scope.list-projects=List projects
|
||||||
|
|
||||||
|
# SAML authentication
|
||||||
|
saml.post-form.title=Authentication Redirect
|
||||||
|
saml.post-form.message=Redirecting, please wait.
|
||||||
|
saml.post-form.js-disabled=JavaScript is disabled. We strongly recommend to enable it. Click the button below to continue.
|
||||||
|
saml.artifactResolutionServiceInvalidResponse=Unable to resolve artifact.
|
||||||
|
|
||||||
|
#authenticators
|
||||||
|
otp-display-name=Authenticator Application
|
||||||
|
otp-help-text=Enter a verification code from authenticator application.
|
||||||
|
password-display-name=Password
|
||||||
|
password-help-text=Sign in by entering your password.
|
||||||
|
auth-username-form-display-name=Username
|
||||||
|
auth-username-form-help-text=Start sign in by entering your username
|
||||||
|
auth-username-password-form-display-name=Username and password
|
||||||
|
auth-username-password-form-help-text=Sign in by entering your username and password.
|
||||||
|
|
||||||
|
# WebAuthn
|
||||||
|
webauthn-display-name=Security Key
|
||||||
|
webauthn-help-text=Use your security key to sign in.
|
||||||
|
webauthn-passwordless-display-name=Security Key
|
||||||
|
webauthn-passwordless-help-text=Use your security key for passwordless sign in.
|
||||||
|
webauthn-login-title=Security Key login
|
||||||
|
webauthn-registration-title=Security Key Registration
|
||||||
|
webauthn-available-authenticators=Available authenticators
|
||||||
|
webauthn-unsupported-browser-text=WebAuthn is not supported by this browser. Try another one or contact your administrator.
|
||||||
|
|
||||||
|
# WebAuthn Error
|
||||||
|
webauthn-error-title=Security Key Error
|
||||||
|
webauthn-error-registration=Failed to register your Security key.<br/> {0}
|
||||||
|
webauthn-error-api-get=Failed to authenticate by the Security key.<br/> {0}
|
||||||
|
webauthn-error-different-user=First authenticated user is not the one authenticated by the Security key.
|
||||||
|
webauthn-error-auth-verification=Security key authentication result is invalid.<br/> {0}
|
||||||
|
webauthn-error-register-verification=Security key registration result is invalid.<br/> {0}
|
||||||
|
webauthn-error-user-not-found=Unknown user authenticated by the Security key.
|
||||||
|
|
||||||
|
# Identity provider
|
||||||
|
identity-provider-redirector=Connect with another Identity Provider
|
||||||
|
identity-provider-login-label=Or sign in with
|
||||||
|
|
||||||
|
finalDeletionConfirmation=If you delete your account, it cannot be restored. To keep your account, click Cancel.
|
||||||
|
irreversibleAction=This action is irreversible
|
||||||
|
deleteAccountConfirm=Delete account confirmation
|
||||||
|
|
||||||
|
deletingImplies=Deleting your account implies:
|
||||||
|
errasingData=Erasing all your data
|
||||||
|
loggingOutImmediately=Logging you out immediately
|
||||||
|
accountUnusable=Any subsequent use of the application will not be possible with this account
|
||||||
|
userDeletedSuccessfully=User deleted successfully
|
||||||
|
|
||||||
|
access-denied=Access denied
|
141
lumbung.space/login/register.ftl
Executable file
141
lumbung.space/login/register.ftl
Executable file
@ -0,0 +1,141 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout displayMessage=!messagesPerField.existsError('firstName','lastName','email','username','password','password-confirm'); section>
|
||||||
|
<#if section = "header">
|
||||||
|
${msg("registerTitle")}
|
||||||
|
<#elseif section = "form">
|
||||||
|
<form id="kc-register-form" class="${properties.kcFormClass!}" action="${url.registrationAction}" method="post">
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<div class="${properties.kcLabelWrapperClass!}">
|
||||||
|
<label for="firstName" class="${properties.kcLabelClass!}">${msg("firstName")}</label>
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcInputWrapperClass!}">
|
||||||
|
<input type="text" id="firstName" class="${properties.kcInputClass!}" name="firstName"
|
||||||
|
value="${(register.formData.firstName!'')}"
|
||||||
|
aria-invalid="<#if messagesPerField.existsError('firstName')>true</#if>"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<#if messagesPerField.existsError('firstName')>
|
||||||
|
<span id="input-error-firstname" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
|
||||||
|
${kcSanitize(messagesPerField.get('firstName'))?no_esc}
|
||||||
|
</span>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<div class="${properties.kcLabelWrapperClass!}">
|
||||||
|
<label for="lastName" class="${properties.kcLabelClass!}">${msg("lastName")}</label>
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcInputWrapperClass!}">
|
||||||
|
<input type="text" id="lastName" class="${properties.kcInputClass!}" name="lastName"
|
||||||
|
value="${(register.formData.lastName!'')}"
|
||||||
|
aria-invalid="<#if messagesPerField.existsError('lastName')>true</#if>"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<#if messagesPerField.existsError('lastName')>
|
||||||
|
<span id="input-error-lastname" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
|
||||||
|
${kcSanitize(messagesPerField.get('lastName'))?no_esc}
|
||||||
|
</span>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<div class="${properties.kcLabelWrapperClass!}">
|
||||||
|
<label for="email" class="${properties.kcLabelClass!}">${msg("email")}</label>
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcInputWrapperClass!}">
|
||||||
|
<input type="text" id="email" class="${properties.kcInputClass!}" name="email"
|
||||||
|
value="${(register.formData.email!'')}" autocomplete="email"
|
||||||
|
aria-invalid="<#if messagesPerField.existsError('email')>true</#if>"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<#if messagesPerField.existsError('email')>
|
||||||
|
<span id="input-error-email" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
|
||||||
|
${kcSanitize(messagesPerField.get('email'))?no_esc}
|
||||||
|
</span>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<#if !realm.registrationEmailAsUsername>
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<div class="${properties.kcLabelWrapperClass!}">
|
||||||
|
<label for="username" class="${properties.kcLabelClass!}">${msg("username")}</label>
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcInputWrapperClass!}">
|
||||||
|
<input type="text" id="username" class="${properties.kcInputClass!}" name="username"
|
||||||
|
value="${(register.formData.username!'')}" autocomplete="username"
|
||||||
|
aria-invalid="<#if messagesPerField.existsError('username')>true</#if>"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<#if messagesPerField.existsError('username')>
|
||||||
|
<span id="input-error-username" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
|
||||||
|
${kcSanitize(messagesPerField.get('username'))?no_esc}
|
||||||
|
</span>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if passwordRequired??>
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<div class="${properties.kcLabelWrapperClass!}">
|
||||||
|
<label for="password" class="${properties.kcLabelClass!}">${msg("password")}</label>
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcInputWrapperClass!}">
|
||||||
|
<input type="password" id="password" class="${properties.kcInputClass!}" name="password"
|
||||||
|
autocomplete="new-password"
|
||||||
|
aria-invalid="<#if messagesPerField.existsError('password','password-confirm')>true</#if>"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<#if messagesPerField.existsError('password')>
|
||||||
|
<span id="input-error-password" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
|
||||||
|
${kcSanitize(messagesPerField.get('password'))?no_esc}
|
||||||
|
</span>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<div class="${properties.kcLabelWrapperClass!}">
|
||||||
|
<label for="password-confirm"
|
||||||
|
class="${properties.kcLabelClass!}">${msg("passwordConfirm")}</label>
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcInputWrapperClass!}">
|
||||||
|
<input type="password" id="password-confirm" class="${properties.kcInputClass!}"
|
||||||
|
name="password-confirm"
|
||||||
|
aria-invalid="<#if messagesPerField.existsError('password-confirm')>true</#if>"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<#if messagesPerField.existsError('password-confirm')>
|
||||||
|
<span id="input-error-password-confirm" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
|
||||||
|
${kcSanitize(messagesPerField.get('password-confirm'))?no_esc}
|
||||||
|
</span>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if recaptchaRequired??>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="${properties.kcInputWrapperClass!}">
|
||||||
|
<div class="g-recaptcha" data-size="compact" data-sitekey="${recaptchaSiteKey}"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<div id="kc-form-options" class="${properties.kcFormOptionsClass!}">
|
||||||
|
<div class="${properties.kcFormOptionsWrapperClass!}">
|
||||||
|
<span><a href="${url.loginUrl}">${kcSanitize(msg("backToLogin"))?no_esc}</a></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="kc-form-buttons" class="${properties.kcFormButtonsClass!}">
|
||||||
|
<input class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!}" type="submit" value="${msg("doRegister")}"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</#if>
|
||||||
|
</@layout.registrationLayout>
|
114
lumbung.space/login/resources/js/base64url.js
Normal file
114
lumbung.space/login/resources/js/base64url.js
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
// for embedded scripts, quoted and modified from https://github.com/swansontec/rfc4648.js by William Swanson
|
||||||
|
'use strict';
|
||||||
|
var base64url = base64url || {};
|
||||||
|
(function(base64url) {
|
||||||
|
|
||||||
|
function parse (string, encoding, opts = {}) {
|
||||||
|
// Build the character lookup table:
|
||||||
|
if (!encoding.codes) {
|
||||||
|
encoding.codes = {};
|
||||||
|
for (let i = 0; i < encoding.chars.length; ++i) {
|
||||||
|
encoding.codes[encoding.chars[i]] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The string must have a whole number of bytes:
|
||||||
|
if (!opts.loose && (string.length * encoding.bits) & 7) {
|
||||||
|
throw new SyntaxError('Invalid padding');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count the padding bytes:
|
||||||
|
let end = string.length;
|
||||||
|
while (string[end - 1] === '=') {
|
||||||
|
--end;
|
||||||
|
|
||||||
|
// If we get a whole number of bytes, there is too much padding:
|
||||||
|
if (!opts.loose && !(((string.length - end) * encoding.bits) & 7)) {
|
||||||
|
throw new SyntaxError('Invalid padding');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate the output:
|
||||||
|
const out = new (opts.out || Uint8Array)(((end * encoding.bits) / 8) | 0);
|
||||||
|
|
||||||
|
// Parse the data:
|
||||||
|
let bits = 0; // Number of bits currently in the buffer
|
||||||
|
let buffer = 0; // Bits waiting to be written out, MSB first
|
||||||
|
let written = 0; // Next byte to write
|
||||||
|
for (let i = 0; i < end; ++i) {
|
||||||
|
// Read one character from the string:
|
||||||
|
const value = encoding.codes[string[i]];
|
||||||
|
if (value === void 0) {
|
||||||
|
throw new SyntaxError('Invalid character ' + string[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append the bits to the buffer:
|
||||||
|
buffer = (buffer << encoding.bits) | value;
|
||||||
|
bits += encoding.bits;
|
||||||
|
|
||||||
|
// Write out some bits if the buffer has a byte's worth:
|
||||||
|
if (bits >= 8) {
|
||||||
|
bits -= 8;
|
||||||
|
out[written++] = 0xff & (buffer >> bits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that we have received just enough bits:
|
||||||
|
if (bits >= encoding.bits || 0xff & (buffer << (8 - bits))) {
|
||||||
|
throw new SyntaxError('Unexpected end of data');
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
function stringify (data, encoding, opts = {}) {
|
||||||
|
const { pad = true } = opts;
|
||||||
|
const mask = (1 << encoding.bits) - 1;
|
||||||
|
let out = '';
|
||||||
|
|
||||||
|
let bits = 0; // Number of bits currently in the buffer
|
||||||
|
let buffer = 0; // Bits waiting to be written out, MSB first
|
||||||
|
for (let i = 0; i < data.length; ++i) {
|
||||||
|
// Slurp data into the buffer:
|
||||||
|
buffer = (buffer << 8) | (0xff & data[i]);
|
||||||
|
bits += 8;
|
||||||
|
|
||||||
|
// Write out as much as we can:
|
||||||
|
while (bits > encoding.bits) {
|
||||||
|
bits -= encoding.bits;
|
||||||
|
out += encoding.chars[mask & (buffer >> bits)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Partial character:
|
||||||
|
if (bits) {
|
||||||
|
out += encoding.chars[mask & (buffer << (encoding.bits - bits))];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add padding characters until we hit a byte boundary:
|
||||||
|
if (pad) {
|
||||||
|
while ((out.length * encoding.bits) & 7) {
|
||||||
|
out += '=';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
const encoding = {
|
||||||
|
chars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_',
|
||||||
|
bits: 6
|
||||||
|
}
|
||||||
|
|
||||||
|
base64url.decode = function (string, opts) {
|
||||||
|
return parse(string, encoding, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
base64url.encode = function (data, opts) {
|
||||||
|
return stringify(data, encoding, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
return base64url;
|
||||||
|
}(base64url));
|
||||||
|
|
||||||
|
|
25
lumbung.space/login/saml-post-form.ftl
Normal file
25
lumbung.space/login/saml-post-form.ftl
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout; section>
|
||||||
|
<#if section = "header">
|
||||||
|
${msg("saml.post-form.title")}
|
||||||
|
<#elseif section = "form">
|
||||||
|
<script>window.onload = function() {document.forms[0].submit()};</script>
|
||||||
|
<p>${msg("saml.post-form.message")}</p>
|
||||||
|
<form name="saml-post-binding" method="post" action="${samlPost.url}">
|
||||||
|
<#if samlPost.SAMLRequest??>
|
||||||
|
<input type="hidden" name="SAMLRequest" value="${samlPost.SAMLRequest}"/>
|
||||||
|
</#if>
|
||||||
|
<#if samlPost.SAMLResponse??>
|
||||||
|
<input type="hidden" name="SAMLResponse" value="${samlPost.SAMLResponse}"/>
|
||||||
|
</#if>
|
||||||
|
<#if samlPost.relayState??>
|
||||||
|
<input type="hidden" name="RelayState" value="${samlPost.relayState}"/>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<noscript>
|
||||||
|
<p>${msg("saml.post-form.js-disabled")}</p>
|
||||||
|
<input type="submit" value="${msg("doContinue")}"/>
|
||||||
|
</noscript>
|
||||||
|
</form>
|
||||||
|
</#if>
|
||||||
|
</@layout.registrationLayout>
|
43
lumbung.space/login/select-authenticator.ftl
Normal file
43
lumbung.space/login/select-authenticator.ftl
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout displayInfo=false; section>
|
||||||
|
<#if section = "header" || section = "show-username">
|
||||||
|
<script type="text/javascript">
|
||||||
|
function fillAndSubmit(authExecId) {
|
||||||
|
document.getElementById('authexec-hidden-input').value = authExecId;
|
||||||
|
document.getElementById('kc-select-credential-form').submit();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<#if section = "header">
|
||||||
|
${msg("loginChooseAuthenticator")}
|
||||||
|
</#if>
|
||||||
|
<#elseif section = "form">
|
||||||
|
|
||||||
|
<form id="kc-select-credential-form" class="${properties.kcFormClass!}" action="${url.loginAction}" method="post">
|
||||||
|
<div class="${properties.kcSelectAuthListClass!}">
|
||||||
|
<#list auth.authenticationSelections as authenticationSelection>
|
||||||
|
<div class="${properties.kcSelectAuthListItemClass!}" onclick="fillAndSubmit('${authenticationSelection.authExecId}')">
|
||||||
|
|
||||||
|
<div class="${properties.kcSelectAuthListItemIconClass!}">
|
||||||
|
<i class="${properties['${authenticationSelection.iconCssClass}']!authenticationSelection.iconCssClass} fa-2x"></i>
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcSelectAuthListItemBodyClass!}">
|
||||||
|
<div class="${properties.kcSelectAuthListItemHeadingClass!}">
|
||||||
|
${msg('${authenticationSelection.displayName}')}
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcSelectAuthListItemDescriptionClass!}">
|
||||||
|
${msg('${authenticationSelection.helpText}')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcSelectAuthListItemFillClass!}"></div>
|
||||||
|
<div class="${properties.kcSelectAuthListItemArrowClass!}">
|
||||||
|
<i class="${properties.kcSelectAuthListItemArrowIconClass!}"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</#list>
|
||||||
|
<input type="hidden" id="authexec-hidden-input" name="authenticationExecution" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</#if>
|
||||||
|
</@layout.registrationLayout>
|
||||||
|
|
152
lumbung.space/login/template.ftl
Normal file
152
lumbung.space/login/template.ftl
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
<#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" />
|
||||||
|
<meta name="robots" content="noindex, nofollow">
|
||||||
|
|
||||||
|
<#if properties.meta?has_content>
|
||||||
|
<#list properties.meta?split(' ') as meta>
|
||||||
|
<meta name="${meta?split('==')[0]}" content="${meta?split('==')[1]}"/>
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
<title>${msg("loginTitle",(realm.displayName!''))}</title>
|
||||||
|
<link rel="icon" href="${url.resourcesPath}/img/favicon.ico" />
|
||||||
|
<#if properties.stylesCommon?has_content>
|
||||||
|
<#list properties.stylesCommon?split(' ') as style>
|
||||||
|
<link href="${url.resourcesCommonPath}/${style}" rel="stylesheet" />
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
<#if properties.styles?has_content>
|
||||||
|
<#list properties.styles?split(' ') as style>
|
||||||
|
<link href="${url.resourcesPath}/${style}" rel="stylesheet" />
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
<#if properties.scripts?has_content>
|
||||||
|
<#list properties.scripts?split(' ') as script>
|
||||||
|
<script src="${url.resourcesPath}/${script}" type="text/javascript"></script>
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
<#if scripts??>
|
||||||
|
<#list scripts as script>
|
||||||
|
<script src="${script}" type="text/javascript"></script>
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="${properties.kcBodyClass!}">
|
||||||
|
<div class="${properties.kcLoginClass!}">
|
||||||
|
<div id="kc-header" class="${properties.kcHeaderClass!}">
|
||||||
|
<div id="kc-header-wrapper"
|
||||||
|
class="${properties.kcHeaderWrapperClass!}">${kcSanitize(msg("loginTitleHtml",(realm.displayNameHtml!'')))?no_esc}</div>
|
||||||
|
</div>
|
||||||
|
<div class="${properties.kcFormCardClass!}">
|
||||||
|
<header class="${properties.kcFormHeaderClass!}">
|
||||||
|
<#if realm.internationalizationEnabled && locale.supported?size gt 1>
|
||||||
|
<div class="${properties.kcLocaleMainClass!}" id="kc-locale">
|
||||||
|
<div id="kc-locale-wrapper" class="${properties.kcLocaleWrapperClass!}">
|
||||||
|
<div id="kc-locale-dropdown" class="${properties.kcLocaleDropDownClass!}">
|
||||||
|
<a href="#" id="kc-current-locale-link">${locale.current}</a>
|
||||||
|
<ul class="${properties.kcLocaleListClass!}">
|
||||||
|
<#list locale.supported as l>
|
||||||
|
<li class="${properties.kcLocaleListItemClass!}">
|
||||||
|
<a class="${properties.kcLocaleItemClass!}" href="${l.url}">${l.label}</a>
|
||||||
|
</li>
|
||||||
|
</#list>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
<#if !(auth?has_content && auth.showUsername() && !auth.showResetCredentials())>
|
||||||
|
<#if displayRequiredFields>
|
||||||
|
<div class="${properties.kcContentWrapperClass!}">
|
||||||
|
<div class="${properties.kcLabelWrapperClass!} subtitle">
|
||||||
|
<span class="subtitle"><span class="required">*</span> ${msg("requiredFields")}</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-10">
|
||||||
|
<h1 id="kc-page-title"><#nested "header"></h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<#else>
|
||||||
|
<h1 id="kc-page-title"><#nested "header"></h1>
|
||||||
|
</#if>
|
||||||
|
<#else>
|
||||||
|
<#if displayRequiredFields>
|
||||||
|
<div class="${properties.kcContentWrapperClass!}">
|
||||||
|
<div class="${properties.kcLabelWrapperClass!} subtitle">
|
||||||
|
<span class="subtitle"><span class="required">*</span> ${msg("requiredFields")}</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-10">
|
||||||
|
<#nested "show-username">
|
||||||
|
<div id="kc-username" class="${properties.kcFormGroupClass!}">
|
||||||
|
<label id="kc-attempted-username">${auth.attemptedUsername}</label>
|
||||||
|
<a id="reset-login" href="${url.loginRestartFlowUrl}">
|
||||||
|
<div class="kc-login-tooltip">
|
||||||
|
<i class="${properties.kcResetFlowIcon!}"></i>
|
||||||
|
<span class="kc-tooltip-text">${msg("restartLoginTooltip")}</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<#else>
|
||||||
|
<#nested "show-username">
|
||||||
|
<div id="kc-username" class="${properties.kcFormGroupClass!}">
|
||||||
|
<label id="kc-attempted-username">${auth.attemptedUsername}</label>
|
||||||
|
<a id="reset-login" href="${url.loginRestartFlowUrl}">
|
||||||
|
<div class="kc-login-tooltip">
|
||||||
|
<i class="${properties.kcResetFlowIcon!}"></i>
|
||||||
|
<span class="kc-tooltip-text">${msg("restartLoginTooltip")}</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
</#if>
|
||||||
|
</header>
|
||||||
|
<div id="kc-content">
|
||||||
|
<div id="kc-content-wrapper">
|
||||||
|
|
||||||
|
<#-- App-initiated actions should not see warning messages about the need to complete the action -->
|
||||||
|
<#-- during login. -->
|
||||||
|
<#if displayMessage && message?has_content && (message.type != 'warning' || !isAppInitiatedAction??)>
|
||||||
|
<div class="alert-${message.type} ${properties.kcAlertClass!} pf-m-<#if message.type = 'error'>danger<#else>${message.type}</#if>">
|
||||||
|
<div class="pf-c-alert__icon">
|
||||||
|
<#if message.type = 'success'><span class="${properties.kcFeedbackSuccessIcon!}"></span></#if>
|
||||||
|
<#if message.type = 'warning'><span class="${properties.kcFeedbackWarningIcon!}"></span></#if>
|
||||||
|
<#if message.type = 'error'><span class="${properties.kcFeedbackErrorIcon!}"></span></#if>
|
||||||
|
<#if message.type = 'info'><span class="${properties.kcFeedbackInfoIcon!}"></span></#if>
|
||||||
|
</div>
|
||||||
|
<span class="${properties.kcAlertTitleClass!}">${kcSanitize(message.summary)?no_esc}</span>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#nested "form">
|
||||||
|
|
||||||
|
<#if auth?has_content && auth.showTryAnotherWayLink() && showAnotherWayIfPresent>
|
||||||
|
<form id="kc-select-try-another-way-form" action="${url.loginAction}" method="post">
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<input type="hidden" name="tryAnotherWay" value="on"/>
|
||||||
|
<a href="#" id="try-another-way"
|
||||||
|
onclick="document.forms['kc-select-try-another-way-form'].submit();return false;">${msg("doTryAnotherWay")}</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<#if displayInfo>
|
||||||
|
<div id="kc-info" class="${properties.kcSignUpClass!}">
|
||||||
|
<div id="kc-info-wrapper" class="${properties.kcInfoAreaWrapperClass!}">
|
||||||
|
<#nested "info">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</#macro>
|
15
lumbung.space/login/terms.ftl
Executable file
15
lumbung.space/login/terms.ftl
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout displayMessage=false; section>
|
||||||
|
<#if section = "header">
|
||||||
|
${msg("termsTitle")}
|
||||||
|
<#elseif section = "form">
|
||||||
|
<div id="kc-terms-text">
|
||||||
|
${kcSanitize(msg("termsText"))?no_esc}
|
||||||
|
</div>
|
||||||
|
<form class="form-actions" action="${url.loginAction}" method="POST">
|
||||||
|
<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="cancel" id="kc-decline" type="submit" value="${msg("doDecline")}"/>
|
||||||
|
</form>
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
</#if>
|
||||||
|
</@layout.registrationLayout>
|
115
lumbung.space/login/webauthn-authenticate.ftl
Normal file
115
lumbung.space/login/webauthn-authenticate.ftl
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout showAnotherWayIfPresent=false; section>
|
||||||
|
<#if section = "title">
|
||||||
|
title
|
||||||
|
<#elseif section = "header">
|
||||||
|
${kcSanitize(msg("webauthn-login-title"))?no_esc}
|
||||||
|
<#elseif section = "form">
|
||||||
|
|
||||||
|
<form id="webauth" class="${properties.kcFormClass!}" action="${url.loginAction}" method="post">
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<input type="hidden" id="clientDataJSON" name="clientDataJSON"/>
|
||||||
|
<input type="hidden" id="authenticatorData" name="authenticatorData"/>
|
||||||
|
<input type="hidden" id="signature" name="signature"/>
|
||||||
|
<input type="hidden" id="credentialId" name="credentialId"/>
|
||||||
|
<input type="hidden" id="userHandle" name="userHandle"/>
|
||||||
|
<input type="hidden" id="error" name="error"/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<#if authenticators??>
|
||||||
|
<form id="authn_select" class="${properties.kcFormClass!}">
|
||||||
|
<#list authenticators.authenticators as authenticator>
|
||||||
|
<input type="hidden" name="authn_use_chk" value="${authenticator.credentialId}"/>
|
||||||
|
</#list>
|
||||||
|
</form>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="${url.resourcesCommonPath}/node_modules/jquery/dist/jquery.min.js"></script>
|
||||||
|
<script type="text/javascript" src="${url.resourcesPath}/js/base64url.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
window.onload = () => {
|
||||||
|
let isUserIdentified = ${isUserIdentified};
|
||||||
|
if (!isUserIdentified) {
|
||||||
|
doAuthenticate([]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
checkAllowCredentials();
|
||||||
|
};
|
||||||
|
|
||||||
|
function checkAllowCredentials() {
|
||||||
|
let allowCredentials = [];
|
||||||
|
let authn_use = document.forms['authn_select'].authn_use_chk;
|
||||||
|
|
||||||
|
if (authn_use !== undefined) {
|
||||||
|
if (authn_use.length === undefined) {
|
||||||
|
allowCredentials.push({
|
||||||
|
id: base64url.decode(authn_use.value, {loose: true}),
|
||||||
|
type: 'public-key',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
for (let i = 0; i < authn_use.length; i++) {
|
||||||
|
allowCredentials.push({
|
||||||
|
id: base64url.decode(authn_use[i].value, {loose: true}),
|
||||||
|
type: 'public-key',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
doAuthenticate(allowCredentials);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function doAuthenticate(allowCredentials) {
|
||||||
|
|
||||||
|
// Check if WebAuthn is supported by this browser
|
||||||
|
if (!window.PublicKeyCredential) {
|
||||||
|
$("#error").val("${msg("webauthn-unsupported-browser-text")?no_esc}");
|
||||||
|
$("#webauth").submit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let challenge = "${challenge}";
|
||||||
|
let userVerification = "${userVerification}";
|
||||||
|
let rpId = "${rpId}";
|
||||||
|
let publicKey = {
|
||||||
|
rpId : rpId,
|
||||||
|
challenge: base64url.decode(challenge, { loose: true })
|
||||||
|
};
|
||||||
|
|
||||||
|
if (allowCredentials.length) {
|
||||||
|
publicKey.allowCredentials = allowCredentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userVerification !== 'not specified') publicKey.userVerification = userVerification;
|
||||||
|
|
||||||
|
navigator.credentials.get({publicKey})
|
||||||
|
.then((result) => {
|
||||||
|
window.result = result;
|
||||||
|
|
||||||
|
let clientDataJSON = result.response.clientDataJSON;
|
||||||
|
let authenticatorData = result.response.authenticatorData;
|
||||||
|
let signature = result.response.signature;
|
||||||
|
|
||||||
|
$("#clientDataJSON").val(base64url.encode(new Uint8Array(clientDataJSON), { pad: false }));
|
||||||
|
$("#authenticatorData").val(base64url.encode(new Uint8Array(authenticatorData), { pad: false }));
|
||||||
|
$("#signature").val(base64url.encode(new Uint8Array(signature), { pad: false }));
|
||||||
|
$("#credentialId").val(result.id);
|
||||||
|
if(result.response.userHandle) {
|
||||||
|
$("#userHandle").val(base64url.encode(new Uint8Array(result.response.userHandle), { pad: false }));
|
||||||
|
}
|
||||||
|
$("#webauth").submit();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
$("#error").val(err);
|
||||||
|
$("#webauth").submit();
|
||||||
|
})
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<#elseif section = "info">
|
||||||
|
|
||||||
|
</#if>
|
||||||
|
</@layout.registrationLayout>
|
55
lumbung.space/login/webauthn-error.ftl
Normal file
55
lumbung.space/login/webauthn-error.ftl
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout displayMessage=true; section>
|
||||||
|
<#if section = "header">
|
||||||
|
${kcSanitize(msg("webauthn-error-title"))?no_esc}
|
||||||
|
<#elseif section = "form">
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
refreshPage = () => {
|
||||||
|
document.getElementById('isSetRetry').value = 'retry';
|
||||||
|
document.getElementById('executionValue').value = '${execution}';
|
||||||
|
document.getElementById('kc-error-credential-form').submit();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<form id="kc-error-credential-form" class="${properties.kcFormClass!}" action="${url.loginAction}"
|
||||||
|
method="post">
|
||||||
|
<input type="hidden" id="executionValue" name="authenticationExecution"/>
|
||||||
|
<input type="hidden" id="isSetRetry" name="isSetRetry"/>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<#if authenticators??>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>${kcSanitize(msg("webauthn-available-authenticators"))?no_esc}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<#list authenticators.authenticators as authenticator>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<span id="kc-webauthn-authenticator">${kcSanitize(authenticator.label)?no_esc}</span>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</#list>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<input tabindex="4" onclick="refreshPage()" type="button"
|
||||||
|
class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!}"
|
||||||
|
name="try-again" id="kc-try-again" value="${kcSanitize(msg("doTryAgain"))?no_esc}"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<#if isAppInitiatedAction??>
|
||||||
|
<form action="${url.loginAction}" class="${properties.kcFormClass!}" id="kc-webauthn-settings-form" method="post">
|
||||||
|
<button type="submit"
|
||||||
|
class="${properties.kcButtonClass!} ${properties.kcButtonDefaultClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!}"
|
||||||
|
id="cancelWebAuthnAIA" name="cancel-aia" value="true"/>${msg("doCancel")}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
</#if>
|
||||||
|
</@layout.registrationLayout>
|
174
lumbung.space/login/webauthn-register.ftl
Normal file
174
lumbung.space/login/webauthn-register.ftl
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
<#import "template.ftl" as layout>
|
||||||
|
<@layout.registrationLayout; section>
|
||||||
|
<#if section = "title">
|
||||||
|
title
|
||||||
|
<#elseif section = "header">
|
||||||
|
<span class="${properties.kcWebAuthnKeyIcon}"></span>
|
||||||
|
${kcSanitize(msg("webauthn-registration-title"))?no_esc}
|
||||||
|
<#elseif section = "form">
|
||||||
|
|
||||||
|
<form id="register" class="${properties.kcFormClass!}" action="${url.loginAction}" method="post">
|
||||||
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
|
<input type="hidden" id="clientDataJSON" name="clientDataJSON"/>
|
||||||
|
<input type="hidden" id="attestationObject" name="attestationObject"/>
|
||||||
|
<input type="hidden" id="publicKeyCredentialId" name="publicKeyCredentialId"/>
|
||||||
|
<input type="hidden" id="authenticatorLabel" name="authenticatorLabel"/>
|
||||||
|
<input type="hidden" id="error" name="error"/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="${url.resourcesCommonPath}/node_modules/jquery/dist/jquery.min.js"></script>
|
||||||
|
<script type="text/javascript" src="${url.resourcesPath}/js/base64url.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
function registerSecurityKey() {
|
||||||
|
|
||||||
|
// Check if WebAuthn is supported by this browser
|
||||||
|
if (!window.PublicKeyCredential) {
|
||||||
|
$("#error").val("${msg("webauthn-unsupported-browser-text")?no_esc}");
|
||||||
|
$("#register").submit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mandatory parameters
|
||||||
|
let challenge = "${challenge}";
|
||||||
|
let userid = "${userid}";
|
||||||
|
let username = "${username}";
|
||||||
|
|
||||||
|
let signatureAlgorithms = "${signatureAlgorithms}";
|
||||||
|
let pubKeyCredParams = getPubKeyCredParams(signatureAlgorithms);
|
||||||
|
|
||||||
|
let rpEntityName = "${rpEntityName}";
|
||||||
|
let rp = {name: rpEntityName};
|
||||||
|
|
||||||
|
let publicKey = {
|
||||||
|
challenge: base64url.decode(challenge, {loose: true}),
|
||||||
|
rp: rp,
|
||||||
|
user: {
|
||||||
|
id: base64url.decode(userid, {loose: true}),
|
||||||
|
name: username,
|
||||||
|
displayName: username
|
||||||
|
},
|
||||||
|
pubKeyCredParams: pubKeyCredParams,
|
||||||
|
};
|
||||||
|
|
||||||
|
// optional parameters
|
||||||
|
let rpId = "${rpId}";
|
||||||
|
publicKey.rp.id = rpId;
|
||||||
|
|
||||||
|
let attestationConveyancePreference = "${attestationConveyancePreference}";
|
||||||
|
if (attestationConveyancePreference !== 'not specified') publicKey.attestation = attestationConveyancePreference;
|
||||||
|
|
||||||
|
let authenticatorSelection = {};
|
||||||
|
let isAuthenticatorSelectionSpecified = false;
|
||||||
|
|
||||||
|
let authenticatorAttachment = "${authenticatorAttachment}";
|
||||||
|
if (authenticatorAttachment !== 'not specified') {
|
||||||
|
authenticatorSelection.authenticatorAttachment = authenticatorAttachment;
|
||||||
|
isAuthenticatorSelectionSpecified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let requireResidentKey = "${requireResidentKey}";
|
||||||
|
if (requireResidentKey !== 'not specified') {
|
||||||
|
if (requireResidentKey === 'Yes')
|
||||||
|
authenticatorSelection.requireResidentKey = true;
|
||||||
|
else
|
||||||
|
authenticatorSelection.requireResidentKey = false;
|
||||||
|
isAuthenticatorSelectionSpecified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let userVerificationRequirement = "${userVerificationRequirement}";
|
||||||
|
if (userVerificationRequirement !== 'not specified') {
|
||||||
|
authenticatorSelection.userVerification = userVerificationRequirement;
|
||||||
|
isAuthenticatorSelectionSpecified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isAuthenticatorSelectionSpecified) publicKey.authenticatorSelection = authenticatorSelection;
|
||||||
|
|
||||||
|
let createTimeout = ${createTimeout};
|
||||||
|
if (createTimeout != 0) publicKey.timeout = createTimeout * 1000;
|
||||||
|
|
||||||
|
let excludeCredentialIds = "${excludeCredentialIds}";
|
||||||
|
let excludeCredentials = getExcludeCredentials(excludeCredentialIds);
|
||||||
|
if (excludeCredentials.length > 0) publicKey.excludeCredentials = excludeCredentials;
|
||||||
|
|
||||||
|
navigator.credentials.create({publicKey})
|
||||||
|
.then(function (result) {
|
||||||
|
window.result = result;
|
||||||
|
let clientDataJSON = result.response.clientDataJSON;
|
||||||
|
let attestationObject = result.response.attestationObject;
|
||||||
|
let publicKeyCredentialId = result.rawId;
|
||||||
|
|
||||||
|
$("#clientDataJSON").val(base64url.encode(new Uint8Array(clientDataJSON), {pad: false}));
|
||||||
|
$("#attestationObject").val(base64url.encode(new Uint8Array(attestationObject), {pad: false}));
|
||||||
|
$("#publicKeyCredentialId").val(base64url.encode(new Uint8Array(publicKeyCredentialId), {pad: false}));
|
||||||
|
|
||||||
|
let initLabel = "WebAuthn Authenticator (Default Label)";
|
||||||
|
let labelResult = window.prompt("Please input your registered authenticator's label", initLabel);
|
||||||
|
if (labelResult === null) labelResult = initLabel;
|
||||||
|
$("#authenticatorLabel").val(labelResult);
|
||||||
|
|
||||||
|
$("#register").submit();
|
||||||
|
|
||||||
|
})
|
||||||
|
.catch(function (err) {
|
||||||
|
$("#error").val(err);
|
||||||
|
$("#register").submit();
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPubKeyCredParams(signatureAlgorithms) {
|
||||||
|
let pubKeyCredParams = [];
|
||||||
|
if (signatureAlgorithms === "") {
|
||||||
|
pubKeyCredParams.push({type: "public-key", alg: -7});
|
||||||
|
return pubKeyCredParams;
|
||||||
|
}
|
||||||
|
let signatureAlgorithmsList = signatureAlgorithms.split(',');
|
||||||
|
|
||||||
|
for (let i = 0; i < signatureAlgorithmsList.length; i++) {
|
||||||
|
pubKeyCredParams.push({
|
||||||
|
type: "public-key",
|
||||||
|
alg: signatureAlgorithmsList[i]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return pubKeyCredParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getExcludeCredentials(excludeCredentialIds) {
|
||||||
|
let excludeCredentials = [];
|
||||||
|
if (excludeCredentialIds === "") return excludeCredentials;
|
||||||
|
|
||||||
|
let excludeCredentialIdsList = excludeCredentialIds.split(',');
|
||||||
|
|
||||||
|
for (let i = 0; i < excludeCredentialIdsList.length; i++) {
|
||||||
|
excludeCredentials.push({
|
||||||
|
type: "public-key",
|
||||||
|
id: base64url.decode(excludeCredentialIdsList[i],
|
||||||
|
{loose: true})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return excludeCredentials;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<#if !isSetRetry?has_content && isAppInitiatedAction?has_content>
|
||||||
|
<input type="submit"
|
||||||
|
class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!}"
|
||||||
|
id="registerWebAuthnAIA" value="${msg("doRegister")}" onclick="registerSecurityKey()"
|
||||||
|
/>
|
||||||
|
<form action="${url.loginAction}" class="${properties.kcFormClass!}" id="kc-webauthn-settings-form"
|
||||||
|
method="post">
|
||||||
|
<button type="submit"
|
||||||
|
class="${properties.kcButtonClass!} ${properties.kcButtonDefaultClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!}"
|
||||||
|
id="cancelWebAuthnAIA" name="cancel-aia" value="true"/>${msg("doCancel")}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<#else>
|
||||||
|
<script>
|
||||||
|
registerSecurityKey();
|
||||||
|
</script>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
</#if>
|
||||||
|
</@layout.registrationLayout>
|
Loading…
Reference in New Issue
Block a user