Add more attribute mappers, cleanup existing mappers
8 files modified
5 files added
| | |
| | | import org.keycloak.Config; |
| | | import org.keycloak.models.KeycloakSession; |
| | | import org.keycloak.models.KeycloakSessionFactory; |
| | | import org.keycloak.models.ProtocolMapperModel; |
| | | import org.keycloak.protocol.ProtocolMapper; |
| | | import org.keycloak.protocol.cas.CASLoginProtocol; |
| | | import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper; |
| | | |
| | | import java.util.Map; |
| | | |
| | | public abstract class AbstractCASProtocolMapper implements ProtocolMapper, CASAttributeMapper { |
| | | public static final String TOKEN_MAPPER_CATEGORY = "Token mapper"; |
| | |
| | | public String getDisplayCategory() { |
| | | return TOKEN_MAPPER_CATEGORY; |
| | | } |
| | | |
| | | protected void setMappedAttribute(Map<String, Object> attributes, ProtocolMapperModel mappingModel, Object attributeValue) { |
| | | setPlainAttribute(attributes, mappingModel, OIDCAttributeMapperHelper.mapAttributeValue(mappingModel, attributeValue)); |
| | | } |
| | | |
| | | protected void setPlainAttribute(Map<String, Object> attributes, ProtocolMapperModel mappingModel, Object attributeValue) { |
| | | String protocolClaim = mappingModel.getConfig().get(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME); |
| | | if (protocolClaim == null || attributeValue == null) { |
| | | return; |
| | | } |
| | | attributes.put(protocolClaim, attributeValue); |
| | | } |
| | | } |
New file |
| | |
| | | /* |
| | | * 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.protocol.cas.mappers; |
| | | |
| | | import org.keycloak.models.*; |
| | | import org.keycloak.models.utils.RoleUtils; |
| | | |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import java.util.function.Predicate; |
| | | import java.util.stream.Collectors; |
| | | import java.util.stream.Stream; |
| | | |
| | | /** |
| | | * Base class for mapping of user role mappings to an ID and Access Token claim. |
| | | * |
| | | * @author <a href="mailto:thomas.darimont@gmail.com">Thomas Darimont</a> |
| | | */ |
| | | abstract class AbstractUserRoleMappingMapper extends AbstractCASProtocolMapper { |
| | | |
| | | /** |
| | | * Returns a stream with roles that come from: |
| | | * <ul> |
| | | * <li>Direct assignment of the role to the user</li> |
| | | * <li>Direct assignment of the role to any group of the user or any of its parent group</li> |
| | | * <li>Composite roles are expanded recursively, the composite role itself is also contained in the returned stream</li> |
| | | * </ul> |
| | | * @param user User to enumerate the roles for |
| | | */ |
| | | public Stream<RoleModel> getAllUserRolesStream(UserModel user) { |
| | | return Stream.concat( |
| | | user.getRoleMappings().stream(), |
| | | user.getGroups().stream() |
| | | .flatMap(this::groupAndItsParentsStream) |
| | | .flatMap(g -> g.getRoleMappings().stream())) |
| | | .flatMap(RoleUtils::expandCompositeRolesStream); |
| | | } |
| | | |
| | | /** |
| | | * Returns stream of the given group and its parents (recursively). |
| | | * @param group |
| | | * @return |
| | | */ |
| | | private Stream<GroupModel> groupAndItsParentsStream(GroupModel group) { |
| | | Stream.Builder<GroupModel> sb = Stream.builder(); |
| | | while (group != null) { |
| | | sb.add(group); |
| | | group = group.getParent(); |
| | | } |
| | | return sb.build(); |
| | | } |
| | | |
| | | /** |
| | | * Retrieves all roles of the current user based on direct roles set to the user, its groups and their parent groups. |
| | | * Then it recursively expands all composite roles, and restricts according to the given predicate {@code restriction}. |
| | | * If the current client sessions is restricted (i.e. no client found in active user session has full scope allowed), |
| | | * the final list of roles is also restricted by the client scope. Finally, the list is mapped to the token into |
| | | * a claim. |
| | | */ |
| | | protected void setAttribute(Map<String, Object> attributes, ProtocolMapperModel mappingModel, UserSessionModel userSession, |
| | | Predicate<RoleModel> restriction, String prefix) { |
| | | String rolePrefix = prefix == null ? "" : prefix; |
| | | UserModel user = userSession.getUser(); |
| | | |
| | | // get a set of all realm roles assigned to the user or its group |
| | | Stream<RoleModel> clientUserRoles = getAllUserRolesStream(user).filter(restriction); |
| | | |
| | | boolean dontLimitScope = userSession.getClientSessions().stream().anyMatch(cs -> cs.getClient().isFullScopeAllowed()); |
| | | if (! dontLimitScope) { |
| | | Set<RoleModel> clientRoles = userSession.getClientSessions().stream() |
| | | .flatMap(cs -> cs.getClient().getScopeMappings().stream()) |
| | | .collect(Collectors.toSet()); |
| | | |
| | | clientUserRoles = clientUserRoles.filter(clientRoles::contains); |
| | | } |
| | | |
| | | Set<String> realmRoleNames = clientUserRoles |
| | | .map(m -> rolePrefix + m.getName()) |
| | | .collect(Collectors.toSet()); |
| | | |
| | | setPlainAttribute(attributes, mappingModel, realmRoleNames); |
| | | } |
| | | } |
New file |
| | |
| | | package org.keycloak.protocol.cas.mappers; |
| | | |
| | | import org.keycloak.models.ProtocolMapperModel; |
| | | import org.keycloak.protocol.cas.CASLoginProtocol; |
| | | import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | public class CASAttributeMapperHelper { |
| | | public static ProtocolMapperModel createClaimMapper(String name, |
| | | String tokenClaimName, String claimType, |
| | | boolean consentRequired, String consentText, |
| | | String mapperId) { |
| | | ProtocolMapperModel mapper = new ProtocolMapperModel(); |
| | | mapper.setName(name); |
| | | mapper.setProtocolMapper(mapperId); |
| | | mapper.setProtocol(CASLoginProtocol.LOGIN_PROTOCOL); |
| | | mapper.setConsentRequired(consentRequired); |
| | | mapper.setConsentText(consentText); |
| | | Map<String, String> config = new HashMap<String, String>(); |
| | | config.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, tokenClaimName); |
| | | config.put(OIDCAttributeMapperHelper.JSON_TYPE, claimType); |
| | | mapper.setConfig(config); |
| | | return mapper; |
| | | } |
| | | |
| | | } |
| | |
| | | import org.keycloak.models.ProtocolMapperModel; |
| | | import org.keycloak.models.UserModel; |
| | | import org.keycloak.models.UserSessionModel; |
| | | import org.keycloak.protocol.cas.CASLoginProtocol; |
| | | import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper; |
| | | import org.keycloak.provider.ProviderConfigProperty; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | import static org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME; |
| | | |
| | | public class FullNameMapper extends AbstractCASProtocolMapper { |
| | | private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>(); |
| | |
| | | @Override |
| | | public void setAttribute(Map<String, Object> attributes, ProtocolMapperModel mappingModel, UserSessionModel userSession) { |
| | | UserModel user = userSession.getUser(); |
| | | String protocolClaim = mappingModel.getConfig().get(TOKEN_CLAIM_NAME); |
| | | if (protocolClaim == null) { |
| | | return; |
| | | } |
| | | String first = user.getFirstName() == null ? "" : user.getFirstName() + " "; |
| | | String last = user.getLastName() == null ? "" : user.getLastName(); |
| | | attributes.put(protocolClaim, first + last); |
| | | setMappedAttribute(attributes, mappingModel, first + last); |
| | | } |
| | | |
| | | public static ProtocolMapperModel create(String name, String tokenClaimName, |
| | | boolean consentRequired, String consentText) { |
| | | ProtocolMapperModel mapper = new ProtocolMapperModel(); |
| | | mapper.setName(name); |
| | | mapper.setProtocolMapper(PROVIDER_ID); |
| | | mapper.setProtocol(CASLoginProtocol.LOGIN_PROTOCOL); |
| | | mapper.setConsentRequired(consentRequired); |
| | | mapper.setConsentText(consentText); |
| | | Map<String, String> config = new HashMap<String, String>(); |
| | | config.put(TOKEN_CLAIM_NAME, tokenClaimName); |
| | | mapper.setConfig(config); |
| | | return mapper; |
| | | return CASAttributeMapperHelper.createClaimMapper(name, tokenClaimName, |
| | | "String", consentRequired, consentText, PROVIDER_ID); |
| | | } |
| | | } |
| | |
| | | import org.keycloak.models.ProtocolMapperModel; |
| | | import org.keycloak.models.UserSessionModel; |
| | | import org.keycloak.models.utils.ModelToRepresentation; |
| | | import org.keycloak.protocol.cas.CASLoginProtocol; |
| | | import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper; |
| | | import org.keycloak.provider.ProviderConfigProperty; |
| | | |
| | | import java.util.*; |
| | | import java.util.ArrayList; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | public class GroupMembershipMapper extends AbstractCASProtocolMapper { |
| | | private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>(); |
| | | |
| | | private static final String FULL_PATH = "full.path"; |
| | | |
| | | static { |
| | | OIDCAttributeMapperHelper.addTokenClaimNameConfig(configProperties); |
| | | ProviderConfigProperty property1 = new ProviderConfigProperty(); |
| | | property1.setName("full.path"); |
| | | property1.setName(FULL_PATH); |
| | | property1.setLabel("Full group path"); |
| | | property1.setType(ProviderConfigProperty.BOOLEAN_TYPE); |
| | | property1.setDefaultValue("true"); |
| | |
| | | membership.add(group.getName()); |
| | | } |
| | | } |
| | | String protocolClaim = mappingModel.getConfig().get(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME); |
| | | |
| | | attributes.put(protocolClaim, membership); |
| | | setPlainAttribute(attributes, mappingModel, membership); |
| | | } |
| | | |
| | | public static boolean useFullPath(ProtocolMapperModel mappingModel) { |
| | | return "true".equals(mappingModel.getConfig().get("full.path")); |
| | | return "true".equals(mappingModel.getConfig().get(FULL_PATH)); |
| | | } |
| | | |
| | | public static ProtocolMapperModel create(String name, String tokenClaimName, |
| | | boolean consentRequired, String consentText, boolean fullPath) { |
| | | ProtocolMapperModel mapper = new ProtocolMapperModel(); |
| | | mapper.setName(name); |
| | | mapper.setProtocolMapper(PROVIDER_ID); |
| | | mapper.setProtocol(CASLoginProtocol.LOGIN_PROTOCOL); |
| | | mapper.setConsentRequired(consentRequired); |
| | | mapper.setConsentText(consentText); |
| | | Map<String, String> config = new HashMap<String, String>(); |
| | | config.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, tokenClaimName); |
| | | config.put("full.path", Boolean.toString(fullPath)); |
| | | mapper.setConfig(config); |
| | | |
| | | ProtocolMapperModel mapper = CASAttributeMapperHelper.createClaimMapper(name, tokenClaimName, |
| | | "String", consentRequired, consentText, PROVIDER_ID); |
| | | mapper.getConfig().put(FULL_PATH, Boolean.toString(fullPath)); |
| | | return mapper; |
| | | } |
| | | } |
| | |
| | | |
| | | @Override |
| | | public void setAttribute(Map<String, Object> attributes, ProtocolMapperModel mappingModel, UserSessionModel userSession) { |
| | | String protocolClaim = mappingModel.getConfig().get(TOKEN_CLAIM_NAME); |
| | | if (protocolClaim == null) { |
| | | return; |
| | | } |
| | | String attributeValue = mappingModel.getConfig().get(CLAIM_VALUE); |
| | | if (attributeValue == null) return; |
| | | attributes.put(protocolClaim, OIDCAttributeMapperHelper.mapAttributeValue(mappingModel, attributeValue)); |
| | | setMappedAttribute(attributes, mappingModel, mappingModel.getConfig().get(CLAIM_VALUE)); |
| | | } |
| | | |
| | | } |
| | |
| | | import org.keycloak.models.UserSessionModel; |
| | | import org.keycloak.models.utils.KeycloakModelUtils; |
| | | import org.keycloak.protocol.ProtocolMapperUtils; |
| | | import org.keycloak.protocol.cas.CASLoginProtocol; |
| | | import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper; |
| | | import org.keycloak.provider.ProviderConfigProperty; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | import static org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper.JSON_TYPE; |
| | | import static org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME; |
| | | |
| | | public class UserAttributeMapper extends AbstractCASProtocolMapper { |
| | | private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>(); |
| | |
| | | @Override |
| | | public void setAttribute(Map<String, Object> attributes, ProtocolMapperModel mappingModel, UserSessionModel userSession) { |
| | | UserModel user = userSession.getUser(); |
| | | String protocolClaim = mappingModel.getConfig().get(TOKEN_CLAIM_NAME); |
| | | if (protocolClaim == null) { |
| | | return; |
| | | } |
| | | String attributeName = mappingModel.getConfig().get(ProtocolMapperUtils.USER_ATTRIBUTE); |
| | | List<String> attributeValue = KeycloakModelUtils.resolveAttribute(user, attributeName); |
| | | if (attributeValue == null) return; |
| | | attributes.put(protocolClaim, OIDCAttributeMapperHelper.mapAttributeValue(mappingModel, attributeValue)); |
| | | setMappedAttribute(attributes, mappingModel, attributeValue); |
| | | } |
| | | |
| | | public static ProtocolMapperModel create(String name, String userAttribute, |
| | | String tokenClaimName, String claimType, |
| | | boolean consentRequired, String consentText, boolean multivalued) { |
| | | ProtocolMapperModel mapper = new ProtocolMapperModel(); |
| | | mapper.setName(name); |
| | | mapper.setProtocolMapper(PROVIDER_ID); |
| | | mapper.setProtocol(CASLoginProtocol.LOGIN_PROTOCOL); |
| | | mapper.setConsentRequired(consentRequired); |
| | | mapper.setConsentText(consentText); |
| | | Map<String, String> config = new HashMap<String, String>(); |
| | | config.put(ProtocolMapperUtils.USER_ATTRIBUTE, userAttribute); |
| | | config.put(TOKEN_CLAIM_NAME, tokenClaimName); |
| | | config.put(JSON_TYPE, claimType); |
| | | ProtocolMapperModel mapper = CASAttributeMapperHelper.createClaimMapper(name, tokenClaimName, |
| | | claimType, consentRequired, consentText, PROVIDER_ID); |
| | | mapper.getConfig().put(ProtocolMapperUtils.USER_ATTRIBUTE, userAttribute); |
| | | if (multivalued) { |
| | | mapper.getConfig().put(ProtocolMapperUtils.MULTIVALUED, "true"); |
| | | } |
| | | mapper.setConfig(config); |
| | | return mapper; |
| | | } |
| | | } |
New file |
| | |
| | | package org.keycloak.protocol.cas.mappers; |
| | | |
| | | import org.keycloak.models.*; |
| | | import org.keycloak.protocol.ProtocolMapperUtils; |
| | | import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper; |
| | | import org.keycloak.provider.ProviderConfigProperty; |
| | | |
| | | import java.util.*; |
| | | import java.util.function.Predicate; |
| | | |
| | | public class UserClientRoleMappingMapper extends AbstractUserRoleMappingMapper { |
| | | |
| | | public static final String PROVIDER_ID = "cas-usermodel-client-role-mapper"; |
| | | |
| | | private static final List<ProviderConfigProperty> CONFIG_PROPERTIES = new ArrayList<>(); |
| | | |
| | | static { |
| | | |
| | | ProviderConfigProperty clientId = new ProviderConfigProperty(); |
| | | clientId.setName(ProtocolMapperUtils.USER_MODEL_CLIENT_ROLE_MAPPING_CLIENT_ID); |
| | | clientId.setLabel(ProtocolMapperUtils.USER_MODEL_CLIENT_ROLE_MAPPING_CLIENT_ID_LABEL); |
| | | clientId.setHelpText(ProtocolMapperUtils.USER_MODEL_CLIENT_ROLE_MAPPING_CLIENT_ID_HELP_TEXT); |
| | | clientId.setType(ProviderConfigProperty.CLIENT_LIST_TYPE); |
| | | CONFIG_PROPERTIES.add(clientId); |
| | | |
| | | ProviderConfigProperty clientRolePrefix = new ProviderConfigProperty(); |
| | | clientRolePrefix.setName(ProtocolMapperUtils.USER_MODEL_CLIENT_ROLE_MAPPING_ROLE_PREFIX); |
| | | clientRolePrefix.setLabel(ProtocolMapperUtils.USER_MODEL_CLIENT_ROLE_MAPPING_ROLE_PREFIX_LABEL); |
| | | clientRolePrefix.setHelpText(ProtocolMapperUtils.USER_MODEL_CLIENT_ROLE_MAPPING_ROLE_PREFIX_HELP_TEXT); |
| | | clientRolePrefix.setType(ProviderConfigProperty.STRING_TYPE); |
| | | CONFIG_PROPERTIES.add(clientRolePrefix); |
| | | |
| | | OIDCAttributeMapperHelper.addTokenClaimNameConfig(CONFIG_PROPERTIES); |
| | | } |
| | | |
| | | @Override |
| | | public List<ProviderConfigProperty> getConfigProperties() { |
| | | return CONFIG_PROPERTIES; |
| | | } |
| | | |
| | | @Override |
| | | public String getId() { |
| | | return PROVIDER_ID; |
| | | } |
| | | |
| | | @Override |
| | | public String getDisplayType() { |
| | | return "User Client Role"; |
| | | } |
| | | |
| | | @Override |
| | | public String getDisplayCategory() { |
| | | return TOKEN_MAPPER_CATEGORY; |
| | | } |
| | | |
| | | @Override |
| | | public String getHelpText() { |
| | | return "Map a user client role to a token claim."; |
| | | } |
| | | |
| | | @Override |
| | | public void setAttribute(Map<String, Object> attributes, ProtocolMapperModel mappingModel, UserSessionModel userSession) { |
| | | String clientId = mappingModel.getConfig().get(ProtocolMapperUtils.USER_MODEL_CLIENT_ROLE_MAPPING_CLIENT_ID); |
| | | String rolePrefix = mappingModel.getConfig().get(ProtocolMapperUtils.USER_MODEL_CLIENT_ROLE_MAPPING_ROLE_PREFIX); |
| | | |
| | | setAttribute(attributes, mappingModel, userSession, getClientRoleFilter(clientId, userSession), rolePrefix); |
| | | } |
| | | |
| | | private static Predicate<RoleModel> getClientRoleFilter(String clientId, UserSessionModel userSession) { |
| | | if (clientId == null) { |
| | | return RoleModel::isClientRole; |
| | | } |
| | | |
| | | RealmModel clientRealm = userSession.getRealm(); |
| | | ClientModel client = clientRealm.getClientByClientId(clientId.trim()); |
| | | |
| | | if (client == null) { |
| | | return RoleModel::isClientRole; |
| | | } |
| | | |
| | | ClientTemplateModel template = client.getClientTemplate(); |
| | | boolean useTemplateScope = template != null && client.useTemplateScope(); |
| | | boolean fullScopeAllowed = (useTemplateScope && template.isFullScopeAllowed()) || client.isFullScopeAllowed(); |
| | | |
| | | Set<RoleModel> clientRoleMappings = client.getRoles(); |
| | | if (fullScopeAllowed) { |
| | | return clientRoleMappings::contains; |
| | | } |
| | | |
| | | Set<RoleModel> scopeMappings = new HashSet<>(); |
| | | |
| | | if (useTemplateScope) { |
| | | Set<RoleModel> templateScopeMappings = template.getScopeMappings(); |
| | | if (templateScopeMappings != null) { |
| | | scopeMappings.addAll(templateScopeMappings); |
| | | } |
| | | } |
| | | |
| | | Set<RoleModel> clientScopeMappings = client.getScopeMappings(); |
| | | if (clientScopeMappings != null) { |
| | | scopeMappings.addAll(clientScopeMappings); |
| | | } |
| | | |
| | | return role -> clientRoleMappings.contains(role) && scopeMappings.contains(role); |
| | | } |
| | | |
| | | public static ProtocolMapperModel create(String clientId, String clientRolePrefix, |
| | | String name, String tokenClaimName) { |
| | | ProtocolMapperModel mapper = CASAttributeMapperHelper.createClaimMapper(name, tokenClaimName, |
| | | "String", true, name, PROVIDER_ID); |
| | | mapper.getConfig().put(ProtocolMapperUtils.USER_MODEL_CLIENT_ROLE_MAPPING_CLIENT_ID, clientId); |
| | | mapper.getConfig().put(ProtocolMapperUtils.USER_MODEL_CLIENT_ROLE_MAPPING_ROLE_PREFIX, clientRolePrefix); |
| | | return mapper; |
| | | } |
| | | } |
| | |
| | | import org.keycloak.models.UserModel; |
| | | import org.keycloak.models.UserSessionModel; |
| | | import org.keycloak.protocol.ProtocolMapperUtils; |
| | | import org.keycloak.protocol.cas.CASLoginProtocol; |
| | | import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper; |
| | | import org.keycloak.provider.ProviderConfigProperty; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | import static org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper.JSON_TYPE; |
| | | import static org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME; |
| | | |
| | | public class UserPropertyMapper extends AbstractCASProtocolMapper { |
| | | private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>(); |
| | |
| | | @Override |
| | | public void setAttribute(Map<String, Object> attributes, ProtocolMapperModel mappingModel, UserSessionModel userSession) { |
| | | UserModel user = userSession.getUser(); |
| | | String protocolClaim = mappingModel.getConfig().get(TOKEN_CLAIM_NAME); |
| | | if (protocolClaim == null) { |
| | | return; |
| | | } |
| | | String propertyName = mappingModel.getConfig().get(ProtocolMapperUtils.USER_ATTRIBUTE); |
| | | String propertyValue = ProtocolMapperUtils.getUserModelValue(user, propertyName); |
| | | attributes.put(protocolClaim, OIDCAttributeMapperHelper.mapAttributeValue(mappingModel, propertyValue)); |
| | | setMappedAttribute(attributes, mappingModel, propertyValue); |
| | | } |
| | | |
| | | public static ProtocolMapperModel create(String name, String userAttribute, |
| | | String tokenClaimName, String claimType, |
| | | boolean consentRequired, String consentText) { |
| | | ProtocolMapperModel mapper = new ProtocolMapperModel(); |
| | | mapper.setName(name); |
| | | mapper.setProtocolMapper(PROVIDER_ID); |
| | | mapper.setProtocol(CASLoginProtocol.LOGIN_PROTOCOL); |
| | | mapper.setConsentRequired(consentRequired); |
| | | mapper.setConsentText(consentText); |
| | | Map<String, String> config = new HashMap<String, String>(); |
| | | config.put(ProtocolMapperUtils.USER_ATTRIBUTE, userAttribute); |
| | | config.put(TOKEN_CLAIM_NAME, tokenClaimName); |
| | | config.put(JSON_TYPE, claimType); |
| | | mapper.setConfig(config); |
| | | ProtocolMapperModel mapper = CASAttributeMapperHelper.createClaimMapper(name, tokenClaimName, |
| | | claimType, consentRequired, consentText, PROVIDER_ID); |
| | | mapper.getConfig().put(ProtocolMapperUtils.USER_ATTRIBUTE, userAttribute); |
| | | return mapper; |
| | | } |
| | | } |
New file |
| | |
| | | package org.keycloak.protocol.cas.mappers; |
| | | |
| | | import org.keycloak.models.ProtocolMapperModel; |
| | | import org.keycloak.models.UserSessionModel; |
| | | import org.keycloak.protocol.ProtocolMapperUtils; |
| | | import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper; |
| | | import org.keycloak.provider.ProviderConfigProperty; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | public class UserRealmRoleMappingMapper extends AbstractUserRoleMappingMapper { |
| | | public static final String PROVIDER_ID = "cas-usermodel-realm-role-mapper"; |
| | | |
| | | private static final List<ProviderConfigProperty> CONFIG_PROPERTIES = new ArrayList<>(); |
| | | |
| | | static { |
| | | |
| | | ProviderConfigProperty realmRolePrefix = new ProviderConfigProperty(); |
| | | realmRolePrefix.setName(ProtocolMapperUtils.USER_MODEL_REALM_ROLE_MAPPING_ROLE_PREFIX); |
| | | realmRolePrefix.setLabel(ProtocolMapperUtils.USER_MODEL_REALM_ROLE_MAPPING_ROLE_PREFIX_LABEL); |
| | | realmRolePrefix.setHelpText(ProtocolMapperUtils.USER_MODEL_REALM_ROLE_MAPPING_ROLE_PREFIX_HELP_TEXT); |
| | | realmRolePrefix.setType(ProviderConfigProperty.STRING_TYPE); |
| | | CONFIG_PROPERTIES.add(realmRolePrefix); |
| | | |
| | | OIDCAttributeMapperHelper.addTokenClaimNameConfig(CONFIG_PROPERTIES); |
| | | } |
| | | |
| | | @Override |
| | | public List<ProviderConfigProperty> getConfigProperties() { |
| | | return CONFIG_PROPERTIES; |
| | | } |
| | | |
| | | @Override |
| | | public String getId() { |
| | | return PROVIDER_ID; |
| | | } |
| | | |
| | | @Override |
| | | public String getDisplayType() { |
| | | return "User Realm Role"; |
| | | } |
| | | |
| | | @Override |
| | | public String getDisplayCategory() { |
| | | return TOKEN_MAPPER_CATEGORY; |
| | | } |
| | | |
| | | @Override |
| | | public String getHelpText() { |
| | | return "Map a user realm role to a token claim."; |
| | | } |
| | | |
| | | @Override |
| | | public void setAttribute(Map<String, Object> attributes, ProtocolMapperModel mappingModel, UserSessionModel userSession) { |
| | | String rolePrefix = mappingModel.getConfig().get(ProtocolMapperUtils.USER_MODEL_REALM_ROLE_MAPPING_ROLE_PREFIX); |
| | | setAttribute(attributes, mappingModel, userSession, role -> ! role.isClientRole(), rolePrefix); |
| | | } |
| | | |
| | | public static ProtocolMapperModel create(String realmRolePrefix, String name, String tokenClaimName) { |
| | | ProtocolMapperModel mapper = CASAttributeMapperHelper.createClaimMapper(name, tokenClaimName, |
| | | "String", true, name, PROVIDER_ID); |
| | | mapper.getConfig().put(ProtocolMapperUtils.USER_MODEL_REALM_ROLE_MAPPING_ROLE_PREFIX, realmRolePrefix); |
| | | return mapper; |
| | | } |
| | | } |
New file |
| | |
| | | package org.keycloak.protocol.cas.mappers; |
| | | |
| | | import org.keycloak.models.ProtocolMapperModel; |
| | | import org.keycloak.models.UserSessionModel; |
| | | import org.keycloak.protocol.ProtocolMapperUtils; |
| | | import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper; |
| | | import org.keycloak.provider.ProviderConfigProperty; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | public class UserSessionNoteMapper extends AbstractCASProtocolMapper { |
| | | |
| | | private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>(); |
| | | |
| | | static { |
| | | ProviderConfigProperty property; |
| | | property = new ProviderConfigProperty(); |
| | | property.setName(ProtocolMapperUtils.USER_SESSION_NOTE); |
| | | property.setLabel(ProtocolMapperUtils.USER_SESSION_MODEL_NOTE_LABEL); |
| | | property.setHelpText(ProtocolMapperUtils.USER_SESSION_MODEL_NOTE_HELP_TEXT); |
| | | property.setType(ProviderConfigProperty.STRING_TYPE); |
| | | configProperties.add(property); |
| | | OIDCAttributeMapperHelper.addTokenClaimNameConfig(configProperties); |
| | | OIDCAttributeMapperHelper.addJsonTypeConfig(configProperties); |
| | | } |
| | | |
| | | public static final String PROVIDER_ID = "cas-usersessionmodel-note-mapper"; |
| | | |
| | | |
| | | public List<ProviderConfigProperty> getConfigProperties() { |
| | | return configProperties; |
| | | } |
| | | |
| | | @Override |
| | | public String getId() { |
| | | return PROVIDER_ID; |
| | | } |
| | | |
| | | @Override |
| | | public String getDisplayType() { |
| | | return "User Session Note"; |
| | | } |
| | | |
| | | @Override |
| | | public String getDisplayCategory() { |
| | | return TOKEN_MAPPER_CATEGORY; |
| | | } |
| | | |
| | | @Override |
| | | public String getHelpText() { |
| | | return "Map a custom user session note to a token claim."; |
| | | } |
| | | |
| | | @Override |
| | | public void setAttribute(Map<String, Object> attributes, ProtocolMapperModel mappingModel, UserSessionModel userSession) { |
| | | String noteName = mappingModel.getConfig().get(ProtocolMapperUtils.USER_SESSION_NOTE); |
| | | String noteValue = userSession.getNote(noteName); |
| | | if (noteValue == null) return; |
| | | setMappedAttribute(attributes, mappingModel, noteValue); |
| | | } |
| | | |
| | | public static ProtocolMapperModel create(String name, |
| | | String userSessionNote, |
| | | String tokenClaimName, String jsonType, |
| | | boolean consentRequired, String consentText) { |
| | | ProtocolMapperModel mapper = CASAttributeMapperHelper.createClaimMapper(name, tokenClaimName, |
| | | jsonType, consentRequired, consentText, PROVIDER_ID); |
| | | mapper.getConfig().put(ProtocolMapperUtils.USER_SESSION_NOTE, userSessionNote); |
| | | return mapper; |
| | | } |
| | | } |
| | |
| | | import javax.xml.bind.annotation.adapters.XmlAdapter; |
| | | import javax.xml.namespace.QName; |
| | | import java.util.ArrayList; |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | |
| | | AttributeWrapperType(Map<String, Object> attributes) { |
| | | this.elements = new ArrayList<>(); |
| | | for (Map.Entry<String, Object> entry : attributes.entrySet()) { |
| | | if (entry.getValue() instanceof List) { |
| | | for (Object item : ((List) entry.getValue())) { |
| | | if (entry.getValue() instanceof Collection) { |
| | | for (Object item : ((Collection) entry.getValue())) { |
| | | addElement(entry.getKey(), item); |
| | | } |
| | | } else { |
| | |
| | | org.keycloak.protocol.cas.mappers.GroupMembershipMapper |
| | | org.keycloak.protocol.cas.mappers.HardcodedClaim |
| | | org.keycloak.protocol.cas.mappers.UserAttributeMapper |
| | | org.keycloak.protocol.cas.mappers.UserClientRoleMappingMapper |
| | | org.keycloak.protocol.cas.mappers.UserPropertyMapper |
| | | org.keycloak.protocol.cas.mappers.UserRealmRoleMappingMapper |
| | | org.keycloak.protocol.cas.mappers.UserSessionNoteMapper |