KEYCLOAK-14199 Client Policy - Executor : Enforce more secure client authentication method when client registration

This commit is contained in:
Takashi Norimatsu 2020-10-16 10:41:28 +09:00 committed by Marek Posolda
parent 7522d5ac74
commit 6dc136dfc0
5 changed files with 28 additions and 30 deletions

View file

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.keycloak.testsuite.services.clientpolicy.executor; package org.keycloak.services.clientpolicy.executor;
import java.util.List; import java.util.List;
@ -25,13 +25,12 @@ import org.keycloak.component.ComponentModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.services.clientpolicy.ClientPolicyException; import org.keycloak.services.clientpolicy.ClientPolicyException;
import org.keycloak.services.clientpolicy.executor.AbstractAugumentingClientRegistrationPolicyExecutor;
public class TestClientAuthenticationExecutor extends AbstractAugumentingClientRegistrationPolicyExecutor { public class SecureClientAuthEnforceExecutor extends AbstractAugumentingClientRegistrationPolicyExecutor {
private static final Logger logger = Logger.getLogger(TestClientAuthenticationExecutor.class); private static final Logger logger = Logger.getLogger(SecureClientAuthEnforceExecutor.class);
public TestClientAuthenticationExecutor(KeycloakSession session, ComponentModel componentModel) { public SecureClientAuthEnforceExecutor(KeycloakSession session, ComponentModel componentModel) {
super(session, componentModel); super(session, componentModel);
} }
@ -45,11 +44,11 @@ public class TestClientAuthenticationExecutor extends AbstractAugumentingClientR
} }
private String enforcedClientAuthenticatorType() { private String enforcedClientAuthenticatorType() {
return componentModel.getConfig().getFirst(TestClientAuthenticationExecutorFactory.CLIENT_AUTHNS_AUGMENT); return componentModel.getConfig().getFirst(SecureClientAuthEnforceExecutorFactory.CLIENT_AUTHNS_AUGMENT);
} }
private void verifyClientAuthenticationMethod(String clientAuthenticatorType) throws ClientPolicyException { private void verifyClientAuthenticationMethod(String clientAuthenticatorType) throws ClientPolicyException {
List<String> acceptableClientAuthn = componentModel.getConfig().getList(TestClientAuthenticationExecutorFactory.CLIENT_AUTHNS); List<String> acceptableClientAuthn = componentModel.getConfig().getList(SecureClientAuthEnforceExecutorFactory.CLIENT_AUTHNS);
if (acceptableClientAuthn != null && acceptableClientAuthn.stream().anyMatch(i->i.equals(clientAuthenticatorType))) return; if (acceptableClientAuthn != null && acceptableClientAuthn.stream().anyMatch(i->i.equals(clientAuthenticatorType))) return;
throw new ClientPolicyException(OAuthErrorException.INVALID_CLIENT_METADATA, "Invalid client metadata: token_endpoint_auth_method"); throw new ClientPolicyException(OAuthErrorException.INVALID_CLIENT_METADATA, "Invalid client metadata: token_endpoint_auth_method");
} }

View file

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.keycloak.testsuite.services.clientpolicy.executor; package org.keycloak.services.clientpolicy.executor;
import java.util.List; import java.util.List;
@ -25,12 +25,11 @@ import org.keycloak.component.ComponentModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.provider.ProviderConfigProperty; import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.services.clientpolicy.executor.AbstractAugumentingClientRegistrationPolicyExecutorFactory;
import org.keycloak.services.clientpolicy.executor.ClientPolicyExecutorProvider; import org.keycloak.services.clientpolicy.executor.ClientPolicyExecutorProvider;
public class TestClientAuthenticationExecutorFactory extends AbstractAugumentingClientRegistrationPolicyExecutorFactory { public class SecureClientAuthEnforceExecutorFactory extends AbstractAugumentingClientRegistrationPolicyExecutorFactory {
public static final String PROVIDER_ID = "test-client-authn-executor"; public static final String PROVIDER_ID = "secure-client-authn-executor";
public static final String CLIENT_AUTHNS = "client-authns"; public static final String CLIENT_AUTHNS = "client-authns";
public static final String CLIENT_AUTHNS_AUGMENT = "client-authns-augment"; public static final String CLIENT_AUTHNS_AUGMENT = "client-authns-augment";
@ -42,7 +41,7 @@ public class TestClientAuthenticationExecutorFactory extends AbstractAugumenting
@Override @Override
public ClientPolicyExecutorProvider create(KeycloakSession session, ComponentModel model) { public ClientPolicyExecutorProvider create(KeycloakSession session, ComponentModel model) {
return new TestClientAuthenticationExecutor(session, model); return new SecureClientAuthEnforceExecutor(session, model);
} }
@Override @Override
@ -64,7 +63,7 @@ public class TestClientAuthenticationExecutorFactory extends AbstractAugumenting
@Override @Override
public String getHelpText() { public String getHelpText() {
return null; return "It makes the client enforce registering/updating secure client authentication.";
} }
@Override @Override

View file

@ -1,2 +1,3 @@
org.keycloak.services.clientpolicy.executor.SecureResponseTypeExecutorFactory org.keycloak.services.clientpolicy.executor.SecureResponseTypeExecutorFactory
org.keycloak.services.clientpolicy.executor.SecureRequestObjectExecutorFactory org.keycloak.services.clientpolicy.executor.SecureRequestObjectExecutorFactory
org.keycloak.services.clientpolicy.executor.SecureClientAuthEnforceExecutorFactory

View file

@ -1,2 +1 @@
org.keycloak.testsuite.services.clientpolicy.executor.TestPKCEEnforceExecutorFactory org.keycloak.testsuite.services.clientpolicy.executor.TestPKCEEnforceExecutorFactory
org.keycloak.testsuite.services.clientpolicy.executor.TestClientAuthenticationExecutorFactory

View file

@ -82,6 +82,7 @@ import org.keycloak.services.clientpolicy.condition.ClientPolicyConditionProvide
import org.keycloak.services.clientpolicy.condition.ClientUpdateContextConditionFactory; import org.keycloak.services.clientpolicy.condition.ClientUpdateContextConditionFactory;
import org.keycloak.services.clientpolicy.condition.ClientRolesConditionFactory; import org.keycloak.services.clientpolicy.condition.ClientRolesConditionFactory;
import org.keycloak.services.clientpolicy.executor.ClientPolicyExecutorProvider; import org.keycloak.services.clientpolicy.executor.ClientPolicyExecutorProvider;
import org.keycloak.services.clientpolicy.executor.SecureClientAuthEnforceExecutorFactory;
import org.keycloak.services.clientpolicy.executor.SecureRequestObjectExecutor; import org.keycloak.services.clientpolicy.executor.SecureRequestObjectExecutor;
import org.keycloak.services.clientpolicy.executor.SecureRequestObjectExecutorFactory; import org.keycloak.services.clientpolicy.executor.SecureRequestObjectExecutorFactory;
import org.keycloak.services.clientpolicy.executor.SecureResponseTypeExecutorFactory; import org.keycloak.services.clientpolicy.executor.SecureResponseTypeExecutorFactory;
@ -93,7 +94,6 @@ import org.keycloak.testsuite.client.resources.TestApplicationResourceUrls;
import org.keycloak.testsuite.client.resources.TestOIDCEndpointsApplicationResource; import org.keycloak.testsuite.client.resources.TestOIDCEndpointsApplicationResource;
import org.keycloak.testsuite.rest.resource.TestingOIDCEndpointsApplicationResource.AuthorizationEndpointRequestObject; import org.keycloak.testsuite.rest.resource.TestingOIDCEndpointsApplicationResource.AuthorizationEndpointRequestObject;
import org.keycloak.testsuite.services.clientpolicy.condition.TestRaiseExeptionConditionFactory; import org.keycloak.testsuite.services.clientpolicy.condition.TestRaiseExeptionConditionFactory;
import org.keycloak.testsuite.services.clientpolicy.executor.TestClientAuthenticationExecutorFactory;
import org.keycloak.testsuite.services.clientpolicy.executor.TestPKCEEnforceExecutorFactory; import org.keycloak.testsuite.services.clientpolicy.executor.TestPKCEEnforceExecutorFactory;
import org.keycloak.testsuite.util.OAuthClient; import org.keycloak.testsuite.util.OAuthClient;
@ -258,7 +258,7 @@ public class ClientPolicyBasicsTest extends AbstractKeycloakTest {
public void testAdminClientAugmentedAuthType() throws ClientPolicyException { public void testAdminClientAugmentedAuthType() throws ClientPolicyException {
setupPolicyAcceptableAuthType("MyPolicy"); setupPolicyAcceptableAuthType("MyPolicy");
updateExecutor("TestClientAuthenticationExecutor", (ComponentRepresentation provider) -> { updateExecutor("SecureClientAuthEnforceExecutor", (ComponentRepresentation provider) -> {
setExecutorAugmentActivate(provider); setExecutorAugmentActivate(provider);
setExecutorAugmentedClientAuthMethod(provider, X509ClientAuthenticator.PROVIDER_ID); setExecutorAugmentedClientAuthMethod(provider, X509ClientAuthenticator.PROVIDER_ID);
}); });
@ -270,7 +270,7 @@ public class ClientPolicyBasicsTest extends AbstractKeycloakTest {
try { try {
assertEquals(X509ClientAuthenticator.PROVIDER_ID, getClientByAdmin(clientId).getClientAuthenticatorType()); assertEquals(X509ClientAuthenticator.PROVIDER_ID, getClientByAdmin(clientId).getClientAuthenticatorType());
updateExecutor("TestClientAuthenticationExecutor", (ComponentRepresentation provider) -> { updateExecutor("SecureClientAuthEnforceExecutor", (ComponentRepresentation provider) -> {
setExecutorAugmentedClientAuthMethod(provider, JWTClientAuthenticator.PROVIDER_ID); setExecutorAugmentedClientAuthMethod(provider, JWTClientAuthenticator.PROVIDER_ID);
}); });
@ -529,13 +529,13 @@ public class ClientPolicyBasicsTest extends AbstractKeycloakTest {
registerCondition(CLIENTUPDATECONTEXT_CONDITION_ALPHA_NAME, policyAlphaName); registerCondition(CLIENTUPDATECONTEXT_CONDITION_ALPHA_NAME, policyAlphaName);
logger.info("... Registered Condition : " + CLIENTUPDATECONTEXT_CONDITION_ALPHA_NAME); logger.info("... Registered Condition : " + CLIENTUPDATECONTEXT_CONDITION_ALPHA_NAME);
createExecutor("TestClientAuthenticationExecutor-alpha", TestClientAuthenticationExecutorFactory.PROVIDER_ID, null, (ComponentRepresentation provider) -> { createExecutor("SecureClientAuthEnforceExecutor-alpha", SecureClientAuthEnforceExecutorFactory.PROVIDER_ID, null, (ComponentRepresentation provider) -> {
setExecutorAcceptedClientAuthMethods(provider, new ArrayList<>(Arrays.asList(ClientIdAndSecretAuthenticator.PROVIDER_ID))); setExecutorAcceptedClientAuthMethods(provider, new ArrayList<>(Arrays.asList(ClientIdAndSecretAuthenticator.PROVIDER_ID)));
setExecutorAugmentActivate(provider); setExecutorAugmentActivate(provider);
setExecutorAugmentedClientAuthMethod(provider, ClientIdAndSecretAuthenticator.PROVIDER_ID); setExecutorAugmentedClientAuthMethod(provider, ClientIdAndSecretAuthenticator.PROVIDER_ID);
}); });
registerExecutor("TestClientAuthenticationExecutor-alpha", policyAlphaName); registerExecutor("SecureClientAuthEnforceExecutor-alpha", policyAlphaName);
logger.info("... Registered Executor : TestClientAuthenticationExecutor-alpha"); logger.info("... Registered Executor : SecureClientAuthEnforceExecutor-alpha");
String policyBetaName = "MyPolicy-beta"; String policyBetaName = "MyPolicy-beta";
createPolicy(policyBetaName, DefaultClientPolicyProviderFactory.PROVIDER_ID, null, null, null); createPolicy(policyBetaName, DefaultClientPolicyProviderFactory.PROVIDER_ID, null, null, null);
@ -836,12 +836,12 @@ public class ClientPolicyBasicsTest extends AbstractKeycloakTest {
registerCondition(CLIENTUPDATECONTEXT_CONDITION_NAME, policyName); registerCondition(CLIENTUPDATECONTEXT_CONDITION_NAME, policyName);
logger.info("... Registered Condition : " + CLIENTUPDATECONTEXT_CONDITION_NAME); logger.info("... Registered Condition : " + CLIENTUPDATECONTEXT_CONDITION_NAME);
createExecutor("TestClientAuthenticationExecutor", TestClientAuthenticationExecutorFactory.PROVIDER_ID, null, (ComponentRepresentation provider) -> { createExecutor("SecureClientAuthEnforceExecutor", SecureClientAuthEnforceExecutorFactory.PROVIDER_ID, null, (ComponentRepresentation provider) -> {
setExecutorAcceptedClientAuthMethods(provider, new ArrayList<>(Arrays.asList( setExecutorAcceptedClientAuthMethods(provider, new ArrayList<>(Arrays.asList(
JWTClientAuthenticator.PROVIDER_ID, JWTClientSecretAuthenticator.PROVIDER_ID, X509ClientAuthenticator.PROVIDER_ID))); JWTClientAuthenticator.PROVIDER_ID, JWTClientSecretAuthenticator.PROVIDER_ID, X509ClientAuthenticator.PROVIDER_ID)));
}); });
registerExecutor("TestClientAuthenticationExecutor", policyName); registerExecutor("SecureClientAuthEnforceExecutor", policyName);
logger.info("... Registered Executor : TestClientAuthenticationExecutor"); logger.info("... Registered Executor : SecureClientAuthEnforceExecutor");
} }
@ -864,13 +864,13 @@ public class ClientPolicyBasicsTest extends AbstractKeycloakTest {
registerCondition(CLIENTROLES_CONDITION_NAME, policyName); registerCondition(CLIENTROLES_CONDITION_NAME, policyName);
logger.info("... Registered Condition : " + CLIENTROLES_CONDITION_NAME); logger.info("... Registered Condition : " + CLIENTROLES_CONDITION_NAME);
createExecutor("TestClientAuthenticationExecutor", TestClientAuthenticationExecutorFactory.PROVIDER_ID, null, (ComponentRepresentation provider) -> { createExecutor("SecureClientAuthEnforceExecutor", SecureClientAuthEnforceExecutorFactory.PROVIDER_ID, null, (ComponentRepresentation provider) -> {
setExecutorAcceptedClientAuthMethods(provider, new ArrayList<>(Arrays.asList(ClientIdAndSecretAuthenticator.PROVIDER_ID, JWTClientAuthenticator.PROVIDER_ID))); setExecutorAcceptedClientAuthMethods(provider, new ArrayList<>(Arrays.asList(ClientIdAndSecretAuthenticator.PROVIDER_ID, JWTClientAuthenticator.PROVIDER_ID)));
setExecutorAugmentedClientAuthMethod(provider, ClientIdAndSecretAuthenticator.PROVIDER_ID); setExecutorAugmentedClientAuthMethod(provider, ClientIdAndSecretAuthenticator.PROVIDER_ID);
setExecutorAugmentActivate(provider); setExecutorAugmentActivate(provider);
}); });
registerExecutor("TestClientAuthenticationExecutor", policyName); registerExecutor("SecureClientAuthEnforceExecutor", policyName);
logger.info("... Registered Executor : TestClientAuthenticationExecutor"); logger.info("... Registered Executor : SecureClientAuthEnforceExecutor");
createExecutor("TestPKCEEnforceExecutor", TestPKCEEnforceExecutorFactory.PROVIDER_ID, null, (ComponentRepresentation provider) -> { createExecutor("TestPKCEEnforceExecutor", TestPKCEEnforceExecutorFactory.PROVIDER_ID, null, (ComponentRepresentation provider) -> {
setExecutorAugmentActivate(provider); setExecutorAugmentActivate(provider);
@ -1149,11 +1149,11 @@ public class ClientPolicyBasicsTest extends AbstractKeycloakTest {
} }
private void setExecutorAcceptedClientAuthMethods(ComponentRepresentation provider, List<String> acceptedClientAuthMethods) { private void setExecutorAcceptedClientAuthMethods(ComponentRepresentation provider, List<String> acceptedClientAuthMethods) {
provider.getConfig().put(TestClientAuthenticationExecutorFactory.CLIENT_AUTHNS, acceptedClientAuthMethods); provider.getConfig().put(SecureClientAuthEnforceExecutorFactory.CLIENT_AUTHNS, acceptedClientAuthMethods);
} }
private void setExecutorAugmentedClientAuthMethod(ComponentRepresentation provider, String augmentedClientAuthMethod) { private void setExecutorAugmentedClientAuthMethod(ComponentRepresentation provider, String augmentedClientAuthMethod) {
provider.getConfig().putSingle(TestClientAuthenticationExecutorFactory.CLIENT_AUTHNS_AUGMENT, augmentedClientAuthMethod); provider.getConfig().putSingle(SecureClientAuthEnforceExecutorFactory.CLIENT_AUTHNS_AUGMENT, augmentedClientAuthMethod);
} }
} }