Search in sources :

Example 16 with CorsErrorResponseException

use of org.keycloak.services.CorsErrorResponseException 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 CorsErrorResponseException

use of org.keycloak.services.CorsErrorResponseException in project keycloak by keycloak.

the class AuthorizationTokenService method fireErrorEvent.

private static void fireErrorEvent(EventBuilder event, String error, Exception cause) {
    if (cause instanceof CorsErrorResponseException) {
        // cast the exception to populate the event with a more descriptive reason
        CorsErrorResponseException originalCause = (CorsErrorResponseException) cause;
        event.detail(Details.REASON, originalCause.getErrorDescription() == null ? "<unknown>" : originalCause.getErrorDescription()).error(error);
    } else {
        event.detail(Details.REASON, cause == null || cause.getMessage() == null ? "<unknown>" : cause.getMessage()).error(error);
    }
    logger.debug(event.getEvent().getType(), cause);
}
Also used : CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException)

Example 18 with CorsErrorResponseException

use of org.keycloak.services.CorsErrorResponseException 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 19 with CorsErrorResponseException

use of org.keycloak.services.CorsErrorResponseException in project keycloak by keycloak.

the class AuthorizationTokenService method getResourceServer.

private ResourceServer getResourceServer(PermissionTicketToken ticket, KeycloakAuthorizationRequest request) {
    AuthorizationProvider authorization = request.getAuthorization();
    StoreFactory storeFactory = authorization.getStoreFactory();
    ResourceServerStore resourceServerStore = storeFactory.getResourceServerStore();
    String issuedFor = ticket.getIssuedFor();
    if (issuedFor == null) {
        CorsErrorResponseException missingIssuedForException = new CorsErrorResponseException(request.getCors(), OAuthErrorException.INVALID_REQUEST, "You must provide the issuedFor", Status.BAD_REQUEST);
        fireErrorEvent(request.getEvent(), Errors.INVALID_REQUEST, missingIssuedForException);
        throw missingIssuedForException;
    }
    ClientModel clientModel = request.getRealm().getClientByClientId(issuedFor);
    if (clientModel == null) {
        CorsErrorResponseException unknownServerIdException = new CorsErrorResponseException(request.getCors(), OAuthErrorException.INVALID_REQUEST, "Unknown resource server id: [" + issuedFor + "]", Status.BAD_REQUEST);
        fireErrorEvent(request.getEvent(), Errors.INVALID_REQUEST, unknownServerIdException);
        throw unknownServerIdException;
    }
    ResourceServer resourceServer = resourceServerStore.findByClient(clientModel);
    if (resourceServer == null) {
        CorsErrorResponseException unsupportedPermissionsException = new CorsErrorResponseException(request.getCors(), OAuthErrorException.INVALID_REQUEST, "Client does not support permissions", Status.BAD_REQUEST);
        fireErrorEvent(request.getEvent(), Errors.INVALID_REQUEST, unsupportedPermissionsException);
        throw unsupportedPermissionsException;
    }
    return resourceServer;
}
Also used : ClientModel(org.keycloak.models.ClientModel) ResourceServerStore(org.keycloak.authorization.store.ResourceServerStore) AuthorizationProvider(org.keycloak.authorization.AuthorizationProvider) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) StoreFactory(org.keycloak.authorization.store.StoreFactory) ResourceServer(org.keycloak.authorization.model.ResourceServer)

Example 20 with CorsErrorResponseException

use of org.keycloak.services.CorsErrorResponseException in project keycloak by keycloak.

the class AuthorizationTokenService method createEvaluationContext.

private EvaluationContext createEvaluationContext(KeycloakAuthorizationRequest request) {
    String claimTokenFormat = request.getClaimTokenFormat();
    if (claimTokenFormat == null) {
        claimTokenFormat = CLAIM_TOKEN_FORMAT_JWT;
    }
    BiFunction<KeycloakAuthorizationRequest, AuthorizationProvider, EvaluationContext> evaluationContextProvider = SUPPORTED_CLAIM_TOKEN_FORMATS.get(claimTokenFormat);
    if (evaluationContextProvider == null) {
        CorsErrorResponseException unsupportedClaimTokenFormatException = new CorsErrorResponseException(request.getCors(), OAuthErrorException.INVALID_REQUEST, "Claim token format [" + claimTokenFormat + "] not supported", Status.BAD_REQUEST);
        fireErrorEvent(request.getEvent(), Errors.INVALID_REQUEST, unsupportedClaimTokenFormatException);
        throw unsupportedClaimTokenFormatException;
    }
    return evaluationContextProvider.apply(request, request.getAuthorization());
}
Also used : AuthorizationProvider(org.keycloak.authorization.AuthorizationProvider) DefaultEvaluationContext(org.keycloak.authorization.common.DefaultEvaluationContext) EvaluationContext(org.keycloak.authorization.policy.evaluation.EvaluationContext) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException)

Aggregations

CorsErrorResponseException (org.keycloak.services.CorsErrorResponseException)30 UserSessionModel (org.keycloak.models.UserSessionModel)13 UserModel (org.keycloak.models.UserModel)11 ClientSessionContext (org.keycloak.models.ClientSessionContext)10 ClientModel (org.keycloak.models.ClientModel)9 ClientPolicyException (org.keycloak.services.clientpolicy.ClientPolicyException)9 OAuthErrorException (org.keycloak.OAuthErrorException)8 AccessTokenResponse (org.keycloak.representations.AccessTokenResponse)8 DefaultClientSessionContext (org.keycloak.services.util.DefaultClientSessionContext)8 Response (javax.ws.rs.core.Response)7 AuthenticationSessionModel (org.keycloak.sessions.AuthenticationSessionModel)6 RootAuthenticationSessionModel (org.keycloak.sessions.RootAuthenticationSessionModel)6 AuthorizationProvider (org.keycloak.authorization.AuthorizationProvider)5 AuthenticatedClientSessionModel (org.keycloak.models.AuthenticatedClientSessionModel)5 TokenManager (org.keycloak.protocol.oidc.TokenManager)5 AccessToken (org.keycloak.representations.AccessToken)5 AuthenticationSessionManager (org.keycloak.services.managers.AuthenticationSessionManager)4 EventBuilder (org.keycloak.events.EventBuilder)3 JWSInput (org.keycloak.jose.jws.JWSInput)3 JWSInputException (org.keycloak.jose.jws.JWSInputException)3