AuthorizationContextUtil.java
/*
* Copyright 2022 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* 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 org.keycloak.services.util;
import org.keycloak.common.Profile;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.protocol.oidc.rar.AuthorizationRequestParserProvider;
import org.keycloak.protocol.oidc.rar.parsers.ClientScopeAuthorizationRequestParserProviderFactory;
import org.keycloak.rar.AuthorizationDetails;
import org.keycloak.rar.AuthorizationRequestContext;
import org.keycloak.rar.AuthorizationRequestSource;
import java.util.stream.Stream;
/**
* @author <a href="mailto:dgozalob@redhat.com">Daniel Gozalo</a>
* Util class to unify a way to obtain the {@link AuthorizationRequestContext}.
* <p>
* As it can be obtained statically from just the OAuth2 scopes parameter, it can be easily referenced from almost anywhere.
*/
public class AuthorizationContextUtil {
/**
* Base function to obtain a bare AuthorizationRequestContext with just OAuth2 Scopes
* @param session
* @param scope
* @return an {@link AuthorizationRequestContext} with scope entries
*/
public static AuthorizationRequestContext getAuthorizationRequestContextFromScopes(KeycloakSession session, String scope) {
if (!Profile.isFeatureEnabled(Profile.Feature.DYNAMIC_SCOPES)) {
throw new RuntimeException("The Dynamic Scopes feature is not enabled and the AuthorizationRequestContext hasn't been generated");
}
AuthorizationRequestParserProvider clientScopeParser = session.getProvider(AuthorizationRequestParserProvider.class,
ClientScopeAuthorizationRequestParserProviderFactory.CLIENT_SCOPE_PARSER_ID);
if (clientScopeParser == null) {
throw new RuntimeException(String.format("No provider found for authorization requests parser %1s",
ClientScopeAuthorizationRequestParserProviderFactory.CLIENT_SCOPE_PARSER_ID));
}
return clientScopeParser.parseScopes(scope);
}
/**
* An extension of {@link AuthorizationContextUtil#getAuthorizationRequestContextFromScopes} that appends the current context's client
* @param session
* @param scope
* @return an {@link AuthorizationRequestContext} with scope entries and a ClientModel
*/
public static AuthorizationRequestContext getAuthorizationRequestContextFromScopesWithClient(KeycloakSession session, String scope) {
AuthorizationRequestContext authorizationRequestContext = getAuthorizationRequestContextFromScopes(session, scope);
authorizationRequestContext.getAuthorizationDetailEntries().add(new AuthorizationDetails(session.getContext().getClient()));
return authorizationRequestContext;
}
/**
* An extension of {@link AuthorizationContextUtil#getAuthorizationRequestContextFromScopesWithClient)} that returns the list as a Stream
* @param session
* @param scope
* @return a Stream of {@link AuthorizationDetails} containing a ClientModel
*/
public static Stream<AuthorizationDetails> getAuthorizationRequestsStreamFromScopesWithClient(KeycloakSession session, String scope) {
AuthorizationRequestContext authorizationRequestContext = getAuthorizationRequestContextFromScopesWithClient(session, scope);
return authorizationRequestContext.getAuthorizationDetailEntries().stream();
}
/**
* Helper method to return a Stream of all the {@link ClientScopeModel} in the current {@link AuthorizationRequestContext}
* @param session
* @param scope
* @return see description
*/
public static Stream<ClientScopeModel> getClientScopesStreamFromAuthorizationRequestContextWithClient(KeycloakSession session, String scope) {
return getAuthorizationRequestContextFromScopesWithClient(session, scope).getAuthorizationDetailEntries().stream()
.filter(authorizationDetails -> authorizationDetails.getSource() == AuthorizationRequestSource.SCOPE)
.map(AuthorizationDetails::getClientScope);
}
}