diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/GroupPolicyManagementTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/GroupPolicyManagementTest.java
index ea7d840b16..fc1cc33094 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/GroupPolicyManagementTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/GroupPolicyManagementTest.java
@@ -23,8 +23,6 @@ import static org.junit.Assert.fail;
import java.util.Arrays;
import java.util.Collections;
-import java.util.function.Function;
-import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.ws.rs.NotFoundException;
@@ -35,16 +33,12 @@ import org.keycloak.admin.client.resource.AuthorizationResource;
import org.keycloak.admin.client.resource.GroupPoliciesResource;
import org.keycloak.admin.client.resource.GroupPolicyResource;
import org.keycloak.admin.client.resource.PolicyResource;
-import org.keycloak.admin.client.resource.RolePoliciesResource;
-import org.keycloak.admin.client.resource.RolePolicyResource;
-import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.idm.GroupRepresentation;
-import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.authorization.DecisionStrategy;
import org.keycloak.representations.idm.authorization.GroupPolicyRepresentation;
import org.keycloak.representations.idm.authorization.Logic;
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
-import org.keycloak.representations.idm.authorization.RolePolicyRepresentation;
import org.keycloak.testsuite.util.GroupBuilder;
import org.keycloak.testsuite.util.RealmBuilder;
@@ -81,6 +75,21 @@ public class GroupPolicyManagementTest extends AbstractPolicyManagementTest {
assertCreated(authorization, representation);
}
+ @Test
+ public void testCreateWithoutGroupsClaim() {
+ AuthorizationResource authorization = getClient().authorization();
+ GroupPolicyRepresentation representation = new GroupPolicyRepresentation();
+
+ representation.setName(KeycloakModelUtils.generateId());
+ representation.setDescription("description");
+ representation.setDecisionStrategy(DecisionStrategy.CONSENSUS);
+ representation.setLogic(Logic.NEGATIVE);
+ representation.addGroupPath("/Group A/Group B/Group C", true);
+ representation.addGroupPath("Group F");
+
+ assertCreated(authorization, representation);
+ }
+
@Test
public void testUpdate() {
AuthorizationResource authorization = getClient().authorization();
@@ -100,6 +109,7 @@ public class GroupPolicyManagementTest extends AbstractPolicyManagementTest {
representation.setDescription("changed");
representation.setDecisionStrategy(DecisionStrategy.AFFIRMATIVE);
representation.setLogic(Logic.POSITIVE);
+ representation.setGroupsClaim(null);
representation.removeGroup("/Group A/Group B");
GroupPoliciesResource policies = authorization.policies().group();
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/GroupPolicyForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/GroupPolicyForm.java
index 3ca088e051..192388359b 100644
--- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/GroupPolicyForm.java
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/GroupPolicyForm.java
@@ -137,7 +137,10 @@ public class GroupPolicyForm extends Form {
representation.setName(getInputValue(name));
representation.setDescription(getInputValue(description));
- representation.setGroupsClaim(getInputValue(groupsClaim));
+
+ String groupsClaimValue = getInputValue(groupsClaim);
+
+ representation.setGroupsClaim(groupsClaim == null || "".equals(groupsClaimValue.trim()) ? null : groupsClaimValue);
representation.setLogic(Logic.valueOf(logic.getFirstSelectedOption().getText().toUpperCase()));
representation.setGroups(new HashSet<>());
diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/GroupPolicyManagementTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/GroupPolicyManagementTest.java
index 91c86f96d6..5b57dbbe3b 100644
--- a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/GroupPolicyManagementTest.java
+++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authorization/GroupPolicyManagementTest.java
@@ -57,6 +57,20 @@ public class GroupPolicyManagementTest extends AbstractAuthorizationSettingsTest
realmResource.groups().add(GroupBuilder.create().name("Group F").build());
}
+ @Test
+ public void testCreateWithoutGroupClaims() throws InterruptedException {
+ authorizationPage.navigateTo();
+ GroupPolicyRepresentation expected = new GroupPolicyRepresentation();
+
+ expected.setName("Test Group Policy");
+ expected.setDescription("description");
+ expected.addGroupPath("/Group A", true);
+ expected.addGroupPath("/Group A/Group B/Group D");
+ expected.addGroupPath("Group F");
+
+ createPolicy(expected);
+ }
+
@Test
public void testUpdate() throws InterruptedException {
authorizationPage.navigateTo();
@@ -76,6 +90,7 @@ public class GroupPolicyManagementTest extends AbstractAuthorizationSettingsTest
expected.setName("Changed Test Group Policy");
expected.setDescription("Changed description");
expected.setLogic(Logic.NEGATIVE);
+ expected.setGroupsClaim(null);
authorizationPage.navigateTo();
authorizationPage.authorizationTabs().policies().update(previousName, expected);
@@ -166,6 +181,7 @@ public class GroupPolicyManagementTest extends AbstractAuthorizationSettingsTest
assertEquals(expected.getName(), actual.getName());
assertEquals(expected.getDescription(), actual.getDescription());
assertEquals(expected.getLogic(), actual.getLogic());
+ assertEquals(expected.getGroupsClaim(), actual.getGroupsClaim());
assertNotNull(actual.getGroups());
assertEquals(expected.getGroups().size(), actual.getGroups().size());
diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
index a062db29e0..5dc7e7010a 100644
--- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
@@ -1340,7 +1340,7 @@ authz-add-aggregated-policy=Add Aggregated Policy
authz-add-group-policy=Add Group Policy
authz-no-groups-assigned=No groups assigned.
authz-policy-group-claim=Groups Claim
-authz-policy-group-claim.tooltip=A claim to use as the source for user's group. If the claim is present it must be an array of strings.
+authz-policy-group-claim.tooltip=If defined, the policy will fetch user's groups from the given claim within an access token or ID token representing the identity asking permissions. If not defined, user's groups are obtained from your realm configuration.
authz-policy-group-groups.tooltip=Specifies the groups allowed by this policy.
# Authz Permission List
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-group-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-group-detail.html
index 71cec334b5..cc1353b830 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-group-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-group-detail.html
@@ -50,9 +50,9 @@