KEYCLOAK-16880 Client Policy - Condition : Negative Logic Support
This commit is contained in:
parent
41dc94fead
commit
c4bf8ecdf0
22 changed files with 223 additions and 332 deletions
|
@ -48,6 +48,18 @@ public interface ClientPolicyConditionProvider extends Provider {
|
|||
return ClientPolicyVote.ABSTAIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* tells whether the result of applyPolicy method is inverted or not as follows.
|
||||
* ClientPolicyVote.YES is inverted to ClientPolicyVote.NO
|
||||
* ClientPolicyVote.NO is inverted to ClientPolicyVote.YES
|
||||
* ClientPolicyVote.ABSTAIN remains unchanged
|
||||
*
|
||||
* @return true if the result of applyPolicy method is inverted.
|
||||
*/
|
||||
default boolean isNegativeLogic() {
|
||||
return false;
|
||||
}
|
||||
|
||||
String getName();
|
||||
|
||||
String getProviderId();
|
||||
|
|
|
@ -96,6 +96,13 @@ public class DefaultClientPolicyManager implements ClientPolicyManager {
|
|||
for (ClientPolicyConditionProvider condition : conditions) {
|
||||
try {
|
||||
ClientPolicyVote vote = op.run(condition);
|
||||
if (condition.isNegativeLogic()) {
|
||||
if (vote == ClientPolicyVote.YES) {
|
||||
vote = ClientPolicyVote.NO;
|
||||
} else if (vote == ClientPolicyVote.NO) {
|
||||
vote = ClientPolicyVote.YES;
|
||||
}
|
||||
}
|
||||
if (vote == ClientPolicyVote.ABSTAIN) {
|
||||
ClientPolicyLogger.logv(logger, "SKIP : This condition is not evaluated due to its nature. name = {0}, provider id = {1}", condition.getName(), condition.getProviderId());
|
||||
continue;
|
||||
|
|
|
@ -88,7 +88,7 @@ public class DefaultClientPolicyProvider implements ClientPolicyProvider {
|
|||
ClientPolicyConditionProvider provider = session.getProvider(ClientPolicyConditionProvider.class, cm);
|
||||
providers.add(provider);
|
||||
session.enlistForClose(provider);
|
||||
ClientPolicyLogger.logv(logger, "Loaded Condition id = {0}, name = {1}, provider id = {2}", conditionId, cm.getName(), cm.getProviderId());
|
||||
ClientPolicyLogger.logv(logger, "Loaded Condition id = {0}, name = {1}, provider id = {2}, is negative logic = {3}", conditionId, cm.getName(), cm.getProviderId(), provider.isNegativeLogic());
|
||||
} catch (Throwable t) {
|
||||
logger.errorv(t, "Failed to load condition {0}", cm.getId());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright 2021 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.condition;
|
||||
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
||||
public abstract class AbstractClientPolicyConditionProvider implements ClientPolicyConditionProvider {
|
||||
|
||||
protected final KeycloakSession session;
|
||||
protected final ComponentModel componentModel;
|
||||
|
||||
public AbstractClientPolicyConditionProvider(KeycloakSession session, ComponentModel componentModel) {
|
||||
this.session = session;
|
||||
this.componentModel = componentModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNegativeLogic() {
|
||||
return Boolean.valueOf(componentModel.getConfig().getFirst(AbstractClientPolicyConditionProviderFactory.IS_NEGATIVE_LOGIC)).booleanValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return componentModel.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProviderId() {
|
||||
return componentModel.getProviderId();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright 2021 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.condition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.keycloak.Config.Scope;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
|
||||
public abstract class AbstractClientPolicyConditionProviderFactory implements ClientPolicyConditionProviderFactory {
|
||||
|
||||
public static final String IS_NEGATIVE_LOGIC = "is-negative-logic";
|
||||
|
||||
private static final ProviderConfigProperty IS_NEGATIVE_LOGIC_PROPERTY = new ProviderConfigProperty(IS_NEGATIVE_LOGIC, "clientpolicycondition-is-negative-logic.label", "clientpolicycondition-is-negative-logic.tooltip", ProviderConfigProperty.BOOLEAN_TYPE, false);
|
||||
|
||||
@Override
|
||||
public void init(Scope config) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProviderConfigProperty> getConfigProperties() {
|
||||
return new ArrayList<>(Arrays.asList(IS_NEGATIVE_LOGIC_PROPERTY));
|
||||
}
|
||||
|
||||
}
|
|
@ -24,15 +24,12 @@ import org.keycloak.services.clientpolicy.ClientPolicyContext;
|
|||
import org.keycloak.services.clientpolicy.ClientPolicyException;
|
||||
import org.keycloak.services.clientpolicy.ClientPolicyVote;
|
||||
|
||||
public class AnyClientCondition implements ClientPolicyConditionProvider {
|
||||
public class AnyClientCondition extends AbstractClientPolicyConditionProvider {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(AnyClientCondition.class);
|
||||
|
||||
private final KeycloakSession session;
|
||||
private final ComponentModel componentModel;
|
||||
|
||||
public AnyClientCondition(KeycloakSession session, ComponentModel componentModel) {
|
||||
this.session = session;
|
||||
this.componentModel = componentModel;
|
||||
super(session, componentModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -40,14 +37,4 @@ public class AnyClientCondition implements ClientPolicyConditionProvider {
|
|||
return ClientPolicyVote.YES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return componentModel.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProviderId() {
|
||||
return componentModel.getProviderId();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,16 +17,10 @@
|
|||
|
||||
package org.keycloak.services.clientpolicy.condition;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.keycloak.Config.Scope;
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
|
||||
public class AnyClientConditionFactory implements ClientPolicyConditionProviderFactory {
|
||||
public class AnyClientConditionFactory extends AbstractClientPolicyConditionProviderFactory {
|
||||
|
||||
public static final String PROVIDER_ID = "anyclient-condition";
|
||||
|
||||
|
@ -35,18 +29,6 @@ public class AnyClientConditionFactory implements ClientPolicyConditionProviderF
|
|||
return new AnyClientCondition(session, model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Scope config) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_ID;
|
||||
|
@ -56,10 +38,4 @@ public class AnyClientConditionFactory implements ClientPolicyConditionProviderF
|
|||
public String getHelpText() {
|
||||
return "The condition is satisfied by any client on any event.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProviderConfigProperty> getConfigProperties() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,26 +29,12 @@ import org.keycloak.services.clientpolicy.ClientPolicyException;
|
|||
import org.keycloak.services.clientpolicy.ClientPolicyLogger;
|
||||
import org.keycloak.services.clientpolicy.ClientPolicyVote;
|
||||
|
||||
public class ClientAccessTypeCondition implements ClientPolicyConditionProvider {
|
||||
public class ClientAccessTypeCondition extends AbstractClientPolicyConditionProvider {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ClientAccessTypeCondition.class);
|
||||
|
||||
private final KeycloakSession session;
|
||||
private final ComponentModel componentModel;
|
||||
|
||||
public ClientAccessTypeCondition(KeycloakSession session, ComponentModel componentModel) {
|
||||
this.session = session;
|
||||
this.componentModel = componentModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return componentModel.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProviderId() {
|
||||
return componentModel.getProviderId();
|
||||
super(session, componentModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,17 +17,14 @@
|
|||
|
||||
package org.keycloak.services.clientpolicy.condition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.keycloak.Config.Scope;
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
|
||||
public class ClientAccessTypeConditionFactory implements ClientPolicyConditionProviderFactory {
|
||||
public class ClientAccessTypeConditionFactory extends AbstractClientPolicyConditionProviderFactory {
|
||||
|
||||
public static final String PROVIDER_ID = "client-accesstype-condition";
|
||||
public static final String TYPE = "type";
|
||||
|
@ -35,14 +32,10 @@ public class ClientAccessTypeConditionFactory implements ClientPolicyConditionPr
|
|||
public static final String TYPE_PUBLIC = "public";
|
||||
public static final String TYPE_BEARERONLY = "bearer-only";
|
||||
|
||||
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||
|
||||
private static final ProviderConfigProperty CLIENTACCESSTYPE_PROPERTY;
|
||||
static {
|
||||
ProviderConfigProperty property;
|
||||
property = new ProviderConfigProperty(TYPE, "client-accesstype.label", "client-accesstype.tooltip", ProviderConfigProperty.MULTIVALUED_LIST_TYPE, TYPE_CONFIDENTIAL);
|
||||
List<String> updateProfileValues = Arrays.asList(TYPE_CONFIDENTIAL, TYPE_PUBLIC, TYPE_BEARERONLY);
|
||||
property.setOptions(updateProfileValues);
|
||||
configProperties.add(property);
|
||||
CLIENTACCESSTYPE_PROPERTY = new ProviderConfigProperty(TYPE, "client-accesstype.label", "client-accesstype.tooltip", ProviderConfigProperty.MULTIVALUED_LIST_TYPE, TYPE_CONFIDENTIAL);
|
||||
CLIENTACCESSTYPE_PROPERTY.setOptions(Arrays.asList(TYPE_CONFIDENTIAL, TYPE_PUBLIC, TYPE_BEARERONLY));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -50,18 +43,6 @@ public class ClientAccessTypeConditionFactory implements ClientPolicyConditionPr
|
|||
return new ClientAccessTypeCondition(session, model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Scope config) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_ID;
|
||||
|
@ -74,7 +55,8 @@ public class ClientAccessTypeConditionFactory implements ClientPolicyConditionPr
|
|||
|
||||
@Override
|
||||
public List<ProviderConfigProperty> getConfigProperties() {
|
||||
return configProperties;
|
||||
List<ProviderConfigProperty> l = super.getConfigProperties();
|
||||
l.add(CLIENTACCESSTYPE_PROPERTY);
|
||||
return l;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,15 +32,12 @@ import org.keycloak.services.clientpolicy.ClientPolicyException;
|
|||
import org.keycloak.services.clientpolicy.ClientPolicyLogger;
|
||||
import org.keycloak.services.clientpolicy.ClientPolicyVote;
|
||||
|
||||
public class ClientRolesCondition implements ClientPolicyConditionProvider {
|
||||
public class ClientRolesCondition extends AbstractClientPolicyConditionProvider {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ClientRolesCondition.class);
|
||||
|
||||
private final KeycloakSession session;
|
||||
private final ComponentModel componentModel;
|
||||
|
||||
public ClientRolesCondition(KeycloakSession session, ComponentModel componentModel) {
|
||||
this.session = session;
|
||||
this.componentModel = componentModel;
|
||||
super(session, componentModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -91,14 +88,4 @@ public class ClientRolesCondition implements ClientPolicyConditionProvider {
|
|||
return new HashSet<>(roles);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return componentModel.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProviderId() {
|
||||
return componentModel.getProviderId();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,44 +17,23 @@
|
|||
|
||||
package org.keycloak.services.clientpolicy.condition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.keycloak.Config.Scope;
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
|
||||
public class ClientRolesConditionFactory implements ClientPolicyConditionProviderFactory {
|
||||
public class ClientRolesConditionFactory extends AbstractClientPolicyConditionProviderFactory {
|
||||
|
||||
public static final String PROVIDER_ID = "clientroles-condition";
|
||||
public static final String ROLES = "roles";
|
||||
|
||||
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||
|
||||
static {
|
||||
ProviderConfigProperty property;
|
||||
property = new ProviderConfigProperty(ROLES, PROVIDER_ID + ".label", PROVIDER_ID + ".tooltip", ProviderConfigProperty.MULTIVALUED_STRING_TYPE, null);
|
||||
configProperties.add(property);
|
||||
}
|
||||
private static final ProviderConfigProperty CLIENTROLES_PROPERTY = new ProviderConfigProperty(
|
||||
ROLES, PROVIDER_ID + ".label", PROVIDER_ID + ".tooltip", ProviderConfigProperty.MULTIVALUED_STRING_TYPE, null);
|
||||
|
||||
@Override
|
||||
public ClientPolicyConditionProvider create(KeycloakSession session, ComponentModel model) {
|
||||
return new ClientRolesCondition(session, model);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Scope config) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -69,7 +48,8 @@ public class ClientRolesConditionFactory implements ClientPolicyConditionProvide
|
|||
|
||||
@Override
|
||||
public List<ProviderConfigProperty> getConfigProperties() {
|
||||
return configProperties;
|
||||
List<ProviderConfigProperty> l = super.getConfigProperties();
|
||||
l.add(CLIENTROLES_PROPERTY);
|
||||
return l;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -37,16 +37,12 @@ import org.keycloak.services.clientpolicy.ClientPolicyLogger;
|
|||
import org.keycloak.services.clientpolicy.ClientPolicyVote;
|
||||
import org.keycloak.services.clientpolicy.TokenRequestContext;
|
||||
|
||||
public class ClientScopesCondition implements ClientPolicyConditionProvider {
|
||||
public class ClientScopesCondition extends AbstractClientPolicyConditionProvider {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ClientScopesCondition.class);
|
||||
|
||||
private final KeycloakSession session;
|
||||
private final ComponentModel componentModel;
|
||||
|
||||
public ClientScopesCondition(KeycloakSession session, ComponentModel componentModel) {
|
||||
this.session = session;
|
||||
this.componentModel = componentModel;
|
||||
super(session, componentModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -63,16 +59,6 @@ public class ClientScopesCondition implements ClientPolicyConditionProvider {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return componentModel.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProviderId() {
|
||||
return componentModel.getProviderId();
|
||||
}
|
||||
|
||||
private boolean isScopeMatched(AuthenticatedClientSessionModel clientSession) {
|
||||
if (clientSession == null) return false;
|
||||
return isScopeMatched(clientSession.getNote(OAuth2Constants.SCOPE), clientSession.getClient());
|
||||
|
|
|
@ -17,16 +17,13 @@
|
|||
|
||||
package org.keycloak.services.clientpolicy.condition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.keycloak.Config.Scope;
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
|
||||
public class ClientScopesConditionFactory implements ClientPolicyConditionProviderFactory {
|
||||
public class ClientScopesConditionFactory extends AbstractClientPolicyConditionProviderFactory {
|
||||
|
||||
public static final String PROVIDER_ID = "clientscopes-condition";
|
||||
public static final String SCOPES = "scopes";
|
||||
|
@ -34,33 +31,16 @@ public class ClientScopesConditionFactory implements ClientPolicyConditionProvid
|
|||
public static final String DEFAULT = "Default";
|
||||
public static final String OPTIONAL = "Optional";
|
||||
|
||||
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||
|
||||
static {
|
||||
ProviderConfigProperty property;
|
||||
property = new ProviderConfigProperty(SCOPES, PROVIDER_ID + ".label", PROVIDER_ID + ".tooltip", ProviderConfigProperty.MULTIVALUED_STRING_TYPE, "offline_access");
|
||||
configProperties.add(property);
|
||||
property = new ProviderConfigProperty(TYPE, "Scope Type", "Default or Optional", ProviderConfigProperty.LIST_TYPE, OPTIONAL);
|
||||
configProperties.add(property);
|
||||
}
|
||||
private static final ProviderConfigProperty CLIENTSCOPES_PROPERTY = new ProviderConfigProperty(
|
||||
SCOPES, PROVIDER_ID + ".label", PROVIDER_ID + ".tooltip", ProviderConfigProperty.MULTIVALUED_STRING_TYPE, "offline_access");
|
||||
private static final ProviderConfigProperty CLIENTSCOPETYPE_PROPERTY = new ProviderConfigProperty(
|
||||
TYPE, "Scope Type", "Default or Optional", ProviderConfigProperty.LIST_TYPE, OPTIONAL);
|
||||
|
||||
@Override
|
||||
public ClientPolicyConditionProvider create(KeycloakSession session, ComponentModel model) {
|
||||
return new ClientScopesCondition(session, model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Scope config) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_ID;
|
||||
|
@ -73,7 +53,9 @@ public class ClientScopesConditionFactory implements ClientPolicyConditionProvid
|
|||
|
||||
@Override
|
||||
public List<ProviderConfigProperty> getConfigProperties() {
|
||||
return configProperties;
|
||||
List<ProviderConfigProperty> l = super.getConfigProperties();
|
||||
l.add(CLIENTSCOPES_PROPERTY);
|
||||
l.add(CLIENTSCOPETYPE_PROPERTY);
|
||||
return l;
|
||||
}
|
||||
|
||||
}
|
|
@ -29,20 +29,15 @@ import org.keycloak.services.clientpolicy.ClientPolicyException;
|
|||
import org.keycloak.services.clientpolicy.ClientPolicyLogger;
|
||||
import org.keycloak.services.clientpolicy.ClientPolicyVote;
|
||||
import org.keycloak.services.clientpolicy.ClientUpdateContext;
|
||||
import org.keycloak.services.clientpolicy.condition.ClientPolicyConditionProvider;
|
||||
import org.keycloak.services.clientregistration.ClientRegistrationTokenUtils;
|
||||
import org.keycloak.util.TokenUtil;
|
||||
|
||||
public class ClientUpdateContextCondition implements ClientPolicyConditionProvider {
|
||||
public class ClientUpdateContextCondition extends AbstractClientPolicyConditionProvider {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ClientUpdateContextCondition.class);
|
||||
|
||||
private final KeycloakSession session;
|
||||
private final ComponentModel componentModel;
|
||||
|
||||
public ClientUpdateContextCondition(KeycloakSession session, ComponentModel componentModel) {
|
||||
this.session = session;
|
||||
this.componentModel = componentModel;
|
||||
super(session, componentModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -108,14 +103,4 @@ public class ClientUpdateContextCondition implements ClientPolicyConditionProvid
|
|||
private boolean isBearerToken(JsonWebToken jwt) {
|
||||
return jwt != null && TokenUtil.TOKEN_TYPE_BEARER.equals(jwt.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return componentModel.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProviderId() {
|
||||
return componentModel.getProviderId();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,19 +17,15 @@
|
|||
|
||||
package org.keycloak.services.clientpolicy.condition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.keycloak.Config.Scope;
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
import org.keycloak.services.clientpolicy.condition.ClientPolicyConditionProvider;
|
||||
import org.keycloak.services.clientpolicy.condition.ClientPolicyConditionProviderFactory;
|
||||
|
||||
public class ClientUpdateContextConditionFactory implements ClientPolicyConditionProviderFactory {
|
||||
public class ClientUpdateContextConditionFactory extends AbstractClientPolicyConditionProviderFactory {
|
||||
|
||||
public static final String PROVIDER_ID = "clientupdatecontext-condition";
|
||||
|
||||
|
@ -40,32 +36,18 @@ public class ClientUpdateContextConditionFactory implements ClientPolicyConditio
|
|||
public static final String BY_INITIAL_ACCESS_TOKEN = "ByInitialAccessToken";
|
||||
public static final String BY_REGISTRATION_ACCESS_TOKEN = "ByRegistrationAccessToken";
|
||||
|
||||
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||
|
||||
private static final ProviderConfigProperty CLIENTUPDATESOURCE_PROPERTY;
|
||||
static {
|
||||
ProviderConfigProperty property;
|
||||
property = new ProviderConfigProperty(UPDATE_CLIENT_SOURCE, null, null, ProviderConfigProperty.MULTIVALUED_LIST_TYPE, BY_AUTHENTICATED_USER);
|
||||
List<String> updateProfileValues = Arrays.asList(BY_AUTHENTICATED_USER, BY_ANONYMOUS, BY_INITIAL_ACCESS_TOKEN, BY_REGISTRATION_ACCESS_TOKEN);
|
||||
property.setOptions(updateProfileValues);
|
||||
configProperties.add(property);
|
||||
CLIENTUPDATESOURCE_PROPERTY = new ProviderConfigProperty(
|
||||
UPDATE_CLIENT_SOURCE, null, null, ProviderConfigProperty.MULTIVALUED_LIST_TYPE, BY_AUTHENTICATED_USER);
|
||||
CLIENTUPDATESOURCE_PROPERTY.setOptions(
|
||||
Arrays.asList(BY_AUTHENTICATED_USER, BY_ANONYMOUS, BY_INITIAL_ACCESS_TOKEN, BY_REGISTRATION_ACCESS_TOKEN));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientPolicyConditionProvider create(KeycloakSession session, ComponentModel model) {
|
||||
return new ClientUpdateContextCondition(session, model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Scope config) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
|
@ -79,7 +61,8 @@ public class ClientUpdateContextConditionFactory implements ClientPolicyConditio
|
|||
|
||||
@Override
|
||||
public List<ProviderConfigProperty> getConfigProperties() {
|
||||
return configProperties;
|
||||
List<ProviderConfigProperty> l = super.getConfigProperties();
|
||||
l.add(CLIENTUPDATESOURCE_PROPERTY);
|
||||
return l;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
package org.keycloak.services.clientpolicy.condition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
@ -25,7 +24,6 @@ import java.util.stream.Collectors;
|
|||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.OAuthErrorException;
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
@ -41,26 +39,12 @@ import org.keycloak.services.clientpolicy.ClientUpdateContext;
|
|||
import org.keycloak.services.clientpolicy.DynamicClientRegisterContext;
|
||||
import org.keycloak.services.clientpolicy.DynamicClientUpdateContext;
|
||||
|
||||
public class ClientUpdateSourceGroupsCondition implements ClientPolicyConditionProvider {
|
||||
public class ClientUpdateSourceGroupsCondition extends AbstractClientPolicyConditionProvider {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ClientUpdateSourceGroupsCondition.class);
|
||||
|
||||
private final KeycloakSession session;
|
||||
private final ComponentModel componentModel;
|
||||
|
||||
public ClientUpdateSourceGroupsCondition(KeycloakSession session, ComponentModel componentModel) {
|
||||
this.session = session;
|
||||
this.componentModel = componentModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return componentModel.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProviderId() {
|
||||
return componentModel.getProviderId();
|
||||
super(session, componentModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,46 +17,26 @@
|
|||
|
||||
package org.keycloak.services.clientpolicy.condition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.keycloak.Config.Scope;
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
|
||||
public class ClientUpdateSourceGroupsConditionFactory implements ClientPolicyConditionProviderFactory {
|
||||
public class ClientUpdateSourceGroupsConditionFactory extends AbstractClientPolicyConditionProviderFactory {
|
||||
|
||||
public static final String PROVIDER_ID = "clientupdatesourcegroups-condition";
|
||||
|
||||
public static final String GROUPS = "groups";
|
||||
|
||||
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||
|
||||
static {
|
||||
ProviderConfigProperty property;
|
||||
property = new ProviderConfigProperty(GROUPS, PROVIDER_ID + ".label", PROVIDER_ID + ".tooltip", ProviderConfigProperty.MULTIVALUED_STRING_TYPE, "topGroup");
|
||||
configProperties.add(property);
|
||||
}
|
||||
private static final ProviderConfigProperty CLIENTUPDATEGROUP_PROPERTY = new ProviderConfigProperty(
|
||||
GROUPS, PROVIDER_ID + ".label", PROVIDER_ID + ".tooltip", ProviderConfigProperty.MULTIVALUED_STRING_TYPE, "topGroup");
|
||||
|
||||
@Override
|
||||
public ClientPolicyConditionProvider create(KeycloakSession session, ComponentModel model) {
|
||||
return new ClientUpdateSourceGroupsCondition(session, model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Scope config) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_ID;
|
||||
|
@ -69,7 +49,8 @@ public class ClientUpdateSourceGroupsConditionFactory implements ClientPolicyCon
|
|||
|
||||
@Override
|
||||
public List<ProviderConfigProperty> getConfigProperties() {
|
||||
return configProperties;
|
||||
List<ProviderConfigProperty> l = super.getConfigProperties();
|
||||
l.add(CLIENTUPDATEGROUP_PROPERTY);
|
||||
return l;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,26 +31,12 @@ import org.keycloak.services.clientpolicy.ClientPolicyException;
|
|||
import org.keycloak.services.clientpolicy.ClientPolicyLogger;
|
||||
import org.keycloak.services.clientpolicy.ClientPolicyVote;
|
||||
|
||||
public class ClientUpdateSourceHostsCondition implements ClientPolicyConditionProvider {
|
||||
public class ClientUpdateSourceHostsCondition extends AbstractClientPolicyConditionProvider {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ClientUpdateSourceHostsCondition.class);
|
||||
|
||||
private final KeycloakSession session;
|
||||
private final ComponentModel componentModel;
|
||||
|
||||
public ClientUpdateSourceHostsCondition(KeycloakSession session, ComponentModel componentModel) {
|
||||
this.session = session;
|
||||
this.componentModel = componentModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return componentModel.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProviderId() {
|
||||
return componentModel.getProviderId();
|
||||
super(session, componentModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,19 +17,16 @@
|
|||
|
||||
package org.keycloak.services.clientpolicy.condition;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.keycloak.Config.Scope;
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.component.ComponentValidationException;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.provider.ConfigurationValidationHelper;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
|
||||
public class ClientUpdateSourceHostsConditionFactory implements ClientPolicyConditionProviderFactory {
|
||||
public class ClientUpdateSourceHostsConditionFactory extends AbstractClientPolicyConditionProviderFactory {
|
||||
|
||||
public static final String PROVIDER_ID = "clientupdatesourcehost-condition";
|
||||
|
||||
|
@ -47,18 +44,6 @@ public class ClientUpdateSourceHostsConditionFactory implements ClientPolicyCond
|
|||
return new ClientUpdateSourceHostsCondition(session, model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Scope config) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_ID;
|
||||
|
@ -71,7 +56,10 @@ public class ClientUpdateSourceHostsConditionFactory implements ClientPolicyCond
|
|||
|
||||
@Override
|
||||
public List<ProviderConfigProperty> getConfigProperties() {
|
||||
return Arrays.asList(TRUSTED_HOSTS_PROPERTY, HOST_SENDING_REGISTRATION_REQUEST_MUST_MATCH_PROPERTY);
|
||||
List<ProviderConfigProperty> l = super.getConfigProperties();
|
||||
l.add(TRUSTED_HOSTS_PROPERTY);
|
||||
l.add(HOST_SENDING_REGISTRATION_REQUEST_MUST_MATCH_PROPERTY);
|
||||
return l;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -40,26 +40,12 @@ import org.keycloak.services.clientpolicy.ClientUpdateContext;
|
|||
import org.keycloak.services.clientpolicy.DynamicClientRegisterContext;
|
||||
import org.keycloak.services.clientpolicy.DynamicClientUpdateContext;
|
||||
|
||||
public class ClientUpdateSourceRolesCondition implements ClientPolicyConditionProvider {
|
||||
public class ClientUpdateSourceRolesCondition extends AbstractClientPolicyConditionProvider {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ClientUpdateSourceRolesCondition.class);
|
||||
|
||||
private final KeycloakSession session;
|
||||
private final ComponentModel componentModel;
|
||||
|
||||
public ClientUpdateSourceRolesCondition(KeycloakSession session, ComponentModel componentModel) {
|
||||
this.session = session;
|
||||
this.componentModel = componentModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return componentModel.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProviderId() {
|
||||
return componentModel.getProviderId();
|
||||
super(session, componentModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,48 +17,25 @@
|
|||
|
||||
package org.keycloak.services.clientpolicy.condition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.keycloak.Config.Scope;
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
|
||||
public class ClientUpdateSourceRolesConditionFactory implements ClientPolicyConditionProviderFactory {
|
||||
public class ClientUpdateSourceRolesConditionFactory extends AbstractClientPolicyConditionProviderFactory {
|
||||
|
||||
public static final String PROVIDER_ID = "clientupdatesourceroles-condition";
|
||||
public static final String ROLES = "roles";
|
||||
|
||||
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||
|
||||
static {
|
||||
ProviderConfigProperty property;
|
||||
property = new ProviderConfigProperty(ROLES, PROVIDER_ID + ".label", PROVIDER_ID + ".tooltip", ProviderConfigProperty.MULTIVALUED_STRING_TYPE, "admin");
|
||||
configProperties.add(property);
|
||||
}
|
||||
private static final ProviderConfigProperty CLIENTUPDATEROLE_PROPERTY = new ProviderConfigProperty(
|
||||
ROLES, PROVIDER_ID + ".label", PROVIDER_ID + ".tooltip", ProviderConfigProperty.MULTIVALUED_STRING_TYPE, "admin");
|
||||
|
||||
@Override
|
||||
public ClientPolicyConditionProvider create(KeycloakSession session, ComponentModel model) {
|
||||
return new ClientUpdateSourceRolesCondition(session, model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Scope config) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_ID;
|
||||
|
@ -67,12 +44,12 @@ public class ClientUpdateSourceRolesConditionFactory implements ClientPolicyCond
|
|||
@Override
|
||||
public String getHelpText() {
|
||||
return "The condition checks the role of the entity who tries to create/update the client to determine whether the policy is applied.";
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProviderConfigProperty> getConfigProperties() {
|
||||
return configProperties;
|
||||
List<ProviderConfigProperty> l = super.getConfigProperties();
|
||||
l.add(CLIENTUPDATEROLE_PROPERTY);
|
||||
return l;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -74,6 +74,7 @@ import org.keycloak.representations.oidc.OIDCClientRepresentation;
|
|||
import org.keycloak.representations.oidc.TokenMetadataRepresentation;
|
||||
import org.keycloak.services.clientpolicy.ClientPolicyException;
|
||||
import org.keycloak.services.clientpolicy.DefaultClientPolicyProviderFactory;
|
||||
import org.keycloak.services.clientpolicy.condition.AbstractClientPolicyConditionProviderFactory;
|
||||
import org.keycloak.services.clientpolicy.condition.AnyClientConditionFactory;
|
||||
import org.keycloak.services.clientpolicy.condition.ClientAccessTypeConditionFactory;
|
||||
import org.keycloak.services.clientpolicy.condition.ClientUpdateContextConditionFactory;
|
||||
|
@ -1279,6 +1280,43 @@ public class ClientPoliciesTest extends AbstractClientPoliciesTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNegativeLogicCondition() throws ClientRegistrationException, ClientPolicyException {
|
||||
String policyName = POLICY_NAME;
|
||||
createPolicy(policyName, DefaultClientPolicyProviderFactory.PROVIDER_ID, null, null, null);
|
||||
logger.info("... Created Policy : " + policyName);
|
||||
|
||||
String conditionName = AnyClientCondition_NAME;
|
||||
createCondition(conditionName, AnyClientConditionFactory.PROVIDER_ID, null, (ComponentRepresentation provider) -> {});
|
||||
registerCondition(conditionName, policyName);
|
||||
logger.info("... Registered Condition : " + conditionName);
|
||||
|
||||
String executorName = SecureSessionEnforceExecutor_NAME;
|
||||
createExecutor(executorName, SecureSessionEnforceExecutorFactory.PROVIDER_ID, null, (ComponentRepresentation provider) -> {});
|
||||
registerExecutor(executorName, policyName);
|
||||
logger.info("... Registered Executor : " + executorName);
|
||||
|
||||
String clientId = generateSuffixedName(CLIENT_NAME);
|
||||
String clientSecret = "secretBeta";
|
||||
createClientByAdmin(clientId, (ClientRepresentation clientRep) -> {
|
||||
clientRep.setSecret(clientSecret);
|
||||
});
|
||||
|
||||
try {
|
||||
failLoginWithoutSecureSessionParameter(clientId, ERR_MSG_MISSING_NONCE);
|
||||
updateCondition("AnyClientCondition", (ComponentRepresentation provider) -> {
|
||||
provider.getConfig().putSingle(AbstractClientPolicyConditionProviderFactory.IS_NEGATIVE_LOGIC, Boolean.TRUE.toString());
|
||||
});
|
||||
successfulLoginAndLogout(clientId, clientSecret);
|
||||
updateCondition("AnyClientCondition", (ComponentRepresentation provider) -> {
|
||||
provider.getConfig().putSingle(AbstractClientPolicyConditionProviderFactory.IS_NEGATIVE_LOGIC, Boolean.FALSE.toString());
|
||||
});
|
||||
failLoginWithoutSecureSessionParameter(clientId, ERR_MSG_MISSING_NONCE);
|
||||
} catch (Exception e) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
private void checkMtlsFlow() throws IOException {
|
||||
// Check login.
|
||||
OAuthClient.AuthorizationEndpointResponse loginResponse = oauth.doLogin(TEST_USER_NAME, TEST_USER_PASSWORD);
|
||||
|
|
Loading…
Reference in a new issue