Skip to content

Commit

Permalink
[KEYCLOAK-7353] Support Policy Management in Protection API
Browse files Browse the repository at this point in the history
  • Loading branch information
chicco785 authored and pedroigor committed Jun 6, 2018
1 parent f8919f8 commit 5a9bfea
Show file tree
Hide file tree
Showing 64 changed files with 2,230 additions and 360 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.keycloak.AuthorizationContext;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.OIDCHttpFacade;
import org.keycloak.adapters.spi.HttpFacade;
import org.keycloak.adapters.spi.HttpFacade.Request;
import org.keycloak.authorization.client.AuthzClient;
import org.keycloak.authorization.client.ClientAuthorizationContext;
Expand Down Expand Up @@ -165,7 +166,7 @@ protected boolean isAuthorized(PathConfig actualPathConfig, MethodConfig methodC
policyEnforcer.getPathMatcher().removeFromCache(getPath(request));
}

return hasValidClaims(actualPathConfig, httpFacade, authorization);
return hasValidClaims(actualPathConfig, permission, httpFacade, authorization);
}
}
} else {
Expand All @@ -187,35 +188,22 @@ protected boolean isAuthorized(PathConfig actualPathConfig, MethodConfig methodC
return false;
}

private boolean hasValidClaims(PathConfig actualPathConfig, OIDCHttpFacade httpFacade, Authorization authorization) {
Map<String, Map<String, Object>> claimInformationPointConfig = actualPathConfig.getClaimInformationPointConfig();
private boolean hasValidClaims(PathConfig actualPathConfig, Permission permission, OIDCHttpFacade httpFacade, Authorization authorization) {
Map<String, Set<String>> grantedClaims = permission.getClaims();

if (claimInformationPointConfig != null) {
Map<String, List<String>> claims = new HashMap<>();

for (Entry<String, Map<String, Object>> entry : claimInformationPointConfig.entrySet()) {
ClaimInformationPointProviderFactory factory = policyEnforcer.getClaimInformationPointProviderFactories().get(entry.getKey());
if (grantedClaims != null) {
Map<String, List<String>> claims = resolveClaims(actualPathConfig, httpFacade);

if (factory == null) {
throw new RuntimeException("Could not find claim information provider with name [" + entry.getKey() + "]");
}

claims.putAll(factory.create(entry.getValue()).resolve(httpFacade));
if (claims.isEmpty()) {
return false;
}

Map<String, List<String>> grantedClaims = authorization.getClaims();
for (Entry<String, Set<String>> entry : grantedClaims.entrySet()) {
List<String> requestClaims = claims.get(entry.getKey());

if (grantedClaims != null) {
if (claims.isEmpty()) {
if (requestClaims == null || requestClaims.isEmpty() || !entry.getValue().containsAll(requestClaims)) {
return false;
}
for (Entry<String, List<String>> entry : grantedClaims.entrySet()) {
List<String> requestClaims = claims.get(entry.getKey());

if (requestClaims == null || requestClaims.isEmpty() || !entry.getValue().containsAll(requestClaims)) {
return false;
}
}
}
}

Expand Down Expand Up @@ -342,4 +330,28 @@ private boolean matchResourcePermission(PathConfig actualPathConfig, Permission
private PathConfig getPathConfig(Request request) {
return isDefaultAccessDeniedUri(request) ? null : policyEnforcer.getPathMatcher().matches(getPath(request));
}

protected Map<String, List<String>> resolveClaims(PathConfig pathConfig, OIDCHttpFacade httpFacade) {
Map<String, List<String>> claims = getClaims(getEnforcerConfig().getClaimInformationPointConfig(), httpFacade);

claims.putAll(getClaims(pathConfig.getClaimInformationPointConfig(), httpFacade));

return claims;
}

private Map<String, List<String>> getClaims(Map<String, Map<String, Object>>claimInformationPointConfig, HttpFacade httpFacade) {
Map<String, List<String>> claims = new HashMap<>();

if (claimInformationPointConfig != null) {
for (Entry<String, Map<String, Object>> claimDef : claimInformationPointConfig.entrySet()) {
ClaimInformationPointProviderFactory factory = getPolicyEnforcer().getClaimInformationPointProviderFactories().get(claimDef.getKey());

if (factory != null) {
claims.putAll(factory.create(claimDef.getValue()).resolve(httpFacade));
}
}
}

return claims;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.jboss.logging.Logger;
import org.keycloak.KeycloakSecurityContext;
Expand Down Expand Up @@ -87,19 +86,6 @@ protected boolean isAuthorized(PathConfig pathConfig, PolicyEnforcerConfig.Metho
grantedPermissions.add(newPermission);
}
}

Map<String, List<String>> newClaims = newAuthorization.getClaims();

if (newClaims != null) {
Map<String, List<String>> claims = authorization.getClaims();

if (claims == null) {
claims = new HashMap<>();
authorization.setClaims(claims);
}

claims.putAll(newClaims);
}
}

original.setAuthorization(authorization);
Expand Down Expand Up @@ -169,11 +155,11 @@ private AccessToken requestAuthorizationToken(PathConfig pathConfig, PolicyEnfor
String ticket = getPermissionTicket(pathConfig, methodConfig, getAuthzClient(), httpFacade);
authzRequest.setTicket(ticket);
} else {
if (accessToken.getAuthorization() != null) {
if (isBearerAuthorization(httpFacade) || accessToken.getAuthorization() != null) {
authzRequest.addPermission(pathConfig.getId(), methodConfig.getScopes());
}

Map<String, List<String>> claims = getClaims(pathConfig, httpFacade);
Map<String, List<String>> claims = resolveClaims(pathConfig, httpFacade);

if (!claims.isEmpty()) {
authzRequest.setClaimTokenFormat("urn:ietf:params:oauth:token-type:jwt");
Expand All @@ -186,7 +172,14 @@ private AccessToken requestAuthorizationToken(PathConfig pathConfig, PolicyEnfor
}

LOGGER.debug("Obtaining authorization for authenticated user.");
AuthorizationResponse authzResponse = getAuthzClient().authorization(accessTokenString).authorize(authzRequest);
AuthorizationResponse authzResponse;

if (isBearerAuthorization(httpFacade)) {
authzRequest.setSubjectToken(accessTokenString);
authzResponse = getAuthzClient().authorization().authorize(authzRequest);
} else {
authzResponse = getAuthzClient().authorization(accessTokenString).authorize(authzRequest);
}

if (authzResponse != null) {
return AdapterRSATokenVerifier.verifyToken(authzResponse.getToken(), deployment);
Expand All @@ -200,7 +193,7 @@ private AccessToken requestAuthorizationToken(PathConfig pathConfig, PolicyEnfor
return null;
}

private String getPermissionTicket(PathConfig pathConfig, PolicyEnforcerConfig.MethodConfig methodConfig, AuthzClient authzClient, HttpFacade httpFacade) {
private String getPermissionTicket(PathConfig pathConfig, PolicyEnforcerConfig.MethodConfig methodConfig, AuthzClient authzClient, OIDCHttpFacade httpFacade) {
if (getEnforcerConfig().getUserManagedAccess() != null) {
ProtectionResource protection = authzClient.protection();
PermissionResource permission = protection.permission();
Expand All @@ -209,7 +202,7 @@ private String getPermissionTicket(PathConfig pathConfig, PolicyEnforcerConfig.M
permissionRequest.setResourceId(pathConfig.getId());
permissionRequest.setScopes(new HashSet<>(methodConfig.getScopes()));

Map<String, List<String>> claims = getClaims(pathConfig, httpFacade);
Map<String, List<String>> claims = resolveClaims(pathConfig, httpFacade);

if (!claims.isEmpty()) {
permissionRequest.setClaims(claims);
Expand All @@ -221,22 +214,6 @@ private String getPermissionTicket(PathConfig pathConfig, PolicyEnforcerConfig.M
return null;
}

private Map<String, List<String>> getClaims(PathConfig pathConfig, HttpFacade httpFacade) {
Map<String, List<String>> claims = new HashMap<>();
Map<String, Map<String, Object>> claimInformationPointConfig = pathConfig.getClaimInformationPointConfig();

if (claimInformationPointConfig != null) {
for (Entry<String, Map<String, Object>> claimDef : claimInformationPointConfig.entrySet()) {
ClaimInformationPointProviderFactory factory = getPolicyEnforcer().getClaimInformationPointProviderFactories().get(claimDef.getKey());

if (factory != null) {
claims.putAll(factory.create(claimDef.getValue()).resolve(httpFacade));
}
}
}
return claims;
}

private boolean isBearerAuthorization(OIDCHttpFacade httpFacade) {
List<String> authHeaders = httpFacade.getRequest().getHeaders("Authorization");
if (authHeaders == null || authHeaders.size() == 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ protected PathConfig resolvePathConfig(PathConfig originalConfig, String path) {
config.setMethods(originalConfig.getMethods());
config.setParentConfig(originalConfig);
config.setEnforcementMode(originalConfig.getEnforcementMode());
config.setClaimInformationPointConfig(originalConfig.getClaimInformationPointConfig());

return config;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ public class ServerConfiguration {

@JsonProperty("permission_endpoint")
private String permissionEndpoint;

@JsonProperty("policy_endpoint")
private String policyEndpoint;

public String getIssuer() {
return issuer;
Expand Down Expand Up @@ -206,4 +209,8 @@ public String getResourceRegistrationEndpoint() {
public String getPermissionEndpoint() {
return permissionEndpoint;
}

public String getPolicyEndpoint() {
return policyEndpoint;
}
}
Loading

0 comments on commit 5a9bfea

Please sign in to comment.