diff --git a/docker/docker-compose.override.yml b/docker/docker-compose.override.yml index 48b71c2..0cc709e 100644 --- a/docker/docker-compose.override.yml +++ b/docker/docker-compose.override.yml @@ -52,6 +52,8 @@ services: - "8888:8080" volumes: - ../keycloak/realm.json:/opt/keycloak/data/import/realm.json + - ../keycloak/theme/customtheme:/opt/keycloak/themes/customtheme + command: start-dev --spi-theme-static-max-age=-1 --spi-theme-cache-themes=false --spi-theme-cache-templates=false --import-realm doc: image: squidfunk/mkdocs-material:8.3.9 diff --git a/keycloak/Dockerfile b/keycloak/Dockerfile index bff4988..7cfc756 100644 --- a/keycloak/Dockerfile +++ b/keycloak/Dockerfile @@ -6,5 +6,6 @@ FROM quay.io/keycloak/keycloak:21.1.0 COPY --from=ubi-micro-build /mnt/rootfs / COPY ./realm.json /opt/keycloak/data/import/realm.json +COPY ./theme/customtheme /opt/keycloak/themes/customtheme diff --git a/keycloak/realm.json b/keycloak/realm.json index 7a5d3d2..620c525 100644 --- a/keycloak/realm.json +++ b/keycloak/realm.json @@ -656,6 +656,7 @@ "frontchannelLogout" : true, "protocol" : "openid-connect", "attributes" : { + "login_theme" : "customtheme", "tls-client-certificate-bound-access-tokens" : "false", "oidc.ciba.grant.enabled" : "false", "backchannel.logout.session.required" : "true", @@ -1461,8 +1462,9 @@ } } ] }, - "internationalizationEnabled" : false, - "supportedLocales" : [ ], + "internationalizationEnabled" : true, + "supportedLocales" : [ "en", "fr" ], + "defaultLocale" : "en", "authenticationFlows" : [ { "id" : "d3c990a3-d06a-44f9-bbc8-f065e9dce1a6", "alias" : "Account verification options", diff --git a/keycloak/theme/customtheme/login/login.ftl b/keycloak/theme/customtheme/login/login.ftl new file mode 100644 index 0000000..d4e7ece --- /dev/null +++ b/keycloak/theme/customtheme/login/login.ftl @@ -0,0 +1,107 @@ +<#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")}

+ + +
+ + + + \ No newline at end of file diff --git a/keycloak/theme/customtheme/login/resources/css/styles.css b/keycloak/theme/customtheme/login/resources/css/styles.css new file mode 100644 index 0000000..5423381 --- /dev/null +++ b/keycloak/theme/customtheme/login/resources/css/styles.css @@ -0,0 +1,39 @@ +body { + background-image: url('../img/background.png') !important; + background-repeat: no-repeat !important; + background-size: cover !important; + background-position: bottom !important; +} + +#geocamlogo { + max-width: 200px; + height: auto; +} + +.card-pf{ + border-radius: 25px; + border-top: none; + box-shadow: 0px 1px 5px 0px rgba(0, 0, 0, 0.12), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 3px 1px -2px rgba(0, 0, 0, 0.20); +} + +#username:focus, #password:focus, #username:hover, #password:hover { + border-bottom-color: #2FA37C; +} + +#username, #password { + background-color: #FFFFFF; + outline: none !important; + box-shadow: none !important; + border-left: none; + border-top: none; + border-right: none; +} + + +#kc-form-buttons input { + border-radius: 50px; + background: #2FA37C; + width: fit-content; + padding: 8px 32px; + margin: 0 auto; +} \ No newline at end of file diff --git a/keycloak/theme/customtheme/login/resources/img/background.png b/keycloak/theme/customtheme/login/resources/img/background.png new file mode 100644 index 0000000..d808c89 Binary files /dev/null and b/keycloak/theme/customtheme/login/resources/img/background.png differ diff --git a/keycloak/theme/customtheme/login/resources/img/logo.png b/keycloak/theme/customtheme/login/resources/img/logo.png new file mode 100644 index 0000000..3b5498e Binary files /dev/null and b/keycloak/theme/customtheme/login/resources/img/logo.png differ diff --git a/keycloak/theme/customtheme/login/template.ftl b/keycloak/theme/customtheme/login/template.ftl new file mode 100644 index 0000000..acb2b9c --- /dev/null +++ b/keycloak/theme/customtheme/login/template.ftl @@ -0,0 +1,155 @@ +<#macro registrationLayout bodyClass="" displayInfo=false displayMessage=true displayRequiredFields=false> + + lang="${locale.currentLanguageTag}"> + + + + + + + <#if properties.meta?has_content> + <#list properties.meta?split(' ') as meta> + + + + GeoCam + + <#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> + + + + + + +
+
+
+
+
+
+
+ <#if realm.internationalizationEnabled && locale.supported?size gt 1> +
+
+
+ ${locale.current} +
    + <#list locale.supported as l> +
  • + ${l.label} +
  • + +
+
+
+
+ + <#if !(auth?has_content && auth.showUsername() && !auth.showResetCredentials())> + <#if displayRequiredFields> +
+
+ * ${msg("requiredFields")} +
+
+

<#nested "header">

+
+
+ <#else> +

<#nested "header">

+ + <#else> + <#if displayRequiredFields> +
+
+ * ${msg("requiredFields")} +
+
+ <#nested "show-username"> +
+ + + + +
+
+
+ <#else> + <#nested "show-username"> +
+ + + + +
+ + +
+
+
+ + <#-- 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??)> +
+
+ <#if message.type = 'success'> + <#if message.type = 'warning'> + <#if message.type = 'error'> + <#if message.type = 'info'> +
+ ${kcSanitize(message.summary)?no_esc} +
+ + + <#nested "form"> + + <#if auth?has_content && auth.showTryAnotherWayLink()> +
+ +
+ + + <#nested "socialProviders"> + + <#if displayInfo> +
+
+ <#nested "info"> +
+
+ +
+
+ +
+
+ + + \ No newline at end of file diff --git a/keycloak/theme/customtheme/login/theme.properties b/keycloak/theme/customtheme/login/theme.properties new file mode 100644 index 0000000..c3376ad --- /dev/null +++ b/keycloak/theme/customtheme/login/theme.properties @@ -0,0 +1,3 @@ +parent=keycloak +import=common/keycloak +styles=web_modules/@fontawesome/fontawesome-free/css/icons/all.css web_modules/@patternfly/react-core/dist/styles/base.css web_modules/@patternfly/react-core/dist/styles/app.css node_modules/patternfly/dist/css/patternfly.min.css node_modules/patternfly/dist/css/patternfly-additions.min.css css/login.css css/styles.css \ No newline at end of file