Merge pull request #2617 from pedroigor/KEYCLOAK-2753
[KEYCLOAK-2753] - Fine-grained Authorization Services
This commit is contained in:
commit
3c0f7e2ee2
387 changed files with 27499 additions and 96 deletions
|
@ -65,6 +65,11 @@
|
|||
<artifactId>keycloak-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-client</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
|
|
|
@ -18,10 +18,12 @@
|
|||
package org.keycloak.adapters;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.AuthorizationContext;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.authorization.PolicyEnforcer;
|
||||
import org.keycloak.common.util.UriUtils;
|
||||
import org.keycloak.constants.AdapterConstants;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.common.util.UriUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
@ -55,6 +57,9 @@ public class AuthenticatedActionsHandler {
|
|||
queryBearerToken();
|
||||
return true;
|
||||
}
|
||||
if (!isAuthorized()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -124,4 +129,24 @@ public class AuthenticatedActionsHandler {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isAuthorized() {
|
||||
PolicyEnforcer policyEnforcer = this.deployment.getPolicyEnforcer();
|
||||
|
||||
if (policyEnforcer == null) {
|
||||
log.debugv("Policy enforcement is disabled.");
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
OIDCHttpFacade facade = (OIDCHttpFacade) this.facade;
|
||||
AuthorizationContext authorizationContext = policyEnforcer.enforce(facade);
|
||||
RefreshableKeycloakSecurityContext session = (RefreshableKeycloakSecurityContext) facade.getSecurityContext();
|
||||
|
||||
session.setAuthorizationContext(authorizationContext);
|
||||
|
||||
return authorizationContext.isGranted();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to enforce policy decisions.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.keycloak.adapters;
|
|||
import org.apache.http.client.HttpClient;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.adapters.authentication.ClientCredentialsProvider;
|
||||
import org.keycloak.adapters.authorization.PolicyEnforcer;
|
||||
import org.keycloak.constants.ServiceUrlConstants;
|
||||
import org.keycloak.common.enums.RelativeUrlsUsed;
|
||||
import org.keycloak.common.enums.SslRequired;
|
||||
|
@ -78,6 +79,7 @@ public class KeycloakDeployment {
|
|||
|
||||
protected volatile int notBefore;
|
||||
protected int tokenMinimumTimeToLive;
|
||||
private PolicyEnforcer policyEnforcer;
|
||||
|
||||
public KeycloakDeployment() {
|
||||
}
|
||||
|
@ -366,4 +368,12 @@ public class KeycloakDeployment {
|
|||
public void setTokenMinimumTimeToLive(final int tokenMinimumTimeToLive) {
|
||||
this.tokenMinimumTimeToLive = tokenMinimumTimeToLive;
|
||||
}
|
||||
|
||||
public void setPolicyEnforcer(PolicyEnforcer policyEnforcer) {
|
||||
this.policyEnforcer = policyEnforcer;
|
||||
}
|
||||
|
||||
public PolicyEnforcer getPolicyEnforcer() {
|
||||
return policyEnforcer;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,10 +21,12 @@ import com.fasterxml.jackson.annotation.JsonInclude;
|
|||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.adapters.authentication.ClientCredentialsProviderUtils;
|
||||
import org.keycloak.adapters.authorization.PolicyEnforcer;
|
||||
import org.keycloak.common.enums.SslRequired;
|
||||
import org.keycloak.common.util.PemUtils;
|
||||
import org.keycloak.enums.TokenStore;
|
||||
import org.keycloak.representations.adapters.config.AdapterConfig;
|
||||
import org.keycloak.common.util.PemUtils;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;
|
||||
import org.keycloak.util.SystemPropertiesJsonParserFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -110,6 +112,12 @@ public class KeycloakDeploymentBuilder {
|
|||
deployment.setTurnOffChangeSessionIdOnLogin(adapterConfig.getTurnOffChangeSessionIdOnLogin());
|
||||
}
|
||||
|
||||
PolicyEnforcerConfig policyEnforcerConfig = adapterConfig.getPolicyEnforcerConfig();
|
||||
|
||||
if (policyEnforcerConfig != null) {
|
||||
deployment.setPolicyEnforcer(new PolicyEnforcer(deployment, adapterConfig));
|
||||
}
|
||||
|
||||
log.debug("Use authServerUrl: " + deployment.getAuthServerBaseUrl() + ", tokenUrl: " + deployment.getTokenUrl() + ", relativeUrls: " + deployment.getRelativeUrls());
|
||||
return deployment;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
package org.keycloak.adapters;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.AuthorizationContext;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.RSATokenVerifier;
|
||||
import org.keycloak.common.VerificationException;
|
||||
|
@ -157,4 +158,8 @@ public class RefreshableKeycloakSecurityContext extends KeycloakSecurityContext
|
|||
tokenStore.refreshCallback(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setAuthorizationContext(AuthorizationContext authorizationContext) {
|
||||
this.authorizationContext = authorizationContext;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* Copyright 2016 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.adapters.authorization;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.AuthorizationContext;
|
||||
import org.keycloak.adapters.OIDCHttpFacade;
|
||||
import org.keycloak.adapters.spi.HttpFacade.Request;
|
||||
import org.keycloak.adapters.spi.HttpFacade.Response;
|
||||
import org.keycloak.authorization.client.AuthzClient;
|
||||
import org.keycloak.authorization.client.representation.ResourceRepresentation;
|
||||
import org.keycloak.authorization.client.resource.ProtectedResource;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.EnforcementMode;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
||||
import org.keycloak.representations.authorization.Permission;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public abstract class AbstractPolicyEnforcer {
|
||||
|
||||
private static Logger LOGGER = Logger.getLogger(AbstractPolicyEnforcer.class);
|
||||
private final PolicyEnforcerConfig enforcerConfig;
|
||||
private final PolicyEnforcer policyEnforcer;
|
||||
|
||||
private List<PathConfig> paths;
|
||||
private AuthzClient authzClient;
|
||||
private PathMatcher pathMatcher;
|
||||
|
||||
public AbstractPolicyEnforcer(PolicyEnforcer policyEnforcer) {
|
||||
this.policyEnforcer = policyEnforcer;
|
||||
this.enforcerConfig = policyEnforcer.getEnforcerConfig();
|
||||
this.authzClient = policyEnforcer.getClient();
|
||||
this.pathMatcher = new PathMatcher();
|
||||
this.paths = policyEnforcer.getPaths();
|
||||
}
|
||||
|
||||
public AuthorizationContext authorize(OIDCHttpFacade httpFacade) {
|
||||
EnforcementMode enforcementMode = this.enforcerConfig.getEnforcementMode();
|
||||
|
||||
if (EnforcementMode.DISABLED.equals(enforcementMode)) {
|
||||
return createEmptyAuthorizationContext(true);
|
||||
}
|
||||
|
||||
AccessToken accessToken = httpFacade.getSecurityContext().getToken();
|
||||
Request request = httpFacade.getRequest();
|
||||
Response response = httpFacade.getResponse();
|
||||
String pathInfo = URI.create(request.getURI()).getPath().substring(1);
|
||||
String path = pathInfo.substring(pathInfo.indexOf('/'), pathInfo.length());
|
||||
PathConfig pathConfig = this.pathMatcher.matches(path, this.paths);
|
||||
|
||||
LOGGER.debugf("Checking permissions for path [%s] with config [%s].", request.getURI(), pathConfig);
|
||||
|
||||
if (pathConfig == null) {
|
||||
if (EnforcementMode.PERMISSIVE.equals(enforcementMode)) {
|
||||
return createAuthorizationContext(accessToken);
|
||||
}
|
||||
|
||||
LOGGER.debugf("Could not find a configuration for path [%s]", path);
|
||||
response.sendError(403, "Could not find a configuration for path [" + path + "].");
|
||||
|
||||
return createEmptyAuthorizationContext(false);
|
||||
}
|
||||
|
||||
PathConfig actualPathConfig = resolvePathConfig(pathConfig, request);
|
||||
Set<String> requiredScopes = getRequiredScopes(actualPathConfig, request);
|
||||
|
||||
if (isAuthorized(actualPathConfig, requiredScopes, accessToken, httpFacade)) {
|
||||
try {
|
||||
return createAuthorizationContext(accessToken);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error processing path [" + actualPathConfig.getPath() + "].", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (!challenge(actualPathConfig, requiredScopes, httpFacade)) {
|
||||
LOGGER.debugf("Sending challenge to the client. Path [%s]", pathConfig);
|
||||
response.sendError(403, "Authorization failed.");
|
||||
}
|
||||
|
||||
return createEmptyAuthorizationContext(false);
|
||||
}
|
||||
|
||||
protected abstract boolean challenge(PathConfig pathConfig, Set<String> requiredScopes, OIDCHttpFacade facade);
|
||||
|
||||
protected boolean isAuthorized(PathConfig actualPathConfig, Set<String> requiredScopes, AccessToken accessToken, OIDCHttpFacade httpFacade) {
|
||||
Request request = httpFacade.getRequest();
|
||||
PolicyEnforcerConfig enforcerConfig = getEnforcerConfig();
|
||||
String accessDeniedPath = enforcerConfig.getAccessDeniedPath();
|
||||
|
||||
if (accessDeniedPath != null) {
|
||||
if (request.getURI().contains(accessDeniedPath)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
AccessToken.Authorization authorization = accessToken.getAuthorization();
|
||||
|
||||
if (authorization == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Permission> permissions = authorization.getPermissions();
|
||||
|
||||
for (Permission permission : permissions) {
|
||||
Set<String> allowedScopes = permission.getScopes();
|
||||
|
||||
if (permission.getResourceSetId() != null) {
|
||||
if (permission.getResourceSetId().equals(actualPathConfig.getId())) {
|
||||
if (((allowedScopes == null || allowedScopes.isEmpty()) && requiredScopes.isEmpty()) || allowedScopes.containsAll(requiredScopes)) {
|
||||
LOGGER.debugf("Authorization GRANTED for path [%s]. Permissions [%s].", actualPathConfig, permissions);
|
||||
if (request.getMethod().equalsIgnoreCase("DELETE") && actualPathConfig.isInstance()) {
|
||||
this.paths.remove(actualPathConfig);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((allowedScopes.isEmpty() && requiredScopes.isEmpty()) || allowedScopes.containsAll(requiredScopes)) {
|
||||
LOGGER.debugf("Authorization GRANTED for path [%s]. Permissions [%s].", actualPathConfig, permissions);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.debugf("Authorization FAILED for path [%s]. No enough permissions [%s].", actualPathConfig, permissions);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected AuthzClient getAuthzClient() {
|
||||
return this.authzClient;
|
||||
}
|
||||
|
||||
protected PolicyEnforcerConfig getEnforcerConfig() {
|
||||
return enforcerConfig;
|
||||
}
|
||||
|
||||
protected PolicyEnforcer getPolicyEnforcer() {
|
||||
return policyEnforcer;
|
||||
}
|
||||
|
||||
private AuthorizationContext createEmptyAuthorizationContext(final boolean granted) {
|
||||
return new AuthorizationContext() {
|
||||
@Override
|
||||
public boolean hasPermission(String resourceName, String scopeName) {
|
||||
return granted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasResourcePermission(String resourceName) {
|
||||
return granted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasScopePermission(String scopeName) {
|
||||
return granted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Permission> getPermissions() {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGranted() {
|
||||
return granted;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private PathConfig resolvePathConfig(PathConfig originalConfig, Request request) {
|
||||
if (originalConfig.hasPattern()) {
|
||||
String pathInfo = URI.create(request.getURI()).getPath().substring(1);
|
||||
String path = pathInfo.substring(pathInfo.indexOf('/'), pathInfo.length());
|
||||
ProtectedResource resource = this.authzClient.protection().resource();
|
||||
Set<String> search = resource.findByFilter("uri=" + path);
|
||||
|
||||
if (!search.isEmpty()) {
|
||||
// resource does exist on the server, cache it
|
||||
ResourceRepresentation targetResource = resource.findById(search.iterator().next()).getResourceDescription();
|
||||
PathConfig config = new PathConfig();
|
||||
|
||||
config.setId(targetResource.getId());
|
||||
config.setName(targetResource.getName());
|
||||
config.setType(targetResource.getType());
|
||||
config.setPath(targetResource.getUri());
|
||||
config.setScopes(originalConfig.getScopes());
|
||||
config.setMethods(originalConfig.getMethods());
|
||||
config.setInstance(true);
|
||||
|
||||
this.paths.add(config);
|
||||
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
return originalConfig;
|
||||
}
|
||||
|
||||
private Set<String> getRequiredScopes(PathConfig pathConfig, Request request) {
|
||||
Set<String> requiredScopes = new HashSet<>();
|
||||
|
||||
requiredScopes.addAll(pathConfig.getScopes());
|
||||
|
||||
String method = request.getMethod();
|
||||
|
||||
for (PolicyEnforcerConfig.MethodConfig methodConfig : pathConfig.getMethods()) {
|
||||
if (methodConfig.getMethod().equals(method)) {
|
||||
requiredScopes.addAll(methodConfig.getScopes());
|
||||
}
|
||||
}
|
||||
|
||||
return requiredScopes;
|
||||
}
|
||||
|
||||
private AuthorizationContext createAuthorizationContext(AccessToken accessToken) {
|
||||
return new AuthorizationContext(accessToken, this.paths);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright 2016 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.adapters.authorization;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.adapters.OIDCHttpFacade;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.keycloak.authorization.client.AuthzClient;
|
||||
import org.keycloak.authorization.client.representation.PermissionRequest;
|
||||
import org.keycloak.authorization.client.resource.PermissionResource;
|
||||
import org.keycloak.authorization.client.resource.ProtectionResource;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class BearerTokenPolicyEnforcer extends AbstractPolicyEnforcer {
|
||||
|
||||
private static Logger LOGGER = Logger.getLogger(BearerTokenPolicyEnforcer.class);
|
||||
|
||||
public BearerTokenPolicyEnforcer(PolicyEnforcer enforcer) {
|
||||
super(enforcer);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean challenge(PathConfig pathConfig, Set<String> requiredScopes, OIDCHttpFacade facade) {
|
||||
if (getEnforcerConfig().getUmaProtocolConfig() != null) {
|
||||
challengeUmaAuthentication(pathConfig, requiredScopes, facade);
|
||||
} else {
|
||||
challengeEntitlementAuthentication(facade);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void challengeEntitlementAuthentication(OIDCHttpFacade facade) {
|
||||
HttpFacade.Response response = facade.getResponse();
|
||||
AuthzClient authzClient = getAuthzClient();
|
||||
String clientId = authzClient.getConfiguration().getClientId();
|
||||
String authorizationServerUri = authzClient.getServerConfiguration().getIssuer().toString() + "/authz/entitlement";
|
||||
response.setStatus(401);
|
||||
response.setHeader("WWW-Authenticate", "KC_ETT realm=\"" + clientId + "\",as_uri=\"" + authorizationServerUri + "\"");
|
||||
}
|
||||
|
||||
private void challengeUmaAuthentication(PathConfig pathConfig, Set<String> requiredScopes, OIDCHttpFacade facade) {
|
||||
HttpFacade.Response response = facade.getResponse();
|
||||
AuthzClient authzClient = getAuthzClient();
|
||||
String ticket = getPermissionTicket(pathConfig, requiredScopes, authzClient);
|
||||
String clientId = authzClient.getConfiguration().getClientId();
|
||||
String authorizationServerUri = authzClient.getServerConfiguration().getIssuer().toString() + "/authz/authorize";
|
||||
response.setStatus(401);
|
||||
response.setHeader("WWW-Authenticate", "UMA realm=\"" + clientId + "\",as_uri=\"" + authorizationServerUri + "\",ticket=\"" + ticket + "\"");
|
||||
}
|
||||
|
||||
private String getPermissionTicket(PathConfig pathConfig, Set<String> requiredScopes, AuthzClient authzClient) {
|
||||
ProtectionResource protection = authzClient.protection();
|
||||
PermissionResource permission = protection.permission();
|
||||
PermissionRequest permissionRequest = new PermissionRequest();
|
||||
permissionRequest.setResourceSetId(pathConfig.getId());
|
||||
permissionRequest.setScopes(requiredScopes);
|
||||
return permission.forResource(permissionRequest).getTicket();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright 2016 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.adapters.authorization;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.RSATokenVerifier;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.OIDCHttpFacade;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.keycloak.authorization.client.AuthorizationDeniedException;
|
||||
import org.keycloak.authorization.client.AuthzClient;
|
||||
import org.keycloak.authorization.client.representation.AuthorizationRequest;
|
||||
import org.keycloak.authorization.client.representation.AuthorizationResponse;
|
||||
import org.keycloak.authorization.client.representation.EntitlementResponse;
|
||||
import org.keycloak.authorization.client.representation.PermissionRequest;
|
||||
import org.keycloak.authorization.client.representation.PermissionResponse;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
|
||||
|
||||
private static Logger LOGGER = Logger.getLogger(KeycloakAdapterPolicyEnforcer.class);
|
||||
|
||||
public KeycloakAdapterPolicyEnforcer(PolicyEnforcer policyEnforcer) {
|
||||
super(policyEnforcer);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isAuthorized(PathConfig pathConfig, Set<String> requiredScopes, AccessToken accessToken, OIDCHttpFacade httpFacade) {
|
||||
int retry = 2;
|
||||
AccessToken original = accessToken;
|
||||
|
||||
while (retry >= 0) {
|
||||
if (super.isAuthorized(pathConfig, requiredScopes, accessToken, httpFacade)) {
|
||||
original.setAuthorization(accessToken.getAuthorization());
|
||||
return true;
|
||||
}
|
||||
|
||||
accessToken = requestAuthorizationToken(pathConfig, requiredScopes, httpFacade);
|
||||
|
||||
if (accessToken == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
retry--;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean challenge(PathConfig pathConfig, Set<String> requiredScopes, OIDCHttpFacade facade) {
|
||||
String accessDeniedPath = getEnforcerConfig().getAccessDeniedPath();
|
||||
HttpFacade.Response response = facade.getResponse();
|
||||
|
||||
if (accessDeniedPath != null) {
|
||||
response.setStatus(302);
|
||||
response.setHeader("Location", accessDeniedPath);
|
||||
} else {
|
||||
response.sendError(403);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private AccessToken requestAuthorizationToken(PathConfig pathConfig, Set<String> requiredScopes, OIDCHttpFacade httpFacade) {
|
||||
try {
|
||||
String accessToken = httpFacade.getSecurityContext().getTokenString();
|
||||
AuthzClient authzClient = getAuthzClient();
|
||||
KeycloakDeployment deployment = getPolicyEnforcer().getDeployment();
|
||||
|
||||
if (getEnforcerConfig().getUmaProtocolConfig() != null) {
|
||||
LOGGER.debug("Obtaining authorization for authenticated user.");
|
||||
PermissionRequest permissionRequest = new PermissionRequest();
|
||||
|
||||
permissionRequest.setResourceSetId(pathConfig.getId());
|
||||
permissionRequest.setScopes(requiredScopes);
|
||||
|
||||
PermissionResponse permissionResponse = authzClient.protection().permission().forResource(permissionRequest);
|
||||
AuthorizationRequest authzRequest = new AuthorizationRequest(permissionResponse.getTicket());
|
||||
AuthorizationResponse authzResponse = authzClient.authorization(accessToken).authorize(authzRequest);
|
||||
|
||||
if (authzResponse != null) {
|
||||
return RSATokenVerifier.verifyToken(authzResponse.getRpt(), deployment.getRealmKey(), deployment.getRealmInfoUrl());
|
||||
}
|
||||
|
||||
return null;
|
||||
} else {
|
||||
LOGGER.debug("Obtaining entitlements for authenticated user.");
|
||||
EntitlementResponse authzResponse = authzClient.entitlement(accessToken).getAll(authzClient.getConfiguration().getClientId());
|
||||
return RSATokenVerifier.verifyToken(authzResponse.getRpt(), deployment.getRealmKey(), deployment.getRealmInfoUrl());
|
||||
}
|
||||
} catch (AuthorizationDeniedException e) {
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unexpected error during authorization request.", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright 2016 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.adapters.authorization;
|
||||
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
class PathMatcher {
|
||||
|
||||
private static final String ANY_RESOURCE_PATTERN = "/*";
|
||||
|
||||
PathConfig matches(final String requestedUri, List<PathConfig> paths) {
|
||||
PathConfig actualConfig = null;
|
||||
|
||||
for (PathConfig entry : paths) {
|
||||
String protectedUri = entry.getPath();
|
||||
String selectedUri = null;
|
||||
|
||||
if (protectedUri.equals(ANY_RESOURCE_PATTERN) && actualConfig == null) {
|
||||
selectedUri = protectedUri;
|
||||
}
|
||||
|
||||
int suffixIndex = protectedUri.indexOf(ANY_RESOURCE_PATTERN + ".");
|
||||
|
||||
if (suffixIndex != -1) {
|
||||
String protectedSuffix = protectedUri.substring(suffixIndex + ANY_RESOURCE_PATTERN.length());
|
||||
|
||||
if (requestedUri.endsWith(protectedSuffix)) {
|
||||
selectedUri = protectedUri;
|
||||
}
|
||||
}
|
||||
|
||||
if (protectedUri.equals(requestedUri)) {
|
||||
selectedUri = protectedUri;
|
||||
}
|
||||
|
||||
if (protectedUri.endsWith(ANY_RESOURCE_PATTERN)) {
|
||||
String formattedPattern = removeWildCardsFromUri(protectedUri);
|
||||
|
||||
if (!formattedPattern.equals("/") && requestedUri.startsWith(formattedPattern)) {
|
||||
selectedUri = protectedUri;
|
||||
}
|
||||
|
||||
if (!formattedPattern.equals("/") && formattedPattern.endsWith("/") && formattedPattern.substring(0, formattedPattern.length() - 1).equals(requestedUri)) {
|
||||
selectedUri = protectedUri;
|
||||
}
|
||||
}
|
||||
|
||||
int startRegex = protectedUri.indexOf('{');
|
||||
|
||||
if (startRegex != -1) {
|
||||
String prefix = protectedUri.substring(0, startRegex);
|
||||
|
||||
if (requestedUri.startsWith(prefix)) {
|
||||
selectedUri = protectedUri;
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedUri != null) {
|
||||
selectedUri = protectedUri;
|
||||
}
|
||||
|
||||
if (selectedUri != null) {
|
||||
if (actualConfig == null) {
|
||||
actualConfig = entry;
|
||||
} else {
|
||||
if (actualConfig.equals(ANY_RESOURCE_PATTERN)) {
|
||||
actualConfig = entry;
|
||||
}
|
||||
|
||||
if (protectedUri.startsWith(removeWildCardsFromUri(actualConfig.getPath()))) {
|
||||
actualConfig = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return actualConfig;
|
||||
}
|
||||
|
||||
private String removeWildCardsFromUri(String protectedUri) {
|
||||
return protectedUri.replaceAll("/[*]", "/");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* Copyright 2016 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.adapters.authorization;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.AuthorizationContext;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.OIDCHttpFacade;
|
||||
import org.keycloak.authorization.client.AuthzClient;
|
||||
import org.keycloak.authorization.client.Configuration;
|
||||
import org.keycloak.authorization.client.representation.RegistrationResponse;
|
||||
import org.keycloak.authorization.client.representation.ResourceRepresentation;
|
||||
import org.keycloak.authorization.client.representation.ScopeRepresentation;
|
||||
import org.keycloak.authorization.client.resource.ProtectedResource;
|
||||
import org.keycloak.representations.adapters.config.AdapterConfig;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
||||
import org.keycloak.representations.authorization.Permission;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class PolicyEnforcer {
|
||||
|
||||
private static Logger LOGGER = Logger.getLogger(PolicyEnforcer.class);
|
||||
|
||||
private final KeycloakDeployment deployment;
|
||||
private final PathMatcher pathMatcher;
|
||||
private final AuthzClient authzClient;
|
||||
private final PolicyEnforcerConfig enforcerConfig;
|
||||
private final List<PathConfig> paths;
|
||||
|
||||
public PolicyEnforcer(KeycloakDeployment deployment, AdapterConfig adapterConfig) {
|
||||
this.deployment = deployment;
|
||||
this.enforcerConfig = adapterConfig.getPolicyEnforcerConfig();
|
||||
this.authzClient = AuthzClient.create(new Configuration(adapterConfig.getAuthServerUrl(), adapterConfig.getRealm(), adapterConfig.getResource(), adapterConfig.getCredentials(), deployment.getClient()));
|
||||
this.pathMatcher = new PathMatcher();
|
||||
this.paths = configurePaths(this.authzClient.protection().resource(), this.enforcerConfig);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Initialization complete. Path configurations:");
|
||||
for (PathConfig pathConfig : this.paths) {
|
||||
LOGGER.debug(pathConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AuthorizationContext enforce(OIDCHttpFacade facade) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debugv("Policy enforcement is enable. Enforcing policy decisions for path [{0}].", facade.getRequest().getURI());
|
||||
}
|
||||
|
||||
AuthorizationContext context;
|
||||
|
||||
if (deployment.isBearerOnly()) {
|
||||
context = new BearerTokenPolicyEnforcer(this).authorize(facade);
|
||||
} else {
|
||||
context = new KeycloakAdapterPolicyEnforcer(this).authorize(facade);
|
||||
}
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debugv("Policy enforcement result for path [{0}] is : {1}", facade.getRequest().getURI(), context.isGranted() ? "GRANTED" : "DENIED");
|
||||
LOGGER.debugv("Returning authorization context with permissions:");
|
||||
for (Permission permission : context.getPermissions()) {
|
||||
LOGGER.debug(permission);
|
||||
}
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
PolicyEnforcerConfig getEnforcerConfig() {
|
||||
return enforcerConfig;
|
||||
}
|
||||
|
||||
AuthzClient getClient() {
|
||||
return authzClient;
|
||||
}
|
||||
|
||||
List<PathConfig> getPaths() {
|
||||
return paths;
|
||||
}
|
||||
|
||||
KeycloakDeployment getDeployment() {
|
||||
return deployment;
|
||||
}
|
||||
|
||||
private List<PathConfig> configurePaths(ProtectedResource protectedResource, PolicyEnforcerConfig enforcerConfig) {
|
||||
if (enforcerConfig.getPaths().isEmpty()) {
|
||||
LOGGER.info("No path provided in configuration.");
|
||||
return configureAllPathsForResourceServer(protectedResource);
|
||||
} else {
|
||||
LOGGER.info("Paths provided in configuration.");
|
||||
return configureDefinedPaths(protectedResource, enforcerConfig);
|
||||
}
|
||||
}
|
||||
|
||||
private List<PathConfig> configureDefinedPaths(ProtectedResource protectedResource, PolicyEnforcerConfig enforcerConfig) {
|
||||
List<PathConfig> paths = new ArrayList<>();
|
||||
|
||||
for (PathConfig pathConfig : enforcerConfig.getPaths()) {
|
||||
Set<String> search;
|
||||
String resourceName = pathConfig.getName();
|
||||
String path = pathConfig.getPath();
|
||||
|
||||
if (resourceName != null) {
|
||||
LOGGER.debugf("Trying to find resource with name [%s] for path [%s].", resourceName, path);
|
||||
search = protectedResource.findByFilter("name=" + resourceName);
|
||||
} else {
|
||||
LOGGER.debugf("Trying to find resource with uri [%s] for path [%s].", path, path);
|
||||
search = protectedResource.findByFilter("uri=" + path);
|
||||
}
|
||||
|
||||
if (search.isEmpty()) {
|
||||
if (enforcerConfig.isCreateResources()) {
|
||||
LOGGER.debugf("Creating resource on server for path [%s].", pathConfig);
|
||||
ResourceRepresentation resource = new ResourceRepresentation();
|
||||
|
||||
resource.setName(resourceName);
|
||||
resource.setType(pathConfig.getType());
|
||||
resource.setUri(path);
|
||||
|
||||
HashSet<ScopeRepresentation> scopes = new HashSet<>();
|
||||
|
||||
for (String scopeName : pathConfig.getScopes()) {
|
||||
ScopeRepresentation scope = new ScopeRepresentation();
|
||||
|
||||
scope.setName(scopeName);
|
||||
|
||||
scopes.add(scope);
|
||||
}
|
||||
|
||||
resource.setScopes(scopes);
|
||||
|
||||
RegistrationResponse registrationResponse = protectedResource.create(resource);
|
||||
|
||||
pathConfig.setId(registrationResponse.getId());
|
||||
} else {
|
||||
throw new RuntimeException("Could not find matching resource on server with uri [" + path + "] or name [" + resourceName + ". Make sure you have created a resource on the server that matches with the path configuration.");
|
||||
}
|
||||
} else {
|
||||
pathConfig.setId(search.iterator().next());
|
||||
}
|
||||
|
||||
paths.add(pathConfig);
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
private List<PathConfig> configureAllPathsForResourceServer(ProtectedResource protectedResource) {
|
||||
LOGGER.info("Querying the server for all resources associated with this application.");
|
||||
List<PathConfig> paths = new ArrayList<>();
|
||||
|
||||
for (String id : protectedResource.findAll()) {
|
||||
RegistrationResponse response = protectedResource.findById(id);
|
||||
ResourceRepresentation resourceDescription = response.getResourceDescription();
|
||||
|
||||
if (resourceDescription.getUri() != null) {
|
||||
paths.add(createPathConfig(resourceDescription));
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
private PathConfig createPathConfig(ResourceRepresentation resourceDescription) {
|
||||
PathConfig pathConfig = new PathConfig();
|
||||
|
||||
pathConfig.setId(resourceDescription.getId());
|
||||
pathConfig.setName(resourceDescription.getName());
|
||||
pathConfig.setPath(resourceDescription.getUri());
|
||||
|
||||
List<String> scopeNames = new ArrayList<>();
|
||||
|
||||
for (ScopeRepresentation scope : resourceDescription.getScopes()) {
|
||||
scopeNames.add(scope.getName());
|
||||
}
|
||||
|
||||
pathConfig.setScopes(scopeNames);
|
||||
pathConfig.setType(resourceDescription.getType());
|
||||
|
||||
return pathConfig;
|
||||
}
|
||||
}
|
|
@ -17,16 +17,16 @@
|
|||
package org.keycloak.adapters.undertow;
|
||||
|
||||
import io.undertow.server.HttpServerExchange;
|
||||
import io.undertow.util.AttachmentKey;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.OIDCHttpFacade;
|
||||
|
||||
import static org.keycloak.adapters.undertow.OIDCUndertowHttpFacade.KEYCLOAK_SECURITY_CONTEXT_KEY;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class OIDCServletUndertowHttpFacade extends ServletHttpFacade implements OIDCHttpFacade {
|
||||
public static final AttachmentKey<KeycloakSecurityContext> KEYCLOAK_SECURITY_CONTEXT_KEY = AttachmentKey.create(KeycloakSecurityContext.class);
|
||||
|
||||
public OIDCServletUndertowHttpFacade(HttpServerExchange exchange) {
|
||||
super(exchange);
|
||||
|
|
53
authz/client/pom.xml
Normal file
53
authz/client/pom.xml
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-parent</artifactId>
|
||||
<version>2.0.0.CR1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>keycloak-authz-client</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>KeyCloak Authz: Client API</name>
|
||||
<description>KeyCloak AuthZ: Client API</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
<version>${jboss.logging.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2016 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.authorization.client;
|
||||
|
||||
import org.keycloak.authorization.client.util.HttpResponseException;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class AuthorizationDeniedException extends RuntimeException {
|
||||
public AuthorizationDeniedException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.authorization.client;
|
||||
|
||||
import org.keycloak.authorization.client.representation.ServerConfiguration;
|
||||
import org.keycloak.authorization.client.resource.AuthorizationResource;
|
||||
import org.keycloak.authorization.client.resource.EntitlementResource;
|
||||
import org.keycloak.authorization.client.resource.ProtectionResource;
|
||||
import org.keycloak.authorization.client.util.Http;
|
||||
import org.keycloak.representations.AccessTokenResponse;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* <p>This is class serves as an entry point for clients looking for access to Keycloak Authorization Services.
|
||||
*
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class AuthzClient {
|
||||
|
||||
private final Http http;
|
||||
|
||||
public static AuthzClient create() {
|
||||
InputStream configStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("keycloak.json");
|
||||
|
||||
if (configStream == null) {
|
||||
throw new RuntimeException("Could not find any keycloak.json file in classpath.");
|
||||
}
|
||||
|
||||
try {
|
||||
return create(JsonSerialization.readValue(configStream, Configuration.class));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Could not parse configuration.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static AuthzClient create(Configuration configuration) {
|
||||
return new AuthzClient(configuration);
|
||||
}
|
||||
|
||||
private final ServerConfiguration serverConfiguration;
|
||||
private final Configuration deployment;
|
||||
|
||||
private AuthzClient(Configuration configuration) {
|
||||
if (configuration == null) {
|
||||
throw new IllegalArgumentException("Client configuration can not be null.");
|
||||
}
|
||||
|
||||
String configurationUrl = configuration.getAuthServerUrl();
|
||||
|
||||
if (configurationUrl == null) {
|
||||
throw new IllegalArgumentException("Configuration URL can not be null.");
|
||||
}
|
||||
|
||||
configurationUrl += "/realms/" + configuration.getRealm() + "/.well-known/uma-configuration";
|
||||
|
||||
this.http = new Http(configuration);
|
||||
|
||||
try {
|
||||
this.serverConfiguration = this.http.<ServerConfiguration>get(URI.create(configurationUrl))
|
||||
.response().json(ServerConfiguration.class)
|
||||
.execute();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Could not obtain configuration from server [" + configurationUrl + "].", e);
|
||||
}
|
||||
|
||||
this.http.setServerConfiguration(this.serverConfiguration);
|
||||
|
||||
this.deployment = configuration;
|
||||
}
|
||||
|
||||
public ProtectionResource protection() {
|
||||
return new ProtectionResource(this.http, obtainAccessToken().getToken());
|
||||
}
|
||||
|
||||
public AuthorizationResource authorization(String accesstoken) {
|
||||
return new AuthorizationResource(this.http, accesstoken);
|
||||
}
|
||||
|
||||
public AuthorizationResource authorization(String userName, String password) {
|
||||
return new AuthorizationResource(this.http, obtainAccessToken(userName, password).getToken());
|
||||
}
|
||||
|
||||
public EntitlementResource entitlement(String eat) {
|
||||
return new EntitlementResource(this.http, eat);
|
||||
}
|
||||
|
||||
public AccessTokenResponse obtainAccessToken() {
|
||||
return this.http.<AccessTokenResponse>post(this.serverConfiguration.getTokenEndpoint())
|
||||
.authentication()
|
||||
.oauth2ClientCredentials()
|
||||
.response()
|
||||
.json(AccessTokenResponse.class)
|
||||
.execute();
|
||||
}
|
||||
|
||||
public AccessTokenResponse obtainAccessToken(String userName, String password) {
|
||||
return this.http.<AccessTokenResponse>post(this.serverConfiguration.getTokenEndpoint())
|
||||
.authentication()
|
||||
.oauth2ResourceOwnerPassword(userName, password)
|
||||
.response()
|
||||
.json(AccessTokenResponse.class)
|
||||
.execute();
|
||||
}
|
||||
|
||||
public ServerConfiguration getServerConfiguration() {
|
||||
return this.serverConfiguration;
|
||||
}
|
||||
|
||||
public Configuration getConfiguration() {
|
||||
return this.deployment;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 2016 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.authorization.client;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public interface ClientAuthenticator {
|
||||
void configureClientCredentials(HashMap<String, String> requestParams, HashMap<String, String> requestHeaders);
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright 2016 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.authorization.client;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.keycloak.util.BasicAuthHelper;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class Configuration {
|
||||
|
||||
@JsonIgnore
|
||||
private HttpClient httpClient;
|
||||
|
||||
@JsonProperty("auth-server-url")
|
||||
protected String authServerUrl;
|
||||
|
||||
@JsonProperty("realm")
|
||||
protected String realm;
|
||||
|
||||
@JsonProperty("resource")
|
||||
protected String clientId;
|
||||
|
||||
@JsonProperty("credentials")
|
||||
protected Map<String, Object> clientCredentials = new HashMap<>();
|
||||
|
||||
public Configuration() {
|
||||
|
||||
}
|
||||
|
||||
public Configuration(String authServerUrl, String realm, String clientId, Map<String, Object> clientCredentials, HttpClient httpClient) {
|
||||
this.authServerUrl = authServerUrl;
|
||||
this.realm = realm;
|
||||
this.clientId = clientId;
|
||||
this.clientCredentials = clientCredentials;
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
private ClientAuthenticator clientAuthenticator = new ClientAuthenticator() {
|
||||
@Override
|
||||
public void configureClientCredentials(HashMap<String, String> requestParams, HashMap<String, String> requestHeaders) {
|
||||
String secret = (String) clientCredentials.get("secret");
|
||||
|
||||
if (secret == null) {
|
||||
throw new RuntimeException("Client secret not provided.");
|
||||
}
|
||||
|
||||
requestHeaders.put("Authorization", BasicAuthHelper.createHeader(clientId, secret));
|
||||
}
|
||||
};
|
||||
|
||||
public HttpClient getHttpClient() {
|
||||
if (this.httpClient == null) {
|
||||
this.httpClient = HttpClients.createDefault();
|
||||
}
|
||||
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public String getAuthServerUrl() {
|
||||
return authServerUrl;
|
||||
}
|
||||
|
||||
public ClientAuthenticator getClientAuthenticator() {
|
||||
return this.clientAuthenticator;
|
||||
}
|
||||
|
||||
public Map<String, Object> getClientCredentials() {
|
||||
return clientCredentials;
|
||||
}
|
||||
|
||||
public String getRealm() {
|
||||
return realm;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.authorization.client.representation;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class AuthorizationRequest {
|
||||
|
||||
private String ticket;
|
||||
private String rpt;
|
||||
|
||||
public AuthorizationRequest(String ticket, String rpt) {
|
||||
this.ticket = ticket;
|
||||
this.rpt = rpt;
|
||||
}
|
||||
|
||||
public AuthorizationRequest(String ticket) {
|
||||
this(ticket, null);
|
||||
}
|
||||
|
||||
public AuthorizationRequest() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
public String getTicket() {
|
||||
return this.ticket;
|
||||
}
|
||||
|
||||
public String getRpt() {
|
||||
return this.rpt;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.authorization.client.representation;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class AuthorizationResponse {
|
||||
|
||||
private String rpt;
|
||||
|
||||
public AuthorizationResponse(String rpt) {
|
||||
this.rpt = rpt;
|
||||
}
|
||||
|
||||
public AuthorizationResponse() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public String getRpt() {
|
||||
return this.rpt;
|
||||
}
|
||||
|
||||
public void setRpt(final String rpt) {
|
||||
this.rpt = rpt;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package org.keycloak.authorization.client.representation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class EntitlementRequest {
|
||||
|
||||
private String rpt;
|
||||
|
||||
private List<PermissionRequest> permissions = new ArrayList<>();
|
||||
|
||||
public List<PermissionRequest> getPermissions() {
|
||||
return permissions;
|
||||
}
|
||||
|
||||
public String getRpt() {
|
||||
return rpt;
|
||||
}
|
||||
|
||||
public void setRpt(String rpt) {
|
||||
this.rpt = rpt;
|
||||
}
|
||||
|
||||
public void setPermissions(List<PermissionRequest> permissions) {
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
public void addPermission(PermissionRequest request) {
|
||||
getPermissions().add(request);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.authorization.client.representation;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class EntitlementResponse {
|
||||
|
||||
private String rpt;
|
||||
|
||||
public EntitlementResponse(String rpt) {
|
||||
this.rpt = rpt;
|
||||
}
|
||||
|
||||
public EntitlementResponse() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public String getRpt() {
|
||||
return this.rpt;
|
||||
}
|
||||
|
||||
public void setRpt(final String rpt) {
|
||||
this.rpt = rpt;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.authorization.client.representation;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class ErrorResponse {
|
||||
|
||||
private String error;
|
||||
|
||||
@JsonProperty("error_description")
|
||||
private String description;
|
||||
|
||||
@JsonProperty("error_uri")
|
||||
private String uri;
|
||||
|
||||
public ErrorResponse(final String error, final String description, final String uri) {
|
||||
this.error = error;
|
||||
this.description = description;
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public ErrorResponse(final String error) {
|
||||
this(error, null, null);
|
||||
}
|
||||
|
||||
public ErrorResponse() {
|
||||
this(null, null, null);
|
||||
}
|
||||
|
||||
public String getError() {
|
||||
return this.error;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
return this.uri;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.authorization.client.representation;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class PermissionRequest {
|
||||
|
||||
@JsonProperty("resource_set_id")
|
||||
private String resourceSetId;
|
||||
|
||||
@JsonProperty("resource_set_name")
|
||||
private String resourceSetName;
|
||||
|
||||
private Set<String> scopes;
|
||||
|
||||
public String getResourceSetId() {
|
||||
return this.resourceSetId;
|
||||
}
|
||||
|
||||
public void setResourceSetId(String resourceSetId) {
|
||||
this.resourceSetId = resourceSetId;
|
||||
}
|
||||
|
||||
public Set<String> getScopes() {
|
||||
return this.scopes;
|
||||
}
|
||||
|
||||
public void setScopes(Set<String> scopes) {
|
||||
this.scopes = scopes;
|
||||
}
|
||||
|
||||
public String getResourceSetName() {
|
||||
return this.resourceSetName;
|
||||
}
|
||||
|
||||
public void setResourceSetName(String resourceSetName) {
|
||||
this.resourceSetName = resourceSetName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.authorization.client.representation;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class PermissionResponse {
|
||||
|
||||
private final String ticket;
|
||||
|
||||
public PermissionResponse(String ticket) {
|
||||
this.ticket = ticket;
|
||||
}
|
||||
|
||||
public PermissionResponse() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public String getTicket() {
|
||||
return this.ticket;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.authorization.client.representation;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonUnwrapped;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class RegistrationResponse {
|
||||
|
||||
private final ResourceRepresentation resourceDescription;
|
||||
|
||||
public RegistrationResponse(ResourceRepresentation resourceDescription) {
|
||||
this.resourceDescription = resourceDescription;
|
||||
}
|
||||
|
||||
public RegistrationResponse() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
@JsonUnwrapped
|
||||
public ResourceRepresentation getResourceDescription() {
|
||||
return this.resourceDescription;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
if (this.resourceDescription != null) {
|
||||
return this.resourceDescription.getId();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.authorization.client.representation;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* <p>One or more resources that the resource server manages as a set of protected resources.
|
||||
*
|
||||
* <p>For more details, <a href="https://docs.kantarainitiative.org/uma/draft-oauth-resource-reg.html#rfc.section.2.2">OAuth-resource-reg</a>.
|
||||
*
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class ResourceRepresentation {
|
||||
|
||||
@JsonProperty("_id")
|
||||
private String id;
|
||||
|
||||
private String name;
|
||||
private String uri;
|
||||
private String type;
|
||||
private Set<ScopeRepresentation> scopes;
|
||||
|
||||
@JsonProperty("icon_uri")
|
||||
private String iconUri;
|
||||
private String owner;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param name a human-readable string describing a set of one or more resources
|
||||
* @param uri a {@link URI} that provides the network location for the resource set being registered
|
||||
* @param type a string uniquely identifying the semantics of the resource set
|
||||
* @param scopes the available scopes for this resource set
|
||||
* @param iconUri a {@link URI} for a graphic icon representing the resource set
|
||||
*/
|
||||
public ResourceRepresentation(String name, Set<ScopeRepresentation> scopes, String uri, String type, String iconUri) {
|
||||
this.name = name;
|
||||
this.scopes = scopes;
|
||||
this.uri = uri;
|
||||
this.type = type;
|
||||
this.iconUri = iconUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param name a human-readable string describing a set of one or more resources
|
||||
* @param uri a {@link URI} that provides the network location for the resource set being registered
|
||||
* @param type a string uniquely identifying the semantics of the resource set
|
||||
* @param scopes the available scopes for this resource set
|
||||
*/
|
||||
public ResourceRepresentation(String name, Set<ScopeRepresentation> scopes, String uri, String type) {
|
||||
this(name, scopes, uri, type, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param name a human-readable string describing a set of one or more resources
|
||||
* @param serverUri a {@link URI} that identifies this resource server
|
||||
* @param scopes the available scopes for this resource set
|
||||
*/
|
||||
public ResourceRepresentation(String name, Set<ScopeRepresentation> scopes) {
|
||||
this(name, scopes, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
*/
|
||||
public ResourceRepresentation() {
|
||||
this(null, null, null, null, null);
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
return this.uri;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public Set<ScopeRepresentation> getScopes() {
|
||||
return Collections.unmodifiableSet(this.scopes);
|
||||
}
|
||||
|
||||
public String getIconUri() {
|
||||
return this.iconUri;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setUri(String uri) {
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void setScopes(Set<ScopeRepresentation> scopes) {
|
||||
this.scopes = scopes;
|
||||
}
|
||||
|
||||
public void setIconUri(String iconUri) {
|
||||
this.iconUri = iconUri;
|
||||
}
|
||||
|
||||
public String getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(String owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public void addScope(ScopeRepresentation scopeRepresentation) {
|
||||
if (this.scopes == null) {
|
||||
this.scopes = new HashSet<>();
|
||||
}
|
||||
this.scopes.add(scopeRepresentation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ResourceRepresentation that = (ResourceRepresentation) o;
|
||||
return Objects.equals(id, that.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ResourceRepresentation{" +
|
||||
"id='" + id + '\'' +
|
||||
", name='" + name + '\'' +
|
||||
", uri='" + uri + '\'' +
|
||||
", type='" + type + '\'' +
|
||||
", owner='" + owner + '\'' +
|
||||
", scopes=" + scopes +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.authorization.client.representation;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* <p>A bounded extent of access that is possible to perform on a resource set. In authorization policy terminology,
|
||||
* a scope is one of the potentially many "verbs" that can logically apply to a resource set ("object").
|
||||
*
|
||||
* <p>For more details, <a href="https://docs.kantarainitiative.org/uma/draft-oauth-resource-reg.html#rfc.section.2.1">OAuth-resource-reg</a>.
|
||||
*
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class ScopeRepresentation {
|
||||
|
||||
private String id;
|
||||
private String name;
|
||||
private String iconUri;
|
||||
|
||||
/**
|
||||
* Creates an instance.
|
||||
*
|
||||
* @param name the a human-readable string describing some scope (extent) of access
|
||||
* @param iconUri a {@link URI} for a graphic icon representing the scope
|
||||
*/
|
||||
public ScopeRepresentation(String name, String iconUri) {
|
||||
this.name = name;
|
||||
this.iconUri = iconUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance.
|
||||
*
|
||||
* @param name the a human-readable string describing some scope (extent) of access
|
||||
*/
|
||||
public ScopeRepresentation(String name) {
|
||||
this(name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance.
|
||||
*/
|
||||
public ScopeRepresentation() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String getIconUri() {
|
||||
return this.iconUri;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ScopeRepresentation scope = (ScopeRepresentation) o;
|
||||
return Objects.equals(getName(), scope.getName());
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return Objects.hash(getName());
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setIconUri(String iconUri) {
|
||||
this.iconUri = iconUri;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,235 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.authorization.client.representation;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class ServerConfiguration {
|
||||
|
||||
private String version;
|
||||
private URI issuer;
|
||||
|
||||
@JsonProperty("pat_profiles_supported")
|
||||
private Set<String> patProfiles;
|
||||
|
||||
@JsonProperty("pat_grant_types_supported")
|
||||
private Set<String> patGrantTypes;
|
||||
|
||||
@JsonProperty("aat_profiles_supported")
|
||||
private Set<String> aatProfiles;
|
||||
|
||||
@JsonProperty("aat_grant_types_supported")
|
||||
private Set<String> aatGrantTypes;
|
||||
|
||||
@JsonProperty("rpt_profiles_supported")
|
||||
private Set<String> rptProfiles;
|
||||
|
||||
@JsonProperty("claim_token_profiles_supported")
|
||||
private Set<String> claimTokenProfiles;
|
||||
|
||||
@JsonProperty("dynamic_client_endpoint")
|
||||
private URI dynamicClientEndpoint;
|
||||
|
||||
@JsonProperty("token_endpoint")
|
||||
private URI tokenEndpoint;
|
||||
|
||||
@JsonProperty("authorization_endpoint")
|
||||
private URI authorizationEndpoint;
|
||||
|
||||
@JsonProperty("requesting_party_claims_endpoint")
|
||||
private URI requestingPartyClaimsEndpoint;
|
||||
|
||||
@JsonProperty("resource_set_registration_endpoint")
|
||||
private URI resourceSetRegistrationEndpoint;
|
||||
|
||||
@JsonProperty("introspection_endpoint")
|
||||
private URI introspectionEndpoint;
|
||||
|
||||
@JsonProperty("permission_registration_endpoint")
|
||||
private URI permissionRegistrationEndpoint;
|
||||
|
||||
@JsonProperty("rpt_endpoint")
|
||||
private URI rptEndpoint;
|
||||
|
||||
/**
|
||||
* Non-standard, Keycloak specific configuration options
|
||||
*/
|
||||
private String realm;
|
||||
|
||||
private String realmPublicKey;
|
||||
|
||||
private URI serverUrl;
|
||||
|
||||
public String getVersion() {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
void setVersion(final String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public URI getIssuer() {
|
||||
return this.issuer;
|
||||
}
|
||||
|
||||
void setIssuer(final URI issuer) {
|
||||
this.issuer = issuer;
|
||||
}
|
||||
|
||||
public Set<String> getPatProfiles() {
|
||||
return this.patProfiles;
|
||||
}
|
||||
|
||||
void setPatProfiles(final Set<String> patProfiles) {
|
||||
this.patProfiles = patProfiles;
|
||||
}
|
||||
|
||||
public Set<String> getPatGrantTypes() {
|
||||
return this.patGrantTypes;
|
||||
}
|
||||
|
||||
void setPatGrantTypes(final Set<String> patGrantTypes) {
|
||||
this.patGrantTypes = patGrantTypes;
|
||||
}
|
||||
|
||||
public Set<String> getAatProfiles() {
|
||||
return this.aatProfiles;
|
||||
}
|
||||
|
||||
void setAatProfiles(final Set<String> aatProfiles) {
|
||||
this.aatProfiles = aatProfiles;
|
||||
}
|
||||
|
||||
public Set<String> getAatGrantTypes() {
|
||||
return this.aatGrantTypes;
|
||||
}
|
||||
|
||||
void setAatGrantTypes(final Set<String> aatGrantTypes) {
|
||||
this.aatGrantTypes = aatGrantTypes;
|
||||
}
|
||||
|
||||
public Set<String> getRptProfiles() {
|
||||
return this.rptProfiles;
|
||||
}
|
||||
|
||||
void setRptProfiles(final Set<String> rptProfiles) {
|
||||
this.rptProfiles = rptProfiles;
|
||||
}
|
||||
|
||||
public Set<String> getClaimTokenProfiles() {
|
||||
return this.claimTokenProfiles;
|
||||
}
|
||||
|
||||
void setClaimTokenProfiles(final Set<String> claimTokenProfiles) {
|
||||
this.claimTokenProfiles = claimTokenProfiles;
|
||||
}
|
||||
|
||||
public URI getDynamicClientEndpoint() {
|
||||
return this.dynamicClientEndpoint;
|
||||
}
|
||||
|
||||
void setDynamicClientEndpoint(final URI dynamicClientEndpoint) {
|
||||
this.dynamicClientEndpoint = dynamicClientEndpoint;
|
||||
}
|
||||
|
||||
public URI getTokenEndpoint() {
|
||||
return this.tokenEndpoint;
|
||||
}
|
||||
|
||||
void setTokenEndpoint(final URI tokenEndpoint) {
|
||||
this.tokenEndpoint = tokenEndpoint;
|
||||
}
|
||||
|
||||
public URI getAuthorizationEndpoint() {
|
||||
return this.authorizationEndpoint;
|
||||
}
|
||||
|
||||
void setAuthorizationEndpoint(final URI authorizationEndpoint) {
|
||||
this.authorizationEndpoint = authorizationEndpoint;
|
||||
}
|
||||
|
||||
public URI getRequestingPartyClaimsEndpoint() {
|
||||
return this.requestingPartyClaimsEndpoint;
|
||||
}
|
||||
|
||||
void setRequestingPartyClaimsEndpoint(final URI requestingPartyClaimsEndpoint) {
|
||||
this.requestingPartyClaimsEndpoint = requestingPartyClaimsEndpoint;
|
||||
}
|
||||
|
||||
public URI getResourceSetRegistrationEndpoint() {
|
||||
return this.resourceSetRegistrationEndpoint;
|
||||
}
|
||||
|
||||
void setResourceSetRegistrationEndpoint(final URI resourceSetRegistrationEndpoint) {
|
||||
this.resourceSetRegistrationEndpoint = resourceSetRegistrationEndpoint;
|
||||
}
|
||||
|
||||
public URI getIntrospectionEndpoint() {
|
||||
return this.introspectionEndpoint;
|
||||
}
|
||||
|
||||
void setIntrospectionEndpoint(final URI introspectionEndpoint) {
|
||||
this.introspectionEndpoint = introspectionEndpoint;
|
||||
}
|
||||
|
||||
public URI getPermissionRegistrationEndpoint() {
|
||||
return this.permissionRegistrationEndpoint;
|
||||
}
|
||||
|
||||
void setPermissionRegistrationEndpoint(final URI permissionRegistrationEndpoint) {
|
||||
this.permissionRegistrationEndpoint = permissionRegistrationEndpoint;
|
||||
}
|
||||
|
||||
public URI getRptEndpoint() {
|
||||
return this.rptEndpoint;
|
||||
}
|
||||
|
||||
void setRptEndpoint(final URI rptEndpoint) {
|
||||
this.rptEndpoint = rptEndpoint;
|
||||
}
|
||||
|
||||
public String getRealm() {
|
||||
return this.realm;
|
||||
}
|
||||
|
||||
public void setRealm(final String realm) {
|
||||
this.realm = realm;
|
||||
}
|
||||
|
||||
public String getRealmPublicKey() {
|
||||
return this.realmPublicKey;
|
||||
}
|
||||
|
||||
public void setRealmPublicKey(String realmPublicKey) {
|
||||
this.realmPublicKey = realmPublicKey;
|
||||
}
|
||||
|
||||
public URI getServerUrl() {
|
||||
return this.serverUrl;
|
||||
}
|
||||
|
||||
public void setServerUrl(URI serverUrl) {
|
||||
this.serverUrl = serverUrl;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright 2016 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.authorization.client.representation;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.keycloak.representations.JsonWebToken;
|
||||
import org.keycloak.representations.authorization.Permission;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class TokenIntrospectionResponse extends JsonWebToken {
|
||||
|
||||
@JsonProperty
|
||||
private Boolean active;
|
||||
|
||||
private List<Permission> permissions;
|
||||
|
||||
public Boolean getActive() {
|
||||
return this.active;
|
||||
}
|
||||
|
||||
public List<Permission> getPermissions() {
|
||||
return this.permissions;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.authorization.client.resource;
|
||||
|
||||
|
||||
import org.keycloak.authorization.client.AuthorizationDeniedException;
|
||||
import org.keycloak.authorization.client.representation.AuthorizationRequest;
|
||||
import org.keycloak.authorization.client.representation.AuthorizationResponse;
|
||||
import org.keycloak.authorization.client.util.Http;
|
||||
import org.keycloak.authorization.client.util.HttpResponseException;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class AuthorizationResource {
|
||||
|
||||
private final Http http;
|
||||
private final String accessToken;
|
||||
|
||||
public AuthorizationResource(Http http, String aat) {
|
||||
this.http = http;
|
||||
this.accessToken = aat;
|
||||
}
|
||||
|
||||
public AuthorizationResponse authorize(AuthorizationRequest request) {
|
||||
try {
|
||||
return this.http.<AuthorizationResponse>post("/authz/authorize")
|
||||
.authorizationBearer(this.accessToken)
|
||||
.json(JsonSerialization.writeValueAsBytes(request))
|
||||
.response().json(AuthorizationResponse.class).execute();
|
||||
} catch (HttpResponseException e) {
|
||||
if (403 == e.getStatusCode()) {
|
||||
throw new AuthorizationDeniedException(e);
|
||||
}
|
||||
throw new RuntimeException("Failed to obtain authorization data.", e);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to obtain authorization data.", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package org.keycloak.authorization.client.resource;
|
||||
|
||||
import org.keycloak.authorization.client.AuthorizationDeniedException;
|
||||
import org.keycloak.authorization.client.representation.EntitlementRequest;
|
||||
import org.keycloak.authorization.client.representation.EntitlementResponse;
|
||||
import org.keycloak.authorization.client.util.Http;
|
||||
import org.keycloak.authorization.client.util.HttpResponseException;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class EntitlementResource {
|
||||
|
||||
private final Http http;
|
||||
private final String eat;
|
||||
|
||||
public EntitlementResource(Http http, String eat) {
|
||||
this.http = http;
|
||||
this.eat = eat;
|
||||
}
|
||||
|
||||
public EntitlementResponse getAll(String resourceServerId) {
|
||||
try {
|
||||
return this.http.<EntitlementResponse>get("/authz/entitlement/" + resourceServerId)
|
||||
.authorizationBearer(this.eat)
|
||||
.response()
|
||||
.json(EntitlementResponse.class).execute();
|
||||
} catch (HttpResponseException e) {
|
||||
if (403 == e.getStatusCode()) {
|
||||
throw new AuthorizationDeniedException(e);
|
||||
}
|
||||
throw new RuntimeException("Failed to obtain entitlements.", e);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to obtain entitlements.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public EntitlementResponse get(String resourceServerId, EntitlementRequest request) {
|
||||
try {
|
||||
return this.http.<EntitlementResponse>post("/authz/entitlement/" + resourceServerId)
|
||||
.authorizationBearer(this.eat)
|
||||
.json(JsonSerialization.writeValueAsBytes(request))
|
||||
.response().json(EntitlementResponse.class).execute();
|
||||
} catch (HttpResponseException e) {
|
||||
if (403 == e.getStatusCode()) {
|
||||
throw new AuthorizationDeniedException(e);
|
||||
}
|
||||
throw new RuntimeException("Failed to obtain entitlements.", e);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to obtain entitlements.", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.authorization.client.resource;
|
||||
|
||||
import org.keycloak.authorization.client.representation.PermissionRequest;
|
||||
import org.keycloak.authorization.client.representation.PermissionResponse;
|
||||
import org.keycloak.authorization.client.util.Http;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class PermissionResource {
|
||||
|
||||
private final Http http;
|
||||
private final String pat;
|
||||
|
||||
public PermissionResource(Http http, String pat) {
|
||||
this.http = http;
|
||||
this.pat = pat;
|
||||
}
|
||||
|
||||
public PermissionResponse forResource(PermissionRequest request) {
|
||||
try {
|
||||
return this.http.<PermissionResponse>post("/authz/protection/permission")
|
||||
.authorizationBearer(this.pat)
|
||||
.json(JsonSerialization.writeValueAsBytes(request))
|
||||
.response().json(PermissionResponse.class).execute();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error obtaining permission ticket.", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.authorization.client.resource;
|
||||
|
||||
import org.keycloak.authorization.client.representation.RegistrationResponse;
|
||||
import org.keycloak.authorization.client.representation.ResourceRepresentation;
|
||||
import org.keycloak.authorization.client.util.Http;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class ProtectedResource {
|
||||
|
||||
private final Http http;
|
||||
private final String pat;
|
||||
|
||||
public ProtectedResource(Http http, String pat) {
|
||||
this.http = http;
|
||||
this.pat = pat;
|
||||
}
|
||||
|
||||
public RegistrationResponse create(ResourceRepresentation resource) {
|
||||
try {
|
||||
return this.http.<RegistrationResponse>post("/authz/protection/resource_set")
|
||||
.authorizationBearer(this.pat)
|
||||
.json(JsonSerialization.writeValueAsBytes(resource))
|
||||
.response().json(RegistrationResponse.class).execute();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Could not create resource.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public RegistrationResponse findById(String id) {
|
||||
try {
|
||||
return this.http.<RegistrationResponse>get("/authz/protection/resource_set/" + id)
|
||||
.authorizationBearer(this.pat)
|
||||
.response().json(RegistrationResponse.class).execute();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Could not find resource.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> findByFilter(String filter) {
|
||||
try {
|
||||
return this.http.<Set>get("/authz/protection/resource_set")
|
||||
.authorizationBearer(this.pat)
|
||||
.param("filter", filter)
|
||||
.response().json(Set.class).execute();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Could not find resource.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> findAll() {
|
||||
try {
|
||||
return this.http.<Set>get("/authz/protection/resource_set")
|
||||
.authorizationBearer(this.pat)
|
||||
.response().json(Set.class).execute();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Could not find resource.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void delete(String id) {
|
||||
try {
|
||||
this.http.delete("/authz/protection/resource_set/" + id)
|
||||
.authorizationBearer(this.pat)
|
||||
.execute();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Could not delete resource.", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright 2016 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.authorization.client.resource;
|
||||
|
||||
import org.keycloak.authorization.client.representation.TokenIntrospectionResponse;
|
||||
import org.keycloak.authorization.client.util.Http;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class ProtectionResource {
|
||||
|
||||
private final String pat;
|
||||
private final Http http;
|
||||
|
||||
public ProtectionResource(Http http, String pat) {
|
||||
if (pat == null) {
|
||||
throw new RuntimeException("No access token was provided when creating client for Protection API.");
|
||||
}
|
||||
|
||||
this.http = http;
|
||||
this.pat = pat;
|
||||
}
|
||||
|
||||
public ProtectedResource resource() {
|
||||
return new ProtectedResource(http, pat);
|
||||
}
|
||||
|
||||
public PermissionResource permission() {
|
||||
return new PermissionResource(http, pat);
|
||||
}
|
||||
|
||||
public TokenIntrospectionResponse introspectRequestingPartyToken(String rpt) {
|
||||
return this.http.<TokenIntrospectionResponse>post("/protocol/openid-connect/token/introspect")
|
||||
.authentication()
|
||||
.oauth2ClientCredentials()
|
||||
.form()
|
||||
.param("token_type_hint", "requesting_party_token")
|
||||
.param("token", rpt)
|
||||
.response().json(TokenIntrospectionResponse.class).execute();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright 2016 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.authorization.client.util;
|
||||
|
||||
import org.apache.http.client.methods.RequestBuilder;
|
||||
import org.keycloak.authorization.client.Configuration;
|
||||
import org.keycloak.authorization.client.representation.ServerConfiguration;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class Http {
|
||||
|
||||
private final Configuration configuration;
|
||||
private ServerConfiguration serverConfiguration;
|
||||
|
||||
public Http(Configuration configuration) {
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
public <R> HttpMethod<R> get(String path) {
|
||||
return method(RequestBuilder.get(this.serverConfiguration.getIssuer() + path));
|
||||
}
|
||||
|
||||
public <R> HttpMethod<R> get(URI path) {
|
||||
return method(RequestBuilder.get(path));
|
||||
}
|
||||
|
||||
public <R> HttpMethod<R> post(URI path) {
|
||||
return method(RequestBuilder.post(path));
|
||||
}
|
||||
|
||||
public <R> HttpMethod<R> post(String path) {
|
||||
return method(RequestBuilder.post(this.serverConfiguration.getIssuer() + path));
|
||||
}
|
||||
|
||||
public <R> HttpMethod<R> delete(String path) {
|
||||
return method(RequestBuilder.delete(this.serverConfiguration.getIssuer() + path));
|
||||
}
|
||||
|
||||
private <R> HttpMethod<R> method(RequestBuilder builder) {
|
||||
return new HttpMethod(this.configuration, builder);
|
||||
}
|
||||
|
||||
public void setServerConfiguration(ServerConfiguration serverConfiguration) {
|
||||
this.serverConfiguration = serverConfiguration;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright 2016 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.authorization.client.util;
|
||||
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.StatusLine;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.RequestBuilder;
|
||||
import org.apache.http.entity.ByteArrayEntity;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.keycloak.authorization.client.Configuration;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class HttpMethod<R> {
|
||||
|
||||
private final HttpClient httpClient;
|
||||
private final RequestBuilder builder;
|
||||
protected final Configuration configuration;
|
||||
protected final HashMap<String, String> headers;
|
||||
protected final HashMap<String, String> params;
|
||||
private HttpMethodResponse<R> response;
|
||||
|
||||
public HttpMethod(Configuration configuration, RequestBuilder builder) {
|
||||
this(configuration, builder, new HashMap<>(), new HashMap<>());
|
||||
}
|
||||
|
||||
public HttpMethod(Configuration configuration, RequestBuilder builder, HashMap<String, String> params, HashMap<String, String> headers) {
|
||||
this.configuration = configuration;
|
||||
this.httpClient = configuration.getHttpClient();
|
||||
this.builder = builder;
|
||||
this.params = params;
|
||||
this.headers = headers;
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
execute(new HttpResponseProcessor<R>() {
|
||||
@Override
|
||||
public R process(byte[] entity) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public R execute(HttpResponseProcessor<R> responseProcessor) {
|
||||
byte[] bytes = null;
|
||||
|
||||
try {
|
||||
for (Map.Entry<String, String> header : this.headers.entrySet()) {
|
||||
this.builder.setHeader(header.getKey(), header.getValue());
|
||||
}
|
||||
|
||||
preExecute(this.builder);
|
||||
|
||||
HttpResponse response = this.httpClient.execute(this.builder.build());
|
||||
HttpEntity entity = response.getEntity();
|
||||
|
||||
if (entity != null) {
|
||||
bytes = EntityUtils.toByteArray(entity);
|
||||
}
|
||||
|
||||
StatusLine statusLine = response.getStatusLine();
|
||||
int statusCode = statusLine.getStatusCode();
|
||||
|
||||
if (statusCode < 200 || statusCode >= 300) {
|
||||
throw new HttpResponseException(statusCode, statusLine.getReasonPhrase(), bytes);
|
||||
}
|
||||
|
||||
if (bytes == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return responseProcessor.process(bytes);
|
||||
} catch (HttpResponseException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error executing http method [" + builder + "]. Response : " + new String(bytes), e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void preExecute(RequestBuilder builder) {
|
||||
for (Map.Entry<String, String> param : params.entrySet()) {
|
||||
builder.addParameter(param.getKey(), param.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public HttpMethod<R> authorizationBearer(String bearer) {
|
||||
this.builder.addHeader("Authorization", "Bearer " + bearer);
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpMethodResponse<R> response() {
|
||||
this.response = new HttpMethodResponse(this);
|
||||
return this.response;
|
||||
}
|
||||
|
||||
public HttpMethodAuthenticator<R> authentication() {
|
||||
return new HttpMethodAuthenticator<R>(this);
|
||||
}
|
||||
|
||||
public HttpMethod<R> param(String name, String value) {
|
||||
this.params.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpMethod<R> json(byte[] entity) {
|
||||
this.builder.addHeader("Content-Type", "application/json");
|
||||
this.builder.setEntity(new ByteArrayEntity(entity));
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpMethod<R> form() {
|
||||
return new HttpMethod<R>(this.configuration, this.builder, this.params, this.headers) {
|
||||
@Override
|
||||
protected void preExecute(RequestBuilder builder) {
|
||||
if (params != null) {
|
||||
List<NameValuePair> formparams = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<String, String> param : params.entrySet()) {
|
||||
formparams.add(new BasicNameValuePair(param.getKey(), param.getValue()));
|
||||
}
|
||||
|
||||
try {
|
||||
builder.setEntity(new UrlEncodedFormEntity(formparams, "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("Error creating form parameters");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright 2016 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.authorization.client.util;
|
||||
|
||||
import org.keycloak.OAuth2Constants;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class HttpMethodAuthenticator<R> {
|
||||
|
||||
private final HttpMethod<R> method;
|
||||
|
||||
public HttpMethodAuthenticator(HttpMethod<R> method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public HttpMethod<R> oauth2ClientCredentials() {
|
||||
this.method.params.put(OAuth2Constants.GRANT_TYPE, OAuth2Constants.CLIENT_CREDENTIALS);
|
||||
configureClientCredentials();
|
||||
return this.method;
|
||||
}
|
||||
|
||||
public HttpMethod<R> oauth2ResourceOwnerPassword(String userName, String password) {
|
||||
this.method.params.put(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD);
|
||||
this.method.params.put("username", userName);
|
||||
this.method.params.put("password", password);
|
||||
configureClientCredentials();
|
||||
return this.method;
|
||||
}
|
||||
|
||||
private void configureClientCredentials() {
|
||||
this.method.configuration.getClientAuthenticator().configureClientCredentials(this.method.params, this.method.headers);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright 2016 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.authorization.client.util;
|
||||
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class HttpMethodResponse<R> {
|
||||
|
||||
private final HttpMethod<R> method;
|
||||
|
||||
public HttpMethodResponse(HttpMethod method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public R execute() {
|
||||
return this.method.execute(new HttpResponseProcessor<R>() {
|
||||
@Override
|
||||
public R process(byte[] entity) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public HttpMethodResponse<R> json(Class<R> responseType) {
|
||||
return new HttpMethodResponse<R>(this.method) {
|
||||
@Override
|
||||
public R execute() {
|
||||
return method.execute(new HttpResponseProcessor<R>() {
|
||||
@Override
|
||||
public R process(byte[] entity) {
|
||||
try {
|
||||
return JsonSerialization.readValue(entity, responseType);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error parsing JSON response.", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright 2016 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.authorization.client.util;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class HttpResponseException extends RuntimeException {
|
||||
|
||||
private final int statusCode;
|
||||
private final String reasonPhrase;
|
||||
private final byte[] bytes;
|
||||
|
||||
public HttpResponseException(int statusCode, String reasonPhrase, byte[] bytes) {
|
||||
this.statusCode = statusCode;
|
||||
this.reasonPhrase = reasonPhrase;
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
public int getStatusCode() {
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
public String getReasonPhrase() {
|
||||
return reasonPhrase;
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright 2016 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.authorization.client.util;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public interface HttpResponseProcessor<R> {
|
||||
|
||||
R process(byte[] entity);
|
||||
}
|
33
authz/policy/aggregate/pom.xml
Normal file
33
authz/policy/aggregate/pom.xml
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-provider-parent</artifactId>
|
||||
<version>2.0.0.CR1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>keycloak-authz-policy-aggregate</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>KeyCloak AuthZ: Aggregate Policy Provider</name>
|
||||
<description>KeyCloak AuthZ: Aggregate Policy Provider</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-server-spi</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2016 Red Hat, Inc., and individual 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.authorization.policy.provider.time;
|
||||
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class AggregatePolicyAdminResource implements PolicyProviderAdminService {
|
||||
|
||||
private final ResourceServer resourceServer;
|
||||
|
||||
public AggregatePolicyAdminResource(ResourceServer resourceServer) {
|
||||
this.resourceServer = resourceServer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Policy policy) {
|
||||
verifyCircularReference(policy, new ArrayList<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(Policy policy) {
|
||||
verifyCircularReference(policy, new ArrayList<>());
|
||||
}
|
||||
|
||||
private void verifyCircularReference(Policy policy, List<String> ids) {
|
||||
if (!policy.getType().equals("aggregate")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ids.contains(policy.getId())) {
|
||||
throw new RuntimeException("Circular reference found [" + policy.getName() + "].");
|
||||
}
|
||||
|
||||
ids.add(policy.getId());
|
||||
|
||||
for (Policy associated : policy.getAssociatedPolicies()) {
|
||||
verifyCircularReference(associated, ids);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove(Policy policy) {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.authorization.policy.provider.time;
|
||||
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.policy.evaluation.DecisionResultCollector;
|
||||
import org.keycloak.authorization.policy.evaluation.Evaluation;
|
||||
import org.keycloak.authorization.policy.evaluation.DefaultEvaluation;
|
||||
import org.keycloak.authorization.policy.evaluation.Result;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class AggregatePolicyProvider implements PolicyProvider {
|
||||
|
||||
private final Policy policy;
|
||||
private final AuthorizationProvider authorization;
|
||||
|
||||
public AggregatePolicyProvider(Policy policy, AuthorizationProvider authorization) {
|
||||
this.policy = policy;
|
||||
this.authorization = authorization;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(Evaluation evaluation) {
|
||||
//TODO: need to detect deep recursions
|
||||
DecisionResultCollector decision = new DecisionResultCollector() {
|
||||
@Override
|
||||
protected void onComplete(List<Result> results) {
|
||||
if (results.isEmpty()) {
|
||||
evaluation.deny();
|
||||
} else {
|
||||
Result result = results.iterator().next();
|
||||
|
||||
if (Effect.PERMIT.equals(result.getEffect())) {
|
||||
evaluation.grant();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.policy.getAssociatedPolicies().forEach(associatedPolicy -> {
|
||||
PolicyProviderFactory providerFactory = authorization.getProviderFactory(associatedPolicy.getType());
|
||||
PolicyProvider policyProvider = providerFactory.create(associatedPolicy, authorization);
|
||||
policyProvider.evaluate(new DefaultEvaluation(evaluation.getPermission(), evaluation.getContext(), policy, associatedPolicy, decision));
|
||||
});
|
||||
|
||||
decision.onComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package org.keycloak.authorization.policy.provider.time;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class AggregatePolicyProviderFactory implements PolicyProviderFactory {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Aggregated";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup() {
|
||||
return "Others";
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
|
||||
return new AggregatePolicyProvider(policy, authorization);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer) {
|
||||
return new AggregatePolicyAdminResource(resourceServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProvider create(KeycloakSession session) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "aggregate";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# JBoss, Home of Professional Open Source.
|
||||
# Copyright 2016 Red Hat, Inc., and individual 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.authorization.policy.provider.time.AggregatePolicyProviderFactory
|
45
authz/policy/drools/pom.xml
Normal file
45
authz/policy/drools/pom.xml
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-provider-parent</artifactId>
|
||||
<version>2.0.0.CR1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>keycloak-authz-policy-drools</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>KeyCloak AuthZ: Drools Policy Provider</name>
|
||||
<description>KeyCloak AuthZ: Drools Policy Provider</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-server-spi</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-services</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.drools</groupId>
|
||||
<artifactId>drools-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jboss.spec.javax.ws.rs</groupId>
|
||||
<artifactId>jboss-jaxrs-api_2.0_spec</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,71 @@
|
|||
package org.keycloak.authorization.policy.provider.drools;
|
||||
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.policy.evaluation.Evaluation;
|
||||
import org.kie.api.KieServices;
|
||||
import org.kie.api.builder.KieScanner;
|
||||
import org.kie.api.runtime.KieContainer;
|
||||
import org.kie.api.runtime.KieSession;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
class DroolsPolicy {
|
||||
|
||||
private static final int SESSION_POOL_SIZE = 10;
|
||||
|
||||
private final KieContainer kc;
|
||||
private final KieScanner kcs;
|
||||
private final String sessionName;
|
||||
|
||||
DroolsPolicy(KieServices ks, Policy associatedPolicy) {
|
||||
String groupId = associatedPolicy.getConfig().get("mavenArtifactGroupId");
|
||||
String artifactId = associatedPolicy.getConfig().get("mavenArtifactId");
|
||||
String version = associatedPolicy.getConfig().get("mavenArtifactVersion");
|
||||
String scannerPeriod = associatedPolicy.getConfig().get("scannerPeriod");
|
||||
String scannerPeriodUnit = associatedPolicy.getConfig().get("scannerPeriodUnit");
|
||||
this.sessionName = associatedPolicy.getConfig().get("sessionName");
|
||||
|
||||
this.kc = ks.newKieContainer(ks.newReleaseId(groupId, artifactId, version));
|
||||
this.kcs = ks.newKieScanner(this.kc);
|
||||
this.kcs.start(toMillis(scannerPeriod, scannerPeriodUnit));
|
||||
|
||||
KieSession session = this.kc.newKieSession(this.sessionName);
|
||||
|
||||
if (session == null) {
|
||||
throw new RuntimeException("Could not obtain session with name [" + this.sessionName + "].");
|
||||
}
|
||||
|
||||
session.dispose();
|
||||
}
|
||||
|
||||
void evaluate(Evaluation evaluation) {
|
||||
KieSession session = this.kc.newKieSession(this.sessionName);
|
||||
|
||||
session.insert(evaluation);
|
||||
session.fireAllRules();
|
||||
|
||||
session.dispose();
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
this.kcs.stop();
|
||||
}
|
||||
|
||||
private long toMillis(final String scannerPeriod, final String scannerPeriodUnit) {
|
||||
switch (scannerPeriodUnit) {
|
||||
case "Seconds":
|
||||
return TimeUnit.SECONDS.toMillis(Integer.valueOf(scannerPeriod));
|
||||
case "Minutes":
|
||||
return TimeUnit.MINUTES.toMillis(Integer.valueOf(scannerPeriod));
|
||||
case "Hours":
|
||||
return TimeUnit.HOURS.toMillis(Integer.valueOf(scannerPeriod));
|
||||
case "Days":
|
||||
return TimeUnit.DAYS.toMillis(Integer.valueOf(scannerPeriod));
|
||||
}
|
||||
|
||||
throw new RuntimeException("Invalid time period [" + scannerPeriodUnit + "].");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package org.keycloak.authorization.policy.provider.drools;
|
||||
|
||||
import org.keycloak.authorization.admin.representation.PolicyRepresentation;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
||||
import org.kie.api.runtime.KieContainer;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class DroolsPolicyAdminResource implements PolicyProviderAdminService {
|
||||
|
||||
private final ResourceServer resourceServer;
|
||||
private final DroolsPolicyProviderFactory factory;
|
||||
|
||||
public DroolsPolicyAdminResource(ResourceServer resourceServer, DroolsPolicyProviderFactory factory) {
|
||||
this.resourceServer = resourceServer;
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Policy policy) {
|
||||
this.factory.update(policy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(Policy policy) {
|
||||
this.factory.update(policy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove(Policy policy) {
|
||||
this.factory.remove(policy);
|
||||
}
|
||||
|
||||
@Path("/resolveModules")
|
||||
@POST
|
||||
@Consumes("application/json")
|
||||
@Produces("application/json")
|
||||
public Response resolveModules(PolicyRepresentation policy) {
|
||||
return Response.ok(getContainer(policy).getKieBaseNames()).build();
|
||||
}
|
||||
|
||||
@Path("/resolveSessions")
|
||||
@POST
|
||||
@Consumes("application/json")
|
||||
@Produces("application/json")
|
||||
public Response resolveSessions(PolicyRepresentation policy) {
|
||||
return Response.ok(getContainer(policy).getKieSessionNamesInKieBase(policy.getConfig().get("moduleName"))).build();
|
||||
}
|
||||
|
||||
private KieContainer getContainer(PolicyRepresentation policy) {
|
||||
String groupId = policy.getConfig().get("mavenArtifactGroupId");
|
||||
String artifactId = policy.getConfig().get("mavenArtifactId");
|
||||
String version = policy.getConfig().get("mavenArtifactVersion");
|
||||
return this.factory.getKieContainer(groupId, artifactId, version);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.authorization.policy.provider.drools;
|
||||
|
||||
import org.keycloak.authorization.policy.evaluation.Evaluation;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class DroolsPolicyProvider implements PolicyProvider {
|
||||
|
||||
private final DroolsPolicy policy;
|
||||
|
||||
public DroolsPolicyProvider(DroolsPolicy policy) {
|
||||
this.policy = policy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(Evaluation evaluationt) {
|
||||
this.policy.evaluate(evaluationt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
package org.keycloak.authorization.policy.provider.drools;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
import org.kie.api.KieServices;
|
||||
import org.kie.api.KieServices.Factory;
|
||||
import org.kie.api.runtime.KieContainer;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class DroolsPolicyProviderFactory implements PolicyProviderFactory {
|
||||
|
||||
private KieServices ks;
|
||||
private final Map<String, DroolsPolicy> containers = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Drools";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup() {
|
||||
return "Rule Based";
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
|
||||
if (!this.containers.containsKey(policy.getId())) {
|
||||
update(policy);
|
||||
}
|
||||
|
||||
return new DroolsPolicyProvider(this.containers.get(policy.getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer) {
|
||||
return new DroolsPolicyAdminResource(resourceServer, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProvider create(KeycloakSession session) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
this.ks = Factory.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
ProviderFactory<AuthorizationProvider> providerFactory = factory.getProviderFactory(AuthorizationProvider.class);
|
||||
AuthorizationProvider authorization = providerFactory.create(factory.create());
|
||||
authorization.getStoreFactory().getPolicyStore().findByType(getId()).forEach(this::update);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
this.containers.values().forEach(DroolsPolicy::dispose);
|
||||
this.containers.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "drools";
|
||||
}
|
||||
|
||||
void update(Policy policy) {
|
||||
remove(policy);
|
||||
this.containers.put(policy.getId(), new DroolsPolicy(this.ks, policy));
|
||||
}
|
||||
|
||||
void remove(Policy policy) {
|
||||
DroolsPolicy holder = this.containers.remove(policy.getId());
|
||||
|
||||
if (holder != null) {
|
||||
holder.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
KieContainer getKieContainer(String groupId, String artifactId, String version) {
|
||||
return this.ks.newKieContainer(this.ks.newReleaseId(groupId, artifactId, version));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# JBoss, Home of Professional Open Source.
|
||||
# Copyright 2016 Red Hat, Inc., and individual 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.authorization.policy.provider.drools.DroolsPolicyProviderFactory
|
33
authz/policy/javascript/pom.xml
Normal file
33
authz/policy/javascript/pom.xml
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-provider-parent</artifactId>
|
||||
<version>2.0.0.CR1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>keycloak-authz-policy-js</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>KeyCloak AuthZ: Javascript-based Policy Provider</name>
|
||||
<description>KeyCloak AuthZ: Javascript-based Policy Provider</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-server-spi</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.authorization.policy.provider.js;
|
||||
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.policy.evaluation.Evaluation;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class JSPolicyProvider implements PolicyProvider {
|
||||
|
||||
private final Policy policy;
|
||||
|
||||
public JSPolicyProvider(Policy policy) {
|
||||
this.policy = policy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(Evaluation evaluation) {
|
||||
ScriptEngineManager manager = new ScriptEngineManager();
|
||||
ScriptEngine engine = manager.getEngineByName("nashorn");
|
||||
|
||||
engine.put("$evaluation", evaluation);
|
||||
|
||||
try {
|
||||
engine.eval(policy.getConfig().get("code"));
|
||||
} catch (ScriptException e) {
|
||||
throw new RuntimeException("Error evaluating JS Policy [" + policy.getName() + "].", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package org.keycloak.authorization.policy.provider.js;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class JSPolicyProviderFactory implements PolicyProviderFactory {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "JavaScript";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup() {
|
||||
return "Rule Based";
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
|
||||
return new JSPolicyProvider(policy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProvider create(KeycloakSession session) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "js";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# JBoss, Home of Professional Open Source.
|
||||
# Copyright 2016 Red Hat, Inc., and individual 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.authorization.policy.provider.js.JSPolicyProviderFactory
|
31
authz/policy/pom.xml
Normal file
31
authz/policy/pom.xml
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-parent</artifactId>
|
||||
<version>2.0.0.CR1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>keycloak-authz-provider-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>KeyCloak AuthZ: Provider Parent</name>
|
||||
<description>KeyCloak AuthZ: Provider Parent</description>
|
||||
|
||||
<modules>
|
||||
<module>user</module>
|
||||
<module>role</module>
|
||||
<module>drools</module>
|
||||
<module>resource</module>
|
||||
<module>scope</module>
|
||||
<module>javascript</module>
|
||||
<module>time</module>
|
||||
<module>aggregate</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
33
authz/policy/resource/pom.xml
Normal file
33
authz/policy/resource/pom.xml
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-provider-parent</artifactId>
|
||||
<version>2.0.0.CR1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>keycloak-authz-policy-resource</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>KeyCloak Authz: Resource Policy Provider</name>
|
||||
<description>KeyCloak Authz: Resource Policy Provider</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-server-spi</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.authorization.policy.provider.resource;
|
||||
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.policy.evaluation.Evaluation;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class ResourcePolicyProvider implements PolicyProvider {
|
||||
|
||||
public ResourcePolicyProvider(Policy policy) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(Evaluation evaluation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package org.keycloak.authorization.policy.provider.resource;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class ResourcePolicyProviderFactory implements PolicyProviderFactory {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Resource-Based";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup() {
|
||||
return "Permission";
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
|
||||
return new ResourcePolicyProvider(policy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProvider create(KeycloakSession session) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "resource";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# JBoss, Home of Professional Open Source.
|
||||
# Copyright 2016 Red Hat, Inc., and individual 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.authorization.policy.provider.resource.ResourcePolicyProviderFactory
|
51
authz/policy/role/pom.xml
Normal file
51
authz/policy/role/pom.xml
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ JBoss, Home of Professional Open Source.
|
||||
~ Copyright 2016 Red Hat, Inc., and individual 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-provider-parent</artifactId>
|
||||
<version>2.0.0.CR1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>keycloak-authz-policy-role</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>KeyCloak AuthZ: Role Policy Provider</name>
|
||||
<description>KeyCloak AuthZ: Role Policy Provider</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-server-spi</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2016 Red Hat, Inc., and individual 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.authorization.policy.provider.identity;
|
||||
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
import org.keycloak.authorization.identity.Identity;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.policy.evaluation.Evaluation;
|
||||
import org.keycloak.authorization.policy.evaluation.EvaluationContext;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
|
||||
import static org.keycloak.authorization.policy.provider.identity.RolePolicyProviderFactory.getRoles;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class RolePolicyProvider implements PolicyProvider {
|
||||
|
||||
private final Policy policy;
|
||||
private final AuthorizationProvider authorization;
|
||||
|
||||
public RolePolicyProvider(Policy policy, AuthorizationProvider authorization) {
|
||||
this.policy = policy;
|
||||
this.authorization = authorization;
|
||||
}
|
||||
|
||||
public RolePolicyProvider() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(Evaluation evaluation) {
|
||||
EvaluationContext context = evaluation.getContext();
|
||||
String[] roleIds = getRoles(this.policy);
|
||||
|
||||
if (roleIds.length > 0) {
|
||||
Identity identity = context.getIdentity();
|
||||
|
||||
for (String roleId : roleIds) {
|
||||
RoleModel role = getCurrentRealm().getRoleById(roleId);
|
||||
|
||||
if (role != null && identity.hasRole(role.getName())) {
|
||||
evaluation.grant();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private RealmModel getCurrentRealm() {
|
||||
return this.authorization.getKeycloakSession().getContext().getRealm();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2016 Red Hat, Inc., and individual 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.authorization.policy.provider.identity;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
||||
import org.keycloak.authorization.store.PolicyStore;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.models.RoleContainerModel.RoleRemovedEvent;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class RolePolicyProviderFactory implements PolicyProviderFactory {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Role-Based";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup() {
|
||||
return "Identity Based";
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
|
||||
return new RolePolicyProvider(policy, authorization);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProvider create(KeycloakSession session) {
|
||||
return new RolePolicyProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
factory.register(event -> {
|
||||
if (event instanceof RoleRemovedEvent) {
|
||||
KeycloakSession keycloakSession = ((RoleRemovedEvent) event).getKeycloakSession();
|
||||
AuthorizationProvider provider = keycloakSession.getProvider(AuthorizationProvider.class);
|
||||
PolicyStore policyStore = provider.getStoreFactory().getPolicyStore();
|
||||
RoleModel removedRole = ((RoleRemovedEvent) event).getRole();
|
||||
|
||||
policyStore.findByType(getId()).forEach(policy -> {
|
||||
List<String> roles = new ArrayList<>();
|
||||
|
||||
for (String roleId : getRoles(policy)) {
|
||||
if (!roleId.equals(removedRole.getId())) {
|
||||
roles.add(roleId);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (roles.isEmpty()) {
|
||||
policyStore.findDependentPolicies(policy.getId()).forEach(dependentPolicy -> {
|
||||
dependentPolicy.removeAssociatedPolicy(policy);
|
||||
});
|
||||
policyStore.delete(policy.getId());
|
||||
} else {
|
||||
policy.getConfig().put("roles", JsonSerialization.writeValueAsString(roles));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error while synchronizing roles with policy [" + policy.getName() + "].", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "role";
|
||||
}
|
||||
|
||||
static String[] getRoles(Policy policy) {
|
||||
String roles = policy.getConfig().get("roles");
|
||||
|
||||
if (roles != null) {
|
||||
try {
|
||||
return JsonSerialization.readValue(roles.getBytes(), String[].class);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Could not parse roles [" + roles + "] from policy config [" + policy.getName() + ".", e);
|
||||
}
|
||||
}
|
||||
|
||||
return new String[]{};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# JBoss, Home of Professional Open Source.
|
||||
# Copyright 2016 Red Hat, Inc., and individual 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.authorization.policy.provider.identity.RolePolicyProviderFactory
|
33
authz/policy/scope/pom.xml
Normal file
33
authz/policy/scope/pom.xml
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-provider-parent</artifactId>
|
||||
<version>2.0.0.CR1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>keycloak-authz-policy-scope</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>KeyCloak AuthZ: Scope Policy Provider</name>
|
||||
<description>KeyCloak AuthZ: Scope Policy Provider</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-server-spi</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.authorization.policy.provider.scope;
|
||||
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.policy.evaluation.Evaluation;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class ScopePolicyProvider implements PolicyProvider {
|
||||
|
||||
private final Policy policy;
|
||||
|
||||
public ScopePolicyProvider(Policy policy) {
|
||||
this.policy = policy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(Evaluation evaluation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package org.keycloak.authorization.policy.provider.scope;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class ScopePolicyProviderFactory implements PolicyProviderFactory {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Scope-Based";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup() {
|
||||
return "Permission";
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
|
||||
return new ScopePolicyProvider(policy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProvider create(KeycloakSession session) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "scope";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# JBoss, Home of Professional Open Source.
|
||||
# Copyright 2016 Red Hat, Inc., and individual 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.authorization.policy.provider.scope.ScopePolicyProviderFactory
|
32
authz/policy/time/pom.xml
Normal file
32
authz/policy/time/pom.xml
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-provider-parent</artifactId>
|
||||
<version>2.0.0.CR1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>keycloak-authz-policy-time</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>KeyCloak AuthZ: Time-based Policy Provider</name>
|
||||
<description>KeyCloak AuthZ: Time-based Policy Provider</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-server-spi</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2016 Red Hat, Inc., and individual 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.authorization.policy.provider.time;
|
||||
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class TimePolicyAdminResource implements PolicyProviderAdminService {
|
||||
|
||||
@Override
|
||||
public void onCreate(Policy policy) {
|
||||
validateConfig(policy);
|
||||
}
|
||||
|
||||
private void validateConfig(Policy policy) {
|
||||
String nbf = policy.getConfig().get("nbf");
|
||||
String noa = policy.getConfig().get("noa");
|
||||
|
||||
if (nbf == null && noa == null) {
|
||||
throw new RuntimeException("You must provide NotBefore, NotOnOrAfter or both.");
|
||||
}
|
||||
|
||||
validateFormat(nbf);
|
||||
validateFormat(noa);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(Policy policy) {
|
||||
validateConfig(policy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove(Policy policy) {
|
||||
}
|
||||
|
||||
private void validateFormat(String date) {
|
||||
try {
|
||||
new SimpleDateFormat(TimePolicyProvider.DEFAULT_DATE_PATTERN).parse(TimePolicyProvider.format(date));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Could not parse a date using format [" + date + "]");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.authorization.policy.provider.time;
|
||||
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.policy.evaluation.Evaluation;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class TimePolicyProvider implements PolicyProvider {
|
||||
|
||||
static String DEFAULT_DATE_PATTERN = "yyyy-MM-dd hh:mm:ss";
|
||||
|
||||
private final Policy policy;
|
||||
private final SimpleDateFormat dateFormat;
|
||||
private final Date currentDate;
|
||||
|
||||
public TimePolicyProvider(Policy policy) {
|
||||
this.policy = policy;
|
||||
this.dateFormat = new SimpleDateFormat(DEFAULT_DATE_PATTERN);
|
||||
this.currentDate = new Date();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(Evaluation evaluation) {
|
||||
try {
|
||||
String notBefore = this.policy.getConfig().get("nbf");
|
||||
|
||||
if (notBefore != null) {
|
||||
|
||||
if (this.currentDate.before(this.dateFormat.parse(format(notBefore)))) {
|
||||
evaluation.deny();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
String notOnOrAfter = this.policy.getConfig().get("noa");
|
||||
|
||||
if (notOnOrAfter != null) {
|
||||
if (this.currentDate.after(this.dateFormat.parse(format(notOnOrAfter)))) {
|
||||
evaluation.deny();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
evaluation.grant();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Could not evaluate time-based policy [" + this.policy.getName() + "].", e);
|
||||
}
|
||||
}
|
||||
|
||||
static String format(String notBefore) {
|
||||
String trimmed = notBefore.trim();
|
||||
|
||||
if (trimmed.length() == 10) {
|
||||
notBefore = trimmed + " 00:00:00";
|
||||
}
|
||||
|
||||
return notBefore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package org.keycloak.authorization.policy.provider.time;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class TimePolicyProviderFactory implements PolicyProviderFactory {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Time";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup() {
|
||||
return "Time Based";
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
|
||||
return new TimePolicyProvider(policy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer) {
|
||||
return new TimePolicyAdminResource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProvider create(KeycloakSession session) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "time";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# JBoss, Home of Professional Open Source.
|
||||
# Copyright 2016 Red Hat, Inc., and individual 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.authorization.policy.provider.time.TimePolicyProviderFactory
|
51
authz/policy/user/pom.xml
Normal file
51
authz/policy/user/pom.xml
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ JBoss, Home of Professional Open Source.
|
||||
~ Copyright 2016 Red Hat, Inc., and individual 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-provider-parent</artifactId>
|
||||
<version>2.0.0.CR1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>keycloak-authz-policy-user</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>KeyCloak AuthZ: User Policy Provider</name>
|
||||
<description>KeyCloak AuthZ: User Policy Provider</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-server-spi</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2016 Red Hat, Inc., and individual 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.authorization.policy.provider.identity;
|
||||
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.policy.evaluation.Evaluation;
|
||||
import org.keycloak.authorization.policy.evaluation.EvaluationContext;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.keycloak.authorization.policy.provider.identity.UserPolicyProviderFactory.getUsers;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class UserPolicyProvider implements PolicyProvider {
|
||||
|
||||
private final Policy policy;
|
||||
|
||||
public UserPolicyProvider(Policy policy) {
|
||||
this.policy = policy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(Evaluation evaluation) {
|
||||
EvaluationContext context = evaluation.getContext();
|
||||
String[] userIds = getUsers(this.policy);
|
||||
|
||||
if (userIds.length > 0) {
|
||||
for (String userId : userIds) {
|
||||
if (context.getIdentity().getId().equals(userId)) {
|
||||
evaluation.grant();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2016 Red Hat, Inc., and individual 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.authorization.policy.provider.identity;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
||||
import org.keycloak.authorization.store.PolicyStore;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserModel.UserRemovedEvent;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class UserPolicyProviderFactory implements PolicyProviderFactory {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "User-Based";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup() {
|
||||
return "Identity Based";
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
|
||||
return new UserPolicyProvider(policy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProvider create(KeycloakSession session) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
factory.register(event -> {
|
||||
if (event instanceof UserRemovedEvent) {
|
||||
KeycloakSession keycloakSession = ((UserRemovedEvent) event).getKeycloakSession();
|
||||
AuthorizationProvider provider = keycloakSession.getProvider(AuthorizationProvider.class);
|
||||
PolicyStore policyStore = provider.getStoreFactory().getPolicyStore();
|
||||
UserModel removedUser = ((UserRemovedEvent) event).getUser();
|
||||
|
||||
policyStore.findByType(getId()).forEach(policy -> {
|
||||
List<String> users = new ArrayList<>();
|
||||
|
||||
for (String userId : getUsers(policy)) {
|
||||
if (!userId.equals(removedUser.getId())) {
|
||||
users.add(userId);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (users.isEmpty()) {
|
||||
policyStore.findDependentPolicies(policy.getId()).forEach(dependentPolicy -> {
|
||||
dependentPolicy.removeAssociatedPolicy(policy);
|
||||
});
|
||||
policyStore.delete(policy.getId());
|
||||
} else {
|
||||
policy.getConfig().put("users", JsonSerialization.writeValueAsString(users));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error while synchronizing users with policy [" + policy.getName() + "].", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "user";
|
||||
}
|
||||
|
||||
static String[] getUsers(Policy policy) {
|
||||
String roles = policy.getConfig().get("users");
|
||||
|
||||
if (roles != null) {
|
||||
try {
|
||||
return JsonSerialization.readValue(roles.getBytes(), String[].class);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Could not parse roles [" + roles + "] from policy config [" + policy.getName() + ".", e);
|
||||
}
|
||||
}
|
||||
|
||||
return new String[]{};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# JBoss, Home of Professional Open Source.
|
||||
# Copyright 2016 Red Hat, Inc., and individual 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.authorization.policy.provider.identity.UserPolicyProviderFactory
|
30
authz/pom.xml
Normal file
30
authz/pom.xml
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<version>2.0.0.CR1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>keycloak-authz-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>KeyCloak Authz: Parent</name>
|
||||
<description>KeyCloak AuthZ: Parent</description>
|
||||
|
||||
<modules>
|
||||
<module>policy</module>
|
||||
<module>client</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
</project>
|
93
core/src/main/java/org/keycloak/AuthorizationContext.java
Normal file
93
core/src/main/java/org/keycloak/AuthorizationContext.java
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright 2016 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;
|
||||
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
||||
import org.keycloak.representations.authorization.Permission;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class AuthorizationContext {
|
||||
|
||||
private final AccessToken authzToken;
|
||||
private final List<PathConfig> paths;
|
||||
private boolean granted;
|
||||
|
||||
public AuthorizationContext(AccessToken authzToken, List<PathConfig> paths) {
|
||||
this.authzToken = authzToken;
|
||||
this.paths = paths;
|
||||
this.granted = true;
|
||||
}
|
||||
|
||||
public AuthorizationContext() {
|
||||
this(null, null);
|
||||
this.granted = false;
|
||||
}
|
||||
|
||||
public boolean hasPermission(String resourceName, String scopeName) {
|
||||
for (Permission permission : authzToken.getAuthorization().getPermissions()) {
|
||||
for (PathConfig pathHolder : this.paths) {
|
||||
if (pathHolder.getName().equals(resourceName)) {
|
||||
if (pathHolder.getId().equals(permission.getResourceSetId())) {
|
||||
if (permission.getScopes().contains(scopeName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasResourcePermission(String resourceName) {
|
||||
for (Permission permission : authzToken.getAuthorization().getPermissions()) {
|
||||
for (PathConfig pathHolder : this.paths) {
|
||||
if (pathHolder.getName().equals(resourceName)) {
|
||||
if (pathHolder.getId().equals(permission.getResourceSetId())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasScopePermission(String scopeName) {
|
||||
for (Permission permission : authzToken.getAuthorization().getPermissions()) {
|
||||
if (permission.getScopes().contains(scopeName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<Permission> getPermissions() {
|
||||
return this.authzToken.getAuthorization().getPermissions();
|
||||
}
|
||||
|
||||
public boolean isGranted() {
|
||||
return granted;
|
||||
}
|
||||
}
|
|
@ -41,6 +41,7 @@ public class KeycloakSecurityContext implements Serializable {
|
|||
// Don't store parsed tokens into HTTP session
|
||||
protected transient AccessToken token;
|
||||
protected transient IDToken idToken;
|
||||
protected transient AuthorizationContext authorizationContext;
|
||||
|
||||
public KeycloakSecurityContext() {
|
||||
}
|
||||
|
@ -60,6 +61,10 @@ public class KeycloakSecurityContext implements Serializable {
|
|||
return tokenString;
|
||||
}
|
||||
|
||||
public AuthorizationContext getAuthorizationContext() {
|
||||
return authorizationContext;
|
||||
}
|
||||
|
||||
public IDToken getIdToken() {
|
||||
return idToken;
|
||||
}
|
||||
|
|
|
@ -19,10 +19,12 @@ package org.keycloak.representations;
|
|||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.keycloak.representations.authorization.Permission;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -81,6 +83,20 @@ public class AccessToken extends IDToken {
|
|||
}
|
||||
}
|
||||
|
||||
public static class Authorization implements Serializable {
|
||||
|
||||
@JsonProperty("permissions")
|
||||
private List<Permission> permissions;
|
||||
|
||||
public List<Permission> getPermissions() {
|
||||
return permissions;
|
||||
}
|
||||
|
||||
public void setPermissions(List<Permission> permissions) {
|
||||
this.permissions = permissions;
|
||||
}
|
||||
}
|
||||
|
||||
@JsonProperty("client_session")
|
||||
protected String clientSession;
|
||||
|
||||
|
@ -96,6 +112,9 @@ public class AccessToken extends IDToken {
|
|||
@JsonProperty("resource_access")
|
||||
protected Map<String, Access> resourceAccess = new HashMap<String, Access>();
|
||||
|
||||
@JsonProperty("authorization")
|
||||
protected Authorization authorization;
|
||||
|
||||
public Map<String, Access> getResourceAccess() {
|
||||
return resourceAccess;
|
||||
}
|
||||
|
@ -219,5 +238,11 @@ public class AccessToken extends IDToken {
|
|||
return (AccessToken)super.issuedFor(issuedFor);
|
||||
}
|
||||
|
||||
public Authorization getAuthorization() {
|
||||
return authorization;
|
||||
}
|
||||
|
||||
public void setAuthorization(Authorization authorization) {
|
||||
this.authorization = authorization;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,8 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
|||
"client-keystore", "client-keystore-password", "client-key-password",
|
||||
"always-refresh-token",
|
||||
"register-node-at-startup", "register-node-period", "token-store", "principal-attribute",
|
||||
"proxy-url", "turn-off-change-session-id-on-login", "token-minimum-time-to-live"
|
||||
"proxy-url", "turn-off-change-session-id-on-login", "token-minimum-time-to-live",
|
||||
"policy-enforcer"
|
||||
})
|
||||
public class AdapterConfig extends BaseAdapterConfig {
|
||||
|
||||
|
@ -70,6 +71,8 @@ public class AdapterConfig extends BaseAdapterConfig {
|
|||
protected Boolean turnOffChangeSessionIdOnLogin;
|
||||
@JsonProperty("token-minimum-time-to-live")
|
||||
protected int tokenMinimumTimeToLive = 0;
|
||||
@JsonProperty("policy-enforcer")
|
||||
protected PolicyEnforcerConfig policyEnforcerConfig;
|
||||
|
||||
/**
|
||||
* The Proxy url to use for requests to the auth-server, configurable via the adapter config property {@code proxy-url}.
|
||||
|
@ -189,6 +192,14 @@ public class AdapterConfig extends BaseAdapterConfig {
|
|||
this.turnOffChangeSessionIdOnLogin = turnOffChangeSessionIdOnLogin;
|
||||
}
|
||||
|
||||
public PolicyEnforcerConfig getPolicyEnforcerConfig() {
|
||||
return policyEnforcerConfig;
|
||||
}
|
||||
|
||||
public void setPolicyEnforcerConfig(PolicyEnforcerConfig policyEnforcerConfig) {
|
||||
this.policyEnforcerConfig = policyEnforcerConfig;
|
||||
}
|
||||
|
||||
public String getProxyUrl() {
|
||||
return proxyUrl;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* Copyright 2016 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.representations.adapters.config;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class PolicyEnforcerConfig {
|
||||
|
||||
@JsonProperty("create-resources")
|
||||
private Boolean createResources;
|
||||
|
||||
@JsonProperty("enforcement-mode")
|
||||
private EnforcementMode enforcementMode = EnforcementMode.ENFORCING;
|
||||
|
||||
@JsonProperty("user-managed-access")
|
||||
private UmaProtocolConfig umaProtocolConfig;
|
||||
|
||||
@JsonProperty("entitlement")
|
||||
private EntitlementProtocolConfig entitlementProtocolConfig;
|
||||
|
||||
@JsonProperty("paths")
|
||||
private List<PathConfig> paths = new ArrayList<>();
|
||||
|
||||
@JsonProperty("online-introspection")
|
||||
private Boolean onlineIntrospection;
|
||||
|
||||
@JsonProperty("on-deny-redirect-to")
|
||||
private String accessDeniedPath;
|
||||
|
||||
public Boolean isCreateResources() {
|
||||
return this.createResources;
|
||||
}
|
||||
|
||||
public List<PathConfig> getPaths() {
|
||||
if (this.paths == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(this.paths);
|
||||
}
|
||||
|
||||
public EnforcementMode getEnforcementMode() {
|
||||
return this.enforcementMode;
|
||||
}
|
||||
|
||||
public void setEnforcementMode(EnforcementMode enforcementMode) {
|
||||
this.enforcementMode = enforcementMode;
|
||||
}
|
||||
|
||||
public UmaProtocolConfig getUmaProtocolConfig() {
|
||||
return this.umaProtocolConfig;
|
||||
}
|
||||
|
||||
public EntitlementProtocolConfig getEntitlementProtocolConfig() {
|
||||
return this.entitlementProtocolConfig;
|
||||
}
|
||||
|
||||
public Boolean isOnlineIntrospection() {
|
||||
return onlineIntrospection;
|
||||
}
|
||||
|
||||
public void setPaths(List<PathConfig> paths) {
|
||||
this.paths = paths;
|
||||
}
|
||||
|
||||
public String getAccessDeniedPath() {
|
||||
return accessDeniedPath;
|
||||
}
|
||||
|
||||
public static class PathConfig {
|
||||
|
||||
private String name;
|
||||
private String type;
|
||||
private String path;
|
||||
private List<MethodConfig> methods = new ArrayList<>();
|
||||
private List<String> scopes = Collections.emptyList();
|
||||
private String id;
|
||||
private boolean instance;
|
||||
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public List<String> getScopes() {
|
||||
return this.scopes;
|
||||
}
|
||||
|
||||
public void setScopes(List<String> scopes) {
|
||||
this.scopes = scopes;
|
||||
}
|
||||
|
||||
public List<MethodConfig> getMethods() {
|
||||
return methods;
|
||||
}
|
||||
|
||||
public void setMethods(List<MethodConfig> methods) {
|
||||
this.methods = methods;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PathConfig{" +
|
||||
"name='" + name + '\'' +
|
||||
", type='" + type + '\'' +
|
||||
", path='" + path + '\'' +
|
||||
", scopes=" + scopes +
|
||||
", id='" + id + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
public boolean hasPattern() {
|
||||
return getPath().indexOf("{") != -1;
|
||||
}
|
||||
|
||||
public boolean isInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void setInstance(boolean instance) {
|
||||
this.instance = instance;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MethodConfig {
|
||||
|
||||
private String method;
|
||||
private List<String> scopes = Collections.emptyList();
|
||||
|
||||
public String getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public void setMethod(String method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public List<String> getScopes() {
|
||||
return scopes;
|
||||
}
|
||||
|
||||
public void setScopes(List<String> scopes) {
|
||||
this.scopes = scopes;
|
||||
}
|
||||
}
|
||||
|
||||
public enum EnforcementMode {
|
||||
PERMISSIVE,
|
||||
ENFORCING,
|
||||
DISABLED
|
||||
}
|
||||
|
||||
public static class UmaProtocolConfig {
|
||||
|
||||
}
|
||||
|
||||
public static class EntitlementProtocolConfig {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright 2016 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.representations.authorization;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class Permission {
|
||||
|
||||
@JsonProperty("resource_set_id")
|
||||
private String resourceSetId;
|
||||
|
||||
@JsonProperty("resource_set_name")
|
||||
private final String resourceSetName;
|
||||
|
||||
private Set<String> scopes;
|
||||
|
||||
public Permission() {
|
||||
this(null, null, null);
|
||||
}
|
||||
|
||||
public Permission(final String resourceSetId, String resourceSetName, final Set<String> scopes) {
|
||||
this.resourceSetId = resourceSetId;
|
||||
this.resourceSetName = resourceSetName;
|
||||
this.scopes = scopes;
|
||||
}
|
||||
|
||||
public String getResourceSetId() {
|
||||
return this.resourceSetId;
|
||||
}
|
||||
|
||||
public String getResourceSetName() {
|
||||
return this.resourceSetName;
|
||||
}
|
||||
|
||||
public Set<String> getScopes() {
|
||||
return this.scopes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append("Permission {").append("id=").append(resourceSetId).append(", name=").append(resourceSetName)
|
||||
.append(", scopes=").append(scopes).append("}");
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public void setScopes(Set<String> scopes) {
|
||||
this.scopes = scopes;
|
||||
}
|
||||
}
|
|
@ -47,6 +47,7 @@ public class ClientRepresentation {
|
|||
protected Boolean implicitFlowEnabled;
|
||||
protected Boolean directAccessGrantsEnabled;
|
||||
protected Boolean serviceAccountsEnabled;
|
||||
protected Boolean authorizationServicesEnabled;
|
||||
@Deprecated
|
||||
protected Boolean directGrantsOnly;
|
||||
protected Boolean publicClient;
|
||||
|
@ -239,6 +240,14 @@ public class ClientRepresentation {
|
|||
this.serviceAccountsEnabled = serviceAccountsEnabled;
|
||||
}
|
||||
|
||||
public Boolean getAuthorizationServicesEnabled() {
|
||||
return authorizationServicesEnabled;
|
||||
}
|
||||
|
||||
public void setAuthorizationServicesEnabled(Boolean authorizationServicesEnabled) {
|
||||
this.authorizationServicesEnabled = authorizationServicesEnabled;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Boolean isDirectGrantsOnly() {
|
||||
return directGrantsOnly;
|
||||
|
|
280
dependencies/server-all/pom.xml
vendored
280
dependencies/server-all/pom.xml
vendored
|
@ -85,6 +85,286 @@
|
|||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Built-in Authorization Policy Providers -->
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-policy-resource</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-policy-scope</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-policy-user</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-policy-role</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-policy-js</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-policy-time</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-policy-aggregate</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Built-in Authorization Drools Policy Provider-->
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-policy-drools</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!-- Drools -->
|
||||
<dependency>
|
||||
<groupId>org.kie</groupId>
|
||||
<artifactId>kie-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.kie</groupId>
|
||||
<artifactId>kie-ci</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.kie</groupId>
|
||||
<artifactId>kie-internal</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.drools</groupId>
|
||||
<artifactId>drools-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.drools</groupId>
|
||||
<artifactId>drools-compiler</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.aether</groupId>
|
||||
<artifactId>aether-api</artifactId>
|
||||
<version>1.0.0.v20140518</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.aether</groupId>
|
||||
<artifactId>aether-connector-basic</artifactId>
|
||||
<version>1.0.0.v20140518</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.aether</groupId>
|
||||
<artifactId>aether-spi</artifactId>
|
||||
<version>1.0.0.v20140518</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.aether</groupId>
|
||||
<artifactId>aether-impl</artifactId>
|
||||
<version>1.0.0.v20140518</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.aether</groupId>
|
||||
<artifactId>aether-transport-file</artifactId>
|
||||
<version>1.0.0.v20140518</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.aether</groupId>
|
||||
<artifactId>aether-transport-http</artifactId>
|
||||
<version>1.0.0.v20140518</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.aether</groupId>
|
||||
<artifactId>aether-transport-wagon</artifactId>
|
||||
<version>1.0.0.v20140518</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.aether</groupId>
|
||||
<artifactId>aether-util</artifactId>
|
||||
<version>1.0.0.v20140518</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.ant</groupId>
|
||||
<artifactId>ant</artifactId>
|
||||
<version>1.8.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.ant</groupId>
|
||||
<artifactId>ant-launcher</artifactId>
|
||||
<version>1.8.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.antlr</groupId>
|
||||
<artifactId>antlr-runtime</artifactId>
|
||||
<version>3.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>aopalliance</groupId>
|
||||
<artifactId>aopalliance</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-aether-provider</artifactId>
|
||||
<version>3.2.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-artifact</artifactId>
|
||||
<version>3.2.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-compat</artifactId>
|
||||
<version>3.2.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-core</artifactId>
|
||||
<version>3.2.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-model</artifactId>
|
||||
<version>3.2.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-model-builder</artifactId>
|
||||
<version>3.2.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-plugin-api</artifactId>
|
||||
<version>3.2.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-repository-metadata</artifactId>
|
||||
<version>3.2.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-settings</artifactId>
|
||||
<version>3.2.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-settings-builder</artifactId>
|
||||
<version>3.2.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mvel</groupId>
|
||||
<artifactId>mvel2</artifactId>
|
||||
<version>2.2.4.Final</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.sisu</groupId>
|
||||
<artifactId>org.eclipse.sisu.inject</artifactId>
|
||||
<version>0.0.0.M5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.sisu</groupId>
|
||||
<artifactId>org.eclipse.sisu.plexus</artifactId>
|
||||
<version>0.0.0.M5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.sonatype.plexus</groupId>
|
||||
<artifactId>plexus-cipher</artifactId>
|
||||
<version>1.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.plexus</groupId>
|
||||
<artifactId>plexus-classworlds</artifactId>
|
||||
<version>2.5.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.plexus</groupId>
|
||||
<artifactId>plexus-component-annotations</artifactId>
|
||||
<version>1.5.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.plexus</groupId>
|
||||
<artifactId>plexus-interpolation</artifactId>
|
||||
<version>1.19</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.sonatype.plexus</groupId>
|
||||
<artifactId>plexus-sec-dispatcher</artifactId>
|
||||
<version>1.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.plexus</groupId>
|
||||
<artifactId>plexus-utils</artifactId>
|
||||
<version>3.0.17</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.wagon</groupId>
|
||||
<artifactId>wagon-http</artifactId>
|
||||
<version>2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.wagon</groupId>
|
||||
<artifactId>wagon-http-shared4</artifactId>
|
||||
<version>2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.wagon</groupId>
|
||||
<artifactId>wagon-provider-api</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.thoughtworks.xstream</groupId>
|
||||
<artifactId>xstream</artifactId>
|
||||
<version>1.4.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>13.0.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jdt.core.compiler</groupId>
|
||||
<artifactId>ecj</artifactId>
|
||||
<version>4.3.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.3.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
<version>4.3.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lowagie</groupId>
|
||||
<artifactId>itext</artifactId>
|
||||
<version>2.1.2</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>bouncycastle</groupId>
|
||||
<artifactId>bcmail-jdk14</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk14</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.sonatype.sisu</groupId>
|
||||
<artifactId>sisu-guice</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -38,6 +38,9 @@
|
|||
<include>org/keycloak/keycloak-wildfly-subsystem/**</include>
|
||||
<include>org/keycloak/keycloak-adapter-subsystem/**</include>
|
||||
<include>org/keycloak/keycloak-servlet-oauth-client/**</include>
|
||||
|
||||
<!-- Authorization -->
|
||||
<include>org/keycloak/keycloak-authz-client/**</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>**/*.war</exclude>
|
||||
|
|
|
@ -73,6 +73,10 @@
|
|||
<maven-resource group="org.keycloak" artifact="keycloak-servlet-oauth-client"/>
|
||||
</module-def>
|
||||
|
||||
<!-- Authorization -->
|
||||
<module-def name="org.keycloak.keycloak-authz-client">
|
||||
<maven-resource group="org.keycloak" artifact="keycloak-authz-client"/>
|
||||
</module-def>
|
||||
</target>
|
||||
|
||||
<target name="clean-target">
|
||||
|
|
|
@ -82,6 +82,12 @@
|
|||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Authorization -->
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-client</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||
<module name="org.keycloak.keycloak-common"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
<module name="org.keycloak.keycloak-authz-client"/>
|
||||
</dependencies>
|
||||
|
||||
</module>
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
~ JBoss, Home of Professional Open Source.
|
||||
~ Copyright 2016 Red Hat, Inc., and individual 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.
|
||||
-->
|
||||
|
||||
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-authz-client">
|
||||
<resources>
|
||||
<!-- Insert resources here -->
|
||||
</resources>
|
||||
<dependencies>
|
||||
<module name="org.bouncycastle" />
|
||||
<module name="javax.api"/>
|
||||
<module name="javax.activation.api"/>
|
||||
<module name="sun.jdk" optional="true" />
|
||||
<module name="javax.ws.rs.api"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
<module name="org.keycloak.keycloak-common"/>
|
||||
<module name="org.apache.httpcomponents"/>
|
||||
<module name="com.fasterxml.jackson.core.jackson-core"/>
|
||||
<module name="com.fasterxml.jackson.core.jackson-annotations"/>
|
||||
<module name="com.fasterxml.jackson.core.jackson-databind"/>
|
||||
<module name="com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider"/>
|
||||
</dependencies>
|
||||
|
||||
</module>
|
|
@ -136,6 +136,14 @@
|
|||
<exclude name="**/*.iml"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
<copy todir="target/examples/authz" overwrite="true">
|
||||
<fileset dir="../../examples/authz">
|
||||
<exclude name="**/target/**"/>
|
||||
<exclude name="**/*.iml"/>
|
||||
<exclude name="**/*.unconfigured"/>
|
||||
<exclude name="**/subsystem-config.xml"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
<copy file="../../examples/pom.xml" tofile="target/examples/pom.xml"/>
|
||||
<copy file="../../examples/README.md" tofile="target/examples/README.md"/>
|
||||
<move file="target/examples/unconfigured-demo/README.md.unconfigured" tofile="target/examples/unconfigured-demo/README.md"/>
|
||||
|
|
|
@ -51,6 +51,13 @@
|
|||
<groupId>org.wildfly</groupId>
|
||||
<artifactId>wildfly-feature-pack</artifactId>
|
||||
<type>zip</type>
|
||||
<!-- Need to exlcude that in order to use the right guava version for drools -->
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
|
|
@ -32,6 +32,10 @@
|
|||
"provider": "jpa"
|
||||
},
|
||||
|
||||
"authorizationPersister": {
|
||||
"provider": "jpa"
|
||||
},
|
||||
|
||||
"timer": {
|
||||
"provider": "basic"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
|
||||
<!--
|
||||
~ JBoss, Home of Professional Open Source.
|
||||
~ Copyright 2016 Red Hat, Inc., and individual 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.
|
||||
-->
|
||||
|
||||
<module xmlns="urn:jboss:module:1.3" name="org.drools">
|
||||
<resources>
|
||||
<artifact name="${org.kie:kie-api}"/>
|
||||
<artifact name="${org.kie:kie-ci}"/>
|
||||
<artifact name="${org.kie:kie-internal}"/>
|
||||
<artifact name="${org.drools:drools-core}"/>
|
||||
<artifact name="${org.drools:drools-compiler}"/>
|
||||
<artifact name="${org.eclipse.aether:aether-api}"/>
|
||||
<artifact name="${org.eclipse.aether:aether-connector-basic}"/>
|
||||
<artifact name="${org.eclipse.aether:aether-spi}"/>
|
||||
<artifact name="${org.eclipse.aether:aether-impl}"/>
|
||||
<artifact name="${org.eclipse.aether:aether-transport-file}"/>
|
||||
<artifact name="${org.eclipse.aether:aether-transport-http}"/>
|
||||
<artifact name="${org.eclipse.aether:aether-transport-wagon}"/>
|
||||
<artifact name="${org.eclipse.aether:aether-util}"/>
|
||||
<artifact name="${org.apache.ant:ant}"/>
|
||||
<artifact name="${org.apache.ant:ant-launcher}"/>
|
||||
<artifact name="${org.antlr:antlr-runtime}"/>
|
||||
<artifact name="${aopalliance:aopalliance}"/>
|
||||
<artifact name="${org.apache.maven:maven-aether-provider}"/>
|
||||
<artifact name="${org.apache.maven:maven-artifact}"/>
|
||||
<artifact name="${org.apache.maven:maven-compat}"/>
|
||||
<artifact name="${org.apache.maven:maven-core}"/>
|
||||
<artifact name="${org.apache.maven:maven-model}"/>
|
||||
<artifact name="${org.apache.maven:maven-model-builder}"/>
|
||||
<artifact name="${org.apache.maven:maven-plugin-api}"/>
|
||||
<artifact name="${org.apache.maven:maven-repository-metadata}"/>
|
||||
<artifact name="${org.apache.maven:maven-settings}"/>
|
||||
<artifact name="${org.apache.maven:maven-settings-builder}"/>
|
||||
<artifact name="${org.mvel:mvel2}"/>
|
||||
<artifact name="${org.eclipse.sisu:org.eclipse.sisu.inject}"/>
|
||||
<artifact name="${org.eclipse.sisu:org.eclipse.sisu.plexus}"/>
|
||||
<artifact name="${org.sonatype.plexus:plexus-cipher}"/>
|
||||
<artifact name="${org.codehaus.plexus:plexus-classworlds}"/>
|
||||
<artifact name="${org.codehaus.plexus:plexus-component-annotations}"/>
|
||||
<artifact name="${org.codehaus.plexus:plexus-interpolation}"/>
|
||||
<artifact name="${org.sonatype.plexus:plexus-sec-dispatcher}"/>
|
||||
<artifact name="${org.codehaus.plexus:plexus-utils}"/>
|
||||
<artifact name="${org.apache.maven.wagon:wagon-http}"/>
|
||||
<artifact name="${org.apache.maven.wagon:wagon-http-shared4}"/>
|
||||
<artifact name="${org.apache.maven.wagon:wagon-provider-api}"/>
|
||||
<artifact name="${com.thoughtworks.xstream:xstream}"/>
|
||||
<artifact name="${com.google.guava:guava}"/>
|
||||
<artifact name="${org.eclipse.jdt.core.compiler:ecj}"/>
|
||||
<artifact name="${org.apache.httpcomponents:httpclient}"/>
|
||||
<artifact name="${org.apache.httpcomponents:httpcore}"/>
|
||||
<artifact name="${com.lowagie:itext}"/>
|
||||
<artifact name="${org.sonatype.sisu:sisu-guice}"/>
|
||||
</resources>
|
||||
<dependencies>
|
||||
<module name="javax.api"/>
|
||||
<module name="javax.inject.api"/>
|
||||
<module name="javax.enterprise.api"/>
|
||||
<module name="org.slf4j"/>
|
||||
<module name="org.apache.commons.logging"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
<module name="org.keycloak.keycloak-common"/>
|
||||
<module name="org.keycloak.keycloak-server-spi"/>
|
||||
</dependencies>
|
||||
|
||||
</module>
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
|
||||
<!--
|
||||
~ JBoss, Home of Professional Open Source.
|
||||
~ Copyright 2016 Red Hat, Inc., and individual 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.
|
||||
-->
|
||||
|
||||
<module xmlns="urn:jboss:module:1.3" name="org.keycloak.keycloak-authz-policy-drools">
|
||||
<resources>
|
||||
<artifact name="${org.keycloak:keycloak-authz-policy-drools}"/>
|
||||
</resources>
|
||||
<dependencies>
|
||||
<module name="javax.api"/>
|
||||
<module name="javax.ws.rs.api"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
<module name="org.keycloak.keycloak-common"/>
|
||||
<module name="org.keycloak.keycloak-server-spi"/>
|
||||
<module name="org.keycloak.keycloak-services"/>
|
||||
<module name="org.drools"/>
|
||||
</dependencies>
|
||||
</module>
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
|
||||
<!--
|
||||
~ JBoss, Home of Professional Open Source.
|
||||
~ Copyright 2016 Red Hat, Inc., and individual 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.
|
||||
-->
|
||||
|
||||
<module xmlns="urn:jboss:module:1.3" name="org.keycloak.keycloak-authz-policy-provider">
|
||||
<resources>
|
||||
<artifact name="${org.keycloak:keycloak-authz-policy-aggregate}"/>
|
||||
<artifact name="${org.keycloak:keycloak-authz-policy-js}"/>
|
||||
<artifact name="${org.keycloak:keycloak-authz-policy-resource}"/>
|
||||
<artifact name="${org.keycloak:keycloak-authz-policy-role}"/>
|
||||
<artifact name="${org.keycloak:keycloak-authz-policy-scope}"/>
|
||||
<artifact name="${org.keycloak:keycloak-authz-policy-time}"/>
|
||||
<artifact name="${org.keycloak:keycloak-authz-policy-user}"/>
|
||||
</resources>
|
||||
<dependencies>
|
||||
<module name="javax.api"/>
|
||||
<module name="javax.ws.rs.api"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
<module name="org.keycloak.keycloak-common"/>
|
||||
<module name="org.keycloak.keycloak-server-spi"/>
|
||||
<module name="org.keycloak.keycloak-services"/>
|
||||
</dependencies>
|
||||
|
||||
</module>
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
|
||||
<module xmlns="urn:jboss:module:1.3" name="org.keycloak.keycloak-authz-server">
|
||||
<dependencies>
|
||||
<module name="org.keycloak.keycloak-authz-policy-provider" export="true" services="export"/>
|
||||
<module name="org.keycloak.keycloak-authz-policy-drools" export="true" services="export"/>
|
||||
</dependencies>
|
||||
</module>
|
|
@ -45,6 +45,7 @@
|
|||
<filter>
|
||||
<filter-name>Keycloak Session Management</filter-name>
|
||||
<filter-class>org.keycloak.services.filters.KeycloakSessionServletFilter</filter-class>
|
||||
<async-supported>true</async-supported>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
|
|
|
@ -44,6 +44,9 @@
|
|||
<module name="org.keycloak.keycloak-services" export="true" services="import"/>
|
||||
<module name="org.keycloak.keycloak-wildfly-extensions" services="import"/>
|
||||
|
||||
<!-- Authorization -->
|
||||
<module name="org.keycloak.keycloak-authz-server" services="import"/>
|
||||
|
||||
<module name="org.freemarker"/>
|
||||
<module name="javax.ws.rs.api"/>
|
||||
<module name="javax.mail.api"/>
|
||||
|
|
|
@ -1 +1 @@
|
|||
layers=keycloak
|
||||
layers=keycloak,keycloak-authz
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue