KEYCLOAK-17681 Client Policy - Executor : Limiting available period of Request Object with its configuration
This commit is contained in:
parent
a48d04bfe0
commit
e9035bb7b3
3 changed files with 36 additions and 7 deletions
|
@ -19,6 +19,7 @@ package org.keycloak.services.clientpolicy.executor;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
|
|
||||||
|
@ -34,27 +35,51 @@ import org.keycloak.services.Urls;
|
||||||
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.context.AuthorizationRequestContext;
|
import org.keycloak.services.clientpolicy.context.AuthorizationRequestContext;
|
||||||
|
import org.keycloak.services.clientpolicy.executor.PKCEEnforceExecutor.Configuration;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:takashi.norimatsu.ws@hitachi.com">Takashi Norimatsu</a>
|
* @author <a href="mailto:takashi.norimatsu.ws@hitachi.com">Takashi Norimatsu</a>
|
||||||
*/
|
*/
|
||||||
public class SecureRequestObjectExecutor implements ClientPolicyExecutorProvider<ClientPolicyExecutorConfiguration> {
|
public class SecureRequestObjectExecutor implements ClientPolicyExecutorProvider<SecureRequestObjectExecutor.Configuration> {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(SecureRequestObjectExecutor.class);
|
private static final Logger logger = Logger.getLogger(SecureRequestObjectExecutor.class);
|
||||||
|
|
||||||
public static final String INVALID_REQUEST_OBJECT = "invalid_request_object";
|
public static final String INVALID_REQUEST_OBJECT = "invalid_request_object";
|
||||||
|
public static final Integer DEFAULT_AVAILABLE_PERIOD = Integer.valueOf(3600); // (sec) from FAPI 1.0 Advanced requirement
|
||||||
|
|
||||||
private final KeycloakSession session;
|
private final KeycloakSession session;
|
||||||
|
private Configuration configuration;
|
||||||
|
|
||||||
public SecureRequestObjectExecutor(KeycloakSession session) {
|
public SecureRequestObjectExecutor(KeycloakSession session) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setupConfiguration(Configuration config) {
|
||||||
|
this.configuration = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<Configuration> getExecutorConfigurationClass() {
|
||||||
|
return Configuration.class;
|
||||||
|
}
|
||||||
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public static class Configuration {
|
public static class Configuration extends ClientPolicyExecutorConfiguration {
|
||||||
|
@JsonProperty("available-period")
|
||||||
|
protected Integer availablePeriod;
|
||||||
|
|
||||||
|
public Integer getAvailablePeriod() {
|
||||||
|
return availablePeriod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAvailablePeriod(Integer availablePeriod) {
|
||||||
|
this.availablePeriod = availablePeriod;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -139,7 +164,8 @@ public class SecureRequestObjectExecutor implements ClientPolicyExecutorProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
// check whether request object's available period is short
|
// check whether request object's available period is short
|
||||||
if (exp - nbf > 3600) {
|
int availablePeriod = Optional.ofNullable(configuration.getAvailablePeriod()).orElse(DEFAULT_AVAILABLE_PERIOD).intValue();
|
||||||
|
if (exp - nbf > availablePeriod) {
|
||||||
logger.trace("request object's available period is long.");
|
logger.trace("request object's available period is long.");
|
||||||
throw new ClientPolicyException(INVALID_REQUEST_OBJECT, "Request's available period is long");
|
throw new ClientPolicyException(INVALID_REQUEST_OBJECT, "Request's available period is long");
|
||||||
}
|
}
|
||||||
|
|
|
@ -865,8 +865,10 @@ public abstract class AbstractClientPoliciesTest extends AbstractKeycloakTest {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Object createSecureRequestObjectExecutorConfig() {
|
protected Object createSecureRequestObjectExecutorConfig(Integer availablePeriod) {
|
||||||
return new SecureRequestObjectExecutor.Configuration();
|
SecureRequestObjectExecutor.Configuration config = new SecureRequestObjectExecutor.Configuration();
|
||||||
|
if (availablePeriod != null) config.setAvailablePeriod(availablePeriod);
|
||||||
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Object createSecureResponseTypeExecutorConfig() {
|
protected Object createSecureResponseTypeExecutorConfig() {
|
||||||
|
|
|
@ -912,11 +912,12 @@ public class ClientPoliciesTest extends AbstractClientPoliciesTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSecureRequestObjectExecutor() throws Exception, URISyntaxException, IOException {
|
public void testSecureRequestObjectExecutor() throws Exception, URISyntaxException, IOException {
|
||||||
|
Integer availablePeriod = Integer.valueOf(SecureRequestObjectExecutor.DEFAULT_AVAILABLE_PERIOD + 400);
|
||||||
// register profiles
|
// register profiles
|
||||||
String json = (new ClientProfilesBuilder()).addProfile(
|
String json = (new ClientProfilesBuilder()).addProfile(
|
||||||
(new ClientProfileBuilder()).createProfile(PROFILE_NAME, "Prvy Profil", Boolean.FALSE, null)
|
(new ClientProfileBuilder()).createProfile(PROFILE_NAME, "Prvy Profil", Boolean.FALSE, null)
|
||||||
.addExecutor(SecureRequestObjectExecutorFactory.PROVIDER_ID,
|
.addExecutor(SecureRequestObjectExecutorFactory.PROVIDER_ID,
|
||||||
createSecureRequestObjectExecutorConfig())
|
createSecureRequestObjectExecutorConfig(availablePeriod))
|
||||||
.toRepresentation()
|
.toRepresentation()
|
||||||
).toString();
|
).toString();
|
||||||
updateProfiles(json);
|
updateProfiles(json);
|
||||||
|
@ -1000,7 +1001,7 @@ public class ClientPoliciesTest extends AbstractClientPoliciesTest {
|
||||||
|
|
||||||
// check whether request object's available period is short
|
// check whether request object's available period is short
|
||||||
requestObject = createValidRequestObjectForSecureRequestObjectExecutor(clientId);
|
requestObject = createValidRequestObjectForSecureRequestObjectExecutor(clientId);
|
||||||
requestObject.exp(requestObject.getNbf() + 3601);
|
requestObject.exp(requestObject.getNbf() + availablePeriod.intValue() + 1);
|
||||||
registerRequestObject(requestObject, clientId, Algorithm.ES256, false);
|
registerRequestObject(requestObject, clientId, Algorithm.ES256, false);
|
||||||
oauth.openLoginForm();
|
oauth.openLoginForm();
|
||||||
assertEquals(SecureRequestObjectExecutor.INVALID_REQUEST_OBJECT, oauth.getCurrentQuery().get(OAuth2Constants.ERROR));
|
assertEquals(SecureRequestObjectExecutor.INVALID_REQUEST_OBJECT, oauth.getCurrentQuery().get(OAuth2Constants.ERROR));
|
||||||
|
|
Loading…
Reference in a new issue