From 4e41927c48e12458bcadcd98c30d5bd33864fd74 Mon Sep 17 00:00:00 2001 From: Nils Behlen <29949516+nilsbehlen@users.noreply.github.com> Date: Thu, 10 Aug 2023 14:08:38 +0200 Subject: [PATCH] Poll in browser message (#157) * small fixes * When doing poll-in-browser, set the message to both OTP+Push messages * Added helper function to js * Simplified some code * Upped keycloak dependency version for security fix * provide default if value is missing * Update privacyIDEA.ftl --- pom.xml | 10 +- .../org/privacyidea/authenticator/Const.java | 1 - .../PrivacyIDEAAuthenticator.java | 47 ++-- .../theme-resources/templates/privacyIDEA.ftl | 211 +++++++++--------- 4 files changed, 126 insertions(+), 143 deletions(-) diff --git a/pom.xml b/pom.xml index dba621c..bae026f 100644 --- a/pom.xml +++ b/pom.xml @@ -116,31 +116,31 @@ org.keycloak keycloak-core - 22.0.0 + 22.0.1 org.keycloak keycloak-server-spi - 22.0.0 + 22.0.1 org.keycloak keycloak-server-spi-private - 22.0.0 + 22.0.1 org.keycloak keycloak-services - 22.0.0 + 22.0.1 org.keycloak keycloak-common - 22.0.0 + 22.0.1 diff --git a/src/main/java/org/privacyidea/authenticator/Const.java b/src/main/java/org/privacyidea/authenticator/Const.java index 9097d6b..a03f299 100644 --- a/src/main/java/org/privacyidea/authenticator/Const.java +++ b/src/main/java/org/privacyidea/authenticator/Const.java @@ -49,7 +49,6 @@ private Const() static final String FORM_IMAGE_PUSH = "pushImage"; static final String FORM_IMAGE_OTP = "otpImage"; static final String FORM_IMAGE_WEBAUTHN = "webauthnImage"; - static final String FORM_POLL_IN_BROWSER = "pollInBrowser"; static final String FORM_POLL_IN_BROWSER_FAILED = "pollInBrowserFailed"; static final String FORM_ERROR_MESSAGE = "errorMsg"; static final String FORM_TRANSACTION_ID = "transactionID"; diff --git a/src/main/java/org/privacyidea/authenticator/PrivacyIDEAAuthenticator.java b/src/main/java/org/privacyidea/authenticator/PrivacyIDEAAuthenticator.java index 20d67f6..75b7be5 100644 --- a/src/main/java/org/privacyidea/authenticator/PrivacyIDEAAuthenticator.java +++ b/src/main/java/org/privacyidea/authenticator/PrivacyIDEAAuthenticator.java @@ -28,19 +28,18 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import org.jboss.logging.Logger; import org.keycloak.authentication.AuthenticationFlowContext; import org.keycloak.authentication.AuthenticationFlowError; import org.keycloak.authentication.AuthenticationFlowException; +import org.keycloak.common.Version; import org.keycloak.forms.login.LoginFormsProvider; import org.keycloak.models.GroupModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.UserModel; -import org.keycloak.common.Version; import org.privacyidea.Challenge; import org.privacyidea.IPILogger; import org.privacyidea.PIResponse; @@ -71,9 +70,7 @@ import static org.privacyidea.authenticator.Const.FORM_OTP_AVAILABLE; import static org.privacyidea.authenticator.Const.FORM_OTP_MESSAGE; import static org.privacyidea.authenticator.Const.FORM_PI_POLL_IN_BROWSER_URL; -import static org.privacyidea.authenticator.Const.FORM_PI_SERVER_URL; import static org.privacyidea.authenticator.Const.FORM_POLL_INTERVAL; -import static org.privacyidea.authenticator.Const.FORM_POLL_IN_BROWSER; import static org.privacyidea.authenticator.Const.FORM_POLL_IN_BROWSER_FAILED; import static org.privacyidea.authenticator.Const.FORM_PUSH_AVAILABLE; import static org.privacyidea.authenticator.Const.FORM_PUSH_MESSAGE; @@ -206,7 +203,6 @@ else if (!config.excludedGroups().isEmpty()) .setAttribute(FORM_IMAGE_PUSH, "") .setAttribute(FORM_IMAGE_OTP, "") .setAttribute(FORM_IMAGE_WEBAUTHN, "") - .setAttribute(FORM_POLL_IN_BROWSER, false) .setAttribute(FORM_POLL_IN_BROWSER_FAILED, false) .setAttribute(FORM_POLL_INTERVAL, config.pollingInterval().get(0)); @@ -465,7 +461,7 @@ private void extractChallengeDataToForm(PIResponse response, AuthenticationFlowC String webAuthnSignRequest = ""; String u2fSignRequest = ""; String mode = "otp"; - + String newOtpMessage = response.otpMessage(); if (response.transactionID != null && !response.transactionID.isEmpty()) { context.getAuthenticationSession().setAuthNote(AUTH_NOTE_TRANSACTION_ID, response.transactionID); @@ -493,14 +489,10 @@ else if ("interactive".equals(c.getClientMode())) if (config.pollInBrowser()) { context.form().setAttribute(FORM_TRANSACTION_ID, response.transactionID); - if (config.pollInBrowserUrl().isEmpty()) - { - context.form().setAttribute(FORM_PI_POLL_IN_BROWSER_URL, config.serverURL()); - } - else - { - context.form().setAttribute(FORM_PI_POLL_IN_BROWSER_URL, config.pollInBrowserUrl()); - } + newOtpMessage = response.otpMessage() + "\n" + response.pushMessage(); + context.form() + .setAttribute(FORM_PI_POLL_IN_BROWSER_URL, + config.pollInBrowserUrl().isEmpty() ? config.serverURL() : config.pollInBrowserUrl()); } // Check for Push @@ -528,36 +520,27 @@ else if ("interactive".equals(c.getClientMode())) // Check if response from server contains preferred client mode if (response.preferredClientMode != null && !response.preferredClientMode.isEmpty()) { - if (response.preferredClientMode.equals("push") && config.pollInBrowser()) - { - mode = "otp"; - } - else - { - mode = response.preferredClientMode; - } + mode = response.preferredClientMode; } else { - // Check if any triggered token matches the preferred token type + // Alternatively check if any triggered token matches the local preferred token type if (response.triggeredTokenTypes().contains(config.prefTokenType())) { - if (config.prefTokenType().equals("push") && config.pollInBrowser()) - { - mode = "otp"; - } - else - { - mode = config.prefTokenType(); - } + mode = config.prefTokenType(); } } + // Using poll in browser does not require push mode + if (mode.equals("push") && config.pollInBrowser()) + { + mode = "otp"; + } context.form() .setAttribute(FORM_MODE, mode) .setAttribute(FORM_WEBAUTHN_SIGN_REQUEST, webAuthnSignRequest) .setAttribute(FORM_U2F_SIGN_REQUEST, u2fSignRequest) - .setAttribute(FORM_OTP_MESSAGE, response.otpMessage()); + .setAttribute(FORM_OTP_MESSAGE, newOtpMessage); } /** diff --git a/src/main/resources/theme-resources/templates/privacyIDEA.ftl b/src/main/resources/theme-resources/templates/privacyIDEA.ftl index f7efd1a..fbeef87 100644 --- a/src/main/resources/theme-resources/templates/privacyIDEA.ftl +++ b/src/main/resources/theme-resources/templates/privacyIDEA.ftl @@ -5,7 +5,8 @@ <#elseif section = "header"> ${msg("loginTitleHtml",realm.name)} <#elseif section = "form"> - @@ -57,7 +58,8 @@ - + <#if transactionID?? && !(transactionID = "") && !(piPollInBrowserUrl = "") && (pollInBrowserFailed = false)> #if> <#if mode = "push"> - <#--The form will be reloaded if push token is enabled to check if it is confirmed. - The interval can be set in the configuration--> - + <#-- Polling for push by reloading every X seconds --> @@ -191,49 +219,38 @@ @@ -250,59 +267,46 @@ #if> - <#if !push_available && (u2fsignrequest = "") && (webauthnsignrequest = "")> + + <#if (!push_available || !(piPollInBrowserUrl! == "") && pollInBrowserFailed == false) && (u2fsignrequest == "") && (webauthnsignrequest == "")> @@ -338,10 +339,10 @@ <#if hasError!false> #if> @@ -350,4 +351,4 @@ #if> -@layout.registrationLayout> +@layout.registrationLayout> \ No newline at end of file