Search in sources :

Example 21 with UPAttribute

use of org.keycloak.userprofile.config.UPAttribute in project keycloak by keycloak.

the class UPConfigParserTest method validateConfiguration_attributeRequirementsErrors.

public static void validateConfiguration_attributeRequirementsErrors(KeycloakSession session) throws IOException {
    UPConfig config = loadValidConfig();
    // we run this test without KeycloakSession so validator configs are not validated here
    UPAttribute attConfig = config.getAttributes().get(1);
    // it is OK without requirements configures at all
    attConfig.setRequired(null);
    List<String> errors = validate(session, config);
    Assert.assertEquals(0, errors.size());
    // it is OK with empty config as it means ALWAYS required
    UPAttributeRequired reqConfig = new UPAttributeRequired();
    attConfig.setRequired(reqConfig);
    errors = validate(session, config);
    Assert.assertEquals(0, errors.size());
    Assert.assertTrue(reqConfig.isAlways());
    // invalid role used
    reqConfig.setRoles(Collections.singleton("invalid"));
    errors = validate(session, config);
    Assert.assertEquals(1, errors.size());
    Assert.assertFalse(reqConfig.isAlways());
}
Also used : UPConfig(org.keycloak.userprofile.config.UPConfig) UPAttributeRequired(org.keycloak.userprofile.config.UPAttributeRequired) UPAttribute(org.keycloak.userprofile.config.UPAttribute)

Example 22 with UPAttribute

use of org.keycloak.userprofile.config.UPAttribute in project keycloak by keycloak.

the class DeclarativeUserProfileProvider method decorateUserProfileForCache.

/**
 * Decorate basic metadata provided from {@link AbstractUserProfileProvider} based on 'per realm' configuration.
 * This method is called for each {@link UserProfileContext} in each realm, and metadata are cached then and this
 * method is called again only if configuration changes.
 *
 * @param decoratedMetadata base to be decorated based on configuration loaded from component model
 * @param model component model to get "per realm" configuration from
 * @return decorated metadata
 */
protected UserProfileMetadata decorateUserProfileForCache(UserProfileMetadata decoratedMetadata, ComponentModel model) {
    UserProfileContext context = decoratedMetadata.getContext();
    UPConfig parsedConfig = getParsedConfig(model);
    // do not change config for REGISTRATION_USER_CREATION context, everything important is covered thanks to REGISTRATION_PROFILE
    if (parsedConfig == null || context == UserProfileContext.REGISTRATION_USER_CREATION) {
        return decoratedMetadata;
    }
    Map<String, UPGroup> groupsByName = asHashMap(parsedConfig.getGroups());
    int guiOrder = 0;
    for (UPAttribute attrConfig : parsedConfig.getAttributes()) {
        String attributeName = attrConfig.getName();
        List<AttributeValidatorMetadata> validators = new ArrayList<>();
        Map<String, Map<String, Object>> validationsConfig = attrConfig.getValidations();
        if (validationsConfig != null) {
            for (Map.Entry<String, Map<String, Object>> vc : validationsConfig.entrySet()) {
                validators.add(createConfiguredValidator(vc.getKey(), vc.getValue()));
            }
        }
        UPAttributeRequired rc = attrConfig.getRequired();
        Predicate<AttributeContext> required = AttributeMetadata.ALWAYS_FALSE;
        if (rc != null && !isUsernameOrEmailAttribute(attributeName)) {
            // driven by business logic from parent!
            if (rc.isAlways() || UPConfigUtils.isRoleForContext(context, rc.getRoles())) {
                required = AttributeMetadata.ALWAYS_TRUE;
            } else if (UPConfigUtils.canBeAuthFlowContext(context) && rc.getScopes() != null && !rc.getScopes().isEmpty()) {
                // for contexts executed from auth flow and with configured scopes requirement
                // we have to create required validation with scopes based selector
                required = (c) -> requestedScopePredicate(c, rc.getScopes());
            }
            validators.add(new AttributeValidatorMetadata(AttributeRequiredByMetadataValidator.ID));
        }
        Predicate<AttributeContext> writeAllowed = AttributeMetadata.ALWAYS_FALSE;
        Predicate<AttributeContext> readAllowed = AttributeMetadata.ALWAYS_FALSE;
        UPAttributePermissions permissions = attrConfig.getPermissions();
        if (permissions != null) {
            Set<String> editRoles = permissions.getEdit();
            if (!editRoles.isEmpty()) {
                writeAllowed = ac -> UPConfigUtils.isRoleForContext(ac.getContext(), editRoles);
            }
            Set<String> viewRoles = permissions.getView();
            if (viewRoles.isEmpty()) {
                readAllowed = writeAllowed;
            } else {
                readAllowed = createViewAllowedPredicate(writeAllowed, viewRoles);
            }
        }
        Predicate<AttributeContext> selector = AttributeMetadata.ALWAYS_TRUE;
        UPAttributeSelector sc = attrConfig.getSelector();
        if (sc != null && !isUsernameOrEmailAttribute(attributeName) && UPConfigUtils.canBeAuthFlowContext(context) && sc.getScopes() != null && !sc.getScopes().isEmpty()) {
            // for contexts executed from auth flow and with configured scopes selector
            // we have to create correct predicate
            selector = (c) -> requestedScopePredicate(c, sc.getScopes());
        }
        Map<String, Object> annotations = attrConfig.getAnnotations();
        String attributeGroup = attrConfig.getGroup();
        AttributeGroupMetadata groupMetadata = toAttributeGroupMeta(groupsByName.get(attributeGroup));
        if (isUsernameOrEmailAttribute(attributeName)) {
            if (permissions == null) {
                writeAllowed = AttributeMetadata.ALWAYS_TRUE;
            }
            List<AttributeMetadata> atts = decoratedMetadata.getAttribute(attributeName);
            if (atts.isEmpty()) {
                // attribute metadata doesn't exist so we have to add it. We keep it optional as Abstract base
                // doesn't require it.
                decoratedMetadata.addAttribute(attributeName, guiOrder++, writeAllowed, validators).addAnnotations(annotations).setAttributeDisplayName(attrConfig.getDisplayName()).setAttributeGroupMetadata(groupMetadata);
            } else {
                final int localGuiOrder = guiOrder++;
                // only add configured validators and annotations if attribute metadata exist
                atts.stream().forEach(c -> c.addValidator(validators).addAnnotations(annotations).setAttributeDisplayName(attrConfig.getDisplayName()).setGuiOrder(localGuiOrder).setAttributeGroupMetadata(groupMetadata));
            }
        } else {
            // always add validation for immutable/read-only attributes
            validators.add(new AttributeValidatorMetadata(ImmutableAttributeValidator.ID));
            decoratedMetadata.addAttribute(attributeName, guiOrder++, validators, selector, writeAllowed, required, readAllowed).addAnnotations(annotations).setAttributeDisplayName(attrConfig.getDisplayName()).setAttributeGroupMetadata(groupMetadata);
        }
    }
    return decoratedMetadata;
}
Also used : ClientModel(org.keycloak.models.ClientModel) UPConfigUtils(org.keycloak.userprofile.config.UPConfigUtils) Profile(org.keycloak.common.Profile) ProviderConfigProperty(org.keycloak.provider.ProviderConfigProperty) HashMap(java.util.HashMap) Config(org.keycloak.Config) Messages(org.keycloak.services.messages.Messages) TokenManager.getRequestedClientScopes(org.keycloak.protocol.oidc.TokenManager.getRequestedClientScopes) ArrayList(java.util.ArrayList) AmphibianProviderFactory(org.keycloak.component.AmphibianProviderFactory) AbstractSimpleValidator(org.keycloak.validate.AbstractSimpleValidator) UserModel(org.keycloak.models.UserModel) ByteArrayInputStream(java.io.ByteArrayInputStream) Map(java.util.Map) DeclarativeUserProfileModel(org.keycloak.userprofile.config.DeclarativeUserProfileModel) UPConfigUtils.readConfig(org.keycloak.userprofile.config.UPConfigUtils.readConfig) ComponentModel(org.keycloak.component.ComponentModel) AttributeRequiredByMetadataValidator(org.keycloak.userprofile.validator.AttributeRequiredByMetadataValidator) UPGroup(org.keycloak.userprofile.config.UPGroup) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RealmModel(org.keycloak.models.RealmModel) UPAttributeSelector(org.keycloak.userprofile.config.UPAttributeSelector) ImmutableAttributeValidator(org.keycloak.userprofile.validator.ImmutableAttributeValidator) ValidatorConfig(org.keycloak.validate.ValidatorConfig) UPAttribute(org.keycloak.userprofile.config.UPAttribute) Predicate(java.util.function.Predicate) UPAttributeRequired(org.keycloak.userprofile.config.UPAttributeRequired) Set(java.util.Set) KeycloakSession(org.keycloak.models.KeycloakSession) IOException(java.io.IOException) Collectors(java.util.stream.Collectors) UPConfig(org.keycloak.userprofile.config.UPConfig) List(java.util.List) ObjectUtil.isBlank(org.keycloak.common.util.ObjectUtil.isBlank) BlankAttributeValidator(org.keycloak.userprofile.validator.BlankAttributeValidator) OIDCLoginProtocol(org.keycloak.protocol.oidc.OIDCLoginProtocol) UPAttributePermissions(org.keycloak.userprofile.config.UPAttributePermissions) EmailValidator(org.keycloak.validate.validators.EmailValidator) MultivaluedHashMap(org.keycloak.common.util.MultivaluedHashMap) Collections(java.util.Collections) ComponentValidationException(org.keycloak.component.ComponentValidationException) ArrayList(java.util.ArrayList) UPAttributeRequired(org.keycloak.userprofile.config.UPAttributeRequired) UPAttribute(org.keycloak.userprofile.config.UPAttribute) UPAttributePermissions(org.keycloak.userprofile.config.UPAttributePermissions) UPConfig(org.keycloak.userprofile.config.UPConfig) UPGroup(org.keycloak.userprofile.config.UPGroup) HashMap(java.util.HashMap) Map(java.util.Map) MultivaluedHashMap(org.keycloak.common.util.MultivaluedHashMap) UPAttributeSelector(org.keycloak.userprofile.config.UPAttributeSelector)

Aggregations

UPAttribute (org.keycloak.userprofile.config.UPAttribute)22 UPConfig (org.keycloak.userprofile.config.UPConfig)22 HashMap (java.util.HashMap)13 ComponentValidationException (org.keycloak.component.ComponentValidationException)12 DeclarativeUserProfileProvider (org.keycloak.userprofile.DeclarativeUserProfileProvider)12 ComponentModel (org.keycloak.component.ComponentModel)11 UserProfile (org.keycloak.userprofile.UserProfile)11 UPAttributePermissions (org.keycloak.userprofile.config.UPAttributePermissions)11 ValidationException (org.keycloak.userprofile.ValidationException)10 UPAttributeRequired (org.keycloak.userprofile.config.UPAttributeRequired)10 RealmModel (org.keycloak.models.RealmModel)3 UserModel (org.keycloak.models.UserModel)3 Map (java.util.Map)2 UserProfileProvider (org.keycloak.userprofile.UserProfileProvider)2 UPAttributeSelector (org.keycloak.userprofile.config.UPAttributeSelector)2 UPGroup (org.keycloak.userprofile.config.UPGroup)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 IOException (java.io.IOException)1 ArrayList (java.util.ArrayList)1 Collections (java.util.Collections)1