From 0cc60a3a62643a7dd810483ba3549f75c7fecc47 Mon Sep 17 00:00:00 2001 From: mrorro Date: Thu, 27 Jun 2024 11:30:56 +0200 Subject: [PATCH 1/5] Add keycloak aiod theme initial commit --- .../{ => data}/import/realm-export.json | 1 + .../aiod/login/resources/css/styles.css | 32 +++++++ .../themes/aiod/login/resources/img/logo.svg | 87 +++++++++++++++++++ .../themes/aiod/login/theme.properties | 3 + docker-compose.yaml | 3 +- 5 files changed, 125 insertions(+), 1 deletion(-) rename data/keycloak/{ => data}/import/realm-export.json (99%) create mode 100644 data/keycloak/themes/aiod/login/resources/css/styles.css create mode 100644 data/keycloak/themes/aiod/login/resources/img/logo.svg create mode 100644 data/keycloak/themes/aiod/login/theme.properties diff --git a/data/keycloak/import/realm-export.json b/data/keycloak/data/import/realm-export.json similarity index 99% rename from data/keycloak/import/realm-export.json rename to data/keycloak/data/import/realm-export.json index cc0972ae..da01070f 100644 --- a/data/keycloak/import/realm-export.json +++ b/data/keycloak/data/import/realm-export.json @@ -1527,6 +1527,7 @@ "strictTransportSecurity": "max-age=31536000; includeSubDomains" }, "smtpServer": {}, + "loginTheme" : "aiod", "eventsEnabled": false, "eventsListeners": [ "jboss-logging" diff --git a/data/keycloak/themes/aiod/login/resources/css/styles.css b/data/keycloak/themes/aiod/login/resources/css/styles.css new file mode 100644 index 00000000..867b3ddd --- /dev/null +++ b/data/keycloak/themes/aiod/login/resources/css/styles.css @@ -0,0 +1,32 @@ +login-pf { + background: none; +} + +.login-pf body { + background: #000613 none; +} + +#kc-header-wrapper { + font-size: 0px; + padding: 124px 10px 20px; + background: url("../img/logo.svg") no-repeat center; + background-size: contain; +} + +.card-pf { + background: transparent; +} + +h1#kc-page-title { + color: white; + font-size: large; +} + +h1#kc-page-title { + color: white; +} + +#kc-content { + color: white; + font-size: medium; +} diff --git a/data/keycloak/themes/aiod/login/resources/img/logo.svg b/data/keycloak/themes/aiod/login/resources/img/logo.svg new file mode 100644 index 00000000..c25c6329 --- /dev/null +++ b/data/keycloak/themes/aiod/login/resources/img/logo.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/keycloak/themes/aiod/login/theme.properties b/data/keycloak/themes/aiod/login/theme.properties new file mode 100644 index 00000000..427586d2 --- /dev/null +++ b/data/keycloak/themes/aiod/login/theme.properties @@ -0,0 +1,3 @@ +parent=keycloak +import=common/keycloak +styles=css/login.css css/styles.css diff --git a/docker-compose.yaml b/docker-compose.yaml index 3b6e9c43..9445f61b 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -146,7 +146,8 @@ services: ports: - 8080:8080 volumes: - - ${DATA_PATH}/keycloak:/opt/keycloak/data + - ${DATA_PATH}/keycloak/data:/opt/keycloak/data + - ${DATA_PATH}/keycloak/themes/aiod:/opt/keycloak/themes/aiod command: > start --hostname-url http://${HOSTNAME}/aiod-auth From f7b0b693f9b31c25d6d8ce7b722faa4c55b0dea5 Mon Sep 17 00:00:00 2001 From: mrorro Date: Fri, 28 Jun 2024 19:43:28 +0200 Subject: [PATCH 2/5] Add AIoD theme to identity providers --- .../themes/aiod/login/resources/css/styles.css | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/data/keycloak/themes/aiod/login/resources/css/styles.css b/data/keycloak/themes/aiod/login/resources/css/styles.css index 867b3ddd..afa3ab22 100644 --- a/data/keycloak/themes/aiod/login/resources/css/styles.css +++ b/data/keycloak/themes/aiod/login/resources/css/styles.css @@ -17,13 +17,26 @@ login-pf { background: transparent; } -h1#kc-page-title { +.pf-c-button.pf-m-control { + color: white; + background-color: var(--pf-c-button--m-primary--BackgroundColor); +} + +.kc-social-gray { color: white; - font-size: large; +} + +#kc-social-providers h4 { + font-size: medium; +} + +.pf-c-button::after { + border: transparent; } h1#kc-page-title { color: white; + font-size: large; } #kc-content { From ca0deecfee99b28487f483c7710c67fb4b4613fc Mon Sep 17 00:00:00 2001 From: mrorro Date: Wed, 3 Jul 2024 18:38:19 +0200 Subject: [PATCH 3/5] Add EGI Check-in button --- .../login/messages/messages_en.properties | 1 + .../aiod/login/resources/css/styles.css | 35 +++++++++++++++ .../login/resources/img/egi-logo-color.svg | 45 +++++++++++++++++++ .../login/resources/img/egi-logo-white.svg | 45 +++++++++++++++++++ .../themes/aiod/login/resources/js/script.js | 22 +++++++++ .../themes/aiod/login/theme.properties | 1 + 6 files changed, 149 insertions(+) create mode 100644 data/keycloak/themes/aiod/login/messages/messages_en.properties create mode 100644 data/keycloak/themes/aiod/login/resources/img/egi-logo-color.svg create mode 100644 data/keycloak/themes/aiod/login/resources/img/egi-logo-white.svg create mode 100644 data/keycloak/themes/aiod/login/resources/js/script.js diff --git a/data/keycloak/themes/aiod/login/messages/messages_en.properties b/data/keycloak/themes/aiod/login/messages/messages_en.properties new file mode 100644 index 00000000..cff63e19 --- /dev/null +++ b/data/keycloak/themes/aiod/login/messages/messages_en.properties @@ -0,0 +1 @@ +identity-provider-login-label=Or sign in with your local account diff --git a/data/keycloak/themes/aiod/login/resources/css/styles.css b/data/keycloak/themes/aiod/login/resources/css/styles.css index afa3ab22..ff7a267b 100644 --- a/data/keycloak/themes/aiod/login/resources/css/styles.css +++ b/data/keycloak/themes/aiod/login/resources/css/styles.css @@ -42,4 +42,39 @@ h1#kc-page-title { #kc-content { color: white; font-size: medium; + text-align: center; +} + +#social-oidc { + display: inline-block; + width: auto; + margin: 20px 20px 0px 0px; + padding: 20px 30px 20px 80px; + border: 2px solid #005faa; + border-radius: 100vw; + background-color: #005faa; + background-image: url(../img/egi-logo-white.svg); + background-position: 30px 43%; + background-size: 36px; + background-repeat: no-repeat; + -webkit-transition: all 200ms ease-in-out; + transition: all 200ms ease-in-out; + font-family: 'DM Sans', sans-serif; + color: #fff; + font-size: 18px; + font-weight: 700; +} + +#social-oidc:hover { + background-color: #fff; + background-image: url(../img/egi-logo-color.svg); + color: #005faa; +} + +#kc-form-wrapper { + display: none; +} + +#kc-form:hover #kc-form-wrapper { + display: block; } diff --git a/data/keycloak/themes/aiod/login/resources/img/egi-logo-color.svg b/data/keycloak/themes/aiod/login/resources/img/egi-logo-color.svg new file mode 100644 index 00000000..1250fe1c --- /dev/null +++ b/data/keycloak/themes/aiod/login/resources/img/egi-logo-color.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/keycloak/themes/aiod/login/resources/img/egi-logo-white.svg b/data/keycloak/themes/aiod/login/resources/img/egi-logo-white.svg new file mode 100644 index 00000000..17798c69 --- /dev/null +++ b/data/keycloak/themes/aiod/login/resources/img/egi-logo-white.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/keycloak/themes/aiod/login/resources/js/script.js b/data/keycloak/themes/aiod/login/resources/js/script.js new file mode 100644 index 00000000..948e2979 --- /dev/null +++ b/data/keycloak/themes/aiod/login/resources/js/script.js @@ -0,0 +1,22 @@ +document.addEventListener('DOMContentLoaded', function() { + + const class1 = document.getElementById("kc-content-wrapper"); + const class2 = document.getElementById("kc-form"); + const class3 = document.getElementById("kc-social-providers"); + + class1.insertBefore(class3, class2); + + // Move specific content from class3 to the beginning of class2 + const hrElement = class3.querySelector('hr'); + const h2Element = class3.querySelector('h2'); + + if (h2Element) { + class2.insertBefore(h2Element, class2.firstChild); + } + + if (hrElement) { + class2.insertBefore(hrElement, h2Element || class2.firstChild); + } + +}); + diff --git a/data/keycloak/themes/aiod/login/theme.properties b/data/keycloak/themes/aiod/login/theme.properties index 427586d2..e5bb685e 100644 --- a/data/keycloak/themes/aiod/login/theme.properties +++ b/data/keycloak/themes/aiod/login/theme.properties @@ -1,3 +1,4 @@ parent=keycloak import=common/keycloak styles=css/login.css css/styles.css +scripts=js/script.js From 5f6e8e38ef280250c285f7ed019821debe99ea67 Mon Sep 17 00:00:00 2001 From: mrorro Date: Mon, 8 Jul 2024 20:17:30 +0200 Subject: [PATCH 4/5] Add login template --- .env | 4 +- data/keycloak/themes/aiod/login/login.ftl | 123 +++++++++++++ .../aiod/login/resources/css/styles.css | 72 ++++---- .../themes/aiod/login/resources/js/script.js | 29 ++- data/keycloak/themes/aiod/login/template.ftl | 173 ++++++++++++++++++ .../themes/aiod/login/theme.properties | 2 + docker-compose.yaml | 2 +- 7 files changed, 351 insertions(+), 54 deletions(-) create mode 100755 data/keycloak/themes/aiod/login/login.ftl create mode 100644 data/keycloak/themes/aiod/login/template.ftl diff --git a/.env b/.env index 7b257f9d..217e7fdf 100644 --- a/.env +++ b/.env @@ -11,6 +11,8 @@ KEYCLOAK_CLIENT_SECRET="QJiOGn09eCEfnqAmcPP2l4vMU8grlmVQ" REDIRECT_URIS=http://${HOSTNAME}/docs/oauth2-redirect POST_LOGOUT_REDIRECT_URIS=http://${HOSTNAME}/aiod-auth/realms/aiod/protocol/openid-connect/logout +EGICHECKINALIAS= + #ELASTICSEARCH ES_USER=elastic ES_PASSWORD=changeme @@ -23,4 +25,4 @@ LS_JAVA_OPTS="-Xmx256m -Xms256m" #DATA STORAGE DATA_PATH=./data -BACKUP_PATH=./data/backups \ No newline at end of file +BACKUP_PATH=./data/backups diff --git a/data/keycloak/themes/aiod/login/login.ftl b/data/keycloak/themes/aiod/login/login.ftl new file mode 100755 index 00000000..94020948 --- /dev/null +++ b/data/keycloak/themes/aiod/login/login.ftl @@ -0,0 +1,123 @@ +<#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 social.providers??> +

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

+
+ <#else> +
+ + <#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?? && social.providers?has_content> +
+ +
+ + + + diff --git a/data/keycloak/themes/aiod/login/resources/css/styles.css b/data/keycloak/themes/aiod/login/resources/css/styles.css index ff7a267b..b8c45139 100644 --- a/data/keycloak/themes/aiod/login/resources/css/styles.css +++ b/data/keycloak/themes/aiod/login/resources/css/styles.css @@ -1,54 +1,61 @@ +body { + color: white; +} + login-pf { - background: none; + background: none; +} + +.form-group { + font-size: small; +} + +.btn-group-lg { + font-size: small; } .login-pf body { - background: #000613 none; + background: #000613 none; } #kc-header-wrapper { - font-size: 0px; - padding: 124px 10px 20px; - background: url("../img/logo.svg") no-repeat center; - background-size: contain; + font-size: 0px; + padding: 124px 10px 20px; + background: url("../img/logo.svg") no-repeat center; + background-size: contain; } .card-pf { - background: transparent; + background: transparent; } -.pf-c-button.pf-m-control { - color: white; - background-color: var(--pf-c-button--m-primary--BackgroundColor); +.kc-form-toggle { + color: white; + text-align: center; } -.kc-social-gray { - color: white; +.kc-form-toggle::after { + content: '▶︎'; + display: inline-block; + transform: rotate(0deg); + transition: transform 0.3s ease; } -#kc-social-providers h4 { - font-size: medium; +.kc-form-toggle.up::after { + transform: rotate(90deg); } -.pf-c-button::after { - border: transparent; +.kc-form-wrapper { + display: none; } h1#kc-page-title { - color: white; - font-size: large; + color: white; } -#kc-content { - color: white; - font-size: medium; - text-align: center; -} - -#social-oidc { +#social-egicheckin { display: inline-block; width: auto; - margin: 20px 20px 0px 0px; padding: 20px 30px 20px 80px; border: 2px solid #005faa; border-radius: 100vw; @@ -63,18 +70,11 @@ h1#kc-page-title { color: #fff; font-size: 18px; font-weight: 700; + --pf-c-button--after--BorderColor: transparent; } -#social-oidc:hover { +#social-egicheckin:hover { background-color: #fff; background-image: url(../img/egi-logo-color.svg); color: #005faa; -} - -#kc-form-wrapper { - display: none; -} - -#kc-form:hover #kc-form-wrapper { - display: block; -} +} \ No newline at end of file diff --git a/data/keycloak/themes/aiod/login/resources/js/script.js b/data/keycloak/themes/aiod/login/resources/js/script.js index 948e2979..e534b137 100644 --- a/data/keycloak/themes/aiod/login/resources/js/script.js +++ b/data/keycloak/themes/aiod/login/resources/js/script.js @@ -1,22 +1,19 @@ document.addEventListener('DOMContentLoaded', function() { + const toggleButton = document.getElementById('kc-form-toggle'); + const kcFormWrapper = document.getElementById('kc-form-wrapper'); - const class1 = document.getElementById("kc-content-wrapper"); - const class2 = document.getElementById("kc-form"); - const class3 = document.getElementById("kc-social-providers"); + function toggleVisibility() { + kcFormWrapper.style.display = kcFormWrapper.style.display === 'block' ? 'none' : 'block'; + toggleButton.classList.toggle('up'); + } - class1.insertBefore(class3, class2); - - // Move specific content from class3 to the beginning of class2 - const hrElement = class3.querySelector('hr'); - const h2Element = class3.querySelector('h2'); - - if (h2Element) { - class2.insertBefore(h2Element, class2.firstChild); - } - - if (hrElement) { - class2.insertBefore(hrElement, h2Element || class2.firstChild); - } + // Add event listener for the click event + toggleButton.addEventListener('click', toggleVisibility); + const inputError = document.getElementById('input-error'); + if (inputError) { + // Call the function once when the content loads if the specific ID is present + toggleVisibility(); + } }); diff --git a/data/keycloak/themes/aiod/login/template.ftl b/data/keycloak/themes/aiod/login/template.ftl new file mode 100644 index 00000000..84fd3e43 --- /dev/null +++ b/data/keycloak/themes/aiod/login/template.ftl @@ -0,0 +1,173 @@ +<#macro registrationLayout bodyClass="" displayInfo=false displayMessage=true displayRequiredFields=false> + + lang="${locale.currentLanguageTag}"> + + + + + + + <#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> + + + + + + + +
+
+
${kcSanitize(msg("loginTitleHtml",(realm.displayNameHtml!'')))?no_esc}
+
+
+
+ <#if realm.internationalizationEnabled && locale.supported?size gt 1> +
+
+ +
+
+ + <#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 "socialProviders"> + + <#nested "form"> + + <#if auth?has_content && auth.showTryAnotherWayLink()> +
+ +
+ + + + + <#if displayInfo> +
+
+ <#nested "info"> +
+
+ +
+
+ +
+
+ + + diff --git a/data/keycloak/themes/aiod/login/theme.properties b/data/keycloak/themes/aiod/login/theme.properties index e5bb685e..b766740f 100644 --- a/data/keycloak/themes/aiod/login/theme.properties +++ b/data/keycloak/themes/aiod/login/theme.properties @@ -2,3 +2,5 @@ parent=keycloak import=common/keycloak styles=css/login.css css/styles.css scripts=js/script.js + +egi_checkin_alias=${env.EGICHECKINALIAS} diff --git a/docker-compose.yaml b/docker-compose.yaml index 9445f61b..cbbf1319 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -147,7 +147,7 @@ services: - 8080:8080 volumes: - ${DATA_PATH}/keycloak/data:/opt/keycloak/data - - ${DATA_PATH}/keycloak/themes/aiod:/opt/keycloak/themes/aiod + - ${DATA_PATH}/keycloak/themes:/opt/keycloak/themes command: > start --hostname-url http://${HOSTNAME}/aiod-auth From 7960ea83624e5d30418a425b3679d2043c55c99a Mon Sep 17 00:00:00 2001 From: mrorro Date: Tue, 9 Jul 2024 09:46:28 +0200 Subject: [PATCH 5/5] Add error check --- data/keycloak/themes/aiod/login/resources/js/script.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/data/keycloak/themes/aiod/login/resources/js/script.js b/data/keycloak/themes/aiod/login/resources/js/script.js index e534b137..06923895 100644 --- a/data/keycloak/themes/aiod/login/resources/js/script.js +++ b/data/keycloak/themes/aiod/login/resources/js/script.js @@ -8,8 +8,9 @@ document.addEventListener('DOMContentLoaded', function() { } // Add event listener for the click event - toggleButton.addEventListener('click', toggleVisibility); - + if (toggleButton) { + toggleButton.addEventListener('click', toggleVisibility); + } const inputError = document.getElementById('input-error'); if (inputError) { // Call the function once when the content loads if the specific ID is present