All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.gravitee.am.gateway.handler.oauth2.service.request.AbstractRequestResolver Maven / Gradle / Ivy

/**
 * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.gravitee.am.gateway.handler.oauth2.service.request;

import io.gravitee.am.gateway.handler.oauth2.exception.InvalidScopeException;
import io.gravitee.am.gateway.handler.oauth2.service.scope.ScopeManager;
import io.gravitee.am.gateway.handler.oauth2.service.utils.ParameterizedScopeUtils;
import io.gravitee.am.model.Role;
import io.gravitee.am.model.User;
import io.gravitee.am.model.application.ApplicationScopeSettings;
import io.gravitee.am.model.oidc.Client;
import io.reactivex.rxjava3.core.Single;

import java.util.*;
import java.util.stream.Collectors;

import static io.gravitee.am.common.oidc.Scope.OPENID;
import static io.gravitee.am.common.oidc.Scope.SCOPE_DELIMITER;

/**
 * @author Titouan COMPIEGNE (titouan.compiegne at graviteesource.com)
 * @author GraviteeSource Team
 */
public abstract class AbstractRequestResolver {

    private ScopeManager scopeManager;

    public void setScopeManager(ScopeManager scopeManager) {
        this.scopeManager = scopeManager;
    }

    /**
     * If the client omits the scope parameter when requesting authorization, the authorization server MUST either process the
     * request using a pre-defined default value or fail the request indicating an invalid scope.
     * See 3.3. Access Token Scope
     *
     * @param request the request to resolve
     * @param client the client which trigger the request
     * @return the oauth 2.0 request
     */
    protected Single resolveAuthorizedScopes(R request, Client client, User endUser) {
        final Set requestScopes = request.getScopes();
        Set clientResolvedScopes = new HashSet<>();
        Set resolvedScopes = new HashSet<>();
        Set invalidScopes = new HashSet<>();
        // client scopes
        if (client.getScopeSettings() != null && !client.getScopeSettings().isEmpty()) {
            final List clientScopes = client.getScopeSettings().stream().map(ApplicationScopeSettings::getScope).toList();
            final List defaultScopes = client.getScopeSettings().stream().filter(ApplicationScopeSettings::isDefaultScope).map(ApplicationScopeSettings::getScope).collect(Collectors.toList());
            final List parameterizedScopes = this.scopeManager == null ? new ArrayList<>() : client.getScopeSettings().stream().map(ApplicationScopeSettings::getScope).filter(scopeManager::isParameterizedScope).collect(Collectors.toList());

            // no requested scope, set default client scopes to the request
            if (requestScopes == null || requestScopes.isEmpty()) {
                resolvedScopes.addAll(new HashSet<>(defaultScopes));
            } else {
                // filter the actual scopes granted by the client
                for (String scope : requestScopes) {
                    if (clientScopes.contains(scope) || ParameterizedScopeUtils.isParameterizedScope(parameterizedScopes, scope)) {
                        resolvedScopes.add(scope);
                        clientResolvedScopes.add(scope);
                    } else {
                        invalidScopes.add(scope);
                    }
                }
            }
        }

        // user scopes
        if (endUser != null && client.isEnhanceScopesWithUserPermissions()) {
            Set roles = endUser.getRolesPermissions();
            if (roles != null && !roles.isEmpty()) {
                Set permissions = roles.stream()
                        .map(role -> role.getOauthScopes() != null ? role.getOauthScopes() : Collections.emptyList())
                        .flatMap(List::stream)
                        .collect(Collectors.toSet());

                if (requestScopes != null) {
                	// filter the actual scopes granted by the resource owner
                    requestScopes.forEach(scope -> {
                        if (!permissions.contains(scope) && !clientResolvedScopes.contains(scope)) {
                        	invalidScopes.add(scope);
                        }
                    });
                }

                // The request must be enhanced with all of user's permissions
                invalidScopes.removeAll(permissions);
                resolvedScopes.addAll(permissions);
            }
        }

        if (!invalidScopes.isEmpty()) {
            return Single.error(new InvalidScopeException("Invalid scope(s): " + String.join(SCOPE_DELIMITER, invalidScopes)));
        }

        if (resolvedScopes.isEmpty() && (requestScopes != null && !requestScopes.isEmpty())) {
            return Single.error(new InvalidScopeException("Invalid scope(s): " + String.join(SCOPE_DELIMITER, requestScopes)));
        }

        // only put default values if there are no requested scopes or only 'openid'
        // since https://github.com/gravitee-io/issues/issues/3839, enhanced scopes are added only if there are no requested scopes
        // but we introduce legacy behaviour with https://github.com/gravitee-io/issues/issues/7455 for user convenience.
        if (requestScopes == null
                || requestScopes.isEmpty()
                || requestScopes.stream().allMatch(scope -> scope.equals(OPENID.getKey()))
                || scopeManager.alwaysProvideEnhancedScopes()) {
            request.setScopes(resolvedScopes);
        }

        return Single.just(request);
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy