diff --git a/services/src/main/java/org/keycloak/services/clientpolicy/executor/RejectRequestExecutor.java b/services/src/main/java/org/keycloak/services/clientpolicy/executor/RejectRequestExecutor.java
new file mode 100644
index 0000000000..f80337b261
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/clientpolicy/executor/RejectRequestExecutor.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2022 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.
+ */
+
+package org.keycloak.services.clientpolicy.executor;
+
+import org.keycloak.OAuthErrorException;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.representations.idm.ClientPolicyExecutorConfigurationRepresentation;
+import org.keycloak.services.clientpolicy.ClientPolicyContext;
+import org.keycloak.services.clientpolicy.ClientPolicyException;
+
+/**
+ * @author Takashi Norimatsu
+ */
+public class RejectRequestExecutor implements ClientPolicyExecutorProvider {
+
+ public RejectRequestExecutor(KeycloakSession session) {
+ }
+
+ @Override
+ public String getProviderId() {
+ return RejectRequestExecutorFactory.PROVIDER_ID;
+ }
+
+ @Override
+ public void executeOnEvent(ClientPolicyContext context) throws ClientPolicyException {
+ throw new ClientPolicyException(OAuthErrorException.INVALID_REQUEST, "request not allowed");
+ }
+}
diff --git a/services/src/main/java/org/keycloak/services/clientpolicy/executor/RejectRequestExecutorFactory.java b/services/src/main/java/org/keycloak/services/clientpolicy/executor/RejectRequestExecutorFactory.java
new file mode 100644
index 0000000000..0f069c2c14
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/clientpolicy/executor/RejectRequestExecutorFactory.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2022 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.
+ */
+
+package org.keycloak.services.clientpolicy.executor;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.keycloak.Config.Scope;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.provider.ProviderConfigProperty;
+
+/**
+ * @author Takashi Norimatsu
+ */
+public class RejectRequestExecutorFactory implements ClientPolicyExecutorProviderFactory {
+
+ public static final String PROVIDER_ID = "reject-request";
+
+ @Override
+ public ClientPolicyExecutorProvider create(KeycloakSession session) {
+ return new RejectRequestExecutor(session);
+ }
+
+ @Override
+ public void init(Scope config) {
+ }
+
+ @Override
+ public void postInit(KeycloakSessionFactory factory) {
+ }
+
+ @Override
+ public void close() {
+ }
+
+ @Override
+ public String getId() {
+ return PROVIDER_ID;
+ }
+
+ @Override
+ public String getHelpText() {
+ return "It rejects all requests from clients.";
+ }
+
+ @Override
+ public List getConfigProperties() {
+ return Collections.emptyList();
+ }
+}
diff --git a/services/src/main/resources/META-INF/services/org.keycloak.services.clientpolicy.executor.ClientPolicyExecutorProviderFactory b/services/src/main/resources/META-INF/services/org.keycloak.services.clientpolicy.executor.ClientPolicyExecutorProviderFactory
index 43d03ba9c6..4e39c85116 100644
--- a/services/src/main/resources/META-INF/services/org.keycloak.services.clientpolicy.executor.ClientPolicyExecutorProviderFactory
+++ b/services/src/main/resources/META-INF/services/org.keycloak.services.clientpolicy.executor.ClientPolicyExecutorProviderFactory
@@ -15,4 +15,5 @@ org.keycloak.protocol.oidc.grants.ciba.clientpolicy.executor.SecureCibaSignedAut
org.keycloak.protocol.oidc.grants.ciba.clientpolicy.executor.SecureCibaAuthenticationRequestSigningAlgorithmExecutorFactory
org.keycloak.services.clientpolicy.executor.SecureLogoutExecutorFactory
org.keycloak.services.clientpolicy.executor.RejectResourceOwnerPasswordCredentialsGrantExecutorFactory
-org.keycloak.services.clientpolicy.executor.ClientSecretRotationExecutorFactory
\ No newline at end of file
+org.keycloak.services.clientpolicy.executor.ClientSecretRotationExecutorFactory
+org.keycloak.services.clientpolicy.executor.RejectRequestExecutorFactory
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/AbstractClientPoliciesTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/AbstractClientPoliciesTest.java
index d59fabee79..c7fb6677e2 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/AbstractClientPoliciesTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/AbstractClientPoliciesTest.java
@@ -181,6 +181,7 @@ public abstract class AbstractClientPoliciesTest extends AbstractKeycloakTest {
protected static final String ERR_MSG_MISSING_NONCE = "Missing parameter: nonce";
protected static final String ERR_MSG_MISSING_STATE = "Missing parameter: state";
protected static final String ERR_MSG_CLIENT_REG_FAIL = "Failed to send request";
+ protected static final String ERR_MSG_REQ_NOT_ALLOWED = "request not allowed";
protected ClientRegistration reg;
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/ClientPoliciesTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/ClientPoliciesTest.java
index fdc8df1377..d05b7702bc 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/ClientPoliciesTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/ClientPoliciesTest.java
@@ -79,6 +79,7 @@ import org.keycloak.services.clientpolicy.executor.ConsentRequiredExecutorFactor
import org.keycloak.services.clientpolicy.executor.FullScopeDisabledExecutorFactory;
import org.keycloak.services.clientpolicy.executor.HolderOfKeyEnforcerExecutorFactory;
import org.keycloak.services.clientpolicy.executor.PKCEEnforcerExecutorFactory;
+import org.keycloak.services.clientpolicy.executor.RejectRequestExecutorFactory;
import org.keycloak.services.clientpolicy.executor.RejectResourceOwnerPasswordCredentialsGrantExecutorFactory;
import org.keycloak.services.clientpolicy.executor.SecureClientAuthenticatorExecutorFactory;
import org.keycloak.services.clientpolicy.executor.SecureClientUrisExecutorFactory;
@@ -2738,6 +2739,43 @@ public class ClientPoliciesTest extends AbstractClientPoliciesTest {
}
+ @Test
+ public void testRejectRequestExecutor() throws Exception {
+ // register profiles
+ String json = (new ClientProfilesBuilder()).addProfile(
+ (new ClientProfileBuilder()).createProfile(PROFILE_NAME, "Le Premier Profil")
+ .addExecutor(RejectRequestExecutorFactory.PROVIDER_ID, null)
+ .toRepresentation()
+ ).toString();
+ updateProfiles(json);
+
+ String clientBetaId = generateSuffixedName("Beta-App");
+ createClientByAdmin(clientBetaId, (ClientRepresentation clientRep) -> {
+ clientRep.setSecret("secretBeta");
+ });
+
+ // register policies
+ json = (new ClientPoliciesBuilder()).addPolicy(
+ (new ClientPolicyBuilder()).createPolicy(POLICY_NAME, "La Premiere Politique", Boolean.TRUE)
+ .addCondition(AnyClientConditionFactory.PROVIDER_ID,
+ createAnyClientConditionConfig())
+ .addProfile(PROFILE_NAME)
+ .toRepresentation()
+ ).toString();
+ updatePolicies(json);
+
+ try {
+ oauth.clientId(clientBetaId);
+ oauth.openLoginForm();
+ assertEquals(OAuthErrorException.INVALID_REQUEST, oauth.getCurrentQuery().get(OAuth2Constants.ERROR));
+ assertEquals(ERR_MSG_REQ_NOT_ALLOWED, oauth.getCurrentQuery().get(OAuth2Constants.ERROR_DESCRIPTION));
+ revertToBuiltinProfiles();
+ successfulLoginAndLogout(clientBetaId, "secretBeta");
+ } catch (Exception e) {
+ fail();
+ }
+ }
+
private void openVerificationPage(String verificationUri) {
driver.navigate().to(verificationUri);
}