ModelToRepresentation.java
/*
* Copyright 2016 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.models.utils;
import org.jboss.logging.Logger;
import org.keycloak.authentication.otp.OTPApplicationProvider;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.AuthorizationProviderFactory;
import org.keycloak.authorization.model.PermissionTicket;
import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.model.Resource;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.model.Scope;
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
import org.keycloak.authorization.store.PolicyStore;
import org.keycloak.authorization.store.StoreFactory;
import org.keycloak.common.Profile;
import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.common.util.Time;
import org.keycloak.component.ComponentModel;
import org.keycloak.credential.CredentialMetadata;
import org.keycloak.credential.CredentialModel;
import org.keycloak.deployment.DeployedConfigurationsManager;
import org.keycloak.events.Event;
import org.keycloak.events.admin.AdminEvent;
import org.keycloak.events.admin.AuthDetails;
import org.keycloak.models.*;
import org.keycloak.models.credential.OTPCredentialModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.account.CredentialMetadataRepresentation;
import org.keycloak.representations.idm.*;
import org.keycloak.representations.idm.authorization.*;
import org.keycloak.storage.StorageId;
import org.keycloak.util.JsonSerialization;
import org.keycloak.utils.StreamsUtil;
import org.keycloak.utils.StringUtil;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ModelToRepresentation {
public static Set<String> REALM_EXCLUDED_ATTRIBUTES = new HashSet<>();
static {
REALM_EXCLUDED_ATTRIBUTES.add("displayName");
REALM_EXCLUDED_ATTRIBUTES.add("displayNameHtml");
REALM_EXCLUDED_ATTRIBUTES.add("defaultSignatureAlgorithm");
REALM_EXCLUDED_ATTRIBUTES.add("bruteForceProtected");
REALM_EXCLUDED_ATTRIBUTES.add("permanentLockout");
REALM_EXCLUDED_ATTRIBUTES.add("maxFailureWaitSeconds");
REALM_EXCLUDED_ATTRIBUTES.add("waitIncrementSeconds");
REALM_EXCLUDED_ATTRIBUTES.add("quickLoginCheckMilliSeconds");
REALM_EXCLUDED_ATTRIBUTES.add("minimumQuickLoginWaitSeconds");
REALM_EXCLUDED_ATTRIBUTES.add("maxDeltaTimeSeconds");
REALM_EXCLUDED_ATTRIBUTES.add("failureFactor");
REALM_EXCLUDED_ATTRIBUTES.add("actionTokenGeneratedByAdminLifespan");
REALM_EXCLUDED_ATTRIBUTES.add("actionTokenGeneratedByUserLifespan");
REALM_EXCLUDED_ATTRIBUTES.add("offlineSessionMaxLifespanEnabled");
REALM_EXCLUDED_ATTRIBUTES.add("offlineSessionMaxLifespan");
REALM_EXCLUDED_ATTRIBUTES.add("webAuthnPolicyRpEntityName");
REALM_EXCLUDED_ATTRIBUTES.add("webAuthnPolicySignatureAlgorithms");
REALM_EXCLUDED_ATTRIBUTES.add("webAuthnPolicyRpId");
REALM_EXCLUDED_ATTRIBUTES.add("webAuthnPolicyAttestationConveyancePreference");
REALM_EXCLUDED_ATTRIBUTES.add("webAuthnPolicyAuthenticatorAttachment");
REALM_EXCLUDED_ATTRIBUTES.add("webAuthnPolicyRequireResidentKey");
REALM_EXCLUDED_ATTRIBUTES.add("webAuthnPolicyUserVerificationRequirement");
REALM_EXCLUDED_ATTRIBUTES.add("webAuthnPolicyCreateTimeout");
REALM_EXCLUDED_ATTRIBUTES.add("webAuthnPolicyAvoidSameAuthenticatorRegister");
REALM_EXCLUDED_ATTRIBUTES.add("webAuthnPolicyAcceptableAaguids");
REALM_EXCLUDED_ATTRIBUTES.add("webAuthnPolicyRpEntityNamePasswordless");
REALM_EXCLUDED_ATTRIBUTES.add("webAuthnPolicySignatureAlgorithmsPasswordless");
REALM_EXCLUDED_ATTRIBUTES.add("webAuthnPolicyRpIdPasswordless");
REALM_EXCLUDED_ATTRIBUTES.add("webAuthnPolicyAttestationConveyancePreferencePasswordless");
REALM_EXCLUDED_ATTRIBUTES.add("webAuthnPolicyAuthenticatorAttachmentPasswordless");
REALM_EXCLUDED_ATTRIBUTES.add("webAuthnPolicyRequireResidentKeyPasswordless");
REALM_EXCLUDED_ATTRIBUTES.add("webAuthnPolicyUserVerificationRequirementPasswordless");
REALM_EXCLUDED_ATTRIBUTES.add("webAuthnPolicyCreateTimeoutPasswordless");
REALM_EXCLUDED_ATTRIBUTES.add("webAuthnPolicyAvoidSameAuthenticatorRegisterPasswordless");
REALM_EXCLUDED_ATTRIBUTES.add("webAuthnPolicyAcceptableAaguidsPasswordless");
REALM_EXCLUDED_ATTRIBUTES.add(Constants.CLIENT_POLICIES);
REALM_EXCLUDED_ATTRIBUTES.add(Constants.CLIENT_PROFILES);
}
private static final Logger LOG = Logger.getLogger(ModelToRepresentation.class);
public static String buildGroupPath(GroupModel group) {
return KeycloakModelUtils.buildGroupPath(group);
}
public static GroupRepresentation groupToBriefRepresentation(GroupModel g) {
return toRepresentation(g, false);
}
public static GroupRepresentation toRepresentation(GroupModel group, boolean full) {
GroupRepresentation rep = new GroupRepresentation();
rep.setId(group.getId());
rep.setName(group.getName());
rep.setPath(buildGroupPath(group));
if (!full) return rep;
// Role mappings
Set<RoleModel> roles = group.getRoleMappingsStream().collect(Collectors.toSet());
List<String> realmRoleNames = new ArrayList<>();
Map<String, List<String>> clientRoleNames = new HashMap<>();
for (RoleModel role : roles) {
if (role.getContainer() instanceof RealmModel) {
realmRoleNames.add(role.getName());
} else {
ClientModel client = (ClientModel)role.getContainer();
String clientId = client.getClientId();
List<String> currentClientRoles = clientRoleNames.computeIfAbsent(clientId, k -> new ArrayList<>());
currentClientRoles.add(role.getName());
}
}
rep.setRealmRoles(realmRoleNames);
rep.setClientRoles(clientRoleNames);
Map<String, List<String>> attributes = group.getAttributes();
rep.setAttributes(attributes);
return rep;
}
public static Stream<GroupRepresentation> searchGroupsByAttributes(KeycloakSession session, RealmModel realm, boolean full, boolean populateHierarchy, Map<String,String> attributes, Integer first, Integer max) {
Stream<GroupModel> groups = searchGroupModelsByAttributes(session, realm, full, populateHierarchy, attributes, first, max);
// and then turn the result into GroupRepresentations creating whole hierarchy of child groups for each root group
return groups.map(g -> toGroupHierarchy(g, full, attributes));
}
public static Stream<GroupModel> searchGroupModelsByAttributes(KeycloakSession session, RealmModel realm, boolean full, boolean populateHierarchy, Map<String,String> attributes, Integer first, Integer max) {
Stream<GroupModel> groups = session.groups().searchGroupsByAttributes(realm, attributes, first, max);
if(populateHierarchy) {
groups = groups
// We need to return whole group hierarchy when any child group fulfills the attribute search,
// therefore for each group from the result, we need to find root group
.map(group -> {
while (Objects.nonNull(group.getParentId())) {
group = group.getParent();
}
return group;
})
// More child groups of one root can fulfill the search, so we need to filter duplicates
.filter(StreamsUtil.distinctByKey(GroupModel::getId));
}
return groups;
}
public static Stream<GroupRepresentation> searchForGroupByName(KeycloakSession session, RealmModel realm, boolean full, String search, Boolean exact, Integer first, Integer max) {
return searchForGroupModelByName(session, realm, full, search, exact, first, max)
.map(g -> toGroupHierarchy(g, full, search, exact));
}
public static Stream<GroupModel> searchForGroupModelByName(KeycloakSession session, RealmModel realm, boolean full, String search, Boolean exact, Integer first, Integer max) {
return session.groups().searchForGroupByNameStream(realm, search, exact, first, max);
}
public static Stream<GroupRepresentation> searchForGroupByName(UserModel user, boolean full, String search, Integer first, Integer max) {
return user.getGroupsStream(search, first, max)
.map(group -> toRepresentation(group, full));
}
public static Stream<GroupRepresentation> toGroupHierarchy(RealmModel realm, boolean full, Integer first, Integer max) {
return toGroupModelHierarchy(realm, full, first, max)
.map(g -> toGroupHierarchy(g, full));
}
public static Stream<GroupModel> toGroupModelHierarchy(RealmModel realm, boolean full, Integer first, Integer max) {
return realm.getTopLevelGroupsStream(first, max);
}
public static Stream<GroupRepresentation> toGroupHierarchy(UserModel user, boolean full, Integer first, Integer max) {
return user.getGroupsStream(null, first, max)
.map(group -> toRepresentation(group, full));
}
public static Stream<GroupRepresentation> toGroupHierarchy(RealmModel realm, boolean full) {
return realm.getTopLevelGroupsStream()
.map(g -> toGroupHierarchy(g, full));
}
public static Stream<GroupRepresentation> toGroupHierarchy(UserModel user, boolean full) {
return user.getGroupsStream()
.map(group -> toRepresentation(group, full));
}
public static GroupRepresentation toGroupHierarchy(GroupModel group, boolean full) {
return toGroupHierarchy(group, full, (String) null);
}
@Deprecated
public static GroupRepresentation toGroupHierarchy(GroupModel group, boolean full, String search) {
return toGroupHierarchy(group, full, search, false);
}
public static GroupRepresentation toGroupHierarchy(GroupModel group, boolean full, String search, Boolean exact) {
GroupRepresentation rep = toRepresentation(group, full);
List<GroupRepresentation> subGroups = group.getSubGroupsStream()
.filter(g -> groupMatchesSearchOrIsPathElement(g, search, exact))
.map(subGroup -> toGroupHierarchy(subGroup, full, search, exact)).collect(Collectors.toList());
rep.setSubGroups(subGroups);
return rep;
}
public static GroupRepresentation toGroupHierarchy(GroupModel group, boolean full, Map<String,String> attributes) {
GroupRepresentation rep = toRepresentation(group, full);
List<GroupRepresentation> subGroups = group.getSubGroupsStream()
.map(subGroup -> toGroupHierarchy(subGroup, full, attributes)).collect(Collectors.toList());
rep.setSubGroups(subGroups);
return rep;
}
private static boolean groupMatchesSearchOrIsPathElement(GroupModel group, String search, Boolean exact) {
if (StringUtil.isBlank(search)) {
return true;
}
if(exact !=null && exact.equals(true)){
if (group.getName().equals(search)){
return true;
}
} else {
if (group.getName().contains(search)) {
return true;
}
}
return group.getSubGroupsStream().findAny().isPresent();
}
public static UserRepresentation toRepresentation(KeycloakSession session, RealmModel realm, UserModel user) {
UserRepresentation rep = new UserRepresentation();
rep.setId(user.getId());
String providerId = StorageId.resolveProviderId(user);
rep.setOrigin(providerId);
rep.setUsername(user.getUsername());
rep.setCreatedTimestamp(user.getCreatedTimestamp());
rep.setLastName(user.getLastName());
rep.setFirstName(user.getFirstName());
rep.setEmail(user.getEmail());
rep.setEnabled(user.isEnabled());
rep.setEmailVerified(user.isEmailVerified());
rep.setTotp(user.credentialManager().isConfiguredFor(OTPCredentialModel.TYPE));
rep.setDisableableCredentialTypes(user.credentialManager()
.getDisableableCredentialTypesStream().collect(Collectors.toSet()));
rep.setFederationLink(user.getFederationLink());
rep.setNotBefore(session.users().getNotBeforeOfUser(realm, user));
rep.setRequiredActions(user.getRequiredActionsStream().collect(Collectors.toList()));
Map<String, List<String>> attributes = user.getAttributes();
Map<String, List<String>> copy = null;
if (attributes != null) {
copy = new HashMap<>(attributes);
copy.remove(UserModel.LAST_NAME);
copy.remove(UserModel.FIRST_NAME);
copy.remove(UserModel.EMAIL);
copy.remove(UserModel.USERNAME);
}
if (attributes != null && !copy.isEmpty()) {
Map<String, List<String>> attrs = new HashMap<>(copy);
rep.setAttributes(attrs);
}
return rep;
}
public static UserRepresentation toBriefRepresentation(UserModel user) {
UserRepresentation rep = new UserRepresentation();
rep.setId(user.getId());
rep.setUsername(user.getUsername());
rep.setCreatedTimestamp(user.getCreatedTimestamp());
rep.setLastName(user.getLastName());
rep.setFirstName(user.getFirstName());
rep.setEmail(user.getEmail());
rep.setEnabled(user.isEnabled());
rep.setEmailVerified(user.isEmailVerified());
rep.setFederationLink(user.getFederationLink());
return rep;
}
public static EventRepresentation toRepresentation(Event event) {
EventRepresentation rep = new EventRepresentation();
rep.setTime(event.getTime());
rep.setType(event.getType().toString());
rep.setRealmId(event.getRealmId());
rep.setClientId(event.getClientId());
rep.setUserId(event.getUserId());
rep.setSessionId(event.getSessionId());
rep.setIpAddress(event.getIpAddress());
rep.setError(event.getError());
rep.setDetails(event.getDetails());
return rep;
}
public static AdminEventRepresentation toRepresentation(AdminEvent adminEvent) {
AdminEventRepresentation rep = new AdminEventRepresentation();
rep.setTime(adminEvent.getTime());
rep.setRealmId(adminEvent.getRealmId());
if (adminEvent.getAuthDetails() != null) {
rep.setAuthDetails(toRepresentation(adminEvent.getAuthDetails()));
}
rep.setOperationType(adminEvent.getOperationType().toString());
if (adminEvent.getResourceTypeAsString() != null) {
rep.setResourceType(adminEvent.getResourceTypeAsString());
}
rep.setResourcePath(adminEvent.getResourcePath());
rep.setRepresentation(adminEvent.getRepresentation());
rep.setError(adminEvent.getError());
return rep;
}
public static AuthDetailsRepresentation toRepresentation(AuthDetails authDetails) {
AuthDetailsRepresentation rep = new AuthDetailsRepresentation();
rep.setRealmId(authDetails.getRealmId());
rep.setClientId(authDetails.getClientId());
rep.setUserId(authDetails.getUserId());
rep.setIpAddress(authDetails.getIpAddress());
return rep;
}
public static RoleRepresentation toRepresentation(RoleModel role) {
RoleRepresentation rep = new RoleRepresentation();
rep.setId(role.getId());
rep.setName(role.getName());
rep.setDescription(role.getDescription());
rep.setComposite(role.isComposite());
rep.setClientRole(role.isClientRole());
rep.setContainerId(role.getContainerId());
rep.setAttributes(role.getAttributes());
return rep;
}
public static RoleRepresentation toBriefRepresentation(RoleModel role) {
RoleRepresentation rep = new RoleRepresentation();
rep.setId(role.getId());
rep.setName(role.getName());
rep.setDescription(role.getDescription());
rep.setComposite(role.isComposite());
rep.setClientRole(role.isClientRole());
rep.setContainerId(role.getContainerId());
return rep;
}
public static RealmRepresentation toBriefRepresentation(RealmModel realm) {
RealmRepresentation rep = new RealmRepresentation();
rep.setId(realm.getId());
rep.setRealm(realm.getName());
rep.setDisplayName(realm.getDisplayName());
rep.setDisplayNameHtml(realm.getDisplayNameHtml());
rep.setEnabled(realm.isEnabled());
return rep;
}
public static RealmRepresentation toRepresentation(KeycloakSession session, RealmModel realm, boolean internal) {
RealmRepresentation rep = new RealmRepresentation();
rep.setId(realm.getId());
rep.setRealm(realm.getName());
rep.setDisplayName(realm.getDisplayName());
rep.setDisplayNameHtml(realm.getDisplayNameHtml());
rep.setEnabled(realm.isEnabled());
rep.setNotBefore(realm.getNotBefore());
rep.setSslRequired(realm.getSslRequired().name().toLowerCase());
rep.setRegistrationAllowed(realm.isRegistrationAllowed());
rep.setRegistrationEmailAsUsername(realm.isRegistrationEmailAsUsername());
rep.setRememberMe(realm.isRememberMe());
rep.setBruteForceProtected(realm.isBruteForceProtected());
rep.setPermanentLockout(realm.isPermanentLockout());
rep.setMaxFailureWaitSeconds(realm.getMaxFailureWaitSeconds());
rep.setMinimumQuickLoginWaitSeconds(realm.getMinimumQuickLoginWaitSeconds());
rep.setWaitIncrementSeconds(realm.getWaitIncrementSeconds());
rep.setQuickLoginCheckMilliSeconds(realm.getQuickLoginCheckMilliSeconds());
rep.setMaxDeltaTimeSeconds(realm.getMaxDeltaTimeSeconds());
rep.setFailureFactor(realm.getFailureFactor());
if (Profile.isFeatureEnabled(Profile.Feature.AUTHORIZATION)) {
rep.setUserManagedAccessAllowed(realm.isUserManagedAccessAllowed());
} else {
rep.setUserManagedAccessAllowed(false);
}
rep.setEventsEnabled(realm.isEventsEnabled());
if (realm.getEventsExpiration() != 0) {
rep.setEventsExpiration(realm.getEventsExpiration());
}
rep.setEventsListeners(realm.getEventsListenersStream().collect(Collectors.toList()));
rep.setEnabledEventTypes(realm.getEnabledEventTypesStream().collect(Collectors.toList()));
rep.setAdminEventsEnabled(realm.isAdminEventsEnabled());
rep.setAdminEventsDetailsEnabled(realm.isAdminEventsDetailsEnabled());
rep.setVerifyEmail(realm.isVerifyEmail());
rep.setLoginWithEmailAllowed(realm.isLoginWithEmailAllowed());
rep.setDuplicateEmailsAllowed(realm.isDuplicateEmailsAllowed());
rep.setResetPasswordAllowed(realm.isResetPasswordAllowed());
rep.setEditUsernameAllowed(realm.isEditUsernameAllowed());
rep.setDefaultSignatureAlgorithm(realm.getDefaultSignatureAlgorithm());
rep.setRevokeRefreshToken(realm.isRevokeRefreshToken());
rep.setRefreshTokenMaxReuse(realm.getRefreshTokenMaxReuse());
rep.setAccessTokenLifespan(realm.getAccessTokenLifespan());
rep.setAccessTokenLifespanForImplicitFlow(realm.getAccessTokenLifespanForImplicitFlow());
rep.setSsoSessionIdleTimeout(realm.getSsoSessionIdleTimeout());
rep.setSsoSessionMaxLifespan(realm.getSsoSessionMaxLifespan());
rep.setSsoSessionIdleTimeoutRememberMe(realm.getSsoSessionIdleTimeoutRememberMe());
rep.setSsoSessionMaxLifespanRememberMe(realm.getSsoSessionMaxLifespanRememberMe());
rep.setOfflineSessionIdleTimeout(realm.getOfflineSessionIdleTimeout());
// KEYCLOAK-7688 Offline Session Max for Offline Token
rep.setOfflineSessionMaxLifespanEnabled(realm.isOfflineSessionMaxLifespanEnabled());
rep.setOfflineSessionMaxLifespan(realm.getOfflineSessionMaxLifespan());
rep.setClientSessionIdleTimeout(realm.getClientSessionIdleTimeout());
rep.setClientSessionMaxLifespan(realm.getClientSessionMaxLifespan());
rep.setClientOfflineSessionIdleTimeout(realm.getClientOfflineSessionIdleTimeout());
rep.setClientOfflineSessionMaxLifespan(realm.getClientOfflineSessionMaxLifespan());
rep.setAccessCodeLifespan(realm.getAccessCodeLifespan());
rep.setAccessCodeLifespanUserAction(realm.getAccessCodeLifespanUserAction());
rep.setAccessCodeLifespanLogin(realm.getAccessCodeLifespanLogin());
rep.setActionTokenGeneratedByAdminLifespan(realm.getActionTokenGeneratedByAdminLifespan());
rep.setActionTokenGeneratedByUserLifespan(realm.getActionTokenGeneratedByUserLifespan());
rep.setOAuth2DeviceCodeLifespan(realm.getOAuth2DeviceConfig().getLifespan());
rep.setOAuth2DevicePollingInterval(realm.getOAuth2DeviceConfig().getPoolingInterval());
rep.setSmtpServer(new HashMap<>(realm.getSmtpConfig()));
rep.setBrowserSecurityHeaders(realm.getBrowserSecurityHeaders());
rep.setAccountTheme(realm.getAccountTheme());
rep.setLoginTheme(realm.getLoginTheme());
rep.setAdminTheme(realm.getAdminTheme());
rep.setEmailTheme(realm.getEmailTheme());
if (realm.getPasswordPolicy() != null) {
rep.setPasswordPolicy(realm.getPasswordPolicy().toString());
}
OTPPolicy otpPolicy = realm.getOTPPolicy();
rep.setOtpPolicyAlgorithm(otpPolicy.getAlgorithm());
rep.setOtpPolicyPeriod(otpPolicy.getPeriod());
rep.setOtpPolicyDigits(otpPolicy.getDigits());
rep.setOtpPolicyInitialCounter(otpPolicy.getInitialCounter());
rep.setOtpPolicyType(otpPolicy.getType());
rep.setOtpPolicyLookAheadWindow(otpPolicy.getLookAheadWindow());
rep.setOtpPolicyCodeReusable(otpPolicy.isCodeReusable());
rep.setOtpSupportedApplications(session.getAllProviders(OTPApplicationProvider.class)
.stream()
.filter(p -> p.supports(otpPolicy))
.map(OTPApplicationProvider::getName)
.sorted(String::compareTo)
.collect(Collectors.toList()));
WebAuthnPolicy webAuthnPolicy = realm.getWebAuthnPolicy();
rep.setWebAuthnPolicyRpEntityName(webAuthnPolicy.getRpEntityName());
rep.setWebAuthnPolicySignatureAlgorithms(webAuthnPolicy.getSignatureAlgorithm());
rep.setWebAuthnPolicyRpId(webAuthnPolicy.getRpId());
rep.setWebAuthnPolicyAttestationConveyancePreference(webAuthnPolicy.getAttestationConveyancePreference());
rep.setWebAuthnPolicyAuthenticatorAttachment(webAuthnPolicy.getAuthenticatorAttachment());
rep.setWebAuthnPolicyRequireResidentKey(webAuthnPolicy.getRequireResidentKey());
rep.setWebAuthnPolicyUserVerificationRequirement(webAuthnPolicy.getUserVerificationRequirement());
rep.setWebAuthnPolicyCreateTimeout(webAuthnPolicy.getCreateTimeout());
rep.setWebAuthnPolicyAvoidSameAuthenticatorRegister(webAuthnPolicy.isAvoidSameAuthenticatorRegister());
rep.setWebAuthnPolicyAcceptableAaguids(webAuthnPolicy.getAcceptableAaguids());
webAuthnPolicy = realm.getWebAuthnPolicyPasswordless();
rep.setWebAuthnPolicyPasswordlessRpEntityName(webAuthnPolicy.getRpEntityName());
rep.setWebAuthnPolicyPasswordlessSignatureAlgorithms(webAuthnPolicy.getSignatureAlgorithm());
rep.setWebAuthnPolicyPasswordlessRpId(webAuthnPolicy.getRpId());
rep.setWebAuthnPolicyPasswordlessAttestationConveyancePreference(webAuthnPolicy.getAttestationConveyancePreference());
rep.setWebAuthnPolicyPasswordlessAuthenticatorAttachment(webAuthnPolicy.getAuthenticatorAttachment());
rep.setWebAuthnPolicyPasswordlessRequireResidentKey(webAuthnPolicy.getRequireResidentKey());
rep.setWebAuthnPolicyPasswordlessUserVerificationRequirement(webAuthnPolicy.getUserVerificationRequirement());
rep.setWebAuthnPolicyPasswordlessCreateTimeout(webAuthnPolicy.getCreateTimeout());
rep.setWebAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister(webAuthnPolicy.isAvoidSameAuthenticatorRegister());
rep.setWebAuthnPolicyPasswordlessAcceptableAaguids(webAuthnPolicy.getAcceptableAaguids());
CibaConfig cibaPolicy = realm.getCibaPolicy();
Map<String, String> attrMap = Optional.ofNullable(rep.getAttributes()).orElse(new HashMap<>());
attrMap.put(CibaConfig.CIBA_BACKCHANNEL_TOKEN_DELIVERY_MODE, cibaPolicy.getBackchannelTokenDeliveryMode());
attrMap.put(CibaConfig.CIBA_EXPIRES_IN, String.valueOf(cibaPolicy.getExpiresIn()));
attrMap.put(CibaConfig.CIBA_INTERVAL, String.valueOf(cibaPolicy.getPoolingInterval()));
attrMap.put(CibaConfig.CIBA_AUTH_REQUESTED_USER_HINT, cibaPolicy.getAuthRequestedUserHint());
ParConfig parPolicy = realm.getParPolicy();
attrMap.put(ParConfig.PAR_REQUEST_URI_LIFESPAN, String.valueOf(parPolicy.getRequestUriLifespan()));
rep.setAttributes(attrMap);
if (realm.getBrowserFlow() != null) rep.setBrowserFlow(realm.getBrowserFlow().getAlias());
if (realm.getRegistrationFlow() != null) rep.setRegistrationFlow(realm.getRegistrationFlow().getAlias());
if (realm.getDirectGrantFlow() != null) rep.setDirectGrantFlow(realm.getDirectGrantFlow().getAlias());
if (realm.getResetCredentialsFlow() != null) rep.setResetCredentialsFlow(realm.getResetCredentialsFlow().getAlias());
if (realm.getClientAuthenticationFlow() != null) rep.setClientAuthenticationFlow(realm.getClientAuthenticationFlow().getAlias());
if (realm.getDockerAuthenticationFlow() != null) rep.setDockerAuthenticationFlow(realm.getDockerAuthenticationFlow().getAlias());
rep.setDefaultRole(toBriefRepresentation(realm.getDefaultRole()));
List<String> defaultGroups = realm.getDefaultGroupsStream()
.map(ModelToRepresentation::buildGroupPath).collect(Collectors.toList());
if (!defaultGroups.isEmpty()) {
rep.setDefaultGroups(defaultGroups);
}
Set<String> reqCredentials = realm.getRequiredCredentialsStream()
.map(RequiredCredentialModel::getType)
.collect(Collectors.toSet());
if (!reqCredentials.isEmpty()) {
rep.setRequiredCredentials(reqCredentials);
}
List<IdentityProviderRepresentation> identityProviders = realm.getIdentityProvidersStream()
.map(provider -> toRepresentation(realm, provider)).collect(Collectors.toList());
rep.setIdentityProviders(identityProviders);
List<IdentityProviderMapperRepresentation> identityProviderMappers = realm.getIdentityProviderMappersStream()
.map(ModelToRepresentation::toRepresentation).collect(Collectors.toList());
rep.setIdentityProviderMappers(identityProviderMappers);
rep.setInternationalizationEnabled(realm.isInternationalizationEnabled());
rep.setSupportedLocales(realm.getSupportedLocalesStream().collect(Collectors.toSet()));
rep.setDefaultLocale(realm.getDefaultLocale());
if (internal) {
exportAuthenticationFlows(session, realm, rep);
exportRequiredActions(realm, rep);
exportGroups(realm, rep);
}
session.clientPolicy().updateRealmRepresentationFromModel(realm, rep);
// Append realm attributes to representation
rep.getAttributes().putAll(stripRealmAttributesIncludedAsFields(realm.getAttributes()));
if (!internal) {
rep = StripSecretsUtils.strip(rep);
}
return rep;
}
public static Map<String, String> stripRealmAttributesIncludedAsFields(Map<String, String> attributes) {
Map<String, String> a = new HashMap<>();
for (Map.Entry<String, String> e : attributes.entrySet()) {
if (REALM_EXCLUDED_ATTRIBUTES.contains(e.getKey())) {
continue;
}
if (e.getKey().startsWith("_browser_header")) {
continue;
}
a.put(e.getKey(), e.getValue());
}
return a;
}
public static void exportGroups(RealmModel realm, RealmRepresentation rep) {
rep.setGroups(toGroupHierarchy(realm, true).collect(Collectors.toList()));
}
public static void exportAuthenticationFlows(KeycloakSession session, RealmModel realm, RealmRepresentation rep) {
List<AuthenticationFlowRepresentation> authenticationFlows = realm.getAuthenticationFlowsStream()
.sorted(AuthenticationFlowModel.AuthenticationFlowComparator.SINGLETON)
.map(flow -> toRepresentation(session, realm, flow))
.collect(Collectors.toList());
rep.setAuthenticationFlows(authenticationFlows);
List<AuthenticatorConfigRepresentation> authenticationConfigs = realm.getAuthenticatorConfigsStream()
.sorted(AuthenticatorConfigModel.AuthenticationConfigComparator.SINGLETON)
.map(ModelToRepresentation::toRepresentation)
.collect(Collectors.toList());
rep.setAuthenticatorConfig(authenticationConfigs);
}
public static void exportRequiredActions(RealmModel realm, RealmRepresentation rep) {
rep.setRequiredActions(realm.getRequiredActionProvidersStream()
.map(ModelToRepresentation::toRepresentation).collect(Collectors.toList()));
}
public static RealmEventsConfigRepresentation toEventsConfigReprensetation(RealmModel realm) {
RealmEventsConfigRepresentation rep = new RealmEventsConfigRepresentation();
rep.setEventsEnabled(realm.isEventsEnabled());
if (realm.getEventsExpiration() != 0) {
rep.setEventsExpiration(realm.getEventsExpiration());
}
rep.setEventsListeners(realm.getEventsListenersStream().collect(Collectors.toList()));
rep.setEnabledEventTypes(realm.getEnabledEventTypesStream().collect(Collectors.toList()));
rep.setAdminEventsEnabled(realm.isAdminEventsEnabled());
rep.setAdminEventsDetailsEnabled(realm.isAdminEventsDetailsEnabled());
return rep;
}
/**
* Handles exceptions that occur when transforming the model to a representation and will remove
* all null objects from the stream.
*
* Entities that have been removed from the store or where a lazy loading exception occurs will not show up
* in the output stream.
*/
public static <M, R> Stream<R> filterValidRepresentations(Stream<M> models, Function<M, R> transformer) {
return models.map(m -> {
try {
return transformer.apply(m);
} catch (ModelIllegalStateException e) {
LOG.warn("unable to retrieve model information, skipping entity", e);
return null;
}
})
.filter(Objects::nonNull);
}
public static CredentialRepresentation toRepresentation(UserCredentialModel cred) {
CredentialRepresentation rep = new CredentialRepresentation();
rep.setType(CredentialRepresentation.SECRET);
rep.setValue(cred.getChallengeResponse());
return rep;
}
public static CredentialRepresentation toRepresentation(CredentialModel cred) {
CredentialRepresentation rep = new CredentialRepresentation();
rep.setId(cred.getId());
rep.setType(cred.getType());
rep.setUserLabel(cred.getUserLabel());
rep.setCreatedDate(cred.getCreatedDate());
rep.setSecretData(cred.getSecretData());
rep.setCredentialData(cred.getCredentialData());
return rep;
}
public static CredentialMetadataRepresentation toRepresentation(CredentialMetadata credentialMetadata) {
CredentialMetadataRepresentation rep = new CredentialMetadataRepresentation();
rep.setCredential(ModelToRepresentation.toRepresentation(credentialMetadata.getCredentialModel()));
try {
rep.setInfoMessage(credentialMetadata.getInfoMessage() == null ? null : JsonSerialization.writeValueAsString(credentialMetadata.getInfoMessage()));
} catch (IOException e) {
LOG.warn("unable to serialize model information, skipping info message", e);
}
try {
rep.setWarningMessageDescription(credentialMetadata.getWarningMessageDescription() == null ? null : JsonSerialization.writeValueAsString(credentialMetadata.getWarningMessageDescription()));
} catch (IOException e) {
LOG.warn("unable to serialize model information, skipping warning message desc", e);
}
try {
rep.setWarningMessageTitle(credentialMetadata.getWarningMessageTitle() == null ? null : JsonSerialization.writeValueAsString(credentialMetadata.getWarningMessageTitle()));
} catch (IOException e) {
LOG.warn("unable to serialize model information, skipping warning message title", e);
}
return rep;
}
public static FederatedIdentityRepresentation toRepresentation(FederatedIdentityModel socialLink) {
FederatedIdentityRepresentation rep = new FederatedIdentityRepresentation();
rep.setUserName(socialLink.getUserName());
rep.setIdentityProvider(socialLink.getIdentityProvider());
rep.setUserId(socialLink.getUserId());
return rep;
}
public static UserSessionRepresentation toRepresentation(UserSessionModel session) {
UserSessionRepresentation rep = new UserSessionRepresentation();
rep.setId(session.getId());
rep.setStart(Time.toMillis(session.getStarted()));
rep.setLastAccess(Time.toMillis(session.getLastSessionRefresh()));
rep.setUsername(session.getUser().getUsername());
rep.setUserId(session.getUser().getId());
rep.setIpAddress(session.getIpAddress());
rep.setRememberMe(session.isRememberMe());
for (AuthenticatedClientSessionModel clientSession : session.getAuthenticatedClientSessions().values()) {
ClientModel client = clientSession.getClient();
rep.getClients().put(client.getId(), client.getClientId());
}
return rep;
}
public static ClientScopeRepresentation toRepresentation(ClientScopeModel clientScopeModel) {
ClientScopeRepresentation rep = new ClientScopeRepresentation();
rep.setId(clientScopeModel.getId());
rep.setName(clientScopeModel.getName());
rep.setDescription(clientScopeModel.getDescription());
rep.setProtocol(clientScopeModel.getProtocol());
List<ProtocolMapperRepresentation> mappings = clientScopeModel.getProtocolMappersStream()
.map(ModelToRepresentation::toRepresentation).collect(Collectors.toList());
if (!mappings.isEmpty())
rep.setProtocolMappers(mappings);
rep.setAttributes(new HashMap<>(clientScopeModel.getAttributes()));
return rep;
}
public static ClientRepresentation toRepresentation(ClientModel clientModel, KeycloakSession session) {
ClientRepresentation rep = new ClientRepresentation();
rep.setId(clientModel.getId());
String providerId = StorageId.resolveProviderId(clientModel);
rep.setOrigin(providerId);
rep.setClientId(clientModel.getClientId());
rep.setName(clientModel.getName());
rep.setDescription(clientModel.getDescription());
rep.setEnabled(clientModel.isEnabled());
rep.setAlwaysDisplayInConsole(clientModel.isAlwaysDisplayInConsole());
rep.setAdminUrl(clientModel.getManagementUrl());
rep.setPublicClient(clientModel.isPublicClient());
rep.setFrontchannelLogout(clientModel.isFrontchannelLogout());
rep.setProtocol(clientModel.getProtocol());
rep.setAttributes(clientModel.getAttributes());
rep.setAuthenticationFlowBindingOverrides(clientModel.getAuthenticationFlowBindingOverrides());
rep.setFullScopeAllowed(clientModel.isFullScopeAllowed());
rep.setBearerOnly(clientModel.isBearerOnly());
rep.setConsentRequired(clientModel.isConsentRequired());
rep.setStandardFlowEnabled(clientModel.isStandardFlowEnabled());
rep.setImplicitFlowEnabled(clientModel.isImplicitFlowEnabled());
rep.setDirectAccessGrantsEnabled(clientModel.isDirectAccessGrantsEnabled());
rep.setServiceAccountsEnabled(clientModel.isServiceAccountsEnabled());
rep.setSurrogateAuthRequired(clientModel.isSurrogateAuthRequired());
rep.setRootUrl(clientModel.getRootUrl());
rep.setBaseUrl(clientModel.getBaseUrl());
rep.setNotBefore(clientModel.getNotBefore());
rep.setNodeReRegistrationTimeout(clientModel.getNodeReRegistrationTimeout());
rep.setClientAuthenticatorType(clientModel.getClientAuthenticatorType());
// adding the secret if non public or bearer only
if (clientModel.isBearerOnly() || clientModel.isPublicClient()) {
rep.setSecret(null);
} else {
rep.setSecret(clientModel.getSecret());
}
rep.setDefaultClientScopes(new LinkedList<>(clientModel.getClientScopes(true).keySet()));
rep.setOptionalClientScopes(new LinkedList<>(clientModel.getClientScopes(false).keySet()));
Set<String> redirectUris = clientModel.getRedirectUris();
if (redirectUris != null) {
rep.setRedirectUris(new LinkedList<>(redirectUris));
}
Set<String> webOrigins = clientModel.getWebOrigins();
if (webOrigins != null) {
rep.setWebOrigins(new LinkedList<>(webOrigins));
}
if (!clientModel.getRegisteredNodes().isEmpty()) {
rep.setRegisteredNodes(new HashMap<>(clientModel.getRegisteredNodes()));
}
List<ProtocolMapperRepresentation> mappings = clientModel.getProtocolMappersStream()
.map(ModelToRepresentation::toRepresentation).collect(Collectors.toList());
if (!mappings.isEmpty())
rep.setProtocolMappers(mappings);
if (Profile.isFeatureEnabled(Profile.Feature.AUTHORIZATION)) {
AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
ResourceServer resourceServer = authorization.getStoreFactory().getResourceServerStore().findByClient(clientModel);
if (resourceServer != null) {
rep.setAuthorizationServicesEnabled(true);
}
}
return rep;
}
public static IdentityProviderRepresentation toBriefRepresentation(RealmModel realm, IdentityProviderModel identityProviderModel) {
IdentityProviderRepresentation providerRep = new IdentityProviderRepresentation();
// brief representation means IDs, names and enabled
providerRep.setInternalId(identityProviderModel.getInternalId());
providerRep.setProviderId(identityProviderModel.getProviderId());
providerRep.setAlias(identityProviderModel.getAlias());
providerRep.setDisplayName(identityProviderModel.getDisplayName());
providerRep.setEnabled(identityProviderModel.isEnabled());
return providerRep;
}
public static IdentityProviderRepresentation toRepresentation(RealmModel realm, IdentityProviderModel identityProviderModel) {
IdentityProviderRepresentation providerRep = toBriefRepresentation(realm, identityProviderModel);
providerRep.setLinkOnly(identityProviderModel.isLinkOnly());
providerRep.setStoreToken(identityProviderModel.isStoreToken());
providerRep.setTrustEmail(identityProviderModel.isTrustEmail());
providerRep.setAuthenticateByDefault(identityProviderModel.isAuthenticateByDefault());
Map<String, String> config = new HashMap<>(identityProviderModel.getConfig());
providerRep.setConfig(config);
providerRep.setAddReadTokenRoleOnCreate(identityProviderModel.isAddReadTokenRoleOnCreate());
String firstBrokerLoginFlowId = identityProviderModel.getFirstBrokerLoginFlowId();
if (firstBrokerLoginFlowId != null) {
AuthenticationFlowModel flow = realm.getAuthenticationFlowById(firstBrokerLoginFlowId);
if (flow == null) {
throw new ModelException("Couldn't find authentication flow with id " + firstBrokerLoginFlowId);
}
providerRep.setFirstBrokerLoginFlowAlias(flow.getAlias());
}
String postBrokerLoginFlowId = identityProviderModel.getPostBrokerLoginFlowId();
if (postBrokerLoginFlowId != null) {
AuthenticationFlowModel flow = realm.getAuthenticationFlowById(postBrokerLoginFlowId);
if (flow == null) {
throw new ModelException("Couldn't find authentication flow with id " + postBrokerLoginFlowId);
}
providerRep.setPostBrokerLoginFlowAlias(flow.getAlias());
}
return providerRep;
}
public static ProtocolMapperRepresentation toRepresentation(ProtocolMapperModel model) {
ProtocolMapperRepresentation rep = new ProtocolMapperRepresentation();
rep.setId(model.getId());
rep.setProtocol(model.getProtocol());
Map<String, String> config = new HashMap<>(model.getConfig());
rep.setConfig(config);
rep.setName(model.getName());
rep.setProtocolMapper(model.getProtocolMapper());
return rep;
}
public static IdentityProviderMapperRepresentation toRepresentation(IdentityProviderMapperModel model) {
IdentityProviderMapperRepresentation rep = new IdentityProviderMapperRepresentation();
rep.setId(model.getId());
rep.setIdentityProviderMapper(model.getIdentityProviderMapper());
rep.setIdentityProviderAlias(model.getIdentityProviderAlias());
Map<String, String> config = new HashMap<>(model.getConfig());
rep.setConfig(config);
rep.setName(model.getName());
return rep;
}
public static UserConsentRepresentation toRepresentation(UserConsentModel model) {
String clientId = model.getClient().getClientId();
List<String> grantedClientScopes = new LinkedList<>();
for (ClientScopeModel clientScope : model.getGrantedClientScopes()) {
if (clientScope instanceof ClientModel) {
grantedClientScopes.add(((ClientModel) clientScope).getClientId());
} else {
grantedClientScopes.add(clientScope.getName());
}
}
UserConsentRepresentation consentRep = new UserConsentRepresentation();
consentRep.setClientId(clientId);
consentRep.setGrantedClientScopes(grantedClientScopes);
consentRep.setCreatedDate(model.getCreatedDate());
consentRep.setLastUpdatedDate(model.getLastUpdatedDate());
return consentRep;
}
public static AuthenticationFlowRepresentation toRepresentation(KeycloakSession session, RealmModel realm, AuthenticationFlowModel model) {
AuthenticationFlowRepresentation rep = new AuthenticationFlowRepresentation();
rep.setId(model.getId());
rep.setBuiltIn(model.isBuiltIn());
rep.setTopLevel(model.isTopLevel());
rep.setProviderId(model.getProviderId());
rep.setAlias(model.getAlias());
rep.setDescription(model.getDescription());
rep.setAuthenticationExecutions(realm.getAuthenticationExecutionsStream(model.getId())
.map(e -> toRepresentation(session, realm, e)).collect(Collectors.toList()));
return rep;
}
public static AuthenticationExecutionExportRepresentation toRepresentation(KeycloakSession session, RealmModel realm, AuthenticationExecutionModel model) {
AuthenticationExecutionExportRepresentation rep = new AuthenticationExecutionExportRepresentation();
if (model.getAuthenticatorConfig() != null) {
AuthenticatorConfigModel config = new DeployedConfigurationsManager(session).getAuthenticatorConfig(realm, model.getAuthenticatorConfig());
rep.setAuthenticatorConfig(config.getAlias());
}
rep.setAuthenticator(model.getAuthenticator());
rep.setAuthenticatorFlow(model.isAuthenticatorFlow());
if (model.getFlowId() != null) {
AuthenticationFlowModel flow = realm.getAuthenticationFlowById(model.getFlowId());
rep.setFlowAlias(flow.getAlias());
}
rep.setPriority(model.getPriority());
rep.setRequirement(model.getRequirement().name());
return rep;
}
public static AuthenticatorConfigRepresentation toRepresentation(AuthenticatorConfigModel model) {
AuthenticatorConfigRepresentation rep = new AuthenticatorConfigRepresentation();
rep.setId(model.getId());
rep.setAlias(model.getAlias());
rep.setConfig(model.getConfig());
return rep;
}
public static RequiredActionProviderRepresentation toRepresentation(RequiredActionProviderModel model) {
RequiredActionProviderRepresentation rep = new RequiredActionProviderRepresentation();
rep.setAlias(model.getAlias());
rep.setDefaultAction(model.isDefaultAction());
rep.setEnabled(model.isEnabled());
rep.setConfig(model.getConfig());
rep.setName(model.getName());
rep.setProviderId(model.getProviderId());
rep.setPriority(model.getPriority());
return rep;
}
public static List<ConfigPropertyRepresentation> toRepresentation(List<ProviderConfigProperty> configProperties) {
List<ConfigPropertyRepresentation> propertiesRep = new LinkedList<>();
for (ProviderConfigProperty prop : configProperties) {
ConfigPropertyRepresentation propRep = toRepresentation(prop);
propertiesRep.add(propRep);
}
return propertiesRep;
}
public static ConfigPropertyRepresentation toRepresentation(ProviderConfigProperty prop) {
ConfigPropertyRepresentation propRep = new ConfigPropertyRepresentation();
propRep.setName(prop.getName());
propRep.setLabel(prop.getLabel());
propRep.setType(prop.getType());
propRep.setDefaultValue(prop.getDefaultValue());
propRep.setOptions(prop.getOptions());
propRep.setHelpText(prop.getHelpText());
propRep.setSecret(prop.isSecret());
return propRep;
}
public static ComponentRepresentation toRepresentation(KeycloakSession session, ComponentModel component, boolean internal) {
ComponentRepresentation rep = toRepresentationWithoutConfig(component);
if (!internal) {
rep = StripSecretsUtils.strip(session, rep);
}
return rep;
}
public static ComponentRepresentation toRepresentationWithoutConfig(ComponentModel component) {
ComponentRepresentation rep = new ComponentRepresentation();
rep.setId(component.getId());
rep.setName(component.getName());
rep.setProviderId(component.getProviderId());
rep.setProviderType(component.getProviderType());
rep.setSubType(component.getSubType());
rep.setParentId(component.getParentId());
rep.setConfig(new MultivaluedHashMap<>(component.getConfig()));
return rep;
}
public static ScopeRepresentation toRepresentation(Scope model) {
ScopeRepresentation scope = new ScopeRepresentation();
scope.setId(model.getId());
scope.setName(model.getName());
scope.setDisplayName(model.getDisplayName());
scope.setIconUri(model.getIconUri());
return scope;
}
public static ResourceServerRepresentation toRepresentation(ResourceServer model, ClientModel client) {
ResourceServerRepresentation server = new ResourceServerRepresentation();
server.setId(model.getId());
server.setClientId(model.getClientId());
server.setName(client.getClientId());
server.setAllowRemoteResourceManagement(model.isAllowRemoteResourceManagement());
server.setPolicyEnforcementMode(model.getPolicyEnforcementMode());
server.setDecisionStrategy(model.getDecisionStrategy());
return server;
}
public static <R extends AbstractPolicyRepresentation> R toRepresentation(Policy policy, AuthorizationProvider authorization) {
return toRepresentation(policy, authorization, false, true);
}
public static <R extends AbstractPolicyRepresentation> R toRepresentation(Policy policy, AuthorizationProvider authorization, boolean genericRepresentation, boolean export) {
return toRepresentation(policy, authorization, genericRepresentation, export, false);
}
public static <R extends AbstractPolicyRepresentation> R toRepresentation(Policy policy, AuthorizationProvider authorization, boolean genericRepresentation, boolean export, boolean allFields) {
PolicyProviderFactory providerFactory = authorization.getProviderFactory(policy.getType());
R representation;
if (genericRepresentation || export) {
representation = (R) new PolicyRepresentation();
PolicyRepresentation.class.cast(representation).setConfig(policy.getConfig());
if (export) {
providerFactory.onExport(policy, PolicyRepresentation.class.cast(representation), authorization);
}
} else {
try {
representation = (R) providerFactory.toRepresentation(policy, authorization);
} catch (Exception cause) {
throw new RuntimeException("Could not create policy [" + policy.getType() + "] representation", cause);
}
}
representation.setId(policy.getId());
representation.setName(policy.getName());
representation.setDescription(policy.getDescription());
representation.setType(policy.getType());
representation.setDecisionStrategy(policy.getDecisionStrategy());
representation.setLogic(policy.getLogic());
if (allFields) {
representation.setResourcesData(policy.getResources().stream()
.map(resource -> toRepresentation(resource, policy.getResourceServer(), authorization, true))
.collect(Collectors.toSet()));
representation.setScopesData(policy.getScopes().stream().map(
resource -> toRepresentation(resource)).collect(Collectors.toSet()));
}
return representation;
}
public static ResourceRepresentation toRepresentation(Resource model, ResourceServer resourceServer, AuthorizationProvider authorization) {
return toRepresentation(model, resourceServer, authorization, true);
}
public static ResourceRepresentation toRepresentation(Resource model, ResourceServer resourceServer, AuthorizationProvider authorization, Boolean deep) {
ResourceRepresentation resource = new ResourceRepresentation();
resource.setId(model.getId());
resource.setType(model.getType());
resource.setName(model.getName());
resource.setDisplayName(model.getDisplayName());
resource.setUris(model.getUris());
resource.setIconUri(model.getIconUri());
resource.setOwnerManagedAccess(model.isOwnerManagedAccess());
ResourceOwnerRepresentation owner = new ResourceOwnerRepresentation();
owner.setId(model.getOwner());
KeycloakSession keycloakSession = authorization.getKeycloakSession();
RealmModel realm = authorization.getRealm();
if (owner.getId().equals(resourceServer.getClientId())) {
ClientModel clientModel = realm.getClientById(resourceServer.getClientId());
owner.setName(clientModel.getClientId());
} else {
UserModel userModel = keycloakSession.users().getUserById(realm, owner.getId());
if (userModel == null) {
throw new RuntimeException("Could not find the user [" + owner.getId() + "] who owns the Resource [" + resource.getId() + "].");
}
owner.setName(userModel.getUsername());
}
resource.setOwner(owner);
if (deep) {
resource.setScopes(model.getScopes().stream().map(model1 -> {
ScopeRepresentation scope = new ScopeRepresentation();
scope.setId(model1.getId());
scope.setName(model1.getName());
String iconUri = model1.getIconUri();
if (iconUri != null) {
scope.setIconUri(iconUri);
}
return scope;
}).collect(Collectors.toSet()));
resource.setAttributes(new HashMap<>(model.getAttributes()));
}
return resource;
}
public static PermissionTicketRepresentation toRepresentation(PermissionTicket ticket, AuthorizationProvider authorization) {
return toRepresentation(ticket, authorization, false);
}
public static PermissionTicketRepresentation toRepresentation(PermissionTicket ticket, AuthorizationProvider authorization, boolean returnNames) {
PermissionTicketRepresentation representation = new PermissionTicketRepresentation();
representation.setId(ticket.getId());
representation.setGranted(ticket.isGranted());
representation.setOwner(ticket.getOwner());
representation.setRequester(ticket.getRequester());
Resource resource = ticket.getResource();
representation.setResource(resource.getId());
if (returnNames) {
representation.setResourceName(resource.getName());
KeycloakSession keycloakSession = authorization.getKeycloakSession();
RealmModel realm = authorization.getRealm();
UserModel userOwner = keycloakSession.users().getUserById(realm, ticket.getOwner());
UserModel requester = keycloakSession.users().getUserById(realm, ticket.getRequester());
representation.setRequesterName(requester.getUsername());
if (userOwner != null) {
representation.setOwnerName(userOwner.getUsername());
} else {
ClientModel clientOwner = realm.getClientById(ticket.getOwner());
representation.setOwnerName(clientOwner.getClientId());
}
}
Scope scope = ticket.getScope();
if (scope != null) {
representation.setScope(scope.getId());
if (returnNames) {
representation.setScopeName(scope.getName());
}
}
return representation;
}
public static ResourceServerRepresentation toResourceServerRepresentation(KeycloakSession session, ClientModel client) {
AuthorizationProviderFactory providerFactory = (AuthorizationProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(AuthorizationProvider.class);
AuthorizationProvider authorization = providerFactory.create(session, client.getRealm());
StoreFactory storeFactory = authorization.getStoreFactory();
ResourceServer settingsModel = authorization.getStoreFactory().getResourceServerStore().findByClient(client);
if (settingsModel == null) {
return null;
}
ResourceServerRepresentation representation = toRepresentation(settingsModel, client);
representation.setId(null);
representation.setName(null);
representation.setClientId(null);
List<ResourceRepresentation> resources = storeFactory.getResourceStore().findByResourceServer(settingsModel)
.stream().map(resource -> {
ResourceRepresentation rep = toRepresentation(resource, settingsModel, authorization);
if (rep.getOwner().getId().equals(settingsModel.getClientId())) {
rep.setOwner((ResourceOwnerRepresentation) null);
} else {
rep.getOwner().setId(null);
}
rep.getScopes().forEach(scopeRepresentation -> {
scopeRepresentation.setId(null);
scopeRepresentation.setIconUri(null);
});
return rep;
}).collect(Collectors.toList());
representation.setResources(resources);
List<PolicyRepresentation> policies = new ArrayList<>();
PolicyStore policyStore = storeFactory.getPolicyStore();
policies.addAll(policyStore.findByResourceServer(settingsModel)
.stream().filter(policy -> !policy.getType().equals("resource") && !policy.getType().equals("scope") && policy.getOwner() == null)
.map(policy -> toRepresentation(authorization, policy)).collect(Collectors.toList()));
policies.addAll(policyStore.findByResourceServer(settingsModel)
.stream().filter(policy -> (policy.getType().equals("resource") || policy.getType().equals("scope") && policy.getOwner() == null))
.map(policy -> toRepresentation(authorization, policy)).collect(Collectors.toList()));
representation.setPolicies(policies);
List<ScopeRepresentation> scopes = storeFactory.getScopeStore().findByResourceServer(settingsModel).stream().map(scope -> {
ScopeRepresentation rep = toRepresentation(scope);
rep.setPolicies(null);
rep.setResources(null);
return rep;
}).collect(Collectors.toList());
representation.setScopes(scopes);
return representation;
}
private static PolicyRepresentation toRepresentation(AuthorizationProvider authorizationProvider, Policy policy) {
try {
PolicyRepresentation rep = toRepresentation(policy, authorizationProvider, true, true);
Map<String, String> config = new HashMap<>(rep.getConfig());
rep.setConfig(config);
Set<Scope> scopes = policy.getScopes();
if (!scopes.isEmpty()) {
List<String> scopeNames = scopes.stream().map(Scope::getName).collect(Collectors.toList());
config.put("scopes", JsonSerialization.writeValueAsString(scopeNames));
}
Set<Resource> policyResources = policy.getResources();
if (!policyResources.isEmpty()) {
List<String> resourceNames = policyResources.stream().map(Resource::getName).collect(Collectors.toList());
config.put("resources", JsonSerialization.writeValueAsString(resourceNames));
}
Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
if (!associatedPolicies.isEmpty()) {
config.put("applyPolicies", JsonSerialization.writeValueAsString(associatedPolicies.stream().map(associated -> associated.getName()).collect(Collectors.toList())));
}
return rep;
} catch (Exception e) {
throw new RuntimeException("Error while exporting policy [" + policy.getName() + "].", e);
}
}
}