Search in sources :

Example 1 with PermissionTicketToken

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

the class HttpMethodAuthenticator method uma.

public HttpMethod<R> uma(AuthorizationRequest request) {
    String ticket = request.getTicket();
    PermissionTicketToken permissions = request.getPermissions();
    if (ticket == null && permissions == null) {
        throw new IllegalArgumentException("You must either provide a permission ticket or the permissions you want to request.");
    }
    uma();
    method.param("ticket", ticket);
    method.param("claim_token", request.getClaimToken());
    method.param("claim_token_format", request.getClaimTokenFormat());
    method.param("pct", request.getPct());
    method.param("rpt", request.getRptToken());
    method.param("scope", request.getScope());
    method.param("audience", request.getAudience());
    method.param("subject_token", request.getSubjectToken());
    if (permissions != null) {
        for (Permission permission : permissions.getPermissions()) {
            String resourceId = permission.getResourceId();
            Set<String> scopes = permission.getScopes();
            StringBuilder value = new StringBuilder();
            if (resourceId != null) {
                value.append(resourceId);
            }
            if (scopes != null && !scopes.isEmpty()) {
                value.append("#");
                for (String scope : scopes) {
                    if (!value.toString().endsWith("#")) {
                        value.append(",");
                    }
                    value.append(scope);
                }
            }
            method.params("permission", value.toString());
        }
    }
    Metadata metadata = request.getMetadata();
    if (metadata != null) {
        if (metadata.getIncludeResourceName() != null) {
            method.param("response_include_resource_name", metadata.getIncludeResourceName().toString());
        }
        if (metadata.getLimit() != null) {
            method.param("response_permissions_limit", metadata.getLimit().toString());
        }
    }
    return method;
}
Also used : PermissionTicketToken(org.keycloak.representations.idm.authorization.PermissionTicketToken) Permission(org.keycloak.representations.idm.authorization.Permission) Metadata(org.keycloak.representations.idm.authorization.AuthorizationRequest.Metadata)

Example 2 with PermissionTicketToken

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

use of org.keycloak.representations.idm.authorization.PermissionTicketToken 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)

Example 4 with PermissionTicketToken

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

the class AuthorizationTokenService method getPermissionTicket.

private PermissionTicketToken getPermissionTicket(KeycloakAuthorizationRequest request) {
    // if there is a ticket is because it is a UMA flow and the ticket was sent by the client after obtaining it from the target resource server
    if (request.getTicket() != null) {
        return verifyPermissionTicket(request);
    }
    // if there is no ticket, we use the permissions the client is asking for.
    // This is a Keycloak extension to UMA flow where clients are capable of obtaining a RPT without a ticket
    PermissionTicketToken permissions = request.getPermissions();
    // an issuedFor must be set by the client when doing this method of obtaining RPT, that is how we know the target resource server
    permissions.issuedFor(request.getAudience());
    return permissions;
}
Also used : PermissionTicketToken(org.keycloak.representations.idm.authorization.PermissionTicketToken)

Example 5 with PermissionTicketToken

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

the class AuthorizationTokenService method verifyPermissionTicket.

private PermissionTicketToken verifyPermissionTicket(KeycloakAuthorizationRequest request) {
    String ticketString = request.getTicket();
    PermissionTicketToken ticket = request.getKeycloakSession().tokens().decode(ticketString, PermissionTicketToken.class);
    if (ticket == null) {
        CorsErrorResponseException ticketVerificationException = new CorsErrorResponseException(request.getCors(), "invalid_ticket", "Ticket verification failed", Status.FORBIDDEN);
        fireErrorEvent(request.getEvent(), Errors.INVALID_PERMISSION_TICKET, ticketVerificationException);
        throw ticketVerificationException;
    }
    if (!ticket.isActive()) {
        CorsErrorResponseException invalidTicketException = new CorsErrorResponseException(request.getCors(), "invalid_ticket", "Invalid permission ticket.", Status.FORBIDDEN);
        fireErrorEvent(request.getEvent(), Errors.INVALID_PERMISSION_TICKET, invalidTicketException);
        throw invalidTicketException;
    }
    return ticket;
}
Also used : PermissionTicketToken(org.keycloak.representations.idm.authorization.PermissionTicketToken) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException)

Aggregations

PermissionTicketToken (org.keycloak.representations.idm.authorization.PermissionTicketToken)6 Permission (org.keycloak.representations.idm.authorization.Permission)4 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 List (java.util.List)2 Metadata (org.keycloak.representations.idm.authorization.AuthorizationRequest.Metadata)2 PermissionRequest (org.keycloak.representations.idm.authorization.PermissionRequest)2 CorsErrorResponseException (org.keycloak.services.CorsErrorResponseException)2 Arrays (java.util.Arrays)1 Collection (java.util.Collection)1 Collections (java.util.Collections)1 HashSet (java.util.HashSet)1 Iterator (java.util.Iterator)1 LinkedHashMap (java.util.LinkedHashMap)1 Collectors (java.util.stream.Collectors)1 Matchers.empty (org.hamcrest.Matchers.empty)1 Matchers.hasItem (org.hamcrest.Matchers.hasItem)1 Matchers.is (org.hamcrest.Matchers.is)1 Matchers.not (org.hamcrest.Matchers.not)1 Assert.assertEquals (org.junit.Assert.assertEquals)1