From 5d9b49b47d4904e45e95f67043bfeacb15dc0dd7 Mon Sep 17 00:00:00 2001 From: Kayden Tebau Date: Fri, 7 Apr 2023 12:51:46 -0700 Subject: [PATCH] Add UNIX.dog theme, no-JS account console --- .../keycloak/forms/account/AccountPages.java | 2 +- .../freemarker/FreeMarkerAccountProvider.java | 17 +- .../forms/account/freemarker/Templates.java | 4 +- .../freemarker/model/AuthenticationBean.java | 244 +++++++++ .../account/freemarker/model/TotpBean.java | 122 ----- .../account/freemarker/model/UrlBean.java | 4 +- .../main/java/org/keycloak/services/Urls.java | 4 +- .../AbstractSecuredLocalService.java | 14 +- .../resources/account/AccountFormService.java | 73 ++- .../resources/META-INF/keycloak-themes.json | 3 + .../theme/unixdog/account/account.ftl | 38 ++ .../theme/unixdog/account/applications.ftl | 72 +++ .../theme/unixdog/account/authentication.ftl | 58 ++ .../unixdog/account/federatedIdentity.ftl | 42 ++ .../resources/theme/unixdog/account/log.ftl | 35 ++ .../account/messages/messages_en.properties | 441 +++++++++++++++ .../theme/unixdog/account/password.ftl | 59 ++ .../theme/unixdog/account/resource-detail.ftl | 277 ++++++++++ .../theme/unixdog/account/resources.ftl | 403 ++++++++++++++ .../unixdog/account/resources/css/main.css | 218 ++++++++ .../unixdog/account/resources/img/favicon.ico | Bin 0 -> 171528 bytes .../unixdog/account/resources/js/base64url.js | 114 ++++ .../theme/unixdog/account/sessions.ftl | 39 ++ .../theme/unixdog/account/template.ftl | 68 +++ .../theme/unixdog/account/theme.properties | 4 + .../theme/unixdog/login/cli_splash.ftl | 7 + .../resources/theme/unixdog/login/code.ftl | 19 + .../unixdog/login/delete-account-confirm.ftl | 33 ++ .../resources/theme/unixdog/login/error.ftl | 16 + .../unixdog/login/frontchannel-logout.ftl | 30 + .../unixdog/login/idp-review-user-profile.ftl | 23 + .../resources/theme/unixdog/login/info.ftl | 24 + .../theme/unixdog/login/login-config-totp.ftl | 108 ++++ .../unixdog/login/login-idp-link-confirm.ftl | 13 + .../unixdog/login/login-idp-link-email.ftl | 16 + .../theme/unixdog/login/login-oauth-grant.ftl | 68 +++ .../login-oauth2-device-verify-user-code.ftl | 31 ++ .../theme/unixdog/login/login-otp.ftl | 58 ++ .../unixdog/login/login-page-expired.ftl | 11 + .../theme/unixdog/login/login-password.ftl | 32 ++ .../login-recovery-authn-code-config.ftl | 184 +++++++ .../login/login-recovery-authn-code-input.ftl | 44 ++ .../unixdog/login/login-reset-password.ftl | 39 ++ .../unixdog/login/login-update-password.ftl | 71 +++ .../unixdog/login/login-update-profile.ftl | 99 ++++ .../theme/unixdog/login/login-username.ftl | 89 +++ .../unixdog/login/login-verify-email.ftl | 14 + .../theme/unixdog/login/login-x509-info.ftl | 55 ++ .../resources/theme/unixdog/login/login.ftl | 105 ++++ .../theme/unixdog/login/logout-confirm.ftl | 38 ++ .../login/messages/messages_en.properties | 511 ++++++++++++++++++ .../unixdog/login/register-user-profile.ftl | 74 +++ .../theme/unixdog/login/register.ftl | 141 +++++ .../unixdog/login/resources/css/main.css | 209 +++++++ .../unixdog/login/resources/img/favicon.ico | Bin 0 -> 171528 bytes .../unixdog/login/resources/js/base64url.js | 114 ++++ .../theme/unixdog/login/saml-post-form.ftl | 25 + .../unixdog/login/select-authenticator.ftl | 39 ++ .../theme/unixdog/login/template.ftl | 162 ++++++ .../resources/theme/unixdog/login/terms.ftl | 15 + .../theme/unixdog/login/theme.properties | 4 + .../theme/unixdog/login/update-email.ftl | 42 ++ .../unixdog/login/update-user-profile.ftl | 28 + .../unixdog/login/user-profile-commons.ftl | 187 +++++++ .../unixdog/login/webauthn-authenticate.ftl | 168 ++++++ .../theme/unixdog/login/webauthn-error.ftl | 36 ++ .../theme/unixdog/login/webauthn-register.ftl | 194 +++++++ 67 files changed, 5348 insertions(+), 183 deletions(-) create mode 100755 services/src/main/java/org/keycloak/forms/account/freemarker/model/AuthenticationBean.java delete mode 100644 services/src/main/java/org/keycloak/forms/account/freemarker/model/TotpBean.java create mode 100755 themes/src/main/resources/theme/unixdog/account/account.ftl create mode 100755 themes/src/main/resources/theme/unixdog/account/applications.ftl create mode 100755 themes/src/main/resources/theme/unixdog/account/authentication.ftl create mode 100755 themes/src/main/resources/theme/unixdog/account/federatedIdentity.ftl create mode 100644 themes/src/main/resources/theme/unixdog/account/log.ftl create mode 100755 themes/src/main/resources/theme/unixdog/account/messages/messages_en.properties create mode 100755 themes/src/main/resources/theme/unixdog/account/password.ftl create mode 100755 themes/src/main/resources/theme/unixdog/account/resource-detail.ftl create mode 100755 themes/src/main/resources/theme/unixdog/account/resources.ftl create mode 100644 themes/src/main/resources/theme/unixdog/account/resources/css/main.css create mode 100644 themes/src/main/resources/theme/unixdog/account/resources/img/favicon.ico create mode 100644 themes/src/main/resources/theme/unixdog/account/resources/js/base64url.js create mode 100755 themes/src/main/resources/theme/unixdog/account/sessions.ftl create mode 100644 themes/src/main/resources/theme/unixdog/account/template.ftl create mode 100644 themes/src/main/resources/theme/unixdog/account/theme.properties create mode 100644 themes/src/main/resources/theme/unixdog/login/cli_splash.ftl create mode 100755 themes/src/main/resources/theme/unixdog/login/code.ftl create mode 100644 themes/src/main/resources/theme/unixdog/login/delete-account-confirm.ftl create mode 100755 themes/src/main/resources/theme/unixdog/login/error.ftl create mode 100644 themes/src/main/resources/theme/unixdog/login/frontchannel-logout.ftl create mode 100644 themes/src/main/resources/theme/unixdog/login/idp-review-user-profile.ftl create mode 100755 themes/src/main/resources/theme/unixdog/login/info.ftl create mode 100755 themes/src/main/resources/theme/unixdog/login/login-config-totp.ftl create mode 100644 themes/src/main/resources/theme/unixdog/login/login-idp-link-confirm.ftl create mode 100644 themes/src/main/resources/theme/unixdog/login/login-idp-link-email.ftl create mode 100755 themes/src/main/resources/theme/unixdog/login/login-oauth-grant.ftl create mode 100644 themes/src/main/resources/theme/unixdog/login/login-oauth2-device-verify-user-code.ftl create mode 100755 themes/src/main/resources/theme/unixdog/login/login-otp.ftl create mode 100644 themes/src/main/resources/theme/unixdog/login/login-page-expired.ftl create mode 100755 themes/src/main/resources/theme/unixdog/login/login-password.ftl create mode 100644 themes/src/main/resources/theme/unixdog/login/login-recovery-authn-code-config.ftl create mode 100644 themes/src/main/resources/theme/unixdog/login/login-recovery-authn-code-input.ftl create mode 100755 themes/src/main/resources/theme/unixdog/login/login-reset-password.ftl create mode 100755 themes/src/main/resources/theme/unixdog/login/login-update-password.ftl create mode 100755 themes/src/main/resources/theme/unixdog/login/login-update-profile.ftl create mode 100755 themes/src/main/resources/theme/unixdog/login/login-username.ftl create mode 100755 themes/src/main/resources/theme/unixdog/login/login-verify-email.ftl create mode 100644 themes/src/main/resources/theme/unixdog/login/login-x509-info.ftl create mode 100755 themes/src/main/resources/theme/unixdog/login/login.ftl create mode 100644 themes/src/main/resources/theme/unixdog/login/logout-confirm.ftl create mode 100755 themes/src/main/resources/theme/unixdog/login/messages/messages_en.properties create mode 100755 themes/src/main/resources/theme/unixdog/login/register-user-profile.ftl create mode 100755 themes/src/main/resources/theme/unixdog/login/register.ftl create mode 100644 themes/src/main/resources/theme/unixdog/login/resources/css/main.css create mode 100644 themes/src/main/resources/theme/unixdog/login/resources/img/favicon.ico create mode 100644 themes/src/main/resources/theme/unixdog/login/resources/js/base64url.js create mode 100644 themes/src/main/resources/theme/unixdog/login/saml-post-form.ftl create mode 100644 themes/src/main/resources/theme/unixdog/login/select-authenticator.ftl create mode 100644 themes/src/main/resources/theme/unixdog/login/template.ftl create mode 100755 themes/src/main/resources/theme/unixdog/login/terms.ftl create mode 100644 themes/src/main/resources/theme/unixdog/login/theme.properties create mode 100644 themes/src/main/resources/theme/unixdog/login/update-email.ftl create mode 100755 themes/src/main/resources/theme/unixdog/login/update-user-profile.ftl create mode 100644 themes/src/main/resources/theme/unixdog/login/user-profile-commons.ftl create mode 100644 themes/src/main/resources/theme/unixdog/login/webauthn-authenticate.ftl create mode 100644 themes/src/main/resources/theme/unixdog/login/webauthn-error.ftl create mode 100644 themes/src/main/resources/theme/unixdog/login/webauthn-register.ftl diff --git a/server-spi-private/src/main/java/org/keycloak/forms/account/AccountPages.java b/server-spi-private/src/main/java/org/keycloak/forms/account/AccountPages.java index 6c01f79aba..a827f3e341 100755 --- a/server-spi-private/src/main/java/org/keycloak/forms/account/AccountPages.java +++ b/server-spi-private/src/main/java/org/keycloak/forms/account/AccountPages.java @@ -22,6 +22,6 @@ package org.keycloak.forms.account; */ public enum AccountPages { - ACCOUNT, PASSWORD, TOTP, FEDERATED_IDENTITY, LOG, SESSIONS, APPLICATIONS, RESOURCES, RESOURCE_DETAIL; + ACCOUNT, PASSWORD, AUTHENTICATION, FEDERATED_IDENTITY, LOG, SESSIONS, APPLICATIONS, RESOURCES, RESOURCE_DETAIL; } diff --git a/services/src/main/java/org/keycloak/forms/account/freemarker/FreeMarkerAccountProvider.java b/services/src/main/java/org/keycloak/forms/account/freemarker/FreeMarkerAccountProvider.java index bac9ed9aec..862605b156 100755 --- a/services/src/main/java/org/keycloak/forms/account/freemarker/FreeMarkerAccountProvider.java +++ b/services/src/main/java/org/keycloak/forms/account/freemarker/FreeMarkerAccountProvider.java @@ -20,18 +20,7 @@ import org.jboss.logging.Logger; import org.keycloak.events.Event; import org.keycloak.forms.account.AccountPages; import org.keycloak.forms.account.AccountProvider; -import org.keycloak.forms.account.freemarker.model.AccountBean; -import org.keycloak.forms.account.freemarker.model.AccountFederatedIdentityBean; -import org.keycloak.forms.account.freemarker.model.ApplicationsBean; -import org.keycloak.forms.account.freemarker.model.AuthorizationBean; -import org.keycloak.forms.account.freemarker.model.FeaturesBean; -import org.keycloak.forms.account.freemarker.model.LogBean; -import org.keycloak.forms.account.freemarker.model.PasswordBean; -import org.keycloak.forms.account.freemarker.model.RealmBean; -import org.keycloak.forms.account.freemarker.model.ReferrerBean; -import org.keycloak.forms.account.freemarker.model.SessionsBean; -import org.keycloak.forms.account.freemarker.model.TotpBean; -import org.keycloak.forms.account.freemarker.model.UrlBean; +import org.keycloak.forms.account.freemarker.model.*; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.UserModel; @@ -164,8 +153,8 @@ public class FreeMarkerAccountProvider implements AccountProvider { attributes.put("account", new AccountBean(user, profileFormData)); switch (page) { - case TOTP: - attributes.put("totp", new TotpBean(session, realm, user, uriInfo.getRequestUriBuilder())); + case AUTHENTICATION: + attributes.put("authentication", new AuthenticationBean(session, realm, user, uriInfo)); break; case FEDERATED_IDENTITY: attributes.put("federatedIdentity", new AccountFederatedIdentityBean(session, realm, user, uriInfo.getBaseUri(), stateChecker)); diff --git a/services/src/main/java/org/keycloak/forms/account/freemarker/Templates.java b/services/src/main/java/org/keycloak/forms/account/freemarker/Templates.java index 48822937f3..ceb7744296 100755 --- a/services/src/main/java/org/keycloak/forms/account/freemarker/Templates.java +++ b/services/src/main/java/org/keycloak/forms/account/freemarker/Templates.java @@ -30,8 +30,8 @@ public class Templates { return "account.ftl"; case PASSWORD: return "password.ftl"; - case TOTP: - return "totp.ftl"; + case AUTHENTICATION: + return "authentication.ftl"; case FEDERATED_IDENTITY: return "federatedIdentity.ftl"; case LOG: diff --git a/services/src/main/java/org/keycloak/forms/account/freemarker/model/AuthenticationBean.java b/services/src/main/java/org/keycloak/forms/account/freemarker/model/AuthenticationBean.java new file mode 100755 index 0000000000..bf6458cf78 --- /dev/null +++ b/services/src/main/java/org/keycloak/forms/account/freemarker/model/AuthenticationBean.java @@ -0,0 +1,244 @@ +/* + * Copyright 2022 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.forms.account.freemarker.model; + +import org.keycloak.authentication.Authenticator; +import org.keycloak.authentication.AuthenticatorFactory; +import org.keycloak.authorization.AuthorizationProvider; +import org.keycloak.common.util.reflections.Types; +import org.keycloak.credential.*; +import org.keycloak.models.*; +import org.keycloak.models.utils.ModelToRepresentation; +import org.keycloak.representations.account.CredentialMetadataRepresentation; +import org.keycloak.representations.idm.CredentialRepresentation; + +import javax.ws.rs.core.UriInfo; +import java.util.*; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.keycloak.models.AuthenticationExecutionModel.Requirement.DISABLED; +import static org.keycloak.utils.CredentialHelper.createUserStorageCredentialRepresentation; + +/** + * @author Kayden Tebau + */ +public class AuthenticationBean { + + private final KeycloakSession session; + private final RealmModel realm; + private final UserModel user; + private final AuthorizationProvider authorization; + private final UriInfo uriInfo; + + private final Map credTypes; + + private final Map> credentials; + + public AuthenticationBean(KeycloakSession session, RealmModel realm, UserModel user, UriInfo uriInfo) { + this.session = session; + this.realm = realm; + this.user = user; + this.uriInfo = uriInfo; + authorization = session.getProvider(AuthorizationProvider.class); + credTypes = findCredentialTypes(); + credentials = new HashMap<>(); + } + + public static class CredentialUserMetadataBean { + + } + + public static class CredentialTypeBean { + // ** category, displayName and helptext attributes can be ordinary UI text or a key into + // a localized message bundle. Typically, it will be a key, but + // the UI will work just fine if you don't care about localization + // and you want to just send UI text. + // + // Also, the ${} shown in Apicurio is not needed. + private String type; + private String category; // ** + private String displayName; + private String helptext; // ** + private String iconCssClass; + private String createAction; + private String updateAction; + private boolean removable; + private List userCredentialMetadatas; + private CredentialTypeMetadata metadata; + + public CredentialTypeBean() { + } + + public CredentialTypeBean(CredentialTypeMetadata metadata, List userCredentialMetadatas) { + this.metadata = metadata; + this.type = metadata.getType(); + this.category = metadata.getCategory().toString(); + this.displayName = metadata.getDisplayName(); + this.helptext = metadata.getHelpText(); + this.iconCssClass = metadata.getIconCssClass(); + this.createAction = metadata.getCreateAction(); + this.updateAction = metadata.getUpdateAction(); + this.removable = metadata.isRemoveable(); + this.userCredentialMetadatas = userCredentialMetadatas; + } + + public String getCategory() { + return category; + } + + public String getType() { + return type; + } + + public String getDisplayName() { + return displayName; + } + + public String getHelpText() { + return helptext; + } + + public String getIconCssClass() { + return iconCssClass; + } + + public String getCreateAction() { + return createAction; + } + + public String getUpdateAction() { + return updateAction; + } + + public boolean getRemovable() { + return removable; + } + + public List getUserCredentialMetadatas() { + return userCredentialMetadatas; + } + + public CredentialTypeMetadata getMetadata() { + return metadata; + } + } + + public List getCredentialTypes() { + return new ArrayList<>(credTypes.values()); + } + + + private Map findCredentialTypes() { + List credentialProviders = session.getKeycloakSessionFactory().getProviderFactoriesStream(CredentialProvider.class) + .filter(f -> Types.supports(CredentialProvider.class, f, CredentialProviderFactory.class)) + .map(f -> session.getProvider(CredentialProvider.class, f.getId())) + .collect(Collectors.toList()); + Set enabledCredentialTypes = getEnabledCredentialTypes(credentialProviders); + + Stream modelsStream = user.credentialManager().getStoredCredentialsStream(); + List models = modelsStream.collect(Collectors.toList()); + + Function toCredentialBean = (credentialProvider) -> { + CredentialTypeMetadataContext ctx = CredentialTypeMetadataContext.builder() + .user(user) + .build(session); + CredentialTypeMetadata metadata = credentialProvider.getCredentialTypeMetadata(ctx); + + List userCredentialMetadataModels = null; + + List modelsOfType = models.stream() + .filter(credentialModel -> credentialProvider.getType().equals(credentialModel.getType())) + .collect(Collectors.toList()); + + + List credentialMetadataList = modelsOfType.stream() + .map(m -> { + return credentialProvider.getCredentialMetadata( + credentialProvider.getCredentialFromModel(m), metadata + ); + }).collect(Collectors.toList()); + + credentialMetadataList.stream().forEach(md -> md.getCredentialModel().setSecretData(null)); + userCredentialMetadataModels = credentialMetadataList.stream().map(ModelToRepresentation::toRepresentation).collect(Collectors.toList()); + + if (userCredentialMetadataModels.isEmpty() && + user.credentialManager().isConfiguredFor(credentialProvider.getType())) { + // In case user is federated in the userStorage, he may have credential configured on the userStorage side. We're + // creating "dummy" credential representing the credential provided by userStorage + CredentialMetadataRepresentation metadataRepresentation = new CredentialMetadataRepresentation(); + CredentialRepresentation credential = createUserStorageCredentialRepresentation(credentialProvider.getType()); + metadataRepresentation.setCredential(credential); + userCredentialMetadataModels = Collections.singletonList(metadataRepresentation); + } + + // In case that there are no userCredentials AND there are not required actions for setup new credential, + // we won't include credentialType as user won't be able to do anything with it + if (userCredentialMetadataModels.isEmpty() && metadata.getCreateAction() == null && metadata.getUpdateAction() == null) { + return null; + } + + return new CredentialTypeBean(metadata, userCredentialMetadataModels); + }; + + return credentialProviders.stream() + .filter(p -> enabledCredentialTypes.contains(p.getType())) + .map(toCredentialBean) + .filter(Objects::nonNull) + .sorted(Comparator.comparing(CredentialTypeBean::getMetadata)) + .collect(Collectors.toMap(CredentialTypeBean::getType, Function.identity())); + } + + private Set getEnabledCredentialTypes(List credentialProviders) { + Stream enabledCredentialTypes = realm.getAuthenticationFlowsStream() + .filter(((Predicate) this::isFlowEffectivelyDisabled).negate()) + .flatMap(flow -> + realm.getAuthenticationExecutionsStream(flow.getId()) + .filter(exe -> Objects.nonNull(exe.getAuthenticator()) && exe.getRequirement() != DISABLED) + .map(exe -> (AuthenticatorFactory) session.getKeycloakSessionFactory() + .getProviderFactory(Authenticator.class, exe.getAuthenticator())) + .filter(Objects::nonNull) + .map(AuthenticatorFactory::getReferenceCategory) + .filter(Objects::nonNull) + ); + + Set credentialTypes = credentialProviders.stream() + .map(CredentialProvider::getType) + .collect(Collectors.toSet()); + + return enabledCredentialTypes.filter(credentialTypes::contains).collect(Collectors.toSet()); + } + + // Returns true if flow is effectively disabled - either it's execution or some parent execution is disabled + private boolean isFlowEffectivelyDisabled(AuthenticationFlowModel flow) { + while (!flow.isTopLevel()) { + AuthenticationExecutionModel flowExecution = realm.getAuthenticationExecutionByFlowId(flow.getId()); + if (flowExecution == null) return false; // Can happen under some corner cases + if (DISABLED == flowExecution.getRequirement()) return true; + if (flowExecution.getParentFlow() == null) return false; + + // Check parent flow + flow = realm.getAuthenticationFlowById(flowExecution.getParentFlow()); + if (flow == null) return false; + } + + return false; + } +} diff --git a/services/src/main/java/org/keycloak/forms/account/freemarker/model/TotpBean.java b/services/src/main/java/org/keycloak/forms/account/freemarker/model/TotpBean.java deleted file mode 100644 index 096c73110f..0000000000 --- a/services/src/main/java/org/keycloak/forms/account/freemarker/model/TotpBean.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.keycloak.forms.account.freemarker.model; - -import org.keycloak.authentication.otp.OTPApplicationProvider; -import org.keycloak.credential.CredentialModel; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.OTPPolicy; -import org.keycloak.models.RealmModel; -import org.keycloak.models.UserModel; -import org.keycloak.models.credential.OTPCredentialModel; -import org.keycloak.models.utils.HmacOTP; -import org.keycloak.models.utils.RepresentationToModel; -import org.keycloak.representations.idm.CredentialRepresentation; -import org.keycloak.utils.TotpUtils; - -import javax.ws.rs.core.UriBuilder; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -import static org.keycloak.utils.CredentialHelper.createUserStorageCredentialRepresentation; - - -/** - * @author Stian Thorgersen - */ -public class TotpBean { - - private final RealmModel realm; - private final String totpSecret; - private final String totpSecretEncoded; - private final String totpSecretQrCode; - private final boolean enabled; - private KeycloakSession session; - private final UriBuilder uriBuilder; - private final List otpCredentials; - private final List supportedApplications; - - public TotpBean(KeycloakSession session, RealmModel realm, UserModel user, UriBuilder uriBuilder) { - this.session = session; - this.uriBuilder = uriBuilder; - this.enabled = user.credentialManager().isConfiguredFor(OTPCredentialModel.TYPE); - if (enabled) { - List otpCredentials = user.credentialManager().getStoredCredentialsByTypeStream(OTPCredentialModel.TYPE).collect(Collectors.toList()); - - if (otpCredentials.isEmpty()) { - // Credential is configured on userStorage side. Create the "fake" credential similar like we do for the new account console - CredentialRepresentation credential = createUserStorageCredentialRepresentation(OTPCredentialModel.TYPE); - this.otpCredentials = Collections.singletonList(RepresentationToModel.toModel(credential)); - } else { - this.otpCredentials = otpCredentials; - } - } else { - this.otpCredentials = Collections.EMPTY_LIST; - } - - this.realm = realm; - this.totpSecret = HmacOTP.generateSecret(20); - this.totpSecretEncoded = TotpUtils.encode(totpSecret); - this.totpSecretQrCode = TotpUtils.qrCode(totpSecret, realm, user); - - OTPPolicy otpPolicy = realm.getOTPPolicy(); - this.supportedApplications = session.getAllProviders(OTPApplicationProvider.class).stream() - .filter(p -> p.supports(otpPolicy)) - .map(OTPApplicationProvider::getName) - .collect(Collectors.toList()); - } - - public boolean isEnabled() { - return enabled; - } - - public String getTotpSecret() { - return totpSecret; - } - - public String getTotpSecretEncoded() { - return totpSecretEncoded; - } - - public String getTotpSecretQrCode() { - return totpSecretQrCode; - } - - public String getManualUrl() { - return uriBuilder.replaceQueryParam("mode", "manual").build().toString(); - } - - public String getQrUrl() { - return uriBuilder.replaceQueryParam("mode", "qr").build().toString(); - } - - public OTPPolicy getPolicy() { - return realm.getOTPPolicy(); - } - - public List getSupportedApplications() { - return supportedApplications; - } - - public List getOtpCredentials() { - return otpCredentials; - } - -} - diff --git a/services/src/main/java/org/keycloak/forms/account/freemarker/model/UrlBean.java b/services/src/main/java/org/keycloak/forms/account/freemarker/model/UrlBean.java index 4562059af3..f4e7531ca4 100755 --- a/services/src/main/java/org/keycloak/forms/account/freemarker/model/UrlBean.java +++ b/services/src/main/java/org/keycloak/forms/account/freemarker/model/UrlBean.java @@ -63,8 +63,8 @@ public class UrlBean { return Urls.accountFederatedIdentityPage(baseQueryURI, realm).toString(); } - public String getTotpUrl() { - return Urls.accountTotpPage(baseQueryURI, realm).toString(); + public String getAuthenticationUrl() { + return Urls.accountAuthenticationPage(baseQueryURI, realm).toString(); } public String getLogUrl() { diff --git a/services/src/main/java/org/keycloak/services/Urls.java b/services/src/main/java/org/keycloak/services/Urls.java index 8381bf94b5..706c13a7e6 100755 --- a/services/src/main/java/org/keycloak/services/Urls.java +++ b/services/src/main/java/org/keycloak/services/Urls.java @@ -129,8 +129,8 @@ public class Urls { .build(realmName); } - public static URI accountTotpPage(URI baseUri, String realmName) { - return accountBase(baseUri).path(AccountFormService.class, "totpPage").build(realmName); + public static URI accountAuthenticationPage(URI baseUri, String realmName) { + return accountBase(baseUri).path(AccountFormService.class, "authenticationPage").build(realmName); } public static URI accountLogPage(URI baseUri, String realmName) { diff --git a/services/src/main/java/org/keycloak/services/resources/AbstractSecuredLocalService.java b/services/src/main/java/org/keycloak/services/resources/AbstractSecuredLocalService.java index 40ec7f4f9a..952cf89d50 100755 --- a/services/src/main/java/org/keycloak/services/resources/AbstractSecuredLocalService.java +++ b/services/src/main/java/org/keycloak/services/resources/AbstractSecuredLocalService.java @@ -131,6 +131,10 @@ public abstract class AbstractSecuredLocalService { protected abstract URI getBaseRedirectUri(); protected Response login(String path) { + return login(path, null); + } + + protected Response login(String path, String action) { OAuthRedirect oauth = new OAuthRedirect(); String authUrl = OIDCLoginProtocolService.authUrl(session.getContext().getUri()).build(realm.getName()).toString(); oauth.setAuthUrl(authUrl); @@ -158,7 +162,7 @@ public abstract class AbstractSecuredLocalService { URI accountUri = uriBuilder.build(realm.getName()); oauth.setStateCookiePath(accountUri.getRawPath()); - return oauth.redirect(session.getContext().getUri(), accountUri.toString()); + return oauth.redirect(session.getContext().getUri(), accountUri.toString(), action); } static class OAuthRedirect extends AbstractOAuthClient { @@ -170,6 +174,10 @@ public abstract class AbstractSecuredLocalService { } public Response redirect(UriInfo uriInfo, String redirectUri) { + return redirect(uriInfo, redirectUri, null); + } + + public Response redirect(UriInfo uriInfo, String redirectUri, String kcAction) { String state = getStateCode(); String scopeParam = TokenUtil.attachOIDCScope(scope); @@ -180,6 +188,10 @@ public abstract class AbstractSecuredLocalService { .queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE) .queryParam(OAuth2Constants.SCOPE, scopeParam); + if (kcAction != null) { + uriBuilder.queryParam("kc_action", kcAction); + } + URI url = uriBuilder.build(); NewCookie cookie = new NewCookie(getStateCookieName(), state, getStateCookiePath(uriInfo), null, null, -1, isSecure, true); diff --git a/services/src/main/java/org/keycloak/services/resources/account/AccountFormService.java b/services/src/main/java/org/keycloak/services/resources/account/AccountFormService.java index eb0257c59c..7125b3d207 100755 --- a/services/src/main/java/org/keycloak/services/resources/account/AccountFormService.java +++ b/services/src/main/java/org/keycloak/services/resources/account/AccountFormService.java @@ -30,6 +30,7 @@ import org.keycloak.common.Profile; import org.keycloak.common.util.Base64Url; import org.keycloak.common.util.Time; import org.keycloak.common.util.UriUtils; +import org.keycloak.credential.CredentialProvider; import org.keycloak.events.Details; import org.keycloak.events.Errors; import org.keycloak.events.Event; @@ -48,14 +49,11 @@ import org.keycloak.models.ClientSessionContext; import org.keycloak.models.FederatedIdentityModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.ModelException; -import org.keycloak.models.OTPPolicy; import org.keycloak.models.RealmModel; import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserModel; import org.keycloak.models.UserSessionModel; -import org.keycloak.models.credential.OTPCredentialModel; import org.keycloak.models.credential.PasswordCredentialModel; -import org.keycloak.models.utils.CredentialValidation; import org.keycloak.models.utils.FormMessage; import org.keycloak.protocol.oidc.TokenManager; import org.keycloak.protocol.oidc.utils.RedirectUtils; @@ -83,7 +81,6 @@ import org.keycloak.userprofile.UserProfile; import org.keycloak.userprofile.UserProfileProvider; import org.keycloak.userprofile.EventAuditingAttributeChangeListener; import org.keycloak.util.JsonSerialization; -import org.keycloak.utils.CredentialHelper; import javax.ws.rs.Consumes; import javax.ws.rs.FormParam; @@ -270,15 +267,15 @@ public class AccountFormService extends AbstractSecuredLocalService { return forwardToPage(null, AccountPages.ACCOUNT); } - public static UriBuilder totpUrl(UriBuilder base) { - return RealmsResource.accountUrl(base).path(AccountFormService.class, "totpPage"); + public static UriBuilder authenticationUrl(UriBuilder base) { + return RealmsResource.accountUrl(base).path(AccountFormService.class, "authenticationPage"); } - @Path("totp") + @Path("authentication") @GET - public Response totpPage() { + public Response authenticationPage() { account.setAttribute("mode", session.getContext().getUri().getQueryParameters().getFirst("mode")); - return forwardToPage("totp", AccountPages.TOTP); + return forwardToPage("authentication", AccountPages.AUTHENTICATION); } public static UriBuilder passwordUrl(UriBuilder base) { @@ -495,24 +492,22 @@ public class AccountFormService extends AbstractSecuredLocalService { * * @return */ - @Path("totp") + @Path("authentication") @POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) - public Response processTotpUpdate() { + public Response processAuthenticationUpdate() { MultivaluedMap formData = request.getDecodedFormParameters(); if (auth == null) { - return login("totp"); + return login("authentication"); } auth.require(AccountRoles.MANAGE_ACCOUNT); - account.setAttribute("mode", session.getContext().getUri().getQueryParameters().getFirst("mode")); - String action = formData.getFirst("submitAction"); if (action != null && action.equals("Cancel")) { setReferrerOnPage(); - return account.createResponse(AccountPages.TOTP); + return account.createResponse(AccountPages.AUTHENTICATION); } csrfCheck(formData); @@ -521,37 +516,37 @@ public class AccountFormService extends AbstractSecuredLocalService { if (action != null && action.equals("Delete")) { String credentialId = formData.getFirst("credentialId"); - if (credentialId == null) { + String credType = formData.getFirst("credentialType"); + if (credentialId == null || credType == null) { setReferrerOnPage(); - return account.setError(Status.OK, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST).createResponse(AccountPages.TOTP); + return account.setError(Status.OK, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST).createResponse(AccountPages.AUTHENTICATION); } - CredentialHelper.deleteOTPCredential(session, realm, user, credentialId); - event.event(EventType.REMOVE_TOTP).client(auth.getClient()).user(auth.getUser()).success(); + CredentialProvider credentialProvider = session.getProvider(CredentialProvider.class, credType); + if (credentialProvider == null) { + setReferrerOnPage(); + return account.setError(Status.OK, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST).createResponse(AccountPages.AUTHENTICATION); + } + boolean removed = credentialProvider.deleteCredential(realm, user, credentialId); + if (!removed) { + setReferrerOnPage(); + return account.setError(Status.OK, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST).createResponse(AccountPages.AUTHENTICATION); + } + + // TODO: event??? + // event.event(EventType.REMOVE_TOTP).client(auth.getClient()).user(auth.getUser()).success(); + + // TODO: string key setReferrerOnPage(); - return account.setSuccess(Messages.SUCCESS_TOTP_REMOVED).createResponse(AccountPages.TOTP); + return account.setSuccess(Messages.SUCCESS_TOTP_REMOVED).createResponse(AccountPages.AUTHENTICATION); } else { - String challengeResponse = formData.getFirst("totp"); - String totpSecret = formData.getFirst("totpSecret"); - String userLabel = formData.getFirst("userLabel"); - - OTPPolicy policy = realm.getOTPPolicy(); - OTPCredentialModel credentialModel = OTPCredentialModel.createFromPolicy(realm, totpSecret, userLabel); - if (Validation.isBlank(challengeResponse)) { + String kcAction = formData.getFirst("kcAction"); + if (kcAction == null) { setReferrerOnPage(); - return account.setError(Status.OK, Messages.MISSING_TOTP).createResponse(AccountPages.TOTP); - } else if (!CredentialValidation.validOTP(challengeResponse, credentialModel, policy.getLookAheadWindow())) { - setReferrerOnPage(); - return account.setError(Status.OK, Messages.INVALID_TOTP).createResponse(AccountPages.TOTP); + return account.setError(Status.OK, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST).createResponse(AccountPages.AUTHENTICATION); } - if (!CredentialHelper.createOTPCredential(session, realm, user, challengeResponse, credentialModel)) { - setReferrerOnPage(); - return account.setError(Status.OK, Messages.INVALID_TOTP).createResponse(AccountPages.TOTP); - } - event.event(EventType.UPDATE_TOTP).client(auth.getClient()).user(auth.getUser()).success(); - - setReferrerOnPage(); - return account.setSuccess(Messages.SUCCESS_TOTP).createResponse(AccountPages.TOTP); + // Do action with kc_action param + return login("authentication", kcAction); } } diff --git a/themes/src/main/resources/META-INF/keycloak-themes.json b/themes/src/main/resources/META-INF/keycloak-themes.json index 1df68b3b51..60c22bf454 100755 --- a/themes/src/main/resources/META-INF/keycloak-themes.json +++ b/themes/src/main/resources/META-INF/keycloak-themes.json @@ -8,5 +8,8 @@ }, { "name" : "keycloak.v2", "types": [ "account", "admin" ] + }, { + "name" : "unixdog", + "types": [ "account", "login" ] }] } diff --git a/themes/src/main/resources/theme/unixdog/account/account.ftl b/themes/src/main/resources/theme/unixdog/account/account.ftl new file mode 100755 index 0000000000..f88833a034 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/account/account.ftl @@ -0,0 +1,38 @@ +<#import "template.ftl" as layout> +<@layout.mainLayout active='account' bodyClass='user'; section> +

${msg("editAccountHtmlTitle")}

+ * ${msg("requiredFields")} + +
+ + + + <#if !realm.registrationEmailAsUsername> +
+ <#if realm.editUsernameAllowed>* + disabled="disabled" value="${(account.username!'')}"/> +
+ + +
+ * + +
+ +
+ * + +
+ +
+ * + +
+ +
+ <#if url.referrerURI??>${kcSanitize(msg("backToApplication")?no_esc)} + + +
+
+ diff --git a/themes/src/main/resources/theme/unixdog/account/applications.ftl b/themes/src/main/resources/theme/unixdog/account/applications.ftl new file mode 100755 index 0000000000..3193a0ae6d --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/account/applications.ftl @@ -0,0 +1,72 @@ +<#import "template.ftl" as layout> +<@layout.mainLayout active='applications' bodyClass='applications'; section> + +

${msg("applicationsHtmlTitle")}

+ +
+ + + + + + + + + + + + + + + + <#list applications.applications as application> + + + + + + + + + + + + + +
${msg("application")}${msg("availableRoles")}${msg("grantedPermissions")}${msg("additionalGrants")}${msg("action")}
+ <#if application.effectiveUrl?has_content> + <#if application.client.name?has_content>${advancedMsg(application.client.name)}<#else>${application.client.clientId} + <#if application.effectiveUrl?has_content> + + <#list application.realmRolesAvailable as role> + <#if role.description??>${advancedMsg(role.description)}<#else>${advancedMsg(role.name)} + <#if role_has_next>, + + <#list application.resourceRolesAvailable?keys as resource> + <#if application.realmRolesAvailable?has_content>, + <#list application.resourceRolesAvailable[resource] as clientRole> + <#if clientRole.roleDescription??>${advancedMsg(clientRole.roleDescription)}<#else>${advancedMsg(clientRole.roleName)} + ${msg("inResource")} <#if clientRole.clientName??>${advancedMsg(clientRole.clientName)}<#else>${clientRole.clientId} + <#if clientRole_has_next>, + + + + <#if application.client.consentRequired> + <#list application.clientScopesGranted as claim> + ${advancedMsg(claim)}<#if claim_has_next>, + + <#else> + ${msg("fullAccess")} + + + <#list application.additionalGrants as grant> + ${advancedMsg(grant)}<#if grant_has_next>, + + + <#if (application.client.consentRequired && application.clientScopesGranted?has_content) || application.additionalGrants?has_content> + + +
+
+ + diff --git a/themes/src/main/resources/theme/unixdog/account/authentication.ftl b/themes/src/main/resources/theme/unixdog/account/authentication.ftl new file mode 100755 index 0000000000..347b157cfd --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/account/authentication.ftl @@ -0,0 +1,58 @@ +<#import "template.ftl" as layout> +<@layout.mainLayout active='authentication' bodyClass='authentication'; section> + +

${msg("authenticationTitle")}

+ + <#list authentication.credentialTypes as credType> +
+

${msg(credType.displayName)}

+

${msg(credType.helpText!"default-help-text")}

+ + + + + + + + + + <#list credType.userCredentialMetadatas as userData> + + + + + + + +
NameCreatedActions
${userData.credential.userLabel!"No label"}${userData.credential.createdDate?number_to_datetime!"No date"} + <#if credType.removable!false> +
+ + + + +
+ + <#if credType.updateAction??> +
+ + + + + +
+ +
+ <#if credType.createAction??> +
+ + + + +
+ +
+ + + + diff --git a/themes/src/main/resources/theme/unixdog/account/federatedIdentity.ftl b/themes/src/main/resources/theme/unixdog/account/federatedIdentity.ftl new file mode 100755 index 0000000000..c2eb76985f --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/account/federatedIdentity.ftl @@ -0,0 +1,42 @@ +<#import "template.ftl" as layout> +<@layout.mainLayout active='social' bodyClass='social'; section> + +
+
+

${msg("federatedIdentitiesHtmlTitle")}

+
+
+ +
+ <#list federatedIdentity.identities as identity> +
+
+ +
+
+ +
+
+ <#if identity.connected> + <#if federatedIdentity.removeLinkPossible> +
+ + + + +
+ + <#else> +
+ + + + +
+ +
+
+ +
+ + diff --git a/themes/src/main/resources/theme/unixdog/account/log.ftl b/themes/src/main/resources/theme/unixdog/account/log.ftl new file mode 100644 index 0000000000..29046cf0d2 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/account/log.ftl @@ -0,0 +1,35 @@ +<#import "template.ftl" as layout> +<@layout.mainLayout active='log' bodyClass='log'; section> + +
+
+

${msg("accountLogHtmlTitle")}

+
+
+ + + + + + + + + + + + + + <#list log.events as event> + + + + + + + + + + +
${msg("date")}${msg("event")}${msg("ip")}${msg("client")}${msg("details")}
${event.date?datetime}${event.event}${event.ipAddress}${event.client!}<#list event.details as detail>${detail.key} = ${detail.value} <#if detail_has_next>,
+ + \ No newline at end of file diff --git a/themes/src/main/resources/theme/unixdog/account/messages/messages_en.properties b/themes/src/main/resources/theme/unixdog/account/messages/messages_en.properties new file mode 100755 index 0000000000..d96e6bdc66 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/account/messages/messages_en.properties @@ -0,0 +1,441 @@ +doSave=Save +doCancel=Cancel +doLogOutAllSessions=Log out all sessions +doRemove=Remove +doAdd=Add +doSignOut=Sign out +doLogIn=Log In +doLink=Link +noAccessMessage=Access not allowed + +personalInfoSidebarTitle=Personal info +accountSecuritySidebarTitle=Account security +signingInSidebarTitle=Signing in +deviceActivitySidebarTitle=Device activity +linkedAccountsSidebarTitle=Linked accounts + +editAccountHtmlTitle=Edit Account +personalInfoHtmlTitle=Personal Info +federatedIdentitiesHtmlTitle=Federated Identities +accountLogHtmlTitle=Account Log +changePasswordHtmlTitle=Change Password +deviceActivityHtmlTitle=Device Activity +sessionsHtmlTitle=Sessions +accountManagementTitle=Keycloak Account Management +authenticatorTitle=Authenticator +applicationsHtmlTitle=Applications +linkedAccountsHtmlTitle=Linked accounts + +accountManagementWelcomeMessage=Welcome to Keycloak Account Management +personalInfoIntroMessage=Manage your basic information +accountSecurityTitle=Account Security +accountSecurityIntroMessage=Control your password and account access +applicationsIntroMessage=Track and manage your app permission to access your account +resourceIntroMessage=Share your resources among team members +passwordLastUpdateMessage=Your password was updated at +updatePasswordTitle=Update Password +updatePasswordMessageTitle=Make sure you choose a strong password +updatePasswordMessage=A strong password contains a mix of numbers, letters, and symbols. It is hard to guess, does not resemble a real word, and is only used for this account. +personalSubTitle=Your Personal Info +personalSubMessage=Manage your basic information. + +authenticatorCode=One-time code +email=Email +firstName=First name +givenName=Given name +fullName=Full name +lastName=Last name +familyName=Family name +password=Password +currentPassword=Current Password +passwordConfirm=Confirmation +passwordNew=New Password +username=Username +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 + +profileScopeConsentText=User profile +emailScopeConsentText=Email address +addressScopeConsentText=Address +phoneScopeConsentText=Phone number +offlineAccessScopeConsentText=Offline Access +samlRoleListScopeConsentText=My Roles +rolesScopeConsentText=User roles + +role_admin=Admin +role_realm-admin=Realm Admin +role_create-realm=Create realm +role_view-realm=View realm +role_view-users=View users +role_view-applications=View applications +role_view-groups=View groups +role_view-clients=View clients +role_view-events=View events +role_view-identity-providers=View identity providers +role_view-consent=View consents +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_manage-consent=Manage consents +role_read-token=Read token +role_offline-access=Offline access +role_uma_authorization=Obtain permissions +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 +allFieldsRequired=All fields required + +backToApplication=« Back to application +backTo=Back to {0} + +date=Date +event=Event +ip=IP +client=Client +clients=Clients +details=Details +started=Started +lastAccess=Last Access +expires=Expires +applications=Applications + +account=Account +federatedIdentity=Federated Identity +authenticator=Authenticator +device-activity=Device activity +sessions=Sessions +log=Log + +application=Application +availableRoles=Available Roles +grantedPermissions=Granted Permissions +grantedPersonalInfo=Granted Personal Info +additionalGrants=Additional Grants +action=Action +inResource=in +fullAccess=Full Access +offlineToken=Offline Token +revoke=Revoke Grant + +configureAuthenticators=Configured Authenticators +mobile=Mobile +totpStep1=Install one of the following applications on your mobile: +totpStep2=Open the application and scan the barcode: +totpStep3=Enter the one-time code provided by the application and click Save to finish the setup. +totpStep3DeviceName=Provide a Device Name to help you manage your OTP devices. + +totpManualStep2=Open the application and enter the key: +totpManualStep3=Use the following configuration values if the application allows setting them: +totpUnableToScan=Unable to scan? +totpScanBarcode=Scan barcode? + +totp.totp=Time-based +totp.hotp=Counter-based + +totpType=Type +totpAlgorithm=Algorithm +totpDigits=Digits +totpInterval=Interval +totpCounter=Counter +totpDeviceName=Device Name + +totpAppFreeOTPName=FreeOTP +totpAppGoogleName=Google Authenticator +totpAppMicrosoftAuthenticatorName=Microsoft Authenticator + +irreversibleAction=This action is irreversible +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 + +missingUsernameMessage=Please specify username. +missingFirstNameMessage=Please specify first name. +invalidEmailMessage=Invalid email address. +missingLastNameMessage=Please specify last name. +missingEmailMessage=Please specify email. +missingPasswordMessage=Please specify password. +notMatchPasswordMessage=Passwords don''t match. +invalidUserMessage=Invalid user +updateReadOnlyAttributesRejectedMessage=Update of read-only attribute rejected + +missingTotpMessage=Please specify authenticator code. +missingTotpDeviceNameMessage=Please specify device name. +invalidPasswordExistingMessage=Invalid existing password. +invalidPasswordConfirmMessage=Password confirmation doesn''t match. +invalidTotpMessage=Invalid authenticator code. + +usernameExistsMessage=Username already exists. +emailExistsMessage=Email already exists. + +readOnlyUserMessage=You can''t update your account as it is read-only. +readOnlyUsernameMessage=You can''t update your username as it is read-only. +readOnlyPasswordMessage=You can''t update your password as your account is read-only. + +successTotpMessage=Mobile authenticator configured. +successTotpRemovedMessage=Mobile authenticator removed. + +successGrantRevokedMessage=Grant revoked successfully. + +accountUpdatedMessage=Your account has been updated. +accountPasswordUpdatedMessage=Your password has been updated. + +missingIdentityProviderMessage=Identity provider not specified. +invalidFederatedIdentityActionMessage=Invalid or missing action. +identityProviderNotFoundMessage=Specified identity provider not found. +federatedIdentityLinkNotActiveMessage=This identity is not active anymore. +federatedIdentityRemovingLastProviderMessage=You can''t remove last federated identity as you don''t have a password. +identityProviderRedirectErrorMessage=Failed to redirect to identity provider. +identityProviderRemovedMessage=Identity provider removed successfully. +identityProviderAlreadyLinkedMessage=Federated identity returned by {0} is already linked to another user. +staleCodeAccountMessage=The page expired. Please try one more time. +consentDenied=Consent denied. +access-denied-when-idp-auth=Access denied when authenticating with {0} + +accountDisabledMessage=Account is disabled, contact your administrator. + +accountTemporarilyDisabledMessage=Account is temporarily disabled, contact your administrator or try again later. +invalidPasswordMinLengthMessage=Invalid password: minimum length {0}. +invalidPasswordMaxLengthMessage=Invalid password: maximum length {0}. +invalidPasswordMinLowerCaseCharsMessage=Invalid password: must contain at least {0} lower case characters. +invalidPasswordMinDigitsMessage=Invalid password: must contain at least {0} numerical digits. +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. +invalidPasswordBlacklistedMessage=Invalid password: password is blacklisted. +invalidPasswordGenericMessage=Invalid password: new password doesn''t match password policies. + +# Authorization +myResources=My Resources +myResourcesSub=My resources +doDeny=Deny +doRevoke=Revoke +doApprove=Approve +doRemoveSharing=Remove Sharing +doRemoveRequest=Remove Request +peopleAccessResource=People with access to this resource +resourceManagedPolicies=Permissions granting access to this resource +resourceNoPermissionsGrantingAccess=No permissions granting access to this resource +anyAction=Any action +description=Description +name=Name +scopes=Scopes +resource=Resource +user=User +peopleSharingThisResource=People sharing this resource +shareWithOthers=Share with others +needMyApproval=Need my approval +requestsWaitingApproval=Your requests waiting approval +icon=Icon +requestor=Requestor +owner=Owner +resourcesSharedWithMe=Resources shared with me +permissionRequestion=Permission Requestion +permission=Permission +shares=share(s) +notBeingShared=This resource is not being shared. +notHaveAnyResource=You don't have any resources +noResourcesSharedWithYou=There are no resources shared with you +havePermissionRequestsWaitingForApproval=You have {0} permission request(s) waiting for approval. +clickHereForDetails=Click here for details. +resourceIsNotBeingShared=The resource is not being shared + +locale_ar=\u0639\u0631\u0628\u064A +locale_ca=Catal\u00e0 +locale_cs=\u010Ce\u0161tina +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_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 +locale_fi=Suomi + +# Applications +applicationName=Name +applicationType=Application Type +applicationInUse=In-use app only +clearAllFilter=Clear all filters +activeFilters=Active filters +filterByName=Filter By Name ... +allApps=All applications +internalApps=Internal applications +thirdpartyApps=Third-Party applications +appResults=Results +clientNotFoundMessage=Client not found. + +# Authentication +authentication=Authentication +authenticationTitle=Authentication + +# Linked account +authorizedProvider=Authorized Provider +authorizedProviderMessage=Authorized Providers linked with your account +identityProvider=Identity Provider +identityProviderMessage=To link your account with identity providers you have configured +socialLogin=Social Login +userDefined=User Defined +removeAccess=Remove Access +removeAccessMessage=You will need to grant access again, if you want to use this app account. + +#Authenticator +authenticatorStatusMessage=Two-factor authentication is currently +authenticatorFinishSetUpTitle=Your Two-Factor Authentication +authenticatorFinishSetUpMessage=Each time you sign in to your Keycloak account, you will be asked to provide a two-factor authentication code. +authenticatorSubTitle=Set Up Two-Factor Authentication +authenticatorSubMessage=To enhance the security of your account, enable at least one of the available two-factor authentication methods. +authenticatorMobileTitle=Mobile Authenticator +authenticatorMobileMessage=Use mobile Authenticator to get Verification codes as the two-factor authentication. +authenticatorMobileFinishSetUpMessage=The authenticator has been bound to your phone. +authenticatorActionSetup=Set up +authenticatorSMSTitle=SMS Code +authenticatorSMSMessage=Keycloak will send the Verification code to your phone as the two-factor authentication. +authenticatorSMSFinishSetUpMessage=Text messages are sent to +authenticatorDefaultStatus=Default +authenticatorChangePhone=Change Phone Number + +#Authenticator - Mobile Authenticator setup +authenticatorMobileSetupTitle=Mobile Authenticator Setup +smscodeIntroMessage=Enter your phone number and a verification code will be sent to your phone. +mobileSetupStep1=Install an authenticator application on your phone. The applications listed here are supported. +mobileSetupStep2=Open the application and scan the barcode: +mobileSetupStep3=Enter the one-time code provided by the application and click Save to finish the setup. +scanBarCode=Want to scan the barcode? +enterBarCode=Enter the one-time code +doCopy=Copy +doFinish=Finish + +#Authenticator - SMS Code setup +authenticatorSMSCodeSetupTitle=SMS Code Setup +chooseYourCountry=Choose your country +enterYourPhoneNumber=Enter your phone number +sendVerficationCode=Send Verification Code +enterYourVerficationCode=Enter your verification code + +#Authenticator - backup Code setup +authenticatorBackupCodesSetupTitle=Recovery Authentication Codes Setup +realmName=Realm +doDownload=Download +doPrint=Print +generateNewBackupCodes=Generate New Recovery Authentication Codes +backtoAuthenticatorPage=Back to Authenticator Page + + +#Resources +resources=Resources +sharedwithMe=Shared with Me +share=Share +sharedwith=Shared with +accessPermissions=Access Permissions +permissionRequests=Permission Requests +approve=Approve +approveAll=Approve all +people=people +perPage=per page +currentPage=Current Page +sharetheResource=Share the resource +group=Group +selectPermission=Select Permission +addPeople=Add people to share your resource with +addTeam=Add team to share your resource with +myPermissions=My Permissions +waitingforApproval=Waiting for approval +anyPermission=Any Permission + +# 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 + +error-invalid-value=Invalid value. +error-invalid-blank=Please specify value. +error-empty=Please specify value. +error-invalid-length=Attribute {0} must have a length between {1} and {2}. +error-invalid-length-too-short=Attribute {0} must have minimal length of {1}. +error-invalid-length-too-long=Attribute {0} must have maximal length of {2}. +error-invalid-email=Invalid email address. +error-invalid-number=Invalid number. +error-number-out-of-range=Attribute {0} must be a number between {1} and {2}. +error-number-out-of-range-too-small=Attribute {0} must have minimal value of {1}. +error-number-out-of-range-too-big=Attribute {0} must have maximal value of {2}. +error-pattern-no-match=Invalid value. +error-invalid-uri=Invalid URL. +error-invalid-uri-scheme=Invalid URL scheme. +error-invalid-uri-fragment=Invalid URL fragment. +error-user-attribute-required=Please specify attribute {0}. +error-invalid-date=Invalid date. +error-user-attribute-read-only=The field {0} is read only. +error-username-invalid-character=Username contains invalid character. +error-person-name-invalid-character=Name contains invalid character. + +# Signing in page +signingIn=Signing in +signingInSubMessage=Configure ways to sign in. +credentialCreatedAt=Created +successRemovedMessage={0} was removed. +stopUsingCred=Stop using {0}? +changePassword=Change password +removeCred=Remove {0} +setUpNew=Set up {0} +removeCredAriaLabel=Remove credential +updateCredAriaLabel=Update credential +notSetUp={0} is not set up. +two-factor=Two-factor authentication +passwordless=Passwordless +unknown=Unknown +password-display-name=Password +password-help-text=Sign in by entering your password. +otp-display-name=OTP Codes (2FA) +otp-help-text=Enter a verification code from authenticator application. +default-help-text= +recovery-authn-code=My recovery authentication codes +recovery-authn-codes-display-name=Recovery authentication codes +recovery-authn-codes-help-text=These codes can be used to regain your access in case your other 2FA means are not available. +recovery-codes-number-used={0} recovery codes used +recovery-codes-number-remaining={0} recovery codes remaining +recovery-codes-generate-new-codes=Generate new codes to ensure access to your account +webauthn-display-name=WebAuthn (2FA) +webauthn-help-text=Use your security key to sign in. +webauthn-passwordless-display-name=Passwordless WebAuthn +webauthn-passwordless-help-text=Use your security key for passwordless sign in. +basic-authentication=Basic authentication +invalidRequestMessage=Invalid request diff --git a/themes/src/main/resources/theme/unixdog/account/password.ftl b/themes/src/main/resources/theme/unixdog/account/password.ftl new file mode 100755 index 0000000000..4a043f28b9 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/account/password.ftl @@ -0,0 +1,59 @@ +<#import "template.ftl" as layout> +<@layout.mainLayout active='password' bodyClass='password'; section> + +
+
+

${msg("changePasswordHtmlTitle")}

+
+
+ ${msg("allFieldsRequired")} +
+
+ +
+ + + <#if password.passwordSet> +
+
+ +
+ +
+ +
+
+ + + + +
+
+ +
+ +
+ +
+
+ +
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+
+
+
+ + diff --git a/themes/src/main/resources/theme/unixdog/account/resource-detail.ftl b/themes/src/main/resources/theme/unixdog/account/resource-detail.ftl new file mode 100755 index 0000000000..2c963d7732 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/account/resource-detail.ftl @@ -0,0 +1,277 @@ +<#import "template.ftl" as layout> +<@layout.mainLayout active='authorization' bodyClass='authorization'; section> + + + + +
+
+

+ ${msg("myResources")} <#if authorization.resource.displayName??>${authorization.resource.displayName}<#else>${authorization.resource.name} +

+
+
+ + <#if authorization.resource.iconUri??> + +
+ + +
+
+

+ ${msg("peopleAccessResource")} +

+
+
+
+
+ + + + + + + + + + + <#if authorization.resource.shares?size != 0> + <#list authorization.resource.shares as permission> + + + + + + + + + + + + + <#else> + + + + + +
${msg("user")}${msg("permission")}${msg("date")}${msg("action")}
+ <#if permission.requester.email??>${permission.requester.email}<#else>${permission.requester.username} + + <#if permission.scopes?size != 0> + <#list permission.scopes as scope> + <#if scope.granted && scope.scope??> + + <#else> + ${msg("anyPermission")} + + + <#else> + Any action + + + ${permission.createdDate?datetime} + + ${msg("doRevoke")} +
${msg("resourceIsNotBeingShared")}
+ +
+
+
+
+

+ ${msg("resourceManagedPolicies")} +

+
+
+
+
+ + + + + + + + + + <#if authorization.resource.policies?size != 0> + <#list authorization.resource.policies as permission> + + + + + + + + + + + + <#else> + + + + + +
${msg("description")}${msg("permission")}${msg("action")}
+ <#if permission.description??> + ${permission.description} + + + <#if permission.scopes?size != 0> + <#list permission.scopes as scope> + + + <#else> + ${msg("anyAction")} + + + ${msg("doRevoke")} +
+ ${msg("resourceNoPermissionsGrantingAccess")} +
+ +
+
+
+
+

+ ${msg("shareWithOthers")} +

+
+
+
+
+
+ +
+ * +
+
+
+
+ +
+
+
+ <#list authorization.resource.scopes as scope> + + +
+ +
+
+
+
+
+
+ diff --git a/themes/src/main/resources/theme/unixdog/account/resources.ftl b/themes/src/main/resources/theme/unixdog/account/resources.ftl new file mode 100755 index 0000000000..d86e8bc323 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/account/resources.ftl @@ -0,0 +1,403 @@ +<#import "template.ftl" as layout> +<@layout.mainLayout active='authorization' bodyClass='authorization'; section> + + +
+
+

+ ${msg("myResources")} +

+
+
+ + <#if authorization.resourcesWaitingApproval?size != 0> +
+
+

+ ${msg("needMyApproval")} +

+
+
+
+
+ + + + + + + + + + + <#list authorization.resourcesWaitingApproval as resource> + <#list resource.permissions as permission> + + + + + + + + + + + + + + +
${msg("resource")}${msg("requestor")}${msg("permissionRequestion")}${msg("action")}
+ <#if resource.displayName??>${resource.displayName}<#else>${resource.name} + + <#if permission.requester.email??>${permission.requester.email}<#else>${permission.requester.username} + + <#list permission.scopes as scope> + <#if scope.scope??> + + <#else> + ${msg("anyPermission")} + + + + ${msg("doApprove")} + ${msg("doDeny")} +
+
+
+ + +
+
+

+ ${msg("myResourcesSub")} +

+
+
+
+
+ + + + + + + + + + + <#if authorization.resources?size != 0> + <#list authorization.resources as resource> + + + + + + + <#else> + + + + + +
${msg("resource")}${msg("application")}${msg("peopleSharingThisResource")}
+ + <#if resource.displayName??>${resource.displayName}<#else>${resource.name} + + + <#if resource.resourceServer.baseUri??> + ${resource.resourceServer.name} + <#else> + ${resource.resourceServer.name} + + + <#if resource.shares?size != 0> + ${resource.shares?size} + <#else> + ${msg("notBeingShared")} + +
${msg("notHaveAnyResource")}
+
+
+ +
+
+

+ ${msg("resourcesSharedWithMe")} +

+
+
+
+
+
+ + + + + + + + + + + + + + <#if authorization.sharedResources?size != 0> + <#list authorization.sharedResources as resource> + + + + + + + + + + <#else> + + + + + +
disabled="true" + ${msg("resource")}${msg("owner")}${msg("application")}${msg("permission")}${msg("date")}
+ + + <#if resource.displayName??>${resource.displayName}<#else>${resource.name} + + ${resource.ownerName} + + <#if resource.resourceServer.baseUri??> + ${resource.resourceServer.name} + <#else> + ${resource.resourceServer.name} + + + <#if resource.permissions?size != 0> +
    + <#list resource.permissions as permission> + <#list permission.scopes as scope> + <#if scope.granted && scope.scope??> +
  • + <#if scope.scope.displayName??> + ${scope.scope.displayName} + <#else> + ${scope.scope.name} + +
  • + <#else> + ${msg("anyPermission")} + + + +
+ <#else> + Any action + +
+ ${resource.permissions[0].grantedDate?datetime} +
${msg("noResourcesSharedWithYou")}
+
+
+ <#if authorization.sharedResources?size != 0> + + +
+ + <#if authorization.resourcesWaitingOthersApproval?size != 0> +
+
+
+

+ ${msg("requestsWaitingApproval")} +

+
+
+
+
+ ${msg("havePermissionRequestsWaitingForApproval",authorization.resourcesWaitingOthersApproval?size)} + ${msg("clickHereForDetails")} +
+
+
+
+
+
+
+
+
+ +
+
+ + + \ No newline at end of file diff --git a/themes/src/main/resources/theme/unixdog/account/resources/css/main.css b/themes/src/main/resources/theme/unixdog/account/resources/css/main.css new file mode 100644 index 0000000000..5b800ef012 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/account/resources/css/main.css @@ -0,0 +1,218 @@ +body { + font-family: monospace; + margin: 0; + background: #080e08; + color: #f6f6f6; + + display: flex; + flex-direction: column; + min-height: 100vh; +} + +h1, h2 { + color: #4af626; +} + +footer { + padding: 10px; + max-width: 800px; + width: 100%; + background: #3a7920; + color: #f6f6f6; + + margin: auto auto 0; + box-sizing: border-box; +} + +a:link { + color: #2cacb0; +} + +a:visited { + color: #b4778f; +} + +tr:nth-child(even) td { + background-color: #222; +} + +@media (prefers-color-scheme: light) { + body { + background: #fcfffc; + color: #211c1b; + } + + h1, h2 { + color: #4c982a; + } + + a:link { + color: #1f7b7e; + } + + a:visited { + color: #7c5263; + } + + textarea { + background: #ffffff; + color: #211c1b; + } + + tr:nth-child(even) td { + background-color: #eee; + } +} + +header { + background: linear-gradient( + 90deg, + rgba(255, 0, 0, 1) 0%, + rgba(255, 154, 0, 1) 10%, + rgba(208, 222, 33, 1) 20%, + rgba(79, 220, 74, 1) 30%, + rgba(63, 218, 216, 1) 40%, + rgba(47, 201, 226, 1) 50%, + rgba(28, 127, 238, 1) 60%, + rgba(95, 21, 242, 1) 70%, + rgba(186, 12, 248, 1) 80%, + rgba(251, 7, 217, 1) 90%, + rgba(255, 0, 0, 1) 100% + ); + min-height: 50px; + display: flex; + color: black; + box-sizing: border-box; +} + +#header-content { + max-width: 800px; + margin: auto; + width: 100%; + align-content: center; + flex-direction: row; + display: flex; + padding: 10px; +} +#header-content h1 { + color: black; + margin: auto auto auto 1rem; +} + +#header-content img { + display: inline; +} + +main { + max-width: 800px; + margin: 0 auto; + padding: 10px; + width: 100%; + box-sizing: border-box; +} + + +span.copyleft { + display: inline-block; + transform: rotate(180deg); +} + +footer a:link, footer a:visited { + text-decoration: none; + font-weight: bold; + color: white; +} + +footer a:hover { + text-decoration: underline; +} + + +input { + background: #332c29; + color: #f6f6f6; +} + +textarea { + background: #332c29; + color: #f6f6f6; +} + +textarea.big { + width: 100%; + height: 5em; +} + +.error, .required, .alert-error, .form-group.has-error { + color: #f00; +} + +#nav { + margin: auto 0 auto auto; + display: flex; + flex-direction: row; + flex-wrap: wrap; +} + +#nav a { + display: block; + padding: 10px; +} + +pre { + white-space: pre-wrap; +} + +#header-content a:link { + text-decoration: none; + color: black; +} +#header-content a:visited { + text-decoration: none; + color: black; +} + +#header-content a:hover { + text-decoration: underline; +} + +label.field-with-error { + color: red; +} + +img.stats { + width: 100%; + display: block; +} + +/* Tables */ +table { + border-collapse: collapse; + width: 100%; +} +th, td { + padding: 5px; +} +th { + border-bottom: solid 2px currentColor; +} + +td:first-child { + border-right: solid 2px currentColor; + border-left: none; +} +td { + border-right: solid 2px currentColor; + border-left: solid 2px currentColor; +} +td:last-child { + border-right: none; + border-left: solid 2px currentColor; +} + +/* Responsive */ +.responsive-wrapper { + overflow-x: auto; + width: 100%; +} + diff --git a/themes/src/main/resources/theme/unixdog/account/resources/img/favicon.ico b/themes/src/main/resources/theme/unixdog/account/resources/img/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..46eafce9bc1d16af673f3d41f4f3c88f58a9ac36 GIT binary patch literal 171528 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 literal 0 HcmV?d00001 diff --git a/themes/src/main/resources/theme/unixdog/account/resources/js/base64url.js b/themes/src/main/resources/theme/unixdog/account/resources/js/base64url.js new file mode 100644 index 0000000000..64555bfbd5 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/account/resources/js/base64url.js @@ -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)); + + diff --git a/themes/src/main/resources/theme/unixdog/account/sessions.ftl b/themes/src/main/resources/theme/unixdog/account/sessions.ftl new file mode 100755 index 0000000000..ad242b8ca9 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/account/sessions.ftl @@ -0,0 +1,39 @@ +<#import "template.ftl" as layout> +<@layout.mainLayout active='sessions' bodyClass='sessions'; section> +

${msg("sessionsHtmlTitle")}

+ + + + + + + + + + + + + + <#list sessions.sessions as session> + + + + + + + + + + +
${msg("ip")}${msg("started")}${msg("lastAccess")}${msg("expires")}${msg("clients")}
${session.ipAddress}${session.started?datetime}${session.lastAccess?datetime}${session.expires?datetime} + <#list session.clients as client> + ${client}
+ +
+ +
+ + +
+ diff --git a/themes/src/main/resources/theme/unixdog/account/template.ftl b/themes/src/main/resources/theme/unixdog/account/template.ftl new file mode 100644 index 0000000000..fbe2552b25 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/account/template.ftl @@ -0,0 +1,68 @@ +<#macro mainLayout active bodyClass> + + + + + + + + ${msg("accountManagementTitle")} + + <#if properties.stylesCommon?has_content> + <#list properties.stylesCommon?split(' ') as style> + + + + <#if properties.styles?has_content> + <#list properties.styles?split(' ') as style> + + + + <#if properties.scripts?has_content> + <#list properties.scripts?split(' ') as script> + + + + + +
+
+ UNIX.dog +

UNIX.dog Account

+
+
+
+ +
+ <#if message?has_content> +
+

+ ${kcSanitize(message.summary)?no_esc} +

+
+ +
+ <#nested "content"> +
+
+ + + + diff --git a/themes/src/main/resources/theme/unixdog/account/theme.properties b/themes/src/main/resources/theme/unixdog/account/theme.properties new file mode 100644 index 0000000000..4a293845f0 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/account/theme.properties @@ -0,0 +1,4 @@ + +styles=css/main.css +kcInputErrorMessageClass=error + diff --git a/themes/src/main/resources/theme/unixdog/login/cli_splash.ftl b/themes/src/main/resources/theme/unixdog/login/cli_splash.ftl new file mode 100644 index 0000000000..cd9ebbb7a2 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/cli_splash.ftl @@ -0,0 +1,7 @@ + _ __ _ _ +| |/ /___ _ _ ___| | ___ __ _| | __ +| ' // _ \ | | |/ __| |/ _ \ / _` | |/ / +| . \ __/ |_| | (__| | (_) | (_| | < +|_|\_\___|\__, |\___|_|\___/ \__,_|_|\_\ + |___/ + diff --git a/themes/src/main/resources/theme/unixdog/login/code.ftl b/themes/src/main/resources/theme/unixdog/login/code.ftl new file mode 100755 index 0000000000..bb0621db93 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/code.ftl @@ -0,0 +1,19 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout; section> + <#if section = "header"> + <#if code.success> + ${msg("codeSuccessTitle")} + <#else> + ${kcSanitize(msg("codeErrorTitle", code.error))} + + <#elseif section = "form"> +
+ <#if code.success> +

${msg("copyCodeInstruction")}

+ + <#else> +

${kcSanitize(code.error)}

+ +
+ + diff --git a/themes/src/main/resources/theme/unixdog/login/delete-account-confirm.ftl b/themes/src/main/resources/theme/unixdog/login/delete-account-confirm.ftl new file mode 100644 index 0000000000..6aa93f0964 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/delete-account-confirm.ftl @@ -0,0 +1,33 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout; section> + + <#if section = "header"> + ${msg("deleteAccountConfirm")} + + <#elseif section = "form"> + +
+ +
+ + ${msg("irreversibleAction")} +
+ +

${msg("deletingImplies")}

+
    +
  • ${msg("loggingOutImmediately")}
  • +
  • ${msg("errasingData")}
  • +
+ + + +
+ + <#if triggered_from_aia> + + +
+
+ + + \ No newline at end of file diff --git a/themes/src/main/resources/theme/unixdog/login/error.ftl b/themes/src/main/resources/theme/unixdog/login/error.ftl new file mode 100755 index 0000000000..112ded3eae --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/error.ftl @@ -0,0 +1,16 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout displayMessage=false; section> + <#if section = "header"> + ${kcSanitize(msg("errorTitle"))?no_esc} + <#elseif section = "form"> +
+

${kcSanitize(message.summary)?no_esc}

+ <#if skipLink??> + <#else> + <#if client?? && client.baseUrl?has_content> +

${kcSanitize(msg("backToApplication"))?no_esc}

+ + +
+ + \ No newline at end of file diff --git a/themes/src/main/resources/theme/unixdog/login/frontchannel-logout.ftl b/themes/src/main/resources/theme/unixdog/login/frontchannel-logout.ftl new file mode 100644 index 0000000000..3de7d2500e --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/frontchannel-logout.ftl @@ -0,0 +1,30 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout; section> + <#if section = "header"> + + ${msg("frontchannel-logout.title")} + <#elseif section = "form"> +

${msg("frontchannel-logout.message")}

+
    + <#list logout.clients as client> +
  • + ${client.name} + +
  • + +
+ <#if logout.logoutRedirectUri?has_content> + + ${msg("doContinue")} + + + diff --git a/themes/src/main/resources/theme/unixdog/login/idp-review-user-profile.ftl b/themes/src/main/resources/theme/unixdog/login/idp-review-user-profile.ftl new file mode 100644 index 0000000000..1b70aeccb9 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/idp-review-user-profile.ftl @@ -0,0 +1,23 @@ +<#import "template.ftl" as layout> +<#import "user-profile-commons.ftl" as userProfileCommons> +<@layout.registrationLayout displayMessage=messagesPerField.exists('global') displayRequiredFields=true; section> + <#if section = "header"> + ${msg("loginIdpReviewProfileTitle")} + <#elseif section = "form"> +
+ + <@userProfileCommons.userProfileFormFields/> + +
+
+
+
+
+ +
+ +
+
+
+ + \ No newline at end of file diff --git a/themes/src/main/resources/theme/unixdog/login/info.ftl b/themes/src/main/resources/theme/unixdog/login/info.ftl new file mode 100755 index 0000000000..400e8bfdff --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/info.ftl @@ -0,0 +1,24 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout displayMessage=false; section> + <#if section = "header"> + <#if messageHeader??> + ${messageHeader} + <#else> + ${message.summary} + + <#elseif section = "form"> +
+

${message.summary}<#if requiredActions??><#list requiredActions>: <#items as reqActionItem>${kcSanitize(msg("requiredAction.${reqActionItem}"))?no_esc}<#sep>, <#else>

+ <#if skipLink??> + <#else> + <#if pageRedirectUri?has_content> +

${kcSanitize(msg("backToApplication"))?no_esc}

+ <#elseif actionUri?has_content> +

${kcSanitize(msg("proceedWithAction"))?no_esc}

+ <#elseif (client.baseUrl)?has_content> +

${kcSanitize(msg("backToApplication"))?no_esc}

+ + +
+ + \ No newline at end of file diff --git a/themes/src/main/resources/theme/unixdog/login/login-config-totp.ftl b/themes/src/main/resources/theme/unixdog/login/login-config-totp.ftl new file mode 100755 index 0000000000..80145856d8 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/login-config-totp.ftl @@ -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"> +
    +
  1. +

    ${msg("loginTotpStep1")}

    + +
      + <#list totp.supportedApplications as app> +
    • ${msg(app)}
    • + +
    +
  2. + + <#if mode?? && mode = "manual"> +
  3. +

    ${msg("loginTotpManualStep2")}

    +

    ${totp.totpSecretEncoded}

    +

    ${msg("loginTotpScanBarcode")}

    +
  4. +
  5. +

    ${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}
    • + +
    +

    +
  6. + <#else> +
  7. +

    ${msg("loginTotpStep2")}

    + Figure: Barcode
    +

    ${msg("loginTotpUnableToScan")}

    +
  8. + +
  9. +

    ${msg("loginTotpStep3")}

    +

    ${msg("loginTotpStep3DeviceName")}

    +
  10. +
+ +
+
+
+ * +
+
+ + + <#if messagesPerField.existsError('totp')> + + ${kcSanitize(messagesPerField.get('totp'))?no_esc} + + + +
+ + <#if mode??> +
+ +
+
+ <#if totp.otpCredentials?size gte 1>* +
+ +
+ + + <#if messagesPerField.existsError('userLabel')> + + ${kcSanitize(messagesPerField.get('userLabel'))?no_esc} + + +
+
+ + <#if isAppInitiatedAction??> + + + <#else> + + +
+ + \ No newline at end of file diff --git a/themes/src/main/resources/theme/unixdog/login/login-idp-link-confirm.ftl b/themes/src/main/resources/theme/unixdog/login/login-idp-link-confirm.ftl new file mode 100644 index 0000000000..c3537c5d3e --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/login-idp-link-confirm.ftl @@ -0,0 +1,13 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout; section> + <#if section = "header"> + ${msg("confirmLinkIdpTitle")} + <#elseif section = "form"> +
+
+ + +
+
+ + diff --git a/themes/src/main/resources/theme/unixdog/login/login-idp-link-email.ftl b/themes/src/main/resources/theme/unixdog/login/login-idp-link-email.ftl new file mode 100644 index 0000000000..0020178f06 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/login-idp-link-email.ftl @@ -0,0 +1,16 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout; section> + <#if section = "header"> + ${msg("emailLinkIdpTitle", idpDisplayName)} + <#elseif section = "form"> +

+ ${msg("emailLinkIdp1", idpDisplayName, brokerContext.username, realm.displayName)} +

+

+ ${msg("emailLinkIdp2")} ${msg("doClickHere")} ${msg("emailLinkIdp3")} +

+

+ ${msg("emailLinkIdp4")} ${msg("doClickHere")} ${msg("emailLinkIdp5")} +

+ + \ No newline at end of file diff --git a/themes/src/main/resources/theme/unixdog/login/login-oauth-grant.ftl b/themes/src/main/resources/theme/unixdog/login/login-oauth-grant.ftl new file mode 100755 index 0000000000..d5cfc4aac7 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/login-oauth-grant.ftl @@ -0,0 +1,68 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout bodyClass="oauth"; section> + <#if section = "header"> + <#if client.attributes.logoUri??> + + +

+ <#if client.name?has_content> + ${msg("oauthGrantTitle",advancedMsg(client.name))} + <#else> + ${msg("oauthGrantTitle",client.clientId)} + +

+ <#elseif section = "form"> +
+

${msg("oauthGrantRequest")}

+
    + <#if oauth.clientScopesRequested??> + <#list oauth.clientScopesRequested as clientScope> +
  • + <#if !clientScope.dynamicScopeParameter??> + ${advancedMsg(clientScope.consentScreenText)} + <#else> + ${advancedMsg(clientScope.consentScreenText)}: ${clientScope.dynamicScopeParameter} + + +
  • + + +
+ <#if client.attributes.policyUri?? || client.attributes.tosUri??> +

+ <#if client.name?has_content> + ${msg("oauthGrantInformation",advancedMsg(client.name))} + <#else> + ${msg("oauthGrantInformation",client.clientId)} + + <#if client.attributes.tosUri??> + ${msg("oauthGrantReview")} + ${msg("oauthGrantTos")} + + <#if client.attributes.policyUri??> + ${msg("oauthGrantReview")} + ${msg("oauthGrantPolicy")} + +

+ + +
+ +
+
+
+
+
+ +
+
+ + +
+
+
+
+
+
+ + diff --git a/themes/src/main/resources/theme/unixdog/login/login-oauth2-device-verify-user-code.ftl b/themes/src/main/resources/theme/unixdog/login/login-oauth2-device-verify-user-code.ftl new file mode 100644 index 0000000000..dfb625fe8b --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/login-oauth2-device-verify-user-code.ftl @@ -0,0 +1,31 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout; section> + <#if section = "header"> + ${msg("oauth2DeviceVerificationTitle")} + <#elseif section = "form"> +
+
+
+ +
+ +
+ +
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+
+ + \ No newline at end of file diff --git a/themes/src/main/resources/theme/unixdog/login/login-otp.ftl b/themes/src/main/resources/theme/unixdog/login/login-otp.ftl new file mode 100755 index 0000000000..a43778d900 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/login-otp.ftl @@ -0,0 +1,58 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout displayMessage=!messagesPerField.existsError('totp'); section> + <#if section="header"> + ${msg("doLogIn")} + <#elseif section="form"> +
+ <#if otpLogin.userOtpCredentials?size gt 1> +
+
+ <#list otpLogin.userOtpCredentials as otpCredential> + checked="checked"> + + +
+
+ + +
+
+ +
+ +
+ + + <#if messagesPerField.existsError('totp')> + + ${kcSanitize(messagesPerField.get('totp'))?no_esc} + + +
+
+ +
+
+
+
+
+ +
+ +
+
+
+ + \ No newline at end of file diff --git a/themes/src/main/resources/theme/unixdog/login/login-page-expired.ftl b/themes/src/main/resources/theme/unixdog/login/login-page-expired.ftl new file mode 100644 index 0000000000..2b470e018b --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/login-page-expired.ftl @@ -0,0 +1,11 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout; section> + <#if section = "header"> + ${msg("pageExpiredTitle")} + <#elseif section = "form"> +

+ ${msg("pageExpiredMsg1")} ${msg("doClickHere")} .
+ ${msg("pageExpiredMsg2")} ${msg("doClickHere")} . +

+ + diff --git a/themes/src/main/resources/theme/unixdog/login/login-password.ftl b/themes/src/main/resources/theme/unixdog/login/login-password.ftl new file mode 100755 index 0000000000..f49e5a4f46 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/login-password.ftl @@ -0,0 +1,32 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout displayMessage=!messagesPerField.existsError('password'); section> + <#if section = "header"> + ${msg("doLogIn")} + <#elseif section = "form"> +
+
+
+
+ + + <#if messagesPerField.existsError('password')> + + ${kcSanitize(messagesPerField.get('password'))?no_esc} + + +
+ +
+ +
+
+
+
+ + + diff --git a/themes/src/main/resources/theme/unixdog/login/login-recovery-authn-code-config.ftl b/themes/src/main/resources/theme/unixdog/login/login-recovery-authn-code-config.ftl new file mode 100644 index 0000000000..5bd3559d73 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/login-recovery-authn-code-config.ftl @@ -0,0 +1,184 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout; section> + +<#if section = "header"> + ${msg("recovery-code-config-header")} +<#elseif section = "form"> + +
+
+ +
+

+ Warning alert: + ${msg("recovery-code-config-warning-title")} +

+
+

${msg("recovery-code-config-warning-message")}

+
+
+ +
    + <#list recoveryAuthnCodesConfigBean.generatedRecoveryAuthnCodesList as code> +
  1. ${code?counter}: ${code[0..3]}-${code[4..7]}-${code[8..]}
  2. + +
+ + +
+ + + +
+ + +
+ + +
+ +
+ + + + + <#if isAppInitiatedAction??> + + + <#else> + + +
+ + + + diff --git a/themes/src/main/resources/theme/unixdog/login/login-recovery-authn-code-input.ftl b/themes/src/main/resources/theme/unixdog/login/login-recovery-authn-code-input.ftl new file mode 100644 index 0000000000..8d67d434c8 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/login-recovery-authn-code-input.ftl @@ -0,0 +1,44 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout displayMessage=!messagesPerField.existsError('recoveryCodeInput'); section> + + <#if section = "header"> + ${msg("auth-recovery-code-header")} + <#elseif section = "form"> +
+
+
+ +
+ +
+ + + <#if messagesPerField.existsError('recoveryCodeInput')> + + ${kcSanitize(messagesPerField.get('recoveryCodeInput'))?no_esc} + + +
+
+ +
+
+
+
+
+ +
+ +
+
+
+ + \ No newline at end of file diff --git a/themes/src/main/resources/theme/unixdog/login/login-reset-password.ftl b/themes/src/main/resources/theme/unixdog/login/login-reset-password.ftl new file mode 100755 index 0000000000..800faea1f0 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/login-reset-password.ftl @@ -0,0 +1,39 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout displayInfo=true displayMessage=!messagesPerField.existsError('username'); section> + <#if section = "header"> + ${msg("emailForgotTitle")} + <#elseif section = "form"> +
+
+
+ +
+
+ + <#if messagesPerField.existsError('username')> + + ${kcSanitize(messagesPerField.get('username'))?no_esc} + + +
+
+ +
+ <#elseif section = "info" > + <#if realm.duplicateEmailsAllowed> + ${msg("emailInstructionUsername")} + <#else> + ${msg("emailInstruction")} + + + diff --git a/themes/src/main/resources/theme/unixdog/login/login-update-password.ftl b/themes/src/main/resources/theme/unixdog/login/login-update-password.ftl new file mode 100755 index 0000000000..b884d75271 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/login-update-password.ftl @@ -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"> +
+ + + +
+
+ +
+
+ + + <#if messagesPerField.existsError('password')> + + ${kcSanitize(messagesPerField.get('password'))?no_esc} + + +
+
+ +
+
+ +
+
+ + + <#if messagesPerField.existsError('password-confirm')> + + ${kcSanitize(messagesPerField.get('password-confirm'))?no_esc} + + + +
+
+ +
+
+
+ <#if isAppInitiatedAction??> +
+ +
+ +
+
+ +
+ <#if isAppInitiatedAction??> + + + <#else> + + +
+
+
+ + \ No newline at end of file diff --git a/themes/src/main/resources/theme/unixdog/login/login-update-profile.ftl b/themes/src/main/resources/theme/unixdog/login/login-update-profile.ftl new file mode 100755 index 0000000000..be579b01bd --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/login-update-profile.ftl @@ -0,0 +1,99 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout displayMessage=!messagesPerField.existsError('username','email','firstName','lastName'); section> + <#if section = "header"> + ${msg("loginProfileTitle")} + <#elseif section = "form"> +
+ <#if user.editUsernameAllowed> +
+
+ +
+
+ + + <#if messagesPerField.existsError('username')> + + ${kcSanitize(messagesPerField.get('username'))?no_esc} + + +
+
+ + <#if user.editEmailAllowed> +
+
+ +
+
+ + + <#if messagesPerField.existsError('email')> + + ${kcSanitize(messagesPerField.get('email'))?no_esc} + + +
+
+ + +
+
+ +
+
+ + + <#if messagesPerField.existsError('firstName')> + + ${kcSanitize(messagesPerField.get('firstName'))?no_esc} + + +
+
+ +
+
+ +
+
+ + + <#if messagesPerField.existsError('lastName')> + + ${kcSanitize(messagesPerField.get('lastName'))?no_esc} + + +
+
+ +
+
+
+
+
+ +
+ <#if isAppInitiatedAction??> + + + <#else> + + +
+
+
+ + diff --git a/themes/src/main/resources/theme/unixdog/login/login-username.ftl b/themes/src/main/resources/theme/unixdog/login/login-username.ftl new file mode 100755 index 0000000000..0c18cb7ccb --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/login-username.ftl @@ -0,0 +1,89 @@ +<#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"> +
+
+ <#if realm.password> +
+ <#if !usernameHidden??> +
+ + + + + <#if messagesPerField.existsError('username')> + + ${kcSanitize(messagesPerField.get('username'))?no_esc} + + +
+ + +
+
+ <#if realm.rememberMe && !usernameHidden??> +
+ +
+ +
+
+ +
+ +
+
+ +
+
+ + <#elseif section = "info" > + <#if realm.password && realm.registrationAllowed && !registrationDisabled??> +
+ ${msg("noAccount")} ${msg("doRegister")} +
+ + <#elseif section = "socialProviders" > + <#if realm.password && social.providers??> +
+
+

${msg("identity-provider-login-label")}

+ + +
+ + + + diff --git a/themes/src/main/resources/theme/unixdog/login/login-verify-email.ftl b/themes/src/main/resources/theme/unixdog/login/login-verify-email.ftl new file mode 100755 index 0000000000..b47d8ca8d5 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/login-verify-email.ftl @@ -0,0 +1,14 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout displayInfo=true; section> + <#if section = "header"> + ${msg("emailVerifyTitle")} + <#elseif section = "form"> +

${msg("emailVerifyInstruction1",user.email)}

+ <#elseif section = "info"> +

+ ${msg("emailVerifyInstruction2")} +
+ ${msg("doClickHere")} ${msg("emailVerifyInstruction3")} +

+ + diff --git a/themes/src/main/resources/theme/unixdog/login/login-x509-info.ftl b/themes/src/main/resources/theme/unixdog/login/login-x509-info.ftl new file mode 100644 index 0000000000..0228b06338 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/login-x509-info.ftl @@ -0,0 +1,55 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout; section> + <#if section = "header"> + ${msg("doLogIn")} + <#elseif section = "form"> + +
+
+ +
+ +
+ <#if x509.formData.subjectDN??> +
+ +
+ <#else> +
+ +
+ +
+ +
+ + <#if x509.formData.isUserEnabled??> +
+ +
+
+ +
+ + +
+ +
+
+
+
+
+ +
+
+ + <#if x509.formData.isUserEnabled??> + + +
+
+
+
+ + + diff --git a/themes/src/main/resources/theme/unixdog/login/login.ftl b/themes/src/main/resources/theme/unixdog/login/login.ftl new file mode 100755 index 0000000000..21f3f9561c --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/login.ftl @@ -0,0 +1,105 @@ +<#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"> +
+
+ <#if realm.password> +
+ <#if !usernameHidden??> +
+ + + + + <#if messagesPerField.existsError('username','password')> + + ${kcSanitize(messagesPerField.getFirstError('username','password'))?no_esc} + + + +
+ + +
+ + + + + <#if usernameHidden?? && messagesPerField.existsError('username','password')> + + ${kcSanitize(messagesPerField.getFirstError('username','password'))?no_esc} + + + +
+ +
+
+ <#if realm.rememberMe && !usernameHidden??> +
+ +
+ +
+
+ <#if realm.resetPasswordAllowed> + ${msg("doForgotPassword")} + +
+ +
+ +
+ value="${auth.selectedCredential}"/> + +
+
+ +
+ +
+ <#elseif section = "info" > + <#if realm.password && realm.registrationAllowed && !registrationDisabled??> +
+
+ ${msg("noAccount")} ${msg("doRegister")} +
+
+ + <#elseif section = "socialProviders" > + <#if realm.password && social.providers??> +
+
+

${msg("identity-provider-login-label")}

+ + +
+ + + + diff --git a/themes/src/main/resources/theme/unixdog/login/logout-confirm.ftl b/themes/src/main/resources/theme/unixdog/login/logout-confirm.ftl new file mode 100644 index 0000000000..6c0b4e97b6 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/logout-confirm.ftl @@ -0,0 +1,38 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout; section> + <#if section = "header"> + ${msg("logoutConfirmTitle")} + <#elseif section = "form"> +
+

${msg("logoutConfirmHeader")}

+ +
+ +
+
+
+
+
+ +
+ +
+ +
+
+ +
+ <#if logoutConfirm.skipLink> + <#else> + <#if (client.baseUrl)?has_content> +

${kcSanitize(msg("backToApplication"))?no_esc}

+ + +
+ +
+
+ + diff --git a/themes/src/main/resources/theme/unixdog/login/messages/messages_en.properties b/themes/src/main/resources/theme/unixdog/login/messages/messages_en.properties new file mode 100755 index 0000000000..9aed132290 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/messages/messages_en.properties @@ -0,0 +1,511 @@ +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={0} Impersonate User +realmChoice=Realm +unknownUser=Unknown user +loginTotpTitle=Mobile Authenticator Setup +loginProfileTitle=Update Account Information +loginIdpReviewProfileTitle=Update Account Information +loginTimeout=Your login attempt timed out. Login will start from the beginning. +reauthenticate=Please re-authenticate to continue +oauthGrantTitle=Grant Access to {0} +oauthGrantTitleHtml={0} +oauthGrantInformation=Make sure you trust {0} by learning how {0} will handle your data. +oauthGrantReview=You could review the +oauthGrantTos=terms of service. +oauthGrantPolicy=privacy policy. +errorTitle=We are sorry... +errorTitleHtml=We are sorry ... +emailVerifyTitle=Email verification +emailForgotTitle=Forgot Your Password? +updateEmailTitle=Update email +emailUpdateConfirmationSentTitle=Confirmation email sent +emailUpdateConfirmationSent=A confirmation email has been sent to {0}. You must follow the instructions of the former to complete the email update. +emailUpdatedTitle=Email updated +emailUpdated=The account email has been successfully updated to {0}. +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 + +# Transports +usb=USB +nfc=NFC +bluetooth=Bluetooth +internal=Internal +unknown=Unknown + +termsTitle=Terms and Conditions +termsText=

Terms and conditions to be defined

+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 + +totpAppFreeOTPName=FreeOTP +totpAppGoogleName=Google Authenticator +totpAppMicrosoftAuthenticatorName=Microsoft Authenticator + +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 your address {0}. +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. +emailInstructionUsername=Enter your username 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. +sessionLimitExceeded=There are too many sessions + +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. + +error-invalid-value=Invalid value. +error-invalid-blank=Please specify value. +error-empty=Please specify value. +error-invalid-length=Length must be between {1} and {2}. +error-invalid-length-too-short=Minimal length is {1}. +error-invalid-length-too-long=Maximal length is {2}. +error-invalid-email=Invalid email address. +error-invalid-number=Invalid number. +error-number-out-of-range=Number must be between {1} and {2}. +error-number-out-of-range-too-small=Number must have minimal value of {1}. +error-number-out-of-range-too-big=Number must have maximal value of {2}. +error-pattern-no-match=Invalid value. +error-invalid-uri=Invalid URL. +error-invalid-uri-scheme=Invalid URL scheme. +error-invalid-uri-fragment=Invalid URL fragment. +error-user-attribute-required=Please specify this field. +error-invalid-date=Invalid date. +error-user-attribute-read-only=This field is read only. +error-username-invalid-character=Value contains invalid character. +error-person-name-invalid-character=Value contains invalid character. + +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 exist. 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. +configureBackupCodesMessage=You need to set up Backup Codes 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. +updateEmailMessage=You need to update your email address 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}. +invalidPasswordMaxLengthMessage=Invalid password: maximum 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 +successLogout=You are logged out +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. +cookieNotFoundMessage=Cookie not found. Please make sure cookies are enabled in your browser. +insufficientLevelOfAuthentication=The requested level of authentication has not been satisfied. +identityProviderUnexpectedErrorMessage=Unexpected error when authenticating with identity provider +identityProviderMissingStateMessage=Missing state parameter in response from identity provider. +identityProviderInvalidResponseMessage=Invalid response from identity provider. +identityProviderInvalidSignatureMessage=Invalid signature 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_ar=\u0639\u0631\u0628\u064A +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 +locale_fi=Suomi + +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 +acrNotFulfilled=Authentication requirements not fulfilled + +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 +requiredAction.CONFIGURE_RECOVERY_AUTHN_CODES=Generate Recovery Codes +requiredAction.webauthn-register-passwordless=Webauthn Register Passwordless + +invalidTokenRequiredActions=Required actions included in the link are not valid + +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. + +# Recovery Codes +auth-recovery-authn-code-form-display-name=Recovery Authentication Code +auth-recovery-authn-code-form-help-text=Enter a recovery authentication code from a previously generated list. +auth-recovery-code-info-message=Enter the specified recovery code. +auth-recovery-code-prompt=Recovery code #{0} +auth-recovery-code-header=Login with a recovery authentication code +recovery-codes-error-invalid=Invalid recovery authentication code +recovery-code-config-header=Recovery Authentication Codes +recovery-code-config-warning-title=These recovery codes won't appear again after leaving this page +recovery-code-config-warning-message=Make sure to print, download, or copy them to a password manager and keep them save. Canceling this setup will remove these recovery codes from your account. +recovery-codes-print=Print +recovery-codes-download=Download +recovery-codes-copy=Copy +recovery-codes-copied=Copied +recovery-codes-confirmation-message=I have saved these codes somewhere safe +recovery-codes-action-complete=Complete setup +recovery-codes-action-cancel=Cancel setup +recovery-codes-download-file-header=Keep these recovery codes somewhere safe. +recovery-codes-download-file-description=Recovery codes are single-use passcodes that allow you to sign in to your account if you do not have access to your authenticator. +recovery-codes-download-file-date= These codes were generated on +recovery-codes-label-default=Recovery codes + +# 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 Security Keys +webauthn-unsupported-browser-text=WebAuthn is not supported by this browser. Try another one or contact your administrator. +webauthn-doAuthenticate=Sign in with Security Key +webauthn-createdAt-label=Created + +# WebAuthn Error +webauthn-error-title=Security Key Error +webauthn-error-registration=Failed to register your Security key.
{0} +webauthn-error-api-get=Failed to authenticate by the Security key.
{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.
{0} +webauthn-error-register-verification=Security key registration result is invalid.
{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 +idp-email-verification-display-name=Email Verification +idp-email-verification-help-text=Link your account by validating your email. +idp-username-password-form-display-name=Username and password +idp-username-password-form-help-text=Link your account by logging in. + +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 +access-denied-when-idp-auth=Access denied when authenticating with {0} + +frontchannel-logout.title=Logging out +frontchannel-logout.message=You are logging out from following apps +logoutConfirmTitle=Logging out +logoutConfirmHeader=Do you want to logout? +doLogout=Logout + +readOnlyUsernameMessage=You can''t update your username as it is read-only. diff --git a/themes/src/main/resources/theme/unixdog/login/register-user-profile.ftl b/themes/src/main/resources/theme/unixdog/login/register-user-profile.ftl new file mode 100755 index 0000000000..e0d533b89f --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/register-user-profile.ftl @@ -0,0 +1,74 @@ +<#import "template.ftl" as layout> +<#import "user-profile-commons.ftl" as userProfileCommons> +<@layout.registrationLayout displayMessage=messagesPerField.exists('global') displayRequiredFields=true; section> + <#if section = "header"> + ${msg("registerTitle")} + <#elseif section = "form"> +
+ + <@userProfileCommons.userProfileFormFields; callback, attribute> + <#if callback = "afterField"> + <#-- render password fields just under the username or email (if used as username) --> + <#if passwordRequired?? && (attribute.name == 'username' || (attribute.name == 'email' && realm.registrationEmailAsUsername))> +
+
+ * +
+
+ + + <#if messagesPerField.existsError('password')> + + ${kcSanitize(messagesPerField.get('password'))?no_esc} + + +
+
+ +
+
+ * +
+
+ + + <#if messagesPerField.existsError('password-confirm')> + + ${kcSanitize(messagesPerField.get('password-confirm'))?no_esc} + + +
+
+ + + + + <#if recaptchaRequired??> +
+
+
+
+
+ + + +
+ + \ No newline at end of file diff --git a/themes/src/main/resources/theme/unixdog/login/register.ftl b/themes/src/main/resources/theme/unixdog/login/register.ftl new file mode 100755 index 0000000000..db50984798 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/register.ftl @@ -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"> +
+
+
+ +
+
+ + + <#if messagesPerField.existsError('firstName')> + + ${kcSanitize(messagesPerField.get('firstName'))?no_esc} + + +
+
+ +
+
+ +
+
+ + + <#if messagesPerField.existsError('lastName')> + + ${kcSanitize(messagesPerField.get('lastName'))?no_esc} + + +
+
+ +
+
+ +
+
+ + + <#if messagesPerField.existsError('email')> + + ${kcSanitize(messagesPerField.get('email'))?no_esc} + + +
+
+ + <#if !realm.registrationEmailAsUsername> +
+
+ +
+
+ + + <#if messagesPerField.existsError('username')> + + ${kcSanitize(messagesPerField.get('username'))?no_esc} + + +
+
+ + + <#if passwordRequired??> +
+
+ +
+
+ + + <#if messagesPerField.existsError('password')> + + ${kcSanitize(messagesPerField.get('password'))?no_esc} + + +
+
+ +
+
+ +
+
+ + + <#if messagesPerField.existsError('password-confirm')> + + ${kcSanitize(messagesPerField.get('password-confirm'))?no_esc} + + +
+
+ + + <#if recaptchaRequired??> +
+
+
+
+
+ + + +
+ + \ No newline at end of file diff --git a/themes/src/main/resources/theme/unixdog/login/resources/css/main.css b/themes/src/main/resources/theme/unixdog/login/resources/css/main.css new file mode 100644 index 0000000000..ff2d6d6778 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/resources/css/main.css @@ -0,0 +1,209 @@ +body { + font-family: monospace; + margin: 0; + background: #080e08; + color: #f6f6f6; + + display: flex; + flex-direction: column; + min-height: 100vh; +} + +h1, h2 { + color: #4af626; +} + +footer { + padding: 10px; + max-width: 800px; + width: 100%; + background: #3a7920; + color: #f6f6f6; + + margin: auto auto 0; + box-sizing: border-box; +} + +a:link { + color: #2cacb0; +} + +a:visited { + color: #b4778f; +} +@media (prefers-color-scheme: light) { + body { + background: #fcfffc; + color: #211c1b; + } + + h1, h2 { + color: #4c982a; + } + + a:link { + color: #1f7b7e; + } + + a:visited { + color: #7c5263; + } + + textarea { + background: #ffffff; + color: #211c1b; + } +} + +header { + background: linear-gradient( + 90deg, + rgba(255, 0, 0, 1) 0%, + rgba(255, 154, 0, 1) 10%, + rgba(208, 222, 33, 1) 20%, + rgba(79, 220, 74, 1) 30%, + rgba(63, 218, 216, 1) 40%, + rgba(47, 201, 226, 1) 50%, + rgba(28, 127, 238, 1) 60%, + rgba(95, 21, 242, 1) 70%, + rgba(186, 12, 248, 1) 80%, + rgba(251, 7, 217, 1) 90%, + rgba(255, 0, 0, 1) 100% + ); + min-height: 50px; + display: flex; + color: black; + box-sizing: border-box; +} + +#header-content { + max-width: 800px; + margin: auto; + width: 100%; + align-content: center; + flex-direction: row; + display: flex; + padding: 10px; +} +#header-content h1 { + color: black; + margin: auto auto auto 1rem; +} + +#header-content img { + display: inline; +} + +main { + max-width: 800px; + margin: 0 auto; + padding: 10px; + width: 100%; + box-sizing: border-box; +} + + +span.copyleft { + display: inline-block; + transform: rotate(180deg); +} + +footer a:link, footer a:visited { + text-decoration: none; + font-weight: bold; + color: white; +} + +footer a:hover { + text-decoration: underline; +} + + +input { + background: #332c29; + color: #f6f6f6; +} + +textarea { + background: #332c29; + color: #f6f6f6; +} + +textarea.big { + width: 100%; + height: 5em; +} + +.error, .required { + color: #f00; +} + +#nav { + margin: auto 0 auto auto; + display: flex; + flex-direction: row; + flex-wrap: wrap; +} + +#nav a { + display: block; + padding: 10px; +} + +pre { + white-space: pre-wrap; +} + +#header-content a:link { + text-decoration: none; + color: black; +} +#header-content a:visited { + text-decoration: none; + color: black; +} + +#header-content a:hover { + text-decoration: underline; +} + +label.field-with-error { + color: red; +} + +img.stats { + width: 100%; + display: block; +} + +/* Tables */ +table { + border-collapse: collapse; + width: 100%; +} +th, td { + padding: 5px; +} +th { + border-bottom: solid 2px currentColor; +} + +td:first-child { + border-right: solid 2px currentColor; + border-left: none; +} +td { + border-right: solid 2px currentColor; + border-left: solid 2px currentColor; +} +td:last-child { + border-right: none; + border-left: solid 2px currentColor; +} + +/* Responsive */ +.responsive-wrapper { + overflow-x: auto; + width: 100%; +} + diff --git a/themes/src/main/resources/theme/unixdog/login/resources/img/favicon.ico b/themes/src/main/resources/theme/unixdog/login/resources/img/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..46eafce9bc1d16af673f3d41f4f3c88f58a9ac36 GIT binary patch literal 171528 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 literal 0 HcmV?d00001 diff --git a/themes/src/main/resources/theme/unixdog/login/resources/js/base64url.js b/themes/src/main/resources/theme/unixdog/login/resources/js/base64url.js new file mode 100644 index 0000000000..64555bfbd5 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/resources/js/base64url.js @@ -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)); + + diff --git a/themes/src/main/resources/theme/unixdog/login/saml-post-form.ftl b/themes/src/main/resources/theme/unixdog/login/saml-post-form.ftl new file mode 100644 index 0000000000..94b0c30fca --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/saml-post-form.ftl @@ -0,0 +1,25 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout; section> + <#if section = "header"> + ${msg("saml.post-form.title")} + <#elseif section = "form"> + +

${msg("saml.post-form.message")}

+
+ <#if samlPost.SAMLRequest??> + + + <#if samlPost.SAMLResponse??> + + + <#if samlPost.relayState??> + + + + +
+ + diff --git a/themes/src/main/resources/theme/unixdog/login/select-authenticator.ftl b/themes/src/main/resources/theme/unixdog/login/select-authenticator.ftl new file mode 100644 index 0000000000..769715b832 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/select-authenticator.ftl @@ -0,0 +1,39 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout displayInfo=false; section> + <#if section = "header" || section = "show-username"> + + <#if section = "header"> + ${msg("loginChooseAuthenticator")} + + <#elseif section = "form"> +
+ + + + + + + <#list auth.authenticationSelections as authenticationSelection> + + + + + + +
MethodDescriptionAction
${msg('${authenticationSelection.displayName}')}${msg('${authenticationSelection.helpText}')} +
+ + +
+
+
+ + + + diff --git a/themes/src/main/resources/theme/unixdog/login/template.ftl b/themes/src/main/resources/theme/unixdog/login/template.ftl new file mode 100644 index 0000000000..b5f6a5159d --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/template.ftl @@ -0,0 +1,162 @@ +<#macro registrationLayout bodyClass="" displayInfo=false displayMessage=true displayRequiredFields=false> + + + + + + + + + <#if properties.meta?has_content> + <#list properties.meta?split(' ') as meta> + + + + ${msg("loginTitle",(realm.displayName!''))} + + <#if properties.stylesCommon?has_content> + <#list properties.stylesCommon?split(' ') as style> + + + + <#if properties.styles?has_content> + <#list properties.styles?split(' ') as style> + + + + <#if properties.scripts?has_content> + <#list properties.scripts?split(' ') as script> + + + + <#if scripts??> + <#list scripts as script> + + + + + + +
+
+ UNIX.dog +

${kcSanitize(msg("loginTitleHtml",(realm.displayNameHtml!'')))?no_esc}

+ +
+
+
+
+
+ + <#if !(auth?has_content && auth.showUsername() && !auth.showResetCredentials())> + <#if displayRequiredFields> +
+
+ * ${msg("requiredFields")} +
+
+

<#nested "header">

+
+
+ <#else> +

<#nested "header">

+ + <#else> + <#if displayRequiredFields> +
+ <#else> + <#nested "show-username"> +
+

Logging in as: + . + + ${msg("restartLoginTooltip")}. + +

+
+ + +
+
+ + <#-- 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??)> +
+ ${kcSanitize(message.summary)?no_esc} +
+ + + <#nested "form"> + + <#if auth?has_content && auth.showTryAnotherWayLink()> +
+
+ + +
+
+ + + <#if displayInfo> +
+
+ <#nested "info"> +
+
+ +
+
+ +
+
+
+
+ 🄯 Copyleft UNIX.dog, + 2023. All pages licensed under CC BY-NC-SA 4.0. +
+Please follow all rules while using these services. +
+ + + diff --git a/themes/src/main/resources/theme/unixdog/login/terms.ftl b/themes/src/main/resources/theme/unixdog/login/terms.ftl new file mode 100755 index 0000000000..687b192c94 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/terms.ftl @@ -0,0 +1,15 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout displayMessage=false; section> + <#if section = "header"> + ${msg("termsTitle")} + <#elseif section = "form"> +
+ ${kcSanitize(msg("termsText"))?no_esc} +
+
+ + +
+
+ + diff --git a/themes/src/main/resources/theme/unixdog/login/theme.properties b/themes/src/main/resources/theme/unixdog/login/theme.properties new file mode 100644 index 0000000000..c6ef88537d --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/theme.properties @@ -0,0 +1,4 @@ + +styles=css/main.css + +kcInputErrorMessageClass=error diff --git a/themes/src/main/resources/theme/unixdog/login/update-email.ftl b/themes/src/main/resources/theme/unixdog/login/update-email.ftl new file mode 100644 index 0000000000..4c85e5b5da --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/update-email.ftl @@ -0,0 +1,42 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout displayMessage=!messagesPerField.existsError('email'); section> + <#if section = "header"> + ${msg("updateEmailTitle")} + <#elseif section = "form"> +
+
+
+ +
+
+ + + <#if messagesPerField.existsError('email')> + + ${kcSanitize(messagesPerField.get('email'))?no_esc} + + +
+
+ +
+
+
+
+
+ +
+ <#if isAppInitiatedAction??> + + + <#else> + + +
+
+
+ + diff --git a/themes/src/main/resources/theme/unixdog/login/update-user-profile.ftl b/themes/src/main/resources/theme/unixdog/login/update-user-profile.ftl new file mode 100755 index 0000000000..e09f5c3884 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/update-user-profile.ftl @@ -0,0 +1,28 @@ +<#import "template.ftl" as layout> +<#import "user-profile-commons.ftl" as userProfileCommons> +<@layout.registrationLayout displayMessage=messagesPerField.exists('global') displayRequiredFields=true; section> + <#if section = "header"> + ${msg("loginProfileTitle")} + <#elseif section = "form"> +
+ + <@userProfileCommons.userProfileFormFields/> + +
+
+
+
+
+ +
+ <#if isAppInitiatedAction??> + + + <#else> + + +
+
+
+ + \ No newline at end of file diff --git a/themes/src/main/resources/theme/unixdog/login/user-profile-commons.ftl b/themes/src/main/resources/theme/unixdog/login/user-profile-commons.ftl new file mode 100644 index 0000000000..140eea31a8 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/user-profile-commons.ftl @@ -0,0 +1,187 @@ +<#macro userProfileFormFields> + <#assign currentGroup=""> + + <#list profile.attributes as attribute> + + <#assign groupName = attribute.group!""> + <#if groupName != currentGroup> + <#assign currentGroup=groupName> + <#if currentGroup != "" > +
+ + <#assign groupDisplayHeader=attribute.groupDisplayHeader!""> + <#if groupDisplayHeader != ""> + <#assign groupHeaderText=advancedMsg(attribute.groupDisplayHeader)!groupName> + <#else> + <#assign groupHeaderText=groupName> + +
+ +
+ + <#assign groupDisplayDescription=attribute.groupDisplayDescription!""> + <#if groupDisplayDescription != ""> + <#assign groupDescriptionText=advancedMsg(attribute.groupDisplayDescription)!""> +
+ +
+ +
+ + + + <#nested "beforeField" attribute> +
+
+ + <#if attribute.required>* +
+
+ <#if attribute.annotations.inputHelperTextBefore??> +
${kcSanitize(advancedMsg(attribute.annotations.inputHelperTextBefore))?no_esc}
+ + <@inputFieldByType attribute=attribute/> + <#if messagesPerField.existsError('${attribute.name}')> + + ${kcSanitize(messagesPerField.get('${attribute.name}'))?no_esc} + + + <#if attribute.annotations.inputHelperTextAfter??> +
${kcSanitize(advancedMsg(attribute.annotations.inputHelperTextAfter))?no_esc}
+ +
+
+ <#nested "afterField" attribute> + + + +<#macro inputFieldByType attribute> + <#switch attribute.annotations.inputType!''> + <#case 'textarea'> + <@textareaTag attribute=attribute/> + <#break> + <#case 'select'> + <#case 'multiselect'> + <@selectTag attribute=attribute/> + <#break> + <#case 'select-radiobuttons'> + <#case 'multiselect-checkboxes'> + <@inputTagSelects attribute=attribute/> + <#break> + <#default> + <@inputTag attribute=attribute/> + + + +<#macro inputTag attribute> + disabled + <#if attribute.autocomplete??>autocomplete="${attribute.autocomplete}" + <#if attribute.annotations.inputTypePlaceholder??>placeholder="${attribute.annotations.inputTypePlaceholder}" + <#if attribute.annotations.inputTypePattern??>pattern="${attribute.annotations.inputTypePattern}" + <#if attribute.annotations.inputTypeSize??>size="${attribute.annotations.inputTypeSize}" + <#if attribute.annotations.inputTypeMaxlength??>maxlength="${attribute.annotations.inputTypeMaxlength}" + <#if attribute.annotations.inputTypeMinlength??>minlength="${attribute.annotations.inputTypeMinlength}" + <#if attribute.annotations.inputTypeMax??>max="${attribute.annotations.inputTypeMax}" + <#if attribute.annotations.inputTypeMin??>min="${attribute.annotations.inputTypeMin}" + <#if attribute.annotations.inputTypeStep??>step="${attribute.annotations.inputTypeStep}" + /> + + +<#macro inputTagType attribute> + <#compress> + <#if attribute.annotations.inputType??> + <#if attribute.annotations.inputType?starts_with("html5-")> + ${attribute.annotations.inputType[6..]} + <#else> + ${attribute.annotations.inputType} + + <#else> + text + + + + +<#macro textareaTag attribute> + + + +<#macro selectTag attribute> + + + +<#macro inputTagSelects attribute> + <#if attribute.annotations.inputType=='select-radiobuttons'> + <#assign inputType='radio'> + <#assign classDiv=properties.kcInputClassRadio!> + <#assign classInput=properties.kcInputClassRadioInput!> + <#assign classLabel=properties.kcInputClassRadioLabel!> + <#else> + <#assign inputType='checkbox'> + <#assign classDiv=properties.kcInputClassCheckbox!> + <#assign classInput=properties.kcInputClassCheckboxInput!> + <#assign classLabel=properties.kcInputClassCheckboxLabel!> + + + <#if attribute.annotations.inputOptionsFromValidation?? && attribute.validators[attribute.annotations.inputOptionsFromValidation]?? && attribute.validators[attribute.annotations.inputOptionsFromValidation].options??> + <#assign options=attribute.validators[attribute.annotations.inputOptionsFromValidation].options> + <#elseif attribute.validators.options?? && attribute.validators.options.options??> + <#assign options=attribute.validators.options.options> + + + <#if options??> + <#list options as option> +
+ disabled + <#if attribute.values?seq_contains(option)>checked + /> + +
+ + + + + +<#macro selectOptionLabelText attribute option> + <#compress> + <#if attribute.annotations.inputOptionLabels??> + ${advancedMsg(attribute.annotations.inputOptionLabels[option]!option)} + <#else> + <#if attribute.annotations.inputOptionLabelsI18nPrefix??> + ${msg(attribute.annotations.inputOptionLabelsI18nPrefix + '.' + option)} + <#else> + ${option} + + + + \ No newline at end of file diff --git a/themes/src/main/resources/theme/unixdog/login/webauthn-authenticate.ftl b/themes/src/main/resources/theme/unixdog/login/webauthn-authenticate.ftl new file mode 100644 index 0000000000..a07f7503d8 --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/webauthn-authenticate.ftl @@ -0,0 +1,168 @@ + <#import "template.ftl" as layout> + <@layout.registrationLayout; section> + <#if section = "title"> + title + <#elseif section = "header"> + ${kcSanitize(msg("webauthn-login-title"))?no_esc} + <#elseif section = "form"> +
+
+ + + + + + +
+ +
+ <#if authenticators??> +
+ <#list authenticators.authenticators as authenticator> + + +
+ + <#if shouldDisplayAuthenticators?? && shouldDisplayAuthenticators> + <#if authenticators.authenticators?size gt 1> +

${kcSanitize(msg("webauthn-available-authenticators"))?no_esc}

+ + +
+ <#list authenticators.authenticators as authenticator> +
+
+ +
+
+
+ ${kcSanitize(msg('${authenticator.label}'))?no_esc} +
+ + <#if authenticator.transports?? && authenticator.transports.displayNameProperties?has_content> +
+ <#list authenticator.transports.displayNameProperties as nameProperty> + ${kcSanitize(msg('${nameProperty!}'))?no_esc} + <#if nameProperty?has_next> + , + + +
+ + +
+ + ${kcSanitize(msg('webauthn-createdAt-label'))?no_esc} + + + ${kcSanitize(authenticator.createdAt)?no_esc} + +
+
+
+
+ +
+ + + +
+ +
+
+
+ + + + + <#elseif section = "info"> + + + diff --git a/themes/src/main/resources/theme/unixdog/login/webauthn-error.ftl b/themes/src/main/resources/theme/unixdog/login/webauthn-error.ftl new file mode 100644 index 0000000000..2474a3f6cc --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/webauthn-error.ftl @@ -0,0 +1,36 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout displayMessage=true; section> + <#if section = "header"> + ${kcSanitize(msg("webauthn-error-title"))?no_esc} + <#elseif section = "form"> + + + +
+ + +
+ + + + <#if isAppInitiatedAction??> +
+ +
+ + + + \ No newline at end of file diff --git a/themes/src/main/resources/theme/unixdog/login/webauthn-register.ftl b/themes/src/main/resources/theme/unixdog/login/webauthn-register.ftl new file mode 100644 index 0000000000..021e8e91dc --- /dev/null +++ b/themes/src/main/resources/theme/unixdog/login/webauthn-register.ftl @@ -0,0 +1,194 @@ + <#import "template.ftl" as layout> + <@layout.registrationLayout; section> + <#if section = "title"> + title + <#elseif section = "header"> + ${kcSanitize(msg("webauthn-registration-title"))?no_esc} + <#elseif section = "form"> + +
+
+ + + + + + +
+
+ + + + + + + + + + <#if !isSetRetry?has_content && isAppInitiatedAction?has_content> +
+ +
+ + + +