Search in sources :

Example 21 with ResourceStore

use of org.keycloak.authorization.store.ResourceStore in project keycloak by keycloak.

the class AuthorizationTokenService method resolveResourcePermission.

private void resolveResourcePermission(KeycloakAuthorizationRequest request, ResourceServer resourceServer, KeycloakIdentity identity, AuthorizationProvider authorization, StoreFactory storeFactory, Map<String, ResourcePermission> permissionsToEvaluate, ResourceStore resourceStore, AtomicInteger limit, Permission permission, Set<Scope> requestedScopesModel, String resourceId) {
    Resource resource;
    if (resourceId.indexOf('-') != -1) {
        resource = resourceStore.findById(resourceId, resourceServer.getId());
    } else {
        resource = null;
    }
    if (resource != null) {
        addPermission(request, resourceServer, authorization, permissionsToEvaluate, limit, requestedScopesModel, resource);
    } else if (resourceId.startsWith("resource-type:")) {
        // only resource types, no resource instances. resource types are owned by the resource server
        String resourceType = resourceId.substring("resource-type:".length());
        resourceStore.findByType(resourceType, resourceServer.getId(), resourceServer.getId(), resource1 -> addPermission(request, resourceServer, authorization, permissionsToEvaluate, limit, requestedScopesModel, resource1));
    } else if (resourceId.startsWith("resource-type-any:")) {
        // any resource with a given type
        String resourceType = resourceId.substring("resource-type-any:".length());
        resourceStore.findByType(resourceType, null, resourceServer.getId(), resource12 -> addPermission(request, resourceServer, authorization, permissionsToEvaluate, limit, requestedScopesModel, resource12));
    } else if (resourceId.startsWith("resource-type-instance:")) {
        // only resource instances with a given type
        String resourceType = resourceId.substring("resource-type-instance:".length());
        resourceStore.findByTypeInstance(resourceType, resourceServer.getId(), resource13 -> addPermission(request, resourceServer, authorization, permissionsToEvaluate, limit, requestedScopesModel, resource13));
    } else if (resourceId.startsWith("resource-type-owner:")) {
        // only resources where the current identity is the owner
        String resourceType = resourceId.substring("resource-type-owner:".length());
        resourceStore.findByType(resourceType, identity.getId(), resourceServer.getId(), resource14 -> addPermission(request, resourceServer, authorization, permissionsToEvaluate, limit, requestedScopesModel, resource14));
    } else {
        Resource ownerResource = resourceStore.findByName(resourceId, identity.getId(), resourceServer.getId());
        if (ownerResource != null) {
            permission.setResourceId(ownerResource.getId());
            addPermission(request, resourceServer, authorization, permissionsToEvaluate, limit, requestedScopesModel, ownerResource);
        }
        if (!identity.isResourceServer() || !identity.getId().equals(resourceServer.getId())) {
            List<PermissionTicket> tickets = storeFactory.getPermissionTicketStore().findGranted(resourceId, identity.getId(), resourceServer.getId());
            if (!tickets.isEmpty()) {
                List<Scope> scopes = new ArrayList<>();
                Resource grantedResource = null;
                for (PermissionTicket permissionTicket : tickets) {
                    if (grantedResource == null) {
                        grantedResource = permissionTicket.getResource();
                    }
                    scopes.add(permissionTicket.getScope());
                }
                requestedScopesModel.retainAll(scopes);
                ResourcePermission resourcePermission = addPermission(request, resourceServer, authorization, permissionsToEvaluate, limit, requestedScopesModel, grantedResource);
                // the permission is explicitly granted by the owner, mark this permission as granted so that we don't run the evaluation engine on it
                resourcePermission.setGranted(true);
            }
            Resource serverResource = resourceStore.findByName(resourceId, resourceServer.getId());
            if (serverResource != null) {
                permission.setResourceId(serverResource.getId());
                addPermission(request, resourceServer, authorization, permissionsToEvaluate, limit, requestedScopesModel, serverResource);
            }
        }
    }
    if (permissionsToEvaluate.isEmpty()) {
        CorsErrorResponseException invalidResourceException = new CorsErrorResponseException(request.getCors(), "invalid_resource", "Resource with id [" + resourceId + "] does not exist.", Status.BAD_REQUEST);
        fireErrorEvent(request.getEvent(), Errors.INVALID_REQUEST, invalidResourceException);
        throw invalidResourceException;
    }
}
Also used : ResourcePermission(org.keycloak.authorization.permission.ResourcePermission) Arrays(java.util.Arrays) Tokens(org.keycloak.authorization.util.Tokens) UserSessionProvider(org.keycloak.models.UserSessionProvider) DefaultClientSessionContext(org.keycloak.services.util.DefaultClientSessionContext) BiFunction(java.util.function.BiFunction) Permissions(org.keycloak.authorization.permission.Permissions) PermissionTicketAwareDecisionResultCollector(org.keycloak.authorization.policy.evaluation.PermissionTicketAwareDecisionResultCollector) AuthenticationSessionManager(org.keycloak.services.managers.AuthenticationSessionManager) Metadata(org.keycloak.representations.idm.authorization.AuthorizationRequest.Metadata) MediaType(javax.ws.rs.core.MediaType) OAuthErrorException(org.keycloak.OAuthErrorException) AuthenticationManager(org.keycloak.services.managers.AuthenticationManager) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AccessToken(org.keycloak.representations.AccessToken) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) ErrorResponseException(org.keycloak.services.ErrorResponseException) Map(java.util.Map) ClientConnection(org.keycloak.common.ClientConnection) AuthorizationProvider(org.keycloak.authorization.AuthorizationProvider) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RealmModel(org.keycloak.models.RealmModel) Collection(java.util.Collection) AuthorizationRequest(org.keycloak.representations.idm.authorization.AuthorizationRequest) Set(java.util.Set) ResourceStore(org.keycloak.authorization.store.ResourceStore) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) Collectors(java.util.stream.Collectors) IDToken(org.keycloak.representations.IDToken) KeycloakIdentity(org.keycloak.authorization.common.KeycloakIdentity) Objects(java.util.Objects) List(java.util.List) ScopeStore(org.keycloak.authorization.store.ScopeStore) ServiceAccountConstants(org.keycloak.common.constants.ServiceAccountConstants) Response(javax.ws.rs.core.Response) Details(org.keycloak.events.Details) DefaultEvaluationContext(org.keycloak.authorization.common.DefaultEvaluationContext) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) Entry(java.util.Map.Entry) OIDCLoginProtocol(org.keycloak.protocol.oidc.OIDCLoginProtocol) ClientModel(org.keycloak.models.ClientModel) Scope(org.keycloak.authorization.model.Scope) KeycloakModelUtils(org.keycloak.models.utils.KeycloakModelUtils) Permission(org.keycloak.representations.idm.authorization.Permission) Logger(org.jboss.logging.Logger) StoreFactory(org.keycloak.authorization.store.StoreFactory) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) RefreshToken(org.keycloak.representations.RefreshToken) TokenManager(org.keycloak.protocol.oidc.TokenManager) HttpMethod(javax.ws.rs.HttpMethod) ArrayList(java.util.ArrayList) PermissionTicket(org.keycloak.authorization.model.PermissionTicket) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) UserModel(org.keycloak.models.UserModel) ClientSessionContext(org.keycloak.models.ClientSessionContext) EventBuilder(org.keycloak.events.EventBuilder) OIDCAdvancedConfigWrapper(org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper) PermissionTicketToken(org.keycloak.representations.idm.authorization.PermissionTicketToken) Cors(org.keycloak.services.resources.Cors) Status(javax.ws.rs.core.Response.Status) Base64Url(org.keycloak.common.util.Base64Url) ResourceServer(org.keycloak.authorization.model.ResourceServer) Errors(org.keycloak.events.Errors) Authorization(org.keycloak.representations.AccessToken.Authorization) KeycloakSession(org.keycloak.models.KeycloakSession) HttpRequest(org.jboss.resteasy.spi.HttpRequest) UserSessionModel(org.keycloak.models.UserSessionModel) AuthorizationResponse(org.keycloak.representations.idm.authorization.AuthorizationResponse) JsonSerialization(org.keycloak.util.JsonSerialization) EvaluationContext(org.keycloak.authorization.policy.evaluation.EvaluationContext) ResourceServerStore(org.keycloak.authorization.store.ResourceServerStore) Urls(org.keycloak.services.Urls) AccessTokenResponseBuilder(org.keycloak.protocol.oidc.TokenManager.AccessTokenResponseBuilder) Resource(org.keycloak.authorization.model.Resource) PermissionTicket(org.keycloak.authorization.model.PermissionTicket) Scope(org.keycloak.authorization.model.Scope) Resource(org.keycloak.authorization.model.Resource) ArrayList(java.util.ArrayList) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) ResourcePermission(org.keycloak.authorization.permission.ResourcePermission)

Example 22 with ResourceStore

use of org.keycloak.authorization.store.ResourceStore in project keycloak by keycloak.

the class AuthorizationTokenService method createPermissions.

private Collection<ResourcePermission> createPermissions(PermissionTicketToken ticket, KeycloakAuthorizationRequest request, ResourceServer resourceServer, AuthorizationProvider authorization, EvaluationContext context) {
    KeycloakIdentity identity = (KeycloakIdentity) context.getIdentity();
    StoreFactory storeFactory = authorization.getStoreFactory();
    Map<String, ResourcePermission> permissionsToEvaluate = new LinkedHashMap<>();
    ResourceStore resourceStore = storeFactory.getResourceStore();
    ScopeStore scopeStore = storeFactory.getScopeStore();
    Metadata metadata = request.getMetadata();
    final AtomicInteger limit = metadata != null && metadata.getLimit() != null ? new AtomicInteger(metadata.getLimit()) : null;
    for (Permission permission : ticket.getPermissions()) {
        if (limit != null && limit.get() <= 0) {
            break;
        }
        Set<Scope> requestedScopesModel = resolveRequestedScopes(request, resourceServer, scopeStore, permission);
        String resourceId = permission.getResourceId();
        if (resourceId != null) {
            resolveResourcePermission(request, resourceServer, identity, authorization, storeFactory, permissionsToEvaluate, resourceStore, limit, permission, requestedScopesModel, resourceId);
        } else {
            resolveScopePermissions(request, resourceServer, authorization, permissionsToEvaluate, resourceStore, limit, requestedScopesModel);
        }
    }
    resolvePreviousGrantedPermissions(ticket, request, resourceServer, permissionsToEvaluate, resourceStore, scopeStore, limit);
    return permissionsToEvaluate.values();
}
Also used : Metadata(org.keycloak.representations.idm.authorization.AuthorizationRequest.Metadata) ScopeStore(org.keycloak.authorization.store.ScopeStore) ResourceStore(org.keycloak.authorization.store.ResourceStore) StoreFactory(org.keycloak.authorization.store.StoreFactory) LinkedHashMap(java.util.LinkedHashMap) Scope(org.keycloak.authorization.model.Scope) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) KeycloakIdentity(org.keycloak.authorization.common.KeycloakIdentity) ResourcePermission(org.keycloak.authorization.permission.ResourcePermission) Permission(org.keycloak.representations.idm.authorization.Permission) ResourcePermission(org.keycloak.authorization.permission.ResourcePermission)

Example 23 with ResourceStore

use of org.keycloak.authorization.store.ResourceStore in project keycloak by keycloak.

the class AbstractPermissionService method verifyRequestedResource.

private List<Permission> verifyRequestedResource(List<PermissionRequest> request) {
    ResourceStore resourceStore = authorization.getStoreFactory().getResourceStore();
    List<Permission> requestedResources = new ArrayList<>();
    for (PermissionRequest permissionRequest : request) {
        String resourceSetId = permissionRequest.getResourceId();
        List<Resource> resources = new ArrayList<>();
        if (resourceSetId == null) {
            if (permissionRequest.getScopes() == null || permissionRequest.getScopes().isEmpty()) {
                throw new ErrorResponseException("invalid_resource_id", "Resource id or name not provided.", Response.Status.BAD_REQUEST);
            }
        } else {
            Resource resource = resourceStore.findById(resourceSetId, resourceServer.getId());
            if (resource != null) {
                resources.add(resource);
            } else {
                Resource userResource = resourceStore.findByName(resourceSetId, identity.getId(), this.resourceServer.getId());
                if (userResource != null) {
                    resources.add(userResource);
                }
                if (!identity.isResourceServer()) {
                    Resource serverResource = resourceStore.findByName(resourceSetId, this.resourceServer.getId());
                    if (serverResource != null) {
                        resources.add(serverResource);
                    }
                }
            }
            if (resources.isEmpty()) {
                throw new ErrorResponseException("invalid_resource_id", "Resource set with id [" + resourceSetId + "] does not exists in this server.", Response.Status.BAD_REQUEST);
            }
        }
        if (resources.isEmpty()) {
            requestedResources.add(new Permission(null, verifyRequestedScopes(permissionRequest, null)));
        } else {
            for (Resource resource : resources) {
                requestedResources.add(new Permission(resource.getId(), verifyRequestedScopes(permissionRequest, resource)));
            }
        }
    }
    return requestedResources;
}
Also used : PermissionRequest(org.keycloak.representations.idm.authorization.PermissionRequest) Permission(org.keycloak.representations.idm.authorization.Permission) ArrayList(java.util.ArrayList) Resource(org.keycloak.authorization.model.Resource) ResourceStore(org.keycloak.authorization.store.ResourceStore) ErrorResponseException(org.keycloak.services.ErrorResponseException)

Example 24 with ResourceStore

use of org.keycloak.authorization.store.ResourceStore in project keycloak by keycloak.

the class PermissionTicketService method create.

@POST
@Consumes("application/json")
@Produces("application/json")
public Response create(PermissionTicketRepresentation representation) {
    PermissionTicketStore ticketStore = authorization.getStoreFactory().getPermissionTicketStore();
    if (representation == null)
        throw new ErrorResponseException(OAuthErrorException.INVALID_REQUEST, "invalid_permission", Response.Status.BAD_REQUEST);
    if (representation.getId() != null)
        throw new ErrorResponseException("invalid_permission", "created permissions should not have id", Response.Status.BAD_REQUEST);
    if (representation.getResource() == null)
        throw new ErrorResponseException("invalid_permission", "created permissions should have resource", Response.Status.BAD_REQUEST);
    if (representation.getScope() == null && representation.getScopeName() == null)
        throw new ErrorResponseException("invalid_permission", "created permissions should have scope or scopeName", Response.Status.BAD_REQUEST);
    if (representation.getRequester() == null && representation.getRequesterName() == null)
        throw new ErrorResponseException("invalid_permission", "created permissions should have requester or requesterName", Response.Status.BAD_REQUEST);
    ResourceStore rstore = this.authorization.getStoreFactory().getResourceStore();
    Resource resource = rstore.findById(representation.getResource(), resourceServer.getId());
    if (resource == null)
        throw new ErrorResponseException("invalid_resource_id", "Resource set with id [" + representation.getResource() + "] does not exists in this server.", Response.Status.BAD_REQUEST);
    if (!resource.getOwner().equals(this.identity.getId()))
        throw new ErrorResponseException("not_authorised", "permissions for [" + representation.getResource() + "] can be only created by the owner", Response.Status.FORBIDDEN);
    UserModel user = null;
    if (representation.getRequester() != null)
        user = this.authorization.getKeycloakSession().userStorageManager().getUserById(this.authorization.getRealm(), representation.getRequester());
    else
        user = this.authorization.getKeycloakSession().userStorageManager().getUserByUsername(this.authorization.getRealm(), representation.getRequesterName());
    if (user == null)
        throw new ErrorResponseException("invalid_permission", "Requester does not exists in this server as user.", Response.Status.BAD_REQUEST);
    Scope scope = null;
    ScopeStore sstore = this.authorization.getStoreFactory().getScopeStore();
    if (representation.getScopeName() != null)
        scope = sstore.findByName(representation.getScopeName(), resourceServer.getId());
    else
        scope = sstore.findById(representation.getScope(), resourceServer.getId());
    if (scope == null && representation.getScope() != null)
        throw new ErrorResponseException("invalid_scope", "Scope [" + representation.getScope() + "] is invalid", Response.Status.BAD_REQUEST);
    if (scope == null && representation.getScopeName() != null)
        throw new ErrorResponseException("invalid_scope", "Scope [" + representation.getScopeName() + "] is invalid", Response.Status.BAD_REQUEST);
    boolean match = resource.getScopes().contains(scope);
    if (!match)
        throw new ErrorResponseException("invalid_resource_id", "Resource set with id [" + representation.getResource() + "] does not have Scope [" + scope.getName() + "]", Response.Status.BAD_REQUEST);
    Map<PermissionTicket.FilterOption, String> attributes = new EnumMap<>(PermissionTicket.FilterOption.class);
    attributes.put(PermissionTicket.FilterOption.RESOURCE_ID, resource.getId());
    attributes.put(PermissionTicket.FilterOption.SCOPE_ID, scope.getId());
    attributes.put(PermissionTicket.FilterOption.REQUESTER, user.getId());
    if (!ticketStore.find(attributes, resourceServer.getId(), -1, -1).isEmpty())
        throw new ErrorResponseException("invalid_permission", "Permission already exists", Response.Status.BAD_REQUEST);
    PermissionTicket ticket = ticketStore.create(resource.getId(), scope.getId(), user.getId(), resourceServer);
    if (representation.isGranted())
        ticket.setGrantedTimestamp(java.lang.System.currentTimeMillis());
    representation = ModelToRepresentation.toRepresentation(ticket, authorization);
    return Response.ok(representation).build();
}
Also used : PermissionTicket(org.keycloak.authorization.model.PermissionTicket) Resource(org.keycloak.authorization.model.Resource) ScopeStore(org.keycloak.authorization.store.ScopeStore) ResourceStore(org.keycloak.authorization.store.ResourceStore) UserModel(org.keycloak.models.UserModel) Scope(org.keycloak.authorization.model.Scope) PermissionTicketStore(org.keycloak.authorization.store.PermissionTicketStore) ErrorResponseException(org.keycloak.services.ErrorResponseException) EnumMap(java.util.EnumMap) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes) Produces(javax.ws.rs.Produces)

Example 25 with ResourceStore

use of org.keycloak.authorization.store.ResourceStore in project keycloak by keycloak.

the class PolicyService method findAll.

@GET
@Produces(MediaType.APPLICATION_JSON)
@NoCache
public Response findAll(@QueryParam("policyId") String id, @QueryParam("name") String name, @QueryParam("type") String type, @QueryParam("resource") String resource, @QueryParam("scope") String scope, @QueryParam("permission") Boolean permission, @QueryParam("owner") String owner, @QueryParam("fields") String fields, @QueryParam("first") Integer firstResult, @QueryParam("max") Integer maxResult) {
    if (auth != null) {
        this.auth.realm().requireViewAuthorization();
    }
    Map<Policy.FilterOption, String[]> search = new EnumMap<>(Policy.FilterOption.class);
    if (id != null && !"".equals(id.trim())) {
        search.put(Policy.FilterOption.ID, new String[] { id });
    }
    if (name != null && !"".equals(name.trim())) {
        search.put(Policy.FilterOption.NAME, new String[] { name });
    }
    if (type != null && !"".equals(type.trim())) {
        search.put(Policy.FilterOption.TYPE, new String[] { type });
    }
    if (owner != null && !"".equals(owner.trim())) {
        search.put(Policy.FilterOption.OWNER, new String[] { owner });
    }
    StoreFactory storeFactory = authorization.getStoreFactory();
    if (resource != null && !"".equals(resource.trim())) {
        ResourceStore resourceStore = storeFactory.getResourceStore();
        Resource resourceModel = resourceStore.findById(resource, resourceServer.getId());
        if (resourceModel == null) {
            Map<Resource.FilterOption, String[]> resourceFilters = new EnumMap<>(Resource.FilterOption.class);
            resourceFilters.put(Resource.FilterOption.NAME, new String[] { resource });
            if (owner != null) {
                resourceFilters.put(Resource.FilterOption.OWNER, new String[] { owner });
            }
            Set<String> resources = resourceStore.findByResourceServer(resourceFilters, resourceServer.getId(), -1, 1).stream().map(Resource::getId).collect(Collectors.toSet());
            if (resources.isEmpty()) {
                return Response.noContent().build();
            }
            search.put(Policy.FilterOption.RESOURCE_ID, resources.toArray(new String[resources.size()]));
        } else {
            search.put(Policy.FilterOption.RESOURCE_ID, new String[] { resourceModel.getId() });
        }
    }
    if (scope != null && !"".equals(scope.trim())) {
        ScopeStore scopeStore = storeFactory.getScopeStore();
        Scope scopeModel = scopeStore.findById(scope, resourceServer.getId());
        if (scopeModel == null) {
            Map<Scope.FilterOption, String[]> scopeFilters = new EnumMap<>(Scope.FilterOption.class);
            scopeFilters.put(Scope.FilterOption.NAME, new String[] { scope });
            Set<String> scopes = scopeStore.findByResourceServer(scopeFilters, resourceServer.getId(), -1, 1).stream().map(Scope::getId).collect(Collectors.toSet());
            if (scopes.isEmpty()) {
                return Response.noContent().build();
            }
            search.put(Policy.FilterOption.SCOPE_ID, scopes.toArray(new String[scopes.size()]));
        } else {
            search.put(Policy.FilterOption.SCOPE_ID, new String[] { scopeModel.getId() });
        }
    }
    if (permission != null) {
        search.put(Policy.FilterOption.PERMISSION, new String[] { permission.toString() });
    }
    return Response.ok(doSearch(firstResult, maxResult, fields, search)).build();
}
Also used : Policy(org.keycloak.authorization.model.Policy) Resource(org.keycloak.authorization.model.Resource) ScopeStore(org.keycloak.authorization.store.ScopeStore) ResourceStore(org.keycloak.authorization.store.ResourceStore) StoreFactory(org.keycloak.authorization.store.StoreFactory) Scope(org.keycloak.authorization.model.Scope) EnumMap(java.util.EnumMap) Produces(javax.ws.rs.Produces) GET(javax.ws.rs.GET) NoCache(org.jboss.resteasy.annotations.cache.NoCache)

Aggregations

ResourceStore (org.keycloak.authorization.store.ResourceStore)29 Resource (org.keycloak.authorization.model.Resource)22 StoreFactory (org.keycloak.authorization.store.StoreFactory)12 Scope (org.keycloak.authorization.model.Scope)11 ResourceServer (org.keycloak.authorization.model.ResourceServer)9 ArrayList (java.util.ArrayList)8 EnumMap (java.util.EnumMap)7 List (java.util.List)7 Map (java.util.Map)7 Set (java.util.Set)7 Policy (org.keycloak.authorization.model.Policy)7 UserModel (org.keycloak.models.UserModel)7 ErrorResponseException (org.keycloak.services.ErrorResponseException)7 HashMap (java.util.HashMap)6 LinkedList (java.util.LinkedList)6 Collectors (java.util.stream.Collectors)6 Produces (javax.ws.rs.Produces)6 AuthorizationProvider (org.keycloak.authorization.AuthorizationProvider)6 PermissionTicket (org.keycloak.authorization.model.PermissionTicket)6 PolicyStore (org.keycloak.authorization.store.PolicyStore)6