KEYCLOAK-17929 SecureSigningAlgorithmForSignedJwtEnforceExecutor polishing for FAPI
This commit is contained in:
parent
b78d151a23
commit
0a4fdc64f3
4 changed files with 54 additions and 8 deletions
|
@ -17,6 +17,9 @@
|
||||||
|
|
||||||
package org.keycloak.services.clientpolicy.executor;
|
package org.keycloak.services.clientpolicy.executor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.jboss.resteasy.spi.HttpRequest;
|
||||||
import org.keycloak.OAuth2Constants;
|
import org.keycloak.OAuth2Constants;
|
||||||
|
@ -27,22 +30,51 @@ import org.keycloak.jose.jws.JWSInputException;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.services.clientpolicy.ClientPolicyContext;
|
import org.keycloak.services.clientpolicy.ClientPolicyContext;
|
||||||
import org.keycloak.services.clientpolicy.ClientPolicyException;
|
import org.keycloak.services.clientpolicy.ClientPolicyException;
|
||||||
|
import org.keycloak.services.clientpolicy.executor.SecureClientAuthEnforceExecutor.Configuration;
|
||||||
|
|
||||||
public class SecureSigningAlgorithmForSignedJwtEnforceExecutor implements ClientPolicyExecutorProvider<ClientPolicyExecutorConfiguration> {
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
public class SecureSigningAlgorithmForSignedJwtEnforceExecutor implements ClientPolicyExecutorProvider<SecureSigningAlgorithmForSignedJwtEnforceExecutor.Configuration> {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(SecureSigningAlgorithmForSignedJwtEnforceExecutor.class);
|
private static final Logger logger = Logger.getLogger(SecureSigningAlgorithmForSignedJwtEnforceExecutor.class);
|
||||||
|
|
||||||
private final KeycloakSession session;
|
private final KeycloakSession session;
|
||||||
|
private Configuration configuration;
|
||||||
|
|
||||||
public SecureSigningAlgorithmForSignedJwtEnforceExecutor(KeycloakSession session) {
|
public SecureSigningAlgorithmForSignedJwtEnforceExecutor(KeycloakSession session) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setupConfiguration(SecureSigningAlgorithmForSignedJwtEnforceExecutor.Configuration config) {
|
||||||
|
this.configuration = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<Configuration> getExecutorConfigurationClass() {
|
||||||
|
return Configuration.class;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getProviderId() {
|
public String getProviderId() {
|
||||||
return SecureSigningAlgorithmForSignedJwtEnforceExecutorFactory.PROVIDER_ID;
|
return SecureSigningAlgorithmForSignedJwtEnforceExecutorFactory.PROVIDER_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public static class Configuration extends ClientPolicyExecutorConfiguration {
|
||||||
|
@JsonProperty("require-client-assertion")
|
||||||
|
protected Boolean requireClientAssertion;
|
||||||
|
|
||||||
|
public Boolean isRequireClientAssertion() {
|
||||||
|
return requireClientAssertion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequireClientAssertion(Boolean augment) {
|
||||||
|
this.requireClientAssertion = augment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void executeOnEvent(ClientPolicyContext context) throws ClientPolicyException {
|
public void executeOnEvent(ClientPolicyContext context) throws ClientPolicyException {
|
||||||
switch (context.getEvent()) {
|
switch (context.getEvent()) {
|
||||||
|
@ -51,6 +83,8 @@ public class SecureSigningAlgorithmForSignedJwtEnforceExecutor implements Client
|
||||||
case TOKEN_REVOKE:
|
case TOKEN_REVOKE:
|
||||||
case TOKEN_INTROSPECT:
|
case TOKEN_INTROSPECT:
|
||||||
case LOGOUT_REQUEST:
|
case LOGOUT_REQUEST:
|
||||||
|
boolean isRequireClientAssertion = Optional.ofNullable(configuration.isRequireClientAssertion()).orElse(Boolean.FALSE).booleanValue();
|
||||||
|
if (!isRequireClientAssertion) break;
|
||||||
HttpRequest req = session.getContext().getContextObject(HttpRequest.class);
|
HttpRequest req = session.getContext().getContextObject(HttpRequest.class);
|
||||||
String clientAssertion = req.getDecodedFormParameters().getFirst(OAuth2Constants.CLIENT_ASSERTION);
|
String clientAssertion = req.getDecodedFormParameters().getFirst(OAuth2Constants.CLIENT_ASSERTION);
|
||||||
JWSInput jws = null;
|
JWSInput jws = null;
|
||||||
|
@ -68,11 +102,6 @@ public class SecureSigningAlgorithmForSignedJwtEnforceExecutor implements Client
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifySecureSigningAlgorithm(String signatureAlgorithm) throws ClientPolicyException {
|
private void verifySecureSigningAlgorithm(String signatureAlgorithm) throws ClientPolicyException {
|
||||||
if (signatureAlgorithm == null) {
|
|
||||||
logger.trace("Signing algorithm not specified explicitly.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Please change also SecureSigningAlgorithmForSignedJwtEnforceExecutorFactory.getHelpText() if you are changing any algorithms here.
|
// Please change also SecureSigningAlgorithmForSignedJwtEnforceExecutorFactory.getHelpText() if you are changing any algorithms here.
|
||||||
switch (signatureAlgorithm) {
|
switch (signatureAlgorithm) {
|
||||||
case Algorithm.PS256:
|
case Algorithm.PS256:
|
||||||
|
|
|
@ -22,6 +22,8 @@ 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 java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -29,6 +31,11 @@ public class SecureSigningAlgorithmForSignedJwtEnforceExecutorFactory implements
|
||||||
|
|
||||||
public static final String PROVIDER_ID = "securesignalgjwt-enforce-executor";
|
public static final String PROVIDER_ID = "securesignalgjwt-enforce-executor";
|
||||||
|
|
||||||
|
public static final String REQUIRE_CLIENT_ASSERTION = "require-client-assertion";
|
||||||
|
|
||||||
|
private static final ProviderConfigProperty REQUIRE_CLIENT_ASSERTION_PROPERTY = new ProviderConfigProperty(
|
||||||
|
REQUIRE_CLIENT_ASSERTION, null, null, ProviderConfigProperty.BOOLEAN_TYPE, false);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClientPolicyExecutorProvider create(KeycloakSession session) {
|
public ClientPolicyExecutorProvider create(KeycloakSession session) {
|
||||||
return new SecureSigningAlgorithmForSignedJwtEnforceExecutor(session);
|
return new SecureSigningAlgorithmForSignedJwtEnforceExecutor(session);
|
||||||
|
@ -58,7 +65,7 @@ public class SecureSigningAlgorithmForSignedJwtEnforceExecutorFactory implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ProviderConfigProperty> getConfigProperties() {
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
return Collections.emptyList();
|
return new ArrayList<>(Arrays.asList(REQUIRE_CLIENT_ASSERTION_PROPERTY));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,6 +128,7 @@ import org.keycloak.services.clientpolicy.executor.SecureRequestObjectExecutorFa
|
||||||
import org.keycloak.services.clientpolicy.executor.SecureResponseTypeExecutorFactory;
|
import org.keycloak.services.clientpolicy.executor.SecureResponseTypeExecutorFactory;
|
||||||
import org.keycloak.services.clientpolicy.executor.SecureSessionEnforceExecutorFactory;
|
import org.keycloak.services.clientpolicy.executor.SecureSessionEnforceExecutorFactory;
|
||||||
import org.keycloak.services.clientpolicy.executor.SecureSigningAlgorithmEnforceExecutorFactory;
|
import org.keycloak.services.clientpolicy.executor.SecureSigningAlgorithmEnforceExecutorFactory;
|
||||||
|
import org.keycloak.services.clientpolicy.executor.SecureSigningAlgorithmForSignedJwtEnforceExecutor;
|
||||||
import org.keycloak.services.clientpolicy.executor.SecureSigningAlgorithmForSignedJwtEnforceExecutorFactory;
|
import org.keycloak.services.clientpolicy.executor.SecureSigningAlgorithmForSignedJwtEnforceExecutorFactory;
|
||||||
import org.keycloak.testsuite.AbstractKeycloakTest;
|
import org.keycloak.testsuite.AbstractKeycloakTest;
|
||||||
import org.keycloak.testsuite.AssertEvents;
|
import org.keycloak.testsuite.AssertEvents;
|
||||||
|
@ -866,6 +867,12 @@ public abstract class AbstractClientPoliciesTest extends AbstractKeycloakTest {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Object createSecureSigningAlgorithmForSignedJwtEnforceExecutorConfig(Boolean requireClientAssertion) {
|
||||||
|
SecureSigningAlgorithmForSignedJwtEnforceExecutor.Configuration config = new SecureSigningAlgorithmForSignedJwtEnforceExecutor.Configuration();
|
||||||
|
config.setRequireClientAssertion(requireClientAssertion);
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
// Client Policies CRUD Operation
|
// Client Policies CRUD Operation
|
||||||
|
|
||||||
protected static class ClientPoliciesBuilder {
|
protected static class ClientPoliciesBuilder {
|
||||||
|
|
|
@ -91,6 +91,7 @@ import org.keycloak.services.clientpolicy.executor.SecureRequestObjectExecutorFa
|
||||||
import org.keycloak.services.clientpolicy.executor.SecureResponseTypeExecutorFactory;
|
import org.keycloak.services.clientpolicy.executor.SecureResponseTypeExecutorFactory;
|
||||||
import org.keycloak.services.clientpolicy.executor.SecureSessionEnforceExecutorFactory;
|
import org.keycloak.services.clientpolicy.executor.SecureSessionEnforceExecutorFactory;
|
||||||
import org.keycloak.services.clientpolicy.executor.SecureSigningAlgorithmEnforceExecutorFactory;
|
import org.keycloak.services.clientpolicy.executor.SecureSigningAlgorithmEnforceExecutorFactory;
|
||||||
|
import org.keycloak.services.clientpolicy.executor.SecureSigningAlgorithmForSignedJwtEnforceExecutor;
|
||||||
import org.keycloak.services.clientpolicy.executor.SecureSigningAlgorithmForSignedJwtEnforceExecutorFactory;
|
import org.keycloak.services.clientpolicy.executor.SecureSigningAlgorithmForSignedJwtEnforceExecutorFactory;
|
||||||
import org.keycloak.services.clientpolicy.executor.SecureRequestObjectExecutor;
|
import org.keycloak.services.clientpolicy.executor.SecureRequestObjectExecutor;
|
||||||
import org.keycloak.testsuite.admin.ApiUtil;
|
import org.keycloak.testsuite.admin.ApiUtil;
|
||||||
|
@ -1255,7 +1256,7 @@ public class ClientPoliciesTest extends AbstractClientPoliciesTest {
|
||||||
// register profiles
|
// register profiles
|
||||||
String json = (new ClientProfilesBuilder()).addProfile(
|
String json = (new ClientProfilesBuilder()).addProfile(
|
||||||
(new ClientProfileBuilder()).createProfile(PROFILE_NAME, "Ensimmainen Profiili", Boolean.FALSE, null)
|
(new ClientProfileBuilder()).createProfile(PROFILE_NAME, "Ensimmainen Profiili", Boolean.FALSE, null)
|
||||||
.addExecutor(SecureSigningAlgorithmForSignedJwtEnforceExecutorFactory.PROVIDER_ID, null)
|
.addExecutor(SecureSigningAlgorithmForSignedJwtEnforceExecutorFactory.PROVIDER_ID, createSecureSigningAlgorithmForSignedJwtEnforceExecutorConfig(Boolean.TRUE))
|
||||||
.toRepresentation()
|
.toRepresentation()
|
||||||
).toString();
|
).toString();
|
||||||
updateProfiles(json);
|
updateProfiles(json);
|
||||||
|
@ -1350,6 +1351,8 @@ public class ClientPoliciesTest extends AbstractClientPoliciesTest {
|
||||||
(new ClientProfileBuilder()).createProfile(PROFILE_NAME, "Az Elso Profil", Boolean.FALSE, null)
|
(new ClientProfileBuilder()).createProfile(PROFILE_NAME, "Az Elso Profil", Boolean.FALSE, null)
|
||||||
.addExecutor(HolderOfKeyEnforceExecutorFactory.PROVIDER_ID,
|
.addExecutor(HolderOfKeyEnforceExecutorFactory.PROVIDER_ID,
|
||||||
createHolderOfKeyEnforceExecutorConfig(Boolean.TRUE))
|
createHolderOfKeyEnforceExecutorConfig(Boolean.TRUE))
|
||||||
|
.addExecutor(SecureSigningAlgorithmForSignedJwtEnforceExecutorFactory.PROVIDER_ID,
|
||||||
|
createSecureSigningAlgorithmForSignedJwtEnforceExecutorConfig(Boolean.FALSE))
|
||||||
.toRepresentation()
|
.toRepresentation()
|
||||||
).toString();
|
).toString();
|
||||||
updateProfiles(json);
|
updateProfiles(json);
|
||||||
|
|
Loading…
Reference in a new issue