From dd0214bc78d9bed7596780c3db92fba598784be7 Mon Sep 17 00:00:00 2001 From: Alexander Schwartz Date: Tue, 20 Jan 2026 11:12:23 +0100 Subject: [PATCH] Do not use whitelist/blacklist in the UI Closes #45539 Signed-off-by: Alexander Schwartz --- .../fine-grain-v2.adoc | 2 +- .../admin/messages/messages_en.properties | 6 ++--- .../VerifyMessageProperties.java | 22 +++++++++++++++++++ .../VerifyMessagePropertiesTest.java | 6 +++++ .../resources/discouragedWord_en.properties | 17 ++++++++++++++ .../account/messages/messages_en.properties | 2 +- .../admin/messages/messages_en.properties | 2 +- .../login/messages/messages_en.properties | 2 +- 8 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 misc/theme-verifier/src/test/resources/discouragedWord_en.properties diff --git a/docs/documentation/server_admin/topics/admin-console-permissions/fine-grain-v2.adoc b/docs/documentation/server_admin/topics/admin-console-permissions/fine-grain-v2.adoc index 7ee0849b806..e16462776b6 100644 --- a/docs/documentation/server_admin/topics/admin-console-permissions/fine-grain-v2.adoc +++ b/docs/documentation/server_admin/topics/admin-console-permissions/fine-grain-v2.adoc @@ -421,7 +421,7 @@ Let's exlude the members of the group itself, so that `test-admins` cannot manag - Create a "Role Policy" allowing access to users assigned the `impersonation-admin` role. - Assign both policies to the permission. -===== Blacklisting specific users from being impersonated +===== Preventing specific users from being impersonated - Create a *User Permission* for the specific users you want to prevent from being impersonated. - Create any policy that evaluates to deny (such as a user policy with no users selected). diff --git a/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties b/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties index cdda458bf7b..d485f2f01a0 100644 --- a/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties +++ b/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties @@ -267,7 +267,7 @@ resourceAttributeHelp=The attributes associated with the resource. updateCredentialUserLabelSuccess=The user label has been changed successfully. product=Product credentialUserLabel=User Label -passwordPoliciesHelp.passwordBlacklist=Prevents the use of a password that is in a blacklist file. +passwordPoliciesHelp.passwordBlacklist=Prevents users to log in with a forbidden password that is listed in a file on the server. bindTypeHelp=Type of the authentication method used during LDAP bind operation. It is used in most of the requests sent to the LDAP server. Currently only 'none' (anonymous LDAP authentication) or 'simple' (bind credential + bind password authentication) mechanisms are available. whoWillAppearPopoverText=Groups are hierarchical. When you select Direct Membership, you see only the child group that the user joined. Ancestor groups are not included. eventTypes.VERIFY_EMAIL.description=Verify email @@ -1055,7 +1055,7 @@ userInfoSignedResponseAlgorithm=User info signed response algorithm selectGroup=Select group scopePermissions.groups.view-members-description=Policies that decide if an administrator can view the members of this group tableOfGroups=Table of groups -allowed-protocol-mappers.tooltip=Whitelist of allowed protocol mapper providers. If there is an attempt to register client, which contains some protocol mappers, which were not whitelisted, registration request will be rejected. +allowed-protocol-mappers.tooltip=List of allowed protocol mapper providers. If there is an attempt to register client, which contains some protocol mappers, which were not allowed, registration request will be rejected. policyProvider.role=Define conditions for your permissions where a set of one or more roles is permitted to access an object. targetOptions.brokerId=BROKER_ID eventTypes.VERIFY_PROFILE.name=Verify profile @@ -2595,7 +2595,7 @@ passwordPoliciesHelp.lowerCase=The number of lowercase letters required in the p searchForProvider=Search for provider ldapSearchingAndUpdatingSettingsDescription=This section contains options related to searching the LDAP server for the available users. sessionsType.regularSSO=Regular SSO -allowed-client-scopes.tooltip=Whitelist of the client scopes, which can be used on a newly registered client. Attempt to register client with some client scope, which is not whitelisted, will be rejected. By default, the whitelist is either empty or contains just realm default client scopes (based on 'Allow Default Scopes' configuration property) +allowed-client-scopes.tooltip=List of the allowed client scopes, which can be used on a newly registered client. Attempt to register client with some client scope, which is not allowed, will be rejected. By default, the list is either empty or contains just realm default client scopes (based on 'Allow Default Scopes' configuration property) maxDeltaTimeSecondsHelp=When will failure count be reset? executorsHelpItem=Executors help item contentSecurityPolicy=Content-Security-Policy diff --git a/misc/theme-verifier/src/main/java/org/keycloak/themeverifier/VerifyMessageProperties.java b/misc/theme-verifier/src/main/java/org/keycloak/themeverifier/VerifyMessageProperties.java index 0bc6989cd19..115fc8d29ff 100644 --- a/misc/theme-verifier/src/main/java/org/keycloak/themeverifier/VerifyMessageProperties.java +++ b/misc/theme-verifier/src/main/java/org/keycloak/themeverifier/VerifyMessageProperties.java @@ -52,6 +52,7 @@ public class VerifyMessageProperties { verifySafeHtml(); verifyNoHtmlEntities(); verifyProblematicBlanks(); + verifyNoDiscouragedWords(); if (validateMessageFormatQuotes) { verifyMessageFormatQuotes(); verifyMessageFormatPlaceholders(); @@ -81,6 +82,27 @@ public class VerifyMessageProperties { }); } + private final static Pattern DISCOURAGED_WORDS = Pattern.compile("(whitelist|blacklist)", Pattern.CASE_INSENSITIVE); + + private void verifyNoDiscouragedWords() { + PropertyResourceBundle bundle = getPropertyResourceBundle(); + + if (!file.getName().endsWith("_en.properties")) { + // Discouraged words only apply to English files. + return; + } + + bundle.getKeys().asIterator().forEachRemaining(key -> { + String value = bundle.getString(key); + + Matcher matcher = DISCOURAGED_WORDS.matcher(value); + if (matcher.find()) { + messages.add("Discouraged word found in '" + key + "' for file " + file + ": '" + matcher.group(0) + "' in '" + value + "'"); + } + + }); + } + private final static Pattern DOUBLE_SINGLE_QUOTES = Pattern.compile("''"); private void verifyNotMessageFormatQuotes() { diff --git a/misc/theme-verifier/src/test/java/org/keycloak/themeverifier/VerifyMessagePropertiesTest.java b/misc/theme-verifier/src/test/java/org/keycloak/themeverifier/VerifyMessagePropertiesTest.java index 29e4dc549a0..749fcedf2fa 100644 --- a/misc/theme-verifier/src/test/java/org/keycloak/themeverifier/VerifyMessagePropertiesTest.java +++ b/misc/theme-verifier/src/test/java/org/keycloak/themeverifier/VerifyMessagePropertiesTest.java @@ -39,6 +39,12 @@ class VerifyMessagePropertiesTest { MatcherAssert.assertThat(verify, Matchers.hasItem(Matchers.containsString("Illegal HTML"))); } + @Test + void verifyDiscouragedWordDetected() throws MojoExecutionException { + List verify = getFile("discouragedWord_en.properties").verify(); + MatcherAssert.assertThat(verify, Matchers.hasItem(Matchers.containsString("Discouraged word"))); + } + @Test void verifyNoHtmlAllowed() throws MojoExecutionException { List verify = getFile("noHtml_de.properties").verify(); diff --git a/misc/theme-verifier/src/test/resources/discouragedWord_en.properties b/misc/theme-verifier/src/test/resources/discouragedWord_en.properties new file mode 100644 index 00000000000..d15facf0f1e --- /dev/null +++ b/misc/theme-verifier/src/test/resources/discouragedWord_en.properties @@ -0,0 +1,17 @@ +# +# Copyright 2026 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. +# +key=This tests whitelist. \ No newline at end of file diff --git a/themes/src/main/resources/theme/base/account/messages/messages_en.properties b/themes/src/main/resources/theme/base/account/messages/messages_en.properties index 45b2db3020d..6421740ab50 100755 --- a/themes/src/main/resources/theme/base/account/messages/messages_en.properties +++ b/themes/src/main/resources/theme/base/account/messages/messages_en.properties @@ -235,7 +235,7 @@ invalidPasswordNotContainsUsernameMessage=Invalid password: Can not contain the 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. +invalidPasswordBlacklistedMessage=Invalid password: password is not allowed. invalidPasswordGenericMessage=Invalid password: new password doesn''t match password policies. # Authorization diff --git a/themes/src/main/resources/theme/base/admin/messages/messages_en.properties b/themes/src/main/resources/theme/base/admin/messages/messages_en.properties index df039d8fba0..b6d2c1c359d 100644 --- a/themes/src/main/resources/theme/base/admin/messages/messages_en.properties +++ b/themes/src/main/resources/theme/base/admin/messages/messages_en.properties @@ -9,7 +9,7 @@ invalidPasswordNotContainsUsernameMessage=Invalid password: Can not contain the 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. +invalidPasswordBlacklistedMessage=Invalid password: password is not allowed. invalidPasswordGenericMessage=Invalid password: new password does not match password policies. ldapErrorEditModeMandatory=Edit Mode is mandatory diff --git a/themes/src/main/resources/theme/base/login/messages/messages_en.properties b/themes/src/main/resources/theme/base/login/messages/messages_en.properties index d6ba240e192..c347d4e80c9 100644 --- a/themes/src/main/resources/theme/base/login/messages/messages_en.properties +++ b/themes/src/main/resources/theme/base/login/messages/messages_en.properties @@ -278,7 +278,7 @@ error-reset-otp-missing-id=Please choose an OTP configuration. error-non-ascii-local-part-email=Local part of the address must contain only ASCII characters. invalidPasswordExistingMessage=Invalid existing password. -invalidPasswordBlacklistedMessage=Invalid password: password is blacklisted. +invalidPasswordBlacklistedMessage=Invalid password: password is not allowed. invalidPasswordConfirmMessage=Password confirmation doesn''t match. invalidTotpMessage=Invalid authenticator code.