[KEYCLOAK-9478] - Support multiple CIP providers in the policy enforcer configuration
This commit is contained in:
parent
bacc1b538f
commit
75d9847672
5 changed files with 119 additions and 7 deletions
|
@ -349,24 +349,23 @@ public abstract class AbstractPolicyEnforcer {
|
|||
}
|
||||
|
||||
protected Map<String, List<String>> resolveClaims(PathConfig pathConfig, OIDCHttpFacade httpFacade) {
|
||||
Map<String, List<String>> claims = getClaims(getEnforcerConfig().getClaimInformationPointConfig(), httpFacade);
|
||||
Map<String, List<String>> claims = new HashMap<>();
|
||||
|
||||
claims.putAll(getClaims(pathConfig.getClaimInformationPointConfig(), httpFacade));
|
||||
resolveClaims(claims, getEnforcerConfig().getClaimInformationPointConfig(), httpFacade);
|
||||
resolveClaims(claims, pathConfig.getClaimInformationPointConfig(), httpFacade);
|
||||
|
||||
return claims;
|
||||
}
|
||||
|
||||
private Map<String, List<String>> getClaims(Map<String, Map<String, Object>>claimInformationPointConfig, HttpFacade httpFacade) {
|
||||
private void resolveClaims(Map<String, List<String>> claims, Map<String, Map<String, Object>> claimInformationPointConfig, HttpFacade httpFacade) {
|
||||
if (claimInformationPointConfig != null) {
|
||||
for (Entry<String, Map<String, Object>> claimDef : claimInformationPointConfig.entrySet()) {
|
||||
ClaimInformationPointProviderFactory factory = getPolicyEnforcer().getClaimInformationPointProviderFactories().get(claimDef.getKey());
|
||||
|
||||
if (factory != null) {
|
||||
return factory.create(claimDef.getValue()).resolve(httpFacade);
|
||||
claims.putAll(factory.create(claimDef.getValue()).resolve(httpFacade));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new HashMap<>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright 2018 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.testsuite.admin.client.authorization;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.keycloak.adapters.authorization.ClaimInformationPointProvider;
|
||||
import org.keycloak.adapters.authorization.ClaimInformationPointProviderFactory;
|
||||
import org.keycloak.adapters.authorization.PolicyEnforcer;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
|
||||
public class MyCustomCIPFactory implements ClaimInformationPointProviderFactory<MyCustomCIP> {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "my-custom-cip";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(PolicyEnforcer policyEnforcer) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public MyCustomCIP create(Map<String, Object> config) {
|
||||
return new MyCustomCIP(config);
|
||||
}
|
||||
}
|
||||
|
||||
class MyCustomCIP implements ClaimInformationPointProvider {
|
||||
|
||||
private final Map<String, Object> config;
|
||||
|
||||
MyCustomCIP(Map<String, Object> config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> resolve(HttpFacade httpFacade) {
|
||||
Map<String, List<String>> claims = new HashMap<>();
|
||||
|
||||
claims.put("resolved-claim", Arrays.asList(config.get("claim-value").toString()));
|
||||
|
||||
return claims;
|
||||
}
|
||||
}
|
|
@ -34,6 +34,7 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -68,6 +69,7 @@ import org.keycloak.representations.idm.RealmRepresentation;
|
|||
import org.keycloak.representations.idm.authorization.AuthorizationRequest;
|
||||
import org.keycloak.representations.idm.authorization.AuthorizationResponse;
|
||||
import org.keycloak.representations.idm.authorization.JSPolicyRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.Permission;
|
||||
import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.RolePolicyRepresentation;
|
||||
|
@ -175,13 +177,40 @@ public class PolicyEnforcerTest extends AbstractKeycloakTest {
|
|||
@Override
|
||||
public String apply(String s) {
|
||||
Assert.assertTrue(resolved.compareAndSet(false, true));
|
||||
return "claim-value";
|
||||
return "value-" + s;
|
||||
}
|
||||
});
|
||||
|
||||
AuthorizationContext context = policyEnforcer.enforce(httpFacade);
|
||||
Permission permission = context.getPermissions().get(0);
|
||||
Map<String, Set<String>> claims = permission.getClaims();
|
||||
|
||||
assertTrue(context.isGranted());
|
||||
assertEquals("value-claim-a", claims.get("claim-a").iterator().next());
|
||||
assertEquals("claim-b", claims.get("claim-b").iterator().next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomClaimProvider() {
|
||||
KeycloakDeployment deployment = KeycloakDeploymentBuilder.build(getAdapterConfiguration("enforcer-bearer-only-with-cip.json"));
|
||||
PolicyEnforcer policyEnforcer = deployment.getPolicyEnforcer();
|
||||
|
||||
oauth.realm(REALM_NAME);
|
||||
oauth.clientId("public-client-test");
|
||||
oauth.doLogin("marta", "password");
|
||||
|
||||
String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
|
||||
OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, null);
|
||||
String token = response.getAccessToken();
|
||||
|
||||
OIDCHttpFacade httpFacade = createHttpFacade("/api/resourcea", token);
|
||||
|
||||
AuthorizationContext context = policyEnforcer.enforce(httpFacade);
|
||||
Permission permission = context.getPermissions().get(0);
|
||||
Map<String, Set<String>> claims = permission.getClaims();
|
||||
|
||||
assertTrue(context.isGranted());
|
||||
assertEquals("test", claims.get("resolved-claim").iterator().next());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
#
|
||||
# * Copyright 2018 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.
|
||||
#
|
||||
|
||||
org.keycloak.testsuite.admin.client.authorization.MyCustomCIPFactory
|
|
@ -19,6 +19,9 @@
|
|||
"claim-information-point": {
|
||||
"claims": {
|
||||
"claim-a": "{request.parameter['claim-a']}"
|
||||
},
|
||||
"my-custom-cip": {
|
||||
"claim-value": "test"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue