Search in sources :

Example 16 with AuthorizationProvider

use of org.keycloak.authorization.AuthorizationProvider in project keycloak by keycloak.

the class AuthorizationTokenService method authorize.

public Response authorize(KeycloakAuthorizationRequest request) {
    EventBuilder event = request.getEvent();
    // it is not secure to allow public clients to push arbitrary claims because message can be tampered
    if (isPublicClientRequestingEntitlementWithClaims(request)) {
        CorsErrorResponseException forbiddenClientException = new CorsErrorResponseException(request.getCors(), OAuthErrorException.INVALID_GRANT, "Public clients are not allowed to send claims", Status.FORBIDDEN);
        fireErrorEvent(event, Errors.INVALID_REQUEST, forbiddenClientException);
        throw forbiddenClientException;
    }
    try {
        PermissionTicketToken ticket = getPermissionTicket(request);
        request.setClaims(ticket.getClaims());
        EvaluationContext evaluationContext = createEvaluationContext(request);
        KeycloakIdentity identity = KeycloakIdentity.class.cast(evaluationContext.getIdentity());
        if (identity != null) {
            event.user(identity.getId());
        }
        ResourceServer resourceServer = getResourceServer(ticket, request);
        Collection<Permission> permissions;
        if (request.getTicket() != null) {
            permissions = evaluateUserManagedPermissions(request, ticket, resourceServer, evaluationContext);
        } else if (ticket.getPermissions().isEmpty() && request.getRpt() == null) {
            permissions = evaluateAllPermissions(request, resourceServer, evaluationContext);
        } else {
            permissions = evaluatePermissions(request, ticket, resourceServer, evaluationContext, identity);
        }
        if (isGranted(ticket, request, permissions)) {
            AuthorizationProvider authorization = request.getAuthorization();
            ClientModel targetClient = authorization.getRealm().getClientById(resourceServer.getId());
            Metadata metadata = request.getMetadata();
            String responseMode = metadata != null ? metadata.getResponseMode() : null;
            if (responseMode != null) {
                if (RESPONSE_MODE_DECISION.equals(metadata.getResponseMode())) {
                    Map<String, Object> responseClaims = new HashMap<>();
                    responseClaims.put(RESPONSE_MODE_DECISION_RESULT, true);
                    return createSuccessfulResponse(responseClaims, request);
                } else if (RESPONSE_MODE_PERMISSIONS.equals(metadata.getResponseMode())) {
                    return createSuccessfulResponse(permissions, request);
                } else {
                    CorsErrorResponseException invalidResponseModeException = new CorsErrorResponseException(request.getCors(), OAuthErrorException.INVALID_REQUEST, "Invalid response_mode", Status.BAD_REQUEST);
                    fireErrorEvent(event, Errors.INVALID_REQUEST, invalidResponseModeException);
                    throw invalidResponseModeException;
                }
            } else {
                return createSuccessfulResponse(createAuthorizationResponse(identity, permissions, request, targetClient), request);
            }
        }
        if (request.isSubmitRequest()) {
            CorsErrorResponseException submittedRequestException = new CorsErrorResponseException(request.getCors(), OAuthErrorException.ACCESS_DENIED, "request_submitted", Status.FORBIDDEN);
            fireErrorEvent(event, Errors.ACCESS_DENIED, submittedRequestException);
            throw submittedRequestException;
        } else {
            CorsErrorResponseException notAuthorizedException = new CorsErrorResponseException(request.getCors(), OAuthErrorException.ACCESS_DENIED, "not_authorized", Status.FORBIDDEN);
            fireErrorEvent(event, Errors.ACCESS_DENIED, notAuthorizedException);
            throw notAuthorizedException;
        }
    } catch (ErrorResponseException | CorsErrorResponseException cause) {
        if (logger.isDebugEnabled()) {
            logger.debug("Error while evaluating permissions", cause);
        }
        throw cause;
    } catch (Exception cause) {
        logger.error("Unexpected error while evaluating permissions", cause);
        throw new CorsErrorResponseException(request.getCors(), OAuthErrorException.SERVER_ERROR, "Unexpected error while evaluating permissions", Status.INTERNAL_SERVER_ERROR);
    }
}
Also used : PermissionTicketToken(org.keycloak.representations.idm.authorization.PermissionTicketToken) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) AuthorizationProvider(org.keycloak.authorization.AuthorizationProvider) Metadata(org.keycloak.representations.idm.authorization.AuthorizationRequest.Metadata) OAuthErrorException(org.keycloak.OAuthErrorException) ErrorResponseException(org.keycloak.services.ErrorResponseException) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) ClientModel(org.keycloak.models.ClientModel) EventBuilder(org.keycloak.events.EventBuilder) KeycloakIdentity(org.keycloak.authorization.common.KeycloakIdentity) ResourcePermission(org.keycloak.authorization.permission.ResourcePermission) Permission(org.keycloak.representations.idm.authorization.Permission) ErrorResponseException(org.keycloak.services.ErrorResponseException) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) DefaultEvaluationContext(org.keycloak.authorization.common.DefaultEvaluationContext) EvaluationContext(org.keycloak.authorization.policy.evaluation.EvaluationContext) ResourceServer(org.keycloak.authorization.model.ResourceServer)

Example 17 with AuthorizationProvider

use of org.keycloak.authorization.AuthorizationProvider in project keycloak by keycloak.

the class AccountFormService method shareResource.

@Path("resource/{resource_id}/share")
@POST
public Response shareResource(@PathParam("resource_id") String resourceId, @FormParam("user_id") String[] userIds, @FormParam("scope_id") String[] scopes) {
    MultivaluedMap<String, String> formData = request.getDecodedFormParameters();
    if (auth == null) {
        return login("resource");
    }
    auth.require(AccountRoles.MANAGE_ACCOUNT);
    csrfCheck(formData);
    AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
    PermissionTicketStore ticketStore = authorization.getStoreFactory().getPermissionTicketStore();
    Resource resource = authorization.getStoreFactory().getResourceStore().findById(resourceId, null);
    ResourceServer resourceServer = authorization.getStoreFactory().getResourceServerStore().findById(resource.getResourceServer());
    if (resource == null) {
        return ErrorResponse.error("Invalid resource", Response.Status.BAD_REQUEST);
    }
    if (userIds == null || userIds.length == 0) {
        setReferrerOnPage();
        return account.setError(Status.BAD_REQUEST, Messages.MISSING_PASSWORD).createResponse(AccountPages.PASSWORD);
    }
    for (String id : userIds) {
        UserModel user = session.users().getUserById(realm, id);
        if (user == null) {
            user = session.users().getUserByUsername(realm, id);
        }
        if (user == null) {
            user = session.users().getUserByEmail(realm, id);
        }
        if (user == null) {
            setReferrerOnPage();
            return account.setError(Status.BAD_REQUEST, Messages.INVALID_USER).createResponse(AccountPages.RESOURCE_DETAIL);
        }
        Map<PermissionTicket.FilterOption, String> filters = new EnumMap<>(PermissionTicket.FilterOption.class);
        filters.put(PermissionTicket.FilterOption.RESOURCE_ID, resource.getId());
        filters.put(PermissionTicket.FilterOption.OWNER, auth.getUser().getId());
        filters.put(PermissionTicket.FilterOption.REQUESTER, user.getId());
        List<PermissionTicket> tickets = ticketStore.find(filters, resource.getResourceServer(), -1, -1);
        if (tickets.isEmpty()) {
            if (scopes != null && scopes.length > 0) {
                for (String scope : scopes) {
                    PermissionTicket ticket = ticketStore.create(resourceId, scope, user.getId(), resourceServer);
                    ticket.setGrantedTimestamp(System.currentTimeMillis());
                }
            } else {
                if (resource.getScopes().isEmpty()) {
                    PermissionTicket ticket = ticketStore.create(resourceId, null, user.getId(), resourceServer);
                    ticket.setGrantedTimestamp(System.currentTimeMillis());
                } else {
                    for (Scope scope : resource.getScopes()) {
                        PermissionTicket ticket = ticketStore.create(resourceId, scope.getId(), user.getId(), resourceServer);
                        ticket.setGrantedTimestamp(System.currentTimeMillis());
                    }
                }
            }
        } else if (scopes != null && scopes.length > 0) {
            List<String> grantScopes = new ArrayList<>(Arrays.asList(scopes));
            for (PermissionTicket ticket : tickets) {
                Scope scope = ticket.getScope();
                if (scope != null) {
                    grantScopes.remove(scope.getId());
                }
            }
            for (String grantScope : grantScopes) {
                PermissionTicket ticket = ticketStore.create(resourceId, grantScope, user.getId(), resourceServer);
                ticket.setGrantedTimestamp(System.currentTimeMillis());
            }
        }
    }
    return forwardToPage("resource", AccountPages.RESOURCE_DETAIL);
}
Also used : PermissionTicket(org.keycloak.authorization.model.PermissionTicket) AuthorizationProvider(org.keycloak.authorization.AuthorizationProvider) RealmsResource(org.keycloak.services.resources.RealmsResource) Resource(org.keycloak.authorization.model.Resource) UserModel(org.keycloak.models.UserModel) Scope(org.keycloak.authorization.model.Scope) PermissionTicketStore(org.keycloak.authorization.store.PermissionTicketStore) List(java.util.List) ArrayList(java.util.ArrayList) ResourceServer(org.keycloak.authorization.model.ResourceServer) EnumMap(java.util.EnumMap) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST)

Example 18 with AuthorizationProvider

use of org.keycloak.authorization.AuthorizationProvider in project keycloak by keycloak.

the class PolicyEvaluationTest method testCheckUserClientRoles.

public static void testCheckUserClientRoles(KeycloakSession session) {
    session.getContext().setRealm(session.realms().getRealmByName("authz-test"));
    AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
    ClientModel clientModel = session.clients().getClientByClientId(session.getContext().getRealm(), "resource-server-test");
    StoreFactory storeFactory = authorization.getStoreFactory();
    ResourceServer resourceServer = storeFactory.getResourceServerStore().findByClient(clientModel);
    JSPolicyRepresentation policyRepresentation = new JSPolicyRepresentation();
    policyRepresentation.setName("testCheckUserClientRoles");
    StringBuilder builder = new StringBuilder();
    builder.append("var realm = $evaluation.getRealm();");
    builder.append("var roles = realm.getUserClientRoles('trinity', 'role-mapping-client');");
    builder.append("if (roles.size() == 1 && roles.contains('client-role-a')) { $evaluation.grant(); }");
    policyRepresentation.setCode(builder.toString());
    Policy policy = storeFactory.getPolicyStore().create(policyRepresentation, resourceServer);
    PolicyProvider provider = authorization.getProvider(policy.getType());
    DefaultEvaluation evaluation = createEvaluation(session, authorization, resourceServer, policy);
    provider.evaluate(evaluation);
    Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
}
Also used : Policy(org.keycloak.authorization.model.Policy) ClientModel(org.keycloak.models.ClientModel) JSPolicyRepresentation(org.keycloak.representations.idm.authorization.JSPolicyRepresentation) AuthorizationProvider(org.keycloak.authorization.AuthorizationProvider) PolicyProvider(org.keycloak.authorization.policy.provider.PolicyProvider) StoreFactory(org.keycloak.authorization.store.StoreFactory) ResourceServer(org.keycloak.authorization.model.ResourceServer) DefaultEvaluation(org.keycloak.authorization.policy.evaluation.DefaultEvaluation)

Example 19 with AuthorizationProvider

use of org.keycloak.authorization.AuthorizationProvider in project keycloak by keycloak.

the class PolicyEvaluationTest method testCheckDateAndTime.

public static void testCheckDateAndTime(KeycloakSession session) {
    session.getContext().setRealm(session.realms().getRealmByName("authz-test"));
    AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
    ClientModel clientModel = session.clients().getClientByClientId(session.getContext().getRealm(), "resource-server-test");
    StoreFactory storeFactory = authorization.getStoreFactory();
    ResourceServer resourceServer = storeFactory.getResourceServerStore().findByClient(clientModel);
    TimePolicyRepresentation policyRepresentation = new TimePolicyRepresentation();
    policyRepresentation.setName("testCheckDateAndTime");
    // set the notOnOrAfter for 1 hour from now
    long notOnOrAfter = System.currentTimeMillis() + 3600000;
    Date notOnOrAfterDate = new Date(notOnOrAfter);
    policyRepresentation.setNotOnOrAfter(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(notOnOrAfterDate));
    // evaluation should succeed with the default context as it uses the current time as the date to be compared.
    Policy policy = storeFactory.getPolicyStore().create(policyRepresentation, resourceServer);
    PolicyProvider provider = authorization.getProvider(policy.getType());
    DefaultEvaluation evaluation = createEvaluation(session, authorization, resourceServer, policy);
    provider.evaluate(evaluation);
    Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
    // lets now override the context to use a time that exceeds the time that was set in the policy.
    long contextTime = System.currentTimeMillis() + 5400000;
    Map<String, Collection<String>> attributes = new HashMap<>();
    attributes.put("kc.time.date_time", Arrays.asList(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(contextTime))));
    evaluation = createEvaluation(session, authorization, null, resourceServer, policy, attributes);
    provider.evaluate(evaluation);
    Assert.assertEquals(Effect.DENY, evaluation.getEffect());
}
Also used : Policy(org.keycloak.authorization.model.Policy) HashMap(java.util.HashMap) AuthorizationProvider(org.keycloak.authorization.AuthorizationProvider) StoreFactory(org.keycloak.authorization.store.StoreFactory) Date(java.util.Date) DefaultEvaluation(org.keycloak.authorization.policy.evaluation.DefaultEvaluation) ClientModel(org.keycloak.models.ClientModel) TimePolicyRepresentation(org.keycloak.representations.idm.authorization.TimePolicyRepresentation) PolicyProvider(org.keycloak.authorization.policy.provider.PolicyProvider) Collection(java.util.Collection) ResourceServer(org.keycloak.authorization.model.ResourceServer) SimpleDateFormat(java.text.SimpleDateFormat)

Example 20 with AuthorizationProvider

use of org.keycloak.authorization.AuthorizationProvider in project keycloak by keycloak.

the class PolicyEvaluationTest method testCheckReadOnlyInstances.

public static void testCheckReadOnlyInstances(KeycloakSession session) {
    session.getContext().setRealm(session.realms().getRealmByName("authz-test"));
    AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
    ClientModel clientModel = session.clients().getClientByClientId(session.getContext().getRealm(), "resource-server-test");
    StoreFactory storeFactory = authorization.getStoreFactory();
    ResourceServer resourceServer = storeFactory.getResourceServerStore().findByClient(clientModel);
    JSPolicyRepresentation policyRepresentation = new JSPolicyRepresentation();
    policyRepresentation.setName("testCheckReadOnlyInstances");
    StringBuilder builder = new StringBuilder();
    builder.append("$evaluation.getPermission().getResource().setName('test')");
    policyRepresentation.setCode(builder.toString());
    Policy policy = storeFactory.getPolicyStore().create(policyRepresentation, resourceServer);
    Resource resource = storeFactory.getResourceStore().create("Resource A", resourceServer, resourceServer.getId());
    Scope scope = storeFactory.getScopeStore().create("Scope A", resourceServer);
    resource.updateScopes(new HashSet<>(Arrays.asList(scope)));
    ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation();
    permission.setName("testCheckReadOnlyInstances permission");
    permission.addPolicy(policy.getId());
    permission.addResource(resource.getId());
    storeFactory.getPolicyStore().create(permission, resourceServer);
    session.getTransactionManager().commit();
    PermissionEvaluator evaluator = authorization.evaluators().from(Arrays.asList(new ResourcePermission(resource, Arrays.asList(scope), resourceServer)), createEvaluationContext(session, Collections.emptyMap()));
    try {
        evaluator.evaluate(resourceServer, null);
        Assert.fail("Instances should be marked as read-only");
    } catch (Exception ignore) {
    }
}
Also used : Policy(org.keycloak.authorization.model.Policy) PermissionEvaluator(org.keycloak.authorization.permission.evaluator.PermissionEvaluator) JSPolicyRepresentation(org.keycloak.representations.idm.authorization.JSPolicyRepresentation) AuthorizationProvider(org.keycloak.authorization.AuthorizationProvider) Resource(org.keycloak.authorization.model.Resource) StoreFactory(org.keycloak.authorization.store.StoreFactory) ResourcePermissionRepresentation(org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation) ClientModel(org.keycloak.models.ClientModel) Scope(org.keycloak.authorization.model.Scope) ResourceServer(org.keycloak.authorization.model.ResourceServer) ResourcePermission(org.keycloak.authorization.permission.ResourcePermission)

Aggregations

AuthorizationProvider (org.keycloak.authorization.AuthorizationProvider)60 Policy (org.keycloak.authorization.model.Policy)35 ClientModel (org.keycloak.models.ClientModel)35 ResourceServer (org.keycloak.authorization.model.ResourceServer)30 StoreFactory (org.keycloak.authorization.store.StoreFactory)24 RealmModel (org.keycloak.models.RealmModel)23 HashMap (java.util.HashMap)18 UserModel (org.keycloak.models.UserModel)18 Resource (org.keycloak.authorization.model.Resource)16 PolicyProvider (org.keycloak.authorization.policy.provider.PolicyProvider)15 ArrayList (java.util.ArrayList)14 Map (java.util.Map)14 Scope (org.keycloak.authorization.model.Scope)13 List (java.util.List)12 DefaultEvaluation (org.keycloak.authorization.policy.evaluation.DefaultEvaluation)12 KeycloakSession (org.keycloak.models.KeycloakSession)12 JSPolicyRepresentation (org.keycloak.representations.idm.authorization.JSPolicyRepresentation)11 Set (java.util.Set)10 Collectors (java.util.stream.Collectors)10 HashSet (java.util.HashSet)9