keycloak-memoizeit

Details

diff --git a/common/src/main/java/org/keycloak/common/util/ObjectUtil.java b/common/src/main/java/org/keycloak/common/util/ObjectUtil.java
index d43d99c..2dd9bab 100644
--- a/common/src/main/java/org/keycloak/common/util/ObjectUtil.java
+++ b/common/src/main/java/org/keycloak/common/util/ObjectUtil.java
@@ -42,7 +42,38 @@ public class ObjectUtil {
         return str1.equals(str2);
     }
 
+
     public static String capitalize(String str) {
         return str.substring(0, 1).toUpperCase() + str.substring(1);
     }
+
+
+    /**
+     * Forked from apache-commons StringUtils
+     *
+     * <p>Checks if a CharSequence is whitespace, empty ("") or null.</p>
+     *
+     * <pre>
+     * ObjectUtil.isBlank(null)      = true
+     * ObjectUtil.isBlank("")        = true
+     * ObjectUtil.isBlank(" ")       = true
+     * ObjectUtil.isBlank("bob")     = false
+     * ObjectUtil.isBlank("  bob  ") = false
+     * </pre>
+     *
+     * @param cs
+     * @return {@code true} if the CharSequence is null, empty or whitespace
+     */
+    public static boolean isBlank(final CharSequence cs) {
+        int strLen;
+        if (cs == null || (strLen = cs.length()) == 0) {
+            return true;
+        }
+        for (int i = 0; i < strLen; i++) {
+            if (!Character.isWhitespace(cs.charAt(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
 }
diff --git a/server-spi/src/main/java/org/keycloak/models/ClientModel.java b/server-spi/src/main/java/org/keycloak/models/ClientModel.java
index ae6453a..43e740a 100755
--- a/server-spi/src/main/java/org/keycloak/models/ClientModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/ClientModel.java
@@ -20,6 +20,8 @@ package org.keycloak.models;
 import java.util.Map;
 import java.util.Set;
 
+import org.keycloak.common.util.ObjectUtil;
+
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
@@ -209,7 +211,7 @@ public interface ClientModel extends ClientScopeModel, RoleContainerModel,  Prot
     @Override
     default String getConsentScreenText() {
         String consentScreenText = ClientScopeModel.super.getConsentScreenText();
-        if (consentScreenText == null) {
+        if (ObjectUtil.isBlank(consentScreenText)) {
             consentScreenText = getClientId();
         }
         return consentScreenText;
diff --git a/server-spi/src/main/java/org/keycloak/models/ClientScopeModel.java b/server-spi/src/main/java/org/keycloak/models/ClientScopeModel.java
index c2c4c02..d40d0e0 100755
--- a/server-spi/src/main/java/org/keycloak/models/ClientScopeModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/ClientScopeModel.java
@@ -19,6 +19,8 @@ package org.keycloak.models;
 
 import java.util.Map;
 
+import org.keycloak.common.util.ObjectUtil;
+
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
@@ -63,7 +65,7 @@ public interface ClientScopeModel extends ProtocolMapperContainerModel, ScopeCon
     // Fallback to name if consentScreenText attribute is null
     default String getConsentScreenText() {
         String consentScreenText = getAttribute(CONSENT_SCREEN_TEXT);
-        if (consentScreenText == null) {
+        if (ObjectUtil.isBlank(consentScreenText)) {
             consentScreenText = getName();
         }
         return consentScreenText;
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCScopeTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCScopeTest.java
index 1c1a590..944f304 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCScopeTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCScopeTest.java
@@ -27,6 +27,7 @@ import org.jboss.shrinkwrap.api.spec.WebArchive;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.keycloak.OAuth2Constants;
 import org.keycloak.admin.client.resource.ClientResource;
 import org.keycloak.admin.client.resource.ClientScopeResource;
 import org.keycloak.common.util.MultivaluedHashMap;
@@ -35,6 +36,7 @@ import org.keycloak.events.EventType;
 import org.keycloak.models.ClientScopeModel;
 import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolFactory;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.representations.AddressClaimSet;
 import org.keycloak.representations.IDToken;
@@ -357,7 +359,40 @@ public class OIDCScopeTest extends AbstractOIDCScopeTest {
         assertPhone(idToken, false);
 
         // Revert
+        thirdPartyRep.getAttributes().put(ClientScopeModel.DISPLAY_ON_CONSENT_SCREEN, "false");
+        thirdParty.update(thirdPartyRep);
+    }
+
+
+    // KEYCLOAK-7855
+    @Test
+    public void testClientDisplayedOnConsentScreenWithEmptyConsentText() throws Exception {
+        // Add "displayOnConsentScreen" to client
+        ClientResource thirdParty = ApiUtil.findClientByClientId(testRealm(), "third-party");
+        ClientRepresentation thirdPartyRep = thirdParty.toRepresentation();
         thirdPartyRep.getAttributes().put(ClientScopeModel.DISPLAY_ON_CONSENT_SCREEN, "true");
+        thirdPartyRep.getAttributes().put(ClientScopeModel.CONSENT_SCREEN_TEXT, "");
+        thirdParty.update(thirdPartyRep);
+
+        // Change consent text on profile scope
+        ClientScopeResource profileScope = ApiUtil.findClientScopeByName(testRealm(), OAuth2Constants.SCOPE_PROFILE);
+        ClientScopeRepresentation profileScopeRep = profileScope.toRepresentation();
+        profileScopeRep.getAttributes().put(ClientScopeModel.CONSENT_SCREEN_TEXT, " ");
+        profileScope.update(profileScopeRep);
+
+        // Login. ConsentTexts are empty for the client and for the "profile" scope, so it should fallback to name/clientId
+        oauth.clientId("third-party");
+        oauth.doLoginGrant("john", "password");
+
+        grantPage.assertCurrent();
+        grantPage.assertGrants("profile", OAuthGrantPage.EMAIL_CONSENT_TEXT, OAuthGrantPage.ROLES_CONSENT_TEXT, "third-party");
+        grantPage.accept();
+
+        // Revert
+        profileScopeRep.getAttributes().put(ClientScopeModel.CONSENT_SCREEN_TEXT, OIDCLoginProtocolFactory.PROFILE_SCOPE_CONSENT_TEXT);
+        profileScope.update(profileScopeRep);
+
+        thirdPartyRep.getAttributes().put(ClientScopeModel.DISPLAY_ON_CONSENT_SCREEN, "false");
         thirdParty.update(thirdPartyRep);
     }