Search in sources :

Example 6 with UPAttributeRequired

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

the class UserProfileTest method testNoValidationsIfAdminReadOnly.

private static void testNoValidationsIfAdminReadOnly(KeycloakSession session) throws IOException {
    DeclarativeUserProfileProvider provider = getDynamicUserProfileProvider(session);
    ComponentModel component = provider.getComponentModel();
    assertNotNull(component);
    UPConfig config = new UPConfig();
    UPAttribute attribute = new UPAttribute();
    attribute.setName(ATT_ADDRESS);
    UPAttributeRequired requirements = new UPAttributeRequired();
    attribute.setRequired(requirements);
    UPAttributePermissions permissions = new UPAttributePermissions();
    permissions.setEdit(Collections.singleton(UPConfigUtils.ROLE_USER));
    attribute.setPermissions(permissions);
    config.addAttribute(attribute);
    provider.setConfiguration(JsonSerialization.writeValueAsString(config));
    Map<String, Object> attributes = new HashMap<>();
    attributes.put(UserModel.USERNAME, "user");
    // Fails on USER context
    UserProfile profile = provider.create(UserProfileContext.UPDATE_PROFILE, attributes);
    try {
        profile.validate();
        fail("Should fail validation");
    } catch (ValidationException ve) {
        assertTrue(ve.isAttributeOnError(ATT_ADDRESS));
    }
    // NO fail on ADMIN context - User REST API
    profile = provider.create(UserProfileContext.USER_API, attributes);
    profile.validate();
}
Also used : UPAttributePermissions(org.keycloak.userprofile.config.UPAttributePermissions) ComponentValidationException(org.keycloak.component.ComponentValidationException) ValidationException(org.keycloak.userprofile.ValidationException) UserProfile(org.keycloak.userprofile.UserProfile) HashMap(java.util.HashMap) DeclarativeUserProfileProvider(org.keycloak.userprofile.DeclarativeUserProfileProvider) UPConfig(org.keycloak.userprofile.config.UPConfig) ComponentModel(org.keycloak.component.ComponentModel) UPAttributeRequired(org.keycloak.userprofile.config.UPAttributeRequired) UPAttribute(org.keycloak.userprofile.config.UPAttribute)

Example 7 with UPAttributeRequired

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

the class UserProfileTest method testRequiredByClientScope.

private static void testRequiredByClientScope(KeycloakSession session) throws IOException {
    DeclarativeUserProfileProvider provider = getDynamicUserProfileProvider(session);
    ComponentModel component = provider.getComponentModel();
    assertNotNull(component);
    UPConfig config = new UPConfig();
    UPAttribute attribute = new UPAttribute();
    attribute.setName(ATT_ADDRESS);
    UPAttributeRequired requirements = new UPAttributeRequired();
    requirements.setScopes(Collections.singleton("client-a"));
    attribute.setRequired(requirements);
    UPAttributePermissions permissions = new UPAttributePermissions();
    permissions.setEdit(Collections.singleton("user"));
    attribute.setPermissions(permissions);
    config.addAttribute(attribute);
    provider.setConfiguration(JsonSerialization.writeValueAsString(config));
    Map<String, Object> attributes = new HashMap<>();
    attributes.put(UserModel.USERNAME, "user");
    attributes.put(UserModel.EMAIL, "user@email.test");
    // client with default scopes for which is attribute NOT configured as required
    configureAuthenticationSession(session, "client-b", null);
    // no fail on User API nor Account console as they do not have scopes
    UserProfile profile = provider.create(UserProfileContext.USER_API, attributes);
    profile.validate();
    profile = provider.create(UserProfileContext.ACCOUNT, attributes);
    profile.validate();
    profile = provider.create(UserProfileContext.ACCOUNT_OLD, attributes);
    profile.validate();
    // no fail on auth flow scopes when scope is not required
    profile = provider.create(UserProfileContext.REGISTRATION_PROFILE, attributes);
    profile.validate();
    profile = provider.create(UserProfileContext.REGISTRATION_USER_CREATION, attributes);
    profile.validate();
    profile = provider.create(UserProfileContext.UPDATE_PROFILE, attributes);
    profile.validate();
    profile = provider.create(UserProfileContext.IDP_REVIEW, attributes);
    profile.validate();
    // client with default scope for which is attribute configured as required
    configureAuthenticationSession(session, "client-a", null);
    // no fail on User API nor Account console as they do not have scopes
    profile = provider.create(UserProfileContext.USER_API, attributes);
    profile.validate();
    profile = provider.create(UserProfileContext.ACCOUNT, attributes);
    profile.validate();
    profile = provider.create(UserProfileContext.ACCOUNT_OLD, attributes);
    profile.validate();
    // fail on auth flow scopes when scope is required
    try {
        profile = provider.create(UserProfileContext.UPDATE_PROFILE, attributes);
        profile.validate();
        fail("Should fail validation");
    } catch (ValidationException ve) {
        assertTrue(ve.isAttributeOnError(ATT_ADDRESS));
    }
    try {
        profile = provider.create(UserProfileContext.REGISTRATION_PROFILE, attributes);
        profile.validate();
        fail("Should fail validation");
    } catch (ValidationException ve) {
        assertTrue(ve.isAttributeOnError(ATT_ADDRESS));
    }
    try {
        profile = provider.create(UserProfileContext.IDP_REVIEW, attributes);
        profile.validate();
        fail("Should fail validation");
    } catch (ValidationException ve) {
        assertTrue(ve.isAttributeOnError(ATT_ADDRESS));
    }
}
Also used : UPAttributePermissions(org.keycloak.userprofile.config.UPAttributePermissions) ComponentValidationException(org.keycloak.component.ComponentValidationException) ValidationException(org.keycloak.userprofile.ValidationException) UserProfile(org.keycloak.userprofile.UserProfile) HashMap(java.util.HashMap) DeclarativeUserProfileProvider(org.keycloak.userprofile.DeclarativeUserProfileProvider) UPConfig(org.keycloak.userprofile.config.UPConfig) ComponentModel(org.keycloak.component.ComponentModel) UPAttributeRequired(org.keycloak.userprofile.config.UPAttributeRequired) UPAttribute(org.keycloak.userprofile.config.UPAttribute)

Example 8 with UPAttributeRequired

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

the class UserProfileTest method testRequiredIfAdmin.

private static void testRequiredIfAdmin(KeycloakSession session) throws IOException {
    DeclarativeUserProfileProvider provider = getDynamicUserProfileProvider(session);
    ComponentModel component = provider.getComponentModel();
    assertNotNull(component);
    UPConfig config = new UPConfig();
    UPAttribute attribute = new UPAttribute();
    attribute.setName(ATT_ADDRESS);
    UPAttributeRequired requirements = new UPAttributeRequired();
    requirements.setRoles(Collections.singleton(ROLE_ADMIN));
    attribute.setRequired(requirements);
    UPAttributePermissions permissions = new UPAttributePermissions();
    permissions.setEdit(Collections.singleton(UPConfigUtils.ROLE_ADMIN));
    attribute.setPermissions(permissions);
    config.addAttribute(attribute);
    provider.setConfiguration(JsonSerialization.writeValueAsString(config));
    Map<String, Object> attributes = new HashMap<>();
    attributes.put(UserModel.USERNAME, "user");
    // NO fail on common contexts
    UserProfile profile = provider.create(UserProfileContext.UPDATE_PROFILE, attributes);
    profile.validate();
    profile = provider.create(UserProfileContext.ACCOUNT, attributes);
    profile.validate();
    profile = provider.create(UserProfileContext.REGISTRATION_PROFILE, attributes);
    profile.validate();
    // fail on User API
    try {
        profile = provider.create(UserProfileContext.USER_API, attributes);
        profile.validate();
        fail("Should fail validation");
    } catch (ValidationException ve) {
        assertTrue(ve.isAttributeOnError(ATT_ADDRESS));
    }
}
Also used : UPAttributePermissions(org.keycloak.userprofile.config.UPAttributePermissions) ComponentValidationException(org.keycloak.component.ComponentValidationException) ValidationException(org.keycloak.userprofile.ValidationException) UserProfile(org.keycloak.userprofile.UserProfile) HashMap(java.util.HashMap) DeclarativeUserProfileProvider(org.keycloak.userprofile.DeclarativeUserProfileProvider) UPConfig(org.keycloak.userprofile.config.UPConfig) ComponentModel(org.keycloak.component.ComponentModel) UPAttributeRequired(org.keycloak.userprofile.config.UPAttributeRequired) UPAttribute(org.keycloak.userprofile.config.UPAttribute)

Example 9 with UPAttributeRequired

use of org.keycloak.userprofile.config.UPAttributeRequired 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 10 with UPAttributeRequired

use of org.keycloak.userprofile.config.UPAttributeRequired 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)10 UPAttributeRequired (org.keycloak.userprofile.config.UPAttributeRequired)10 UPConfig (org.keycloak.userprofile.config.UPConfig)10 ComponentValidationException (org.keycloak.component.ComponentValidationException)9 ComponentModel (org.keycloak.component.ComponentModel)8 DeclarativeUserProfileProvider (org.keycloak.userprofile.DeclarativeUserProfileProvider)8 UPAttributePermissions (org.keycloak.userprofile.config.UPAttributePermissions)8 HashMap (java.util.HashMap)7 UserProfile (org.keycloak.userprofile.UserProfile)7 ValidationException (org.keycloak.userprofile.ValidationException)7 RealmModel (org.keycloak.models.RealmModel)3 UserModel (org.keycloak.models.UserModel)2 UPAttributeSelector (org.keycloak.userprofile.config.UPAttributeSelector)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 IOException (java.io.IOException)1 ArrayList (java.util.ArrayList)1 Collections (java.util.Collections)1 List (java.util.List)1 Map (java.util.Map)1 Set (java.util.Set)1