Search in sources :

Example 6 with Permission

use of org.keycloak.representations.idm.authorization.Permission in project keycloak by keycloak.

the class PolicyEnforcerTest method testResolvingClaimsOnce.

@Test
public void testResolvingClaimsOnce() {
    KeycloakDeployment deployment = KeycloakDeploymentBuilder.build(getAdapterConfiguration("enforcer-bearer-only-with-cip.json"));
    PolicyEnforcer policyEnforcer = deployment.getPolicyEnforcer();
    oauth.realm(REALM_NAME);
    oauth.clientId("public-client-test");
    oauth.doLogin("marta", "password");
    String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
    OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, null);
    String token = response.getAccessToken();
    OIDCHttpFacade httpFacade = createHttpFacade("/api/resourcea", token, new Function<String, String>() {

        AtomicBoolean resolved = new AtomicBoolean();

        @Override
        public String apply(String s) {
            Assert.assertTrue(resolved.compareAndSet(false, true));
            return "value-" + s;
        }
    });
    AuthorizationContext context = policyEnforcer.enforce(httpFacade);
    Permission permission = context.getPermissions().get(0);
    Map<String, Set<String>> claims = permission.getClaims();
    assertTrue(context.isGranted());
    assertEquals("value-claim-a", claims.get("claim-a").iterator().next());
    assertEquals("claim-b", claims.get("claim-b").iterator().next());
}
Also used : Set(java.util.Set) OAuthClient(org.keycloak.testsuite.util.OAuthClient) OIDCHttpFacade(org.keycloak.adapters.OIDCHttpFacade) AuthorizationContext(org.keycloak.AuthorizationContext) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) KeycloakDeployment(org.keycloak.adapters.KeycloakDeployment) Permission(org.keycloak.representations.idm.authorization.Permission) PolicyEnforcer(org.keycloak.adapters.authorization.PolicyEnforcer) AbstractKeycloakTest(org.keycloak.testsuite.AbstractKeycloakTest) Test(org.junit.Test)

Example 7 with Permission

use of org.keycloak.representations.idm.authorization.Permission in project keycloak by keycloak.

the class PolicyEnforcerClaimsTest method testEnforceUMAAccessWithClaimsUsingBearerToken.

@Test
public void testEnforceUMAAccessWithClaimsUsingBearerToken() {
    initAuthorizationSettings(getClientResource("resource-server-uma-test"));
    KeycloakDeployment deployment = KeycloakDeploymentBuilder.build(getAdapterConfiguration("enforcer-uma-claims-test.json"));
    PolicyEnforcer policyEnforcer = deployment.getPolicyEnforcer();
    HashMap<String, List<String>> headers = new HashMap<>();
    HashMap<String, List<String>> parameters = new HashMap<>();
    parameters.put("withdrawal.amount", Arrays.asList("50"));
    AuthzClient authzClient = getAuthzClient("enforcer-uma-claims-test.json");
    String token = authzClient.obtainAccessToken("marta", "password").getToken();
    headers.put("Authorization", Arrays.asList("Bearer " + token));
    AuthorizationContext context = policyEnforcer.enforce(createHttpFacade("/api/bank/account/1/withdrawal", "POST", token, headers, parameters));
    assertFalse(context.isGranted());
    AuthorizationRequest request = new AuthorizationRequest();
    request.setTicket(extractTicket(headers));
    AuthorizationResponse response = authzClient.authorization("marta", "password").authorize(request);
    token = response.getToken();
    assertNotNull(token);
    context = policyEnforcer.enforce(createHttpFacade("/api/bank/account/1/withdrawal", "POST", token, headers, parameters));
    assertTrue(context.isGranted());
    parameters.put("withdrawal.amount", Arrays.asList("200"));
    context = policyEnforcer.enforce(createHttpFacade("/api/bank/account/1/withdrawal", "POST", token, headers, parameters));
    assertFalse(context.isGranted());
    parameters.put("withdrawal.amount", Arrays.asList("50"));
    context = policyEnforcer.enforce(createHttpFacade("/api/bank/account/1/withdrawal", "POST", token, headers, parameters));
    assertTrue(context.isGranted());
    parameters.put("withdrawal.amount", Arrays.asList("10"));
    context = policyEnforcer.enforce(createHttpFacade("/api/bank/account/1/withdrawal", "POST", token, headers, parameters));
    request = new AuthorizationRequest();
    request.setTicket(extractTicket(headers));
    response = authzClient.authorization("marta", "password").authorize(request);
    token = response.getToken();
    context = policyEnforcer.enforce(createHttpFacade("/api/bank/account/1/withdrawal", "POST", token, headers, parameters));
    assertTrue(context.isGranted());
    request = new AuthorizationRequest();
    request.setTicket(extractTicket(headers));
    response = authzClient.authorization("marta", "password").authorize(request);
    token = response.getToken();
    context = policyEnforcer.enforce(createHttpFacade("/api/bank/account/1/withdrawal", "GET", token, headers, parameters));
    assertTrue(context.isGranted());
    assertEquals(1, context.getPermissions().size());
    Permission permission = context.getPermissions().get(0);
    assertEquals(parameters.get("withdrawal.amount").get(0), permission.getClaims().get("withdrawal.amount").iterator().next());
}
Also used : AuthzClient(org.keycloak.authorization.client.AuthzClient) AuthorizationRequest(org.keycloak.representations.idm.authorization.AuthorizationRequest) HashMap(java.util.HashMap) KeycloakDeployment(org.keycloak.adapters.KeycloakDeployment) Permission(org.keycloak.representations.idm.authorization.Permission) PolicyEnforcer(org.keycloak.adapters.authorization.PolicyEnforcer) List(java.util.List) AuthorizationContext(org.keycloak.AuthorizationContext) AuthorizationResponse(org.keycloak.representations.idm.authorization.AuthorizationResponse) AbstractKeycloakTest(org.keycloak.testsuite.AbstractKeycloakTest) Test(org.junit.Test)

Example 8 with Permission

use of org.keycloak.representations.idm.authorization.Permission 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 9 with Permission

use of org.keycloak.representations.idm.authorization.Permission in project keycloak by keycloak.

the class AuthorizationTokenService method resolvePreviousGrantedPermissions.

private void resolvePreviousGrantedPermissions(PermissionTicketToken ticket, KeycloakAuthorizationRequest request, ResourceServer resourceServer, Map<String, ResourcePermission> permissionsToEvaluate, ResourceStore resourceStore, ScopeStore scopeStore, AtomicInteger limit) {
    AccessToken rpt = request.getRpt();
    if (rpt != null && rpt.isActive()) {
        Authorization authorizationData = rpt.getAuthorization();
        if (authorizationData != null) {
            Collection<Permission> permissions = authorizationData.getPermissions();
            if (permissions != null) {
                for (Permission grantedPermission : permissions) {
                    if (limit != null && limit.get() <= 0) {
                        break;
                    }
                    Resource resource = resourceStore.findById(grantedPermission.getResourceId(), ticket.getIssuedFor());
                    if (resource != null) {
                        ResourcePermission permission = permissionsToEvaluate.get(resource.getId());
                        if (permission == null) {
                            permission = new ResourcePermission(resource, new ArrayList<>(), resourceServer, grantedPermission.getClaims());
                            permissionsToEvaluate.put(resource.getId(), permission);
                            if (limit != null) {
                                limit.decrementAndGet();
                            }
                        } else {
                            if (grantedPermission.getClaims() != null) {
                                for (Entry<String, Set<String>> entry : grantedPermission.getClaims().entrySet()) {
                                    Set<String> claims = permission.getClaims().get(entry.getKey());
                                    if (claims != null) {
                                        claims.addAll(entry.getValue());
                                    }
                                }
                            }
                        }
                        for (String scopeName : grantedPermission.getScopes()) {
                            Scope scope = scopeStore.findByName(scopeName, resourceServer.getId());
                            if (scope != null) {
                                if (!permission.getScopes().contains(scope)) {
                                    permission.getScopes().add(scope);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
Also used : Authorization(org.keycloak.representations.AccessToken.Authorization) Set(java.util.Set) HashSet(java.util.HashSet) Scope(org.keycloak.authorization.model.Scope) AccessToken(org.keycloak.representations.AccessToken) ResourcePermission(org.keycloak.authorization.permission.ResourcePermission) Permission(org.keycloak.representations.idm.authorization.Permission) Resource(org.keycloak.authorization.model.Resource) ArrayList(java.util.ArrayList) ResourcePermission(org.keycloak.authorization.permission.ResourcePermission)

Example 10 with Permission

use of org.keycloak.representations.idm.authorization.Permission in project keycloak by keycloak.

the class AbstractPermissionService method createPermissionTicket.

private String createPermissionTicket(List<PermissionRequest> request) {
    List<Permission> permissions = verifyRequestedResource(request);
    String audience = Urls.realmIssuer(this.authorization.getKeycloakSession().getContext().getUri().getBaseUri(), this.authorization.getRealm().getName());
    PermissionTicketToken token = new PermissionTicketToken(permissions, audience, this.identity.getAccessToken());
    Map<String, List<String>> claims = new HashMap<>();
    for (PermissionRequest permissionRequest : request) {
        Map<String, List<String>> requestClaims = permissionRequest.getClaims();
        if (requestClaims != null) {
            claims.putAll(requestClaims);
        }
    }
    if (!claims.isEmpty()) {
        token.setClaims(claims);
    }
    return this.authorization.getKeycloakSession().tokens().encode(token);
}
Also used : PermissionRequest(org.keycloak.representations.idm.authorization.PermissionRequest) PermissionTicketToken(org.keycloak.representations.idm.authorization.PermissionTicketToken) HashMap(java.util.HashMap) Permission(org.keycloak.representations.idm.authorization.Permission) ArrayList(java.util.ArrayList) List(java.util.List)

Aggregations

Permission (org.keycloak.representations.idm.authorization.Permission)73 Test (org.junit.Test)50 AuthorizationResponse (org.keycloak.representations.idm.authorization.AuthorizationResponse)44 AccessToken (org.keycloak.representations.AccessToken)36 AuthorizationRequest (org.keycloak.representations.idm.authorization.AuthorizationRequest)29 ResourceRepresentation (org.keycloak.representations.idm.authorization.ResourceRepresentation)27 AuthorizationResource (org.keycloak.admin.client.resource.AuthorizationResource)23 AuthzClient (org.keycloak.authorization.client.AuthzClient)22 ClientResource (org.keycloak.admin.client.resource.ClientResource)20 ArrayList (java.util.ArrayList)19 ResourcePermissionRepresentation (org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation)19 OAuthClient (org.keycloak.testsuite.util.OAuthClient)15 ScopePermissionRepresentation (org.keycloak.representations.idm.authorization.ScopePermissionRepresentation)14 JSPolicyRepresentation (org.keycloak.representations.idm.authorization.JSPolicyRepresentation)13 Response (javax.ws.rs.core.Response)12 AuthorizationDeniedException (org.keycloak.authorization.client.AuthorizationDeniedException)12 AccessTokenResponse (org.keycloak.representations.AccessTokenResponse)12 PermissionRequest (org.keycloak.representations.idm.authorization.PermissionRequest)12 PermissionResponse (org.keycloak.representations.idm.authorization.PermissionResponse)12 Authorization (org.keycloak.representations.AccessToken.Authorization)11