update for KEYCLOAK-6630 Client scopes initial support
| | |
| | | } |
| | | |
| | | @Override |
| | | public Response authenticated(UserSessionModel userSession, AuthenticatedClientSessionModel clientSession) { |
| | | public Response authenticated(UserSessionModel userSession, ClientSessionContext clientSessionCtx) { |
| | | AuthenticatedClientSessionModel clientSession = clientSessionCtx.getClientSession(); |
| | | ClientSessionCode<AuthenticatedClientSessionModel> accessCode = new ClientSessionCode<>(session, realm, clientSession); |
| | | |
| | | String service = clientSession.getRedirectUri(); |
| | |
| | | |
| | | import org.jboss.logging.Logger; |
| | | import org.keycloak.events.EventBuilder; |
| | | import org.keycloak.models.*; |
| | | import org.keycloak.models.ClientModel; |
| | | import org.keycloak.models.KeycloakSession; |
| | | import org.keycloak.models.ProtocolMapperModel; |
| | | import org.keycloak.models.RealmModel; |
| | | import org.keycloak.protocol.AbstractLoginProtocolFactory; |
| | | import org.keycloak.protocol.LoginProtocol; |
| | | import org.keycloak.protocol.ProtocolMapperUtils; |
| | | import org.keycloak.protocol.cas.mappers.FullNameMapper; |
| | | import org.keycloak.protocol.cas.mappers.UserAttributeMapper; |
| | | import org.keycloak.protocol.cas.mappers.UserPropertyMapper; |
| | | import org.keycloak.representations.idm.ClientRepresentation; |
| | | import org.keycloak.representations.idm.ClientTemplateRepresentation; |
| | | |
| | | 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 CASLoginProtocolFactory extends AbstractLoginProtocolFactory { |
| | | private static final Logger logger = Logger.getLogger(CASLoginProtocolFactory.class); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<ProtocolMapperModel> getBuiltinMappers() { |
| | | public Map<String, ProtocolMapperModel> getBuiltinMappers() { |
| | | return builtins; |
| | | } |
| | | |
| | | @Override |
| | | public List<ProtocolMapperModel> getDefaultBuiltinMappers() { |
| | | return defaultBuiltins; |
| | | } |
| | | |
| | | static List<ProtocolMapperModel> builtins = new ArrayList<>(); |
| | | static Map<String, ProtocolMapperModel> builtins = new HashMap<>(); |
| | | static List<ProtocolMapperModel> defaultBuiltins = new ArrayList<>(); |
| | | |
| | | static { |
| | | ProtocolMapperModel model; |
| | | |
| | | model = UserPropertyMapper.create(EMAIL, "email", "mail", "String", |
| | | true, EMAIL_CONSENT_TEXT); |
| | | builtins.add(model); |
| | | model = UserPropertyMapper.create(EMAIL, "email", "mail", "String"); |
| | | builtins.put(EMAIL, model); |
| | | defaultBuiltins.add(model); |
| | | model = UserPropertyMapper.create(GIVEN_NAME, "firstName", "givenName", "String", |
| | | true, GIVEN_NAME_CONSENT_TEXT); |
| | | builtins.add(model); |
| | | model = UserPropertyMapper.create(GIVEN_NAME, "firstName", "givenName", "String"); |
| | | builtins.put(GIVEN_NAME, model); |
| | | defaultBuiltins.add(model); |
| | | model = UserPropertyMapper.create(FAMILY_NAME, "lastName", "sn", "String", |
| | | true, FAMILY_NAME_CONSENT_TEXT); |
| | | builtins.add(model); |
| | | model = UserPropertyMapper.create(FAMILY_NAME, "lastName", "sn", "String"); |
| | | builtins.put(FAMILY_NAME, model); |
| | | defaultBuiltins.add(model); |
| | | model = UserPropertyMapper.create(EMAIL_VERIFIED, |
| | | "emailVerified", |
| | | "emailVerified", "boolean", |
| | | false, EMAIL_VERIFIED_CONSENT_TEXT); |
| | | builtins.add(model); |
| | | "emailVerified", "boolean"); |
| | | builtins.put(EMAIL_VERIFIED, model); |
| | | model = UserAttributeMapper.create(LOCALE, |
| | | "locale", |
| | | "locale", "String", |
| | | false, LOCALE_CONSENT_TEXT, |
| | | false); |
| | | builtins.add(model); |
| | | builtins.put(LOCALE, model); |
| | | |
| | | model = FullNameMapper.create(FULL_NAME, "cn", |
| | | true, FULL_NAME_CONSENT_TEXT); |
| | | builtins.add(model); |
| | | model = FullNameMapper.create(FULL_NAME, "cn"); |
| | | builtins.put(FULL_NAME, model); |
| | | defaultBuiltins.add(model); |
| | | } |
| | | |
| | | @Override |
| | | protected void createDefaultClientScopesImpl(RealmModel newRealm) { |
| | | // no-op |
| | | } |
| | | |
| | | @Override |
| | |
| | | if (rep.getAdminUrl() == null && rep.getRootUrl() != null) { |
| | | newClient.setManagementUrl(rep.getRootUrl()); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void setupTemplateDefaults(ClientTemplateRepresentation clientRep, ClientTemplateModel newClient) { |
| | | |
| | | } |
| | | } |
| | |
| | | package org.keycloak.protocol.cas.endpoints; |
| | | |
| | | import org.keycloak.events.EventBuilder; |
| | | import org.keycloak.models.KeycloakSessionFactory; |
| | | import org.keycloak.models.ProtocolMapperModel; |
| | | import org.keycloak.models.RealmModel; |
| | | import org.keycloak.models.UserSessionModel; |
| | | import org.keycloak.models.*; |
| | | import org.keycloak.protocol.ProtocolMapper; |
| | | import org.keycloak.protocol.cas.mappers.CASAttributeMapper; |
| | | import org.keycloak.protocol.cas.representations.CASServiceResponse; |
| | |
| | | import org.keycloak.protocol.cas.utils.ContentTypeHelper; |
| | | import org.keycloak.protocol.cas.utils.ServiceResponseHelper; |
| | | import org.keycloak.services.managers.ClientSessionCode; |
| | | import org.keycloak.services.util.DefaultClientSessionContext; |
| | | |
| | | import javax.ws.rs.core.*; |
| | | import java.util.HashMap; |
| | |
| | | @Override |
| | | protected Response successResponse() { |
| | | UserSessionModel userSession = clientSession.getUserSession(); |
| | | // CAS protocol does not support scopes, so pass null scopeParam |
| | | ClientSessionContext clientSessionCtx = DefaultClientSessionContext.fromClientSessionAndScopeParameter(clientSession, null); |
| | | |
| | | Set<ProtocolMapperModel> mappings = new ClientSessionCode<>(session, realm, clientSession).getRequestedProtocolMappers(); |
| | | Set<ProtocolMapperModel> mappings = clientSessionCtx.getProtocolMappers(); |
| | | KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); |
| | | Map<String, Object> attributes = new HashMap<>(); |
| | | for (ProtocolMapperModel mapping : mappings) { |
| | |
| | | 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); |
| | |
| | | setMappedAttribute(attributes, mappingModel, first + last); |
| | | } |
| | | |
| | | public static ProtocolMapperModel create(String name, String tokenClaimName, |
| | | boolean consentRequired, String consentText) { |
| | | public static ProtocolMapperModel create(String name, String tokenClaimName) { |
| | | return CASAttributeMapperHelper.createClaimMapper(name, tokenClaimName, |
| | | "String", consentRequired, consentText, PROVIDER_ID); |
| | | "String", PROVIDER_ID); |
| | | } |
| | | } |
| | |
| | | return "true".equals(mappingModel.getConfig().get(FULL_PATH)); |
| | | } |
| | | |
| | | public static ProtocolMapperModel create(String name, String tokenClaimName, |
| | | boolean consentRequired, String consentText, boolean fullPath) { |
| | | public static ProtocolMapperModel create(String name, String tokenClaimName, boolean fullPath) { |
| | | ProtocolMapperModel mapper = CASAttributeMapperHelper.createClaimMapper(name, tokenClaimName, |
| | | "String", consentRequired, consentText, PROVIDER_ID); |
| | | "String", PROVIDER_ID); |
| | | mapper.getConfig().put(FULL_PATH, Boolean.toString(fullPath)); |
| | | return mapper; |
| | | } |
| | |
| | | |
| | | public static ProtocolMapperModel create(String name, String userAttribute, |
| | | String tokenClaimName, String claimType, |
| | | boolean consentRequired, String consentText, boolean multivalued) { |
| | | boolean multivalued) { |
| | | ProtocolMapperModel mapper = CASAttributeMapperHelper.createClaimMapper(name, tokenClaimName, |
| | | claimType, consentRequired, consentText, PROVIDER_ID); |
| | | claimType, PROVIDER_ID); |
| | | mapper.getConfig().put(ProtocolMapperUtils.USER_ATTRIBUTE, userAttribute); |
| | | if (multivalued) { |
| | | mapper.getConfig().put(ProtocolMapperUtils.MULTIVALUED, "true"); |
| | |
| | | |
| | | import org.keycloak.models.*; |
| | | import org.keycloak.protocol.ProtocolMapperUtils; |
| | | import org.keycloak.protocol.oidc.TokenManager; |
| | | import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper; |
| | | import org.keycloak.provider.ProviderConfigProperty; |
| | | |
| | |
| | | return RoleModel::isClientRole; |
| | | } |
| | | |
| | | ClientTemplateModel template = client.getClientTemplate(); |
| | | boolean useTemplateScope = template != null && client.useTemplateScope(); |
| | | boolean fullScopeAllowed = (useTemplateScope && template.isFullScopeAllowed()) || client.isFullScopeAllowed(); |
| | | |
| | | boolean fullScopeAllowed = 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); |
| | | // CAS protocol does not support scopes, so pass null scopeParam |
| | | Set<ClientScopeModel> clientScopes = TokenManager.getRequestedClientScopes(null, client); |
| | | for (ClientScopeModel clientScope : clientScopes) { |
| | | scopeMappings.addAll(clientScope.getScopeMappings()); |
| | | } |
| | | |
| | | 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); |
| | | "String", 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; |
| | |
| | | } |
| | | |
| | | public static ProtocolMapperModel create(String name, String userAttribute, |
| | | String tokenClaimName, String claimType, |
| | | boolean consentRequired, String consentText) { |
| | | String tokenClaimName, String claimType) { |
| | | ProtocolMapperModel mapper = CASAttributeMapperHelper.createClaimMapper(name, tokenClaimName, |
| | | claimType, consentRequired, consentText, PROVIDER_ID); |
| | | claimType, PROVIDER_ID); |
| | | mapper.getConfig().put(ProtocolMapperUtils.USER_ATTRIBUTE, userAttribute); |
| | | return mapper; |
| | | } |
| | |
| | | |
| | | public static ProtocolMapperModel create(String realmRolePrefix, String name, String tokenClaimName) { |
| | | ProtocolMapperModel mapper = CASAttributeMapperHelper.createClaimMapper(name, tokenClaimName, |
| | | "String", true, name, PROVIDER_ID); |
| | | "String", PROVIDER_ID); |
| | | mapper.getConfig().put(ProtocolMapperUtils.USER_MODEL_REALM_ROLE_MAPPING_ROLE_PREFIX, realmRolePrefix); |
| | | return mapper; |
| | | } |
| | |
| | | |
| | | public static ProtocolMapperModel create(String name, |
| | | String userSessionNote, |
| | | String tokenClaimName, String jsonType, |
| | | boolean consentRequired, String consentText) { |
| | | String tokenClaimName, String jsonType) { |
| | | ProtocolMapperModel mapper = CASAttributeMapperHelper.createClaimMapper(name, tokenClaimName, |
| | | jsonType, consentRequired, consentText, PROVIDER_ID); |
| | | jsonType, PROVIDER_ID); |
| | | mapper.getConfig().put(ProtocolMapperUtils.USER_SESSION_NOTE, userSessionNote); |
| | | return mapper; |
| | | } |