Search in sources :

Example 1 with UserModelDelegate

use of org.keycloak.models.utils.UserModelDelegate in project keycloak by keycloak.

the class IdpReviewProfileAuthenticator method actionImpl.

@Override
protected void actionImpl(AuthenticationFlowContext context, SerializedBrokeredIdentityContext userCtx, BrokeredIdentityContext brokerContext) {
    EventBuilder event = context.getEvent();
    // velias: looks like UPDATE_PROFILE event is not fired. IMHO it should not be fired here as user record in keycloak is not changed, user doesn't exist yet
    event.event(EventType.UPDATE_PROFILE).detail(Details.CONTEXT, UserProfileContext.IDP_REVIEW.name());
    MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
    UserModelDelegate updatedProfile = new UserModelDelegate(null) {

        @Override
        public String getId() {
            return userCtx.getId();
        }

        @Override
        public Map<String, List<String>> getAttributes() {
            return userCtx.getAttributes();
        }

        @Override
        public Stream<String> getAttributeStream(String name) {
            return userCtx.getAttribute(name).stream();
        }

        @Override
        public void setAttribute(String name, List<String> values) {
            userCtx.setAttribute(name, values);
        }

        @Override
        public void removeAttribute(String name) {
            userCtx.getAttributes().remove(name);
        }

        @Override
        public String getFirstAttribute(String name) {
            return userCtx.getFirstAttribute(name);
        }

        @Override
        public String getUsername() {
            return userCtx.getUsername();
        }
    };
    UserProfileProvider profileProvider = context.getSession().getProvider(UserProfileProvider.class);
    UserProfile profile = profileProvider.create(UserProfileContext.IDP_REVIEW, formData, updatedProfile);
    try {
        String oldEmail = userCtx.getEmail();
        profile.update((attributeName, userModel, oldValue) -> {
            if (attributeName.equals(UserModel.EMAIL)) {
                context.getAuthenticationSession().setAuthNote(UPDATE_PROFILE_EMAIL_CHANGED, "true");
                event.clone().event(EventType.UPDATE_EMAIL).detail(Details.CONTEXT, UserProfileContext.IDP_REVIEW.name()).detail(Details.PREVIOUS_EMAIL, oldEmail).detail(Details.UPDATED_EMAIL, profile.getAttributes().getFirstValue(UserModel.EMAIL)).success();
            }
        });
    } catch (ValidationException pve) {
        List<FormMessage> errors = Validation.getFormErrorsFromValidation(pve.getErrors());
        Response challenge = context.form().setErrors(errors).setAttribute(LoginFormsProvider.UPDATE_PROFILE_CONTEXT_ATTR, userCtx).setFormData(formData).createUpdateProfilePage();
        context.challenge(challenge);
        return;
    }
    userCtx.saveToAuthenticationSession(context.getAuthenticationSession(), BROKERED_CONTEXT_NOTE);
    logger.debugf("Profile updated successfully after first authentication with identity provider '%s' for broker user '%s'.", brokerContext.getIdpConfig().getAlias(), userCtx.getUsername());
    String newEmail = profile.getAttributes().getFirstValue(UserModel.EMAIL);
    event.detail(Details.UPDATED_EMAIL, newEmail);
    // Ensure page is always shown when user later returns to it - for example with form "back" button
    context.getAuthenticationSession().setAuthNote(ENFORCE_UPDATE_PROFILE, "true");
    context.success();
}
Also used : Response(javax.ws.rs.core.Response) EventBuilder(org.keycloak.events.EventBuilder) UserModelDelegate(org.keycloak.models.utils.UserModelDelegate) ValidationException(org.keycloak.userprofile.ValidationException) UserProfile(org.keycloak.userprofile.UserProfile) UserProfileProvider(org.keycloak.userprofile.UserProfileProvider) List(java.util.List)

Example 2 with UserModelDelegate

use of org.keycloak.models.utils.UserModelDelegate in project keycloak by keycloak.

the class HardcodedAttributeMapper method proxy.

@Override
public UserModel proxy(final LDAPObject ldapUser, UserModel delegate, RealmModel realm) {
    String userModelAttrName = getUserModelAttribute();
    String attributeValue = getAttributeValue();
    delegate = new UserModelDelegate(delegate) {

        @Override
        public Stream<String> getAttributeStream(String name) {
            if (userModelAttrName.equals(name)) {
                return Stream.of(attributeValue);
            }
            return super.getAttributeStream(name);
        }

        @Override
        public boolean isEmailVerified() {
            if (userModelAttrName.equals("emailVerified")) {
                return Boolean.valueOf(attributeValue);
            }
            return super.isEmailVerified();
        }

        @Override
        public boolean isEnabled() {
            if (userModelAttrName.equals("enabled")) {
                return Boolean.valueOf(attributeValue);
            }
            return super.isEnabled();
        }
    };
    return delegate;
}
Also used : UserModelDelegate(org.keycloak.models.utils.UserModelDelegate) Stream(java.util.stream.Stream)

Example 3 with UserModelDelegate

use of org.keycloak.models.utils.UserModelDelegate in project keycloak by keycloak.

the class UserAttributeLDAPStorageMapper method proxy.

@Override
public UserModel proxy(final LDAPObject ldapUser, UserModel delegate, RealmModel realm) {
    final String userModelAttrName = getUserModelAttribute();
    final String ldapAttrName = getLdapAttributeName();
    boolean isAlwaysReadValueFromLDAP = parseBooleanParameter(mapperModel, ALWAYS_READ_VALUE_FROM_LDAP);
    final boolean isMandatoryInLdap = parseBooleanParameter(mapperModel, IS_MANDATORY_IN_LDAP);
    final boolean isBinaryAttribute = parseBooleanParameter(mapperModel, IS_BINARY_ATTRIBUTE);
    // For writable mode, we want to propagate writing of attribute to LDAP as well
    if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE && !isReadOnly()) {
        delegate = new TxAwareLDAPUserModelDelegate(delegate, ldapProvider, ldapUser) {

            @Override
            public void setSingleAttribute(String name, String value) {
                if (UserModel.USERNAME.equals(name)) {
                    setUsername(value);
                } else if (UserModel.EMAIL.equals(name)) {
                    setEmail(value);
                } else if (setLDAPAttribute(name, value)) {
                    super.setSingleAttribute(name, value);
                }
            }

            @Override
            public void setAttribute(String name, List<String> values) {
                if (UserModel.USERNAME.equals(name)) {
                    setUsername((values != null && values.size() > 0) ? values.get(0) : null);
                } else if (UserModel.EMAIL.equals(name)) {
                    setEmail((values != null && values.size() > 0) ? values.get(0) : null);
                } else if (setLDAPAttribute(name, values)) {
                    super.setAttribute(name, values);
                }
            }

            @Override
            public void removeAttribute(String name) {
                if (!UserModel.USERNAME.equals(name)) {
                    // do not remove username
                    if (setLDAPAttribute(name, null)) {
                        super.removeAttribute(name);
                    }
                }
            }

            @Override
            public void setUsername(String username) {
                String lowercaseUsername = KeycloakModelUtils.toLowerCaseSafe(username);
                checkDuplicateUsername(userModelAttrName, lowercaseUsername, realm, ldapProvider.getSession(), this);
                setLDAPAttribute(UserModel.USERNAME, lowercaseUsername);
                super.setUsername(lowercaseUsername);
            }

            @Override
            public void setEmail(String email) {
                String lowercaseEmail = KeycloakModelUtils.toLowerCaseSafe(email);
                checkDuplicateEmail(userModelAttrName, email, realm, ldapProvider.getSession(), this);
                setLDAPAttribute(UserModel.EMAIL, email);
                super.setEmail(lowercaseEmail);
            }

            @Override
            public void setEnabled(boolean enabled) {
                setLDAPAttribute(UserModel.ENABLED, Boolean.toString(enabled));
                super.setEnabled(enabled);
            }

            @Override
            public void setLastName(String lastName) {
                setLDAPAttribute(UserModel.LAST_NAME, lastName);
                super.setLastName(lastName);
            }

            @Override
            public void setFirstName(String firstName) {
                setLDAPAttribute(UserModel.FIRST_NAME, firstName);
                super.setFirstName(firstName);
            }

            @Override
            public void setEmailVerified(boolean verified) {
                setLDAPAttribute(UserModel.EMAIL_VERIFIED, Boolean.toString(verified));
                super.setEmailVerified(verified);
            }

            protected boolean setLDAPAttribute(String modelAttrName, Object value) {
                if (modelAttrName.equalsIgnoreCase(userModelAttrName)) {
                    if (UserAttributeLDAPStorageMapper.logger.isTraceEnabled()) {
                        UserAttributeLDAPStorageMapper.logger.tracef("Pushing user attribute to LDAP. username: %s, Model attribute name: %s, LDAP attribute name: %s, Attribute value: %s", getUsername(), modelAttrName, ldapAttrName, value);
                    }
                    markUpdatedAttributeInTransaction(modelAttrName);
                    if (value == null) {
                        if (isMandatoryInLdap) {
                            ldapUser.setSingleAttribute(ldapAttrName, LDAPConstants.EMPTY_ATTRIBUTE_VALUE);
                        } else {
                            ldapUser.setAttribute(ldapAttrName, new LinkedHashSet<String>());
                        }
                    } else if (value instanceof String) {
                        ldapUser.setSingleAttribute(ldapAttrName, (String) value);
                    } else {
                        List<String> asList = (List<String>) value;
                        if (asList.isEmpty() && isMandatoryInLdap) {
                            ldapUser.setSingleAttribute(ldapAttrName, LDAPConstants.EMPTY_ATTRIBUTE_VALUE);
                        } else {
                            ldapUser.setAttribute(ldapAttrName, new LinkedHashSet<>(asList));
                        }
                    }
                    if (isBinaryAttribute) {
                        UserAttributeLDAPStorageMapper.logger.debugf("Skip writing model attribute '%s' to DB for user '%s' as it is mapped to binary LDAP attribute.", userModelAttrName, getUsername());
                        return false;
                    } else {
                        return true;
                    }
                }
                return true;
            }
        };
    } else if (isBinaryAttribute) {
        delegate = new UserModelDelegate(delegate) {

            @Override
            public void setSingleAttribute(String name, String value) {
                if (name.equalsIgnoreCase(userModelAttrName)) {
                    logSkipDBWrite();
                } else {
                    super.setSingleAttribute(name, value);
                }
            }

            @Override
            public void setAttribute(String name, List<String> values) {
                if (name.equalsIgnoreCase(userModelAttrName)) {
                    logSkipDBWrite();
                } else {
                    super.setAttribute(name, values);
                }
            }

            @Override
            public void removeAttribute(String name) {
                if (name.equalsIgnoreCase(userModelAttrName)) {
                    logSkipDBWrite();
                } else {
                    super.removeAttribute(name);
                }
            }

            private void logSkipDBWrite() {
                logger.debugf("Skip writing model attribute '%s' to DB for user '%s' as it is mapped to binary LDAP attribute", userModelAttrName, getUsername());
            }
        };
    }
    // We prefer to read attribute value from LDAP instead of from local Keycloak DB
    if (isAlwaysReadValueFromLDAP) {
        delegate = new UserModelDelegate(delegate) {

            @Override
            public String getFirstAttribute(String name) {
                if (name.equalsIgnoreCase(userModelAttrName)) {
                    return ldapUser.getAttributeAsString(ldapAttrName);
                } else {
                    return super.getFirstAttribute(name);
                }
            }

            @Override
            public Stream<String> getAttributeStream(String name) {
                if (name.equalsIgnoreCase(userModelAttrName)) {
                    Collection<String> ldapAttrValue = ldapUser.getAttributeAsSet(ldapAttrName);
                    if (ldapAttrValue == null) {
                        return Stream.empty();
                    } else {
                        return ldapAttrValue.stream();
                    }
                } else {
                    return super.getAttributeStream(name);
                }
            }

            @Override
            public Map<String, List<String>> getAttributes() {
                Map<String, List<String>> attrs = new HashMap<>(super.getAttributes());
                // Ignore UserModel properties
                if (userModelProperties.get(userModelAttrName.toLowerCase()) != null) {
                    return attrs;
                }
                Set<String> allLdapAttrValues = ldapUser.getAttributeAsSet(ldapAttrName);
                if (allLdapAttrValues != null) {
                    attrs.put(userModelAttrName, new ArrayList<>(allLdapAttrValues));
                }
                return attrs;
            }

            @Override
            public String getEmail() {
                if (UserModel.EMAIL.equalsIgnoreCase(userModelAttrName)) {
                    return ldapUser.getAttributeAsString(ldapAttrName);
                } else {
                    return super.getEmail();
                }
            }

            @Override
            public boolean isEnabled() {
                if (UserModel.ENABLED.equalsIgnoreCase(userModelAttrName)) {
                    return Boolean.parseBoolean(ldapUser.getAttributeAsString(ldapAttrName));
                } else {
                    return super.isEnabled();
                }
            }

            @Override
            public boolean isEmailVerified() {
                if (UserModel.EMAIL_VERIFIED.equalsIgnoreCase(userModelAttrName)) {
                    return Boolean.parseBoolean(ldapUser.getAttributeAsString(ldapAttrName));
                } else {
                    return super.isEmailVerified();
                }
            }

            @Override
            public String getLastName() {
                if (UserModel.LAST_NAME.equalsIgnoreCase(userModelAttrName)) {
                    return ldapUser.getAttributeAsString(ldapAttrName);
                } else {
                    return super.getLastName();
                }
            }

            @Override
            public String getFirstName() {
                if (UserModel.FIRST_NAME.equalsIgnoreCase(userModelAttrName)) {
                    return ldapUser.getAttributeAsString(ldapAttrName);
                } else {
                    return super.getFirstName();
                }
            }
        };
    }
    return delegate;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) LinkedHashSet(java.util.LinkedHashSet) Set(java.util.Set) ArrayList(java.util.ArrayList) UserModelDelegate(org.keycloak.models.utils.UserModelDelegate) Collection(java.util.Collection) LDAPObject(org.keycloak.storage.ldap.idm.model.LDAPObject) ArrayList(java.util.ArrayList) List(java.util.List) Stream(java.util.stream.Stream) HashMap(java.util.HashMap) Map(java.util.Map)

Example 4 with UserModelDelegate

use of org.keycloak.models.utils.UserModelDelegate in project keycloak by keycloak.

the class LdapManyObjectsInitializerCommand method addLDAPUser.

private static LDAPObject addLDAPUser(LDAPStorageProvider ldapProvider, RealmModel realm, final String username, final String firstName, final String lastName, final String email, String groupsDN, int startOffsetGroups, int countGroups) {
    UserModel helperUser = new UserModelDelegate(null) {

        @Override
        public String getUsername() {
            return username;
        }

        @Override
        public String getFirstName() {
            return firstName;
        }

        @Override
        public String getLastName() {
            return lastName;
        }

        @Override
        public String getEmail() {
            return email;
        }

        @Override
        public Stream<String> getAttributeStream(String name) {
            if (UserModel.FIRST_NAME.equals(name)) {
                return Stream.of(firstName);
            } else if (UserModel.LAST_NAME.equals(name)) {
                return Stream.of(lastName);
            } else if (UserModel.EMAIL.equals(name)) {
                return Stream.of(email);
            } else if (UserModel.USERNAME.equals(name)) {
                return Stream.of(username);
            } else if ("street".equals(name)) {
                Stream.Builder<String> builder = Stream.builder();
                for (int i = startOffsetGroups; i < startOffsetGroups + countGroups; i++) {
                    String groupName = "group" + i;
                    LDAPDn groupDn = LDAPDn.fromString(groupsDN);
                    groupDn.addFirst("cn", groupName);
                    builder.add(groupDn.toString());
                }
                return builder.build();
            } else {
                return Stream.empty();
            }
        }
    };
    return LDAPUtils.addUserToLDAP(ldapProvider, realm, helperUser);
}
Also used : UserModel(org.keycloak.models.UserModel) UserModelDelegate(org.keycloak.models.utils.UserModelDelegate) Stream(java.util.stream.Stream) LDAPDn(org.keycloak.storage.ldap.idm.model.LDAPDn)

Example 5 with UserModelDelegate

use of org.keycloak.models.utils.UserModelDelegate in project keycloak by keycloak.

the class HardcodedLDAPRoleStorageMapper method proxy.

@Override
public UserModel proxy(LDAPObject ldapUser, UserModel delegate, RealmModel realm) {
    return new UserModelDelegate(delegate) {

        @Override
        public Stream<RoleModel> getRealmRoleMappingsStream() {
            Stream<RoleModel> realmRoleMappings = super.getRealmRoleMappingsStream();
            RoleModel role = getRole(realm);
            if (role != null && role.getContainer().equals(realm)) {
                realmRoleMappings = Stream.concat(realmRoleMappings, Stream.of(role));
            }
            return realmRoleMappings;
        }

        @Override
        public Stream<RoleModel> getClientRoleMappingsStream(ClientModel app) {
            Stream<RoleModel> clientRoleMappings = super.getClientRoleMappingsStream(app);
            RoleModel role = getRole(realm);
            if (role != null && role.getContainer().equals(app)) {
                return Stream.concat(clientRoleMappings, Stream.of(role));
            }
            return clientRoleMappings;
        }

        @Override
        public boolean hasDirectRole(RoleModel role) {
            return super.hasDirectRole(role) || role.equals(getRole(realm));
        }

        @Override
        public boolean hasRole(RoleModel role) {
            return super.hasRole(role) || role.equals(getRole(realm));
        }

        @Override
        public Stream<RoleModel> getRoleMappingsStream() {
            Stream<RoleModel> roleMappings = super.getRoleMappingsStream();
            RoleModel role = getRole(realm);
            if (role != null) {
                roleMappings = Stream.concat(roleMappings, Stream.of(role));
            }
            return roleMappings;
        }

        @Override
        public void deleteRoleMapping(RoleModel role) {
            if (role.equals(getRole(realm))) {
                throw new ModelException("Not possible to delete role. It's hardcoded by LDAP mapper");
            } else {
                super.deleteRoleMapping(role);
            }
        }
    };
}
Also used : ClientModel(org.keycloak.models.ClientModel) UserModelDelegate(org.keycloak.models.utils.UserModelDelegate) ModelException(org.keycloak.models.ModelException) RoleModel(org.keycloak.models.RoleModel)

Aggregations

UserModelDelegate (org.keycloak.models.utils.UserModelDelegate)5 Stream (java.util.stream.Stream)3 List (java.util.List)2 ArrayList (java.util.ArrayList)1 Collection (java.util.Collection)1 HashMap (java.util.HashMap)1 LinkedHashSet (java.util.LinkedHashSet)1 Map (java.util.Map)1 Set (java.util.Set)1 Response (javax.ws.rs.core.Response)1 EventBuilder (org.keycloak.events.EventBuilder)1 ClientModel (org.keycloak.models.ClientModel)1 ModelException (org.keycloak.models.ModelException)1 RoleModel (org.keycloak.models.RoleModel)1 UserModel (org.keycloak.models.UserModel)1 LDAPDn (org.keycloak.storage.ldap.idm.model.LDAPDn)1 LDAPObject (org.keycloak.storage.ldap.idm.model.LDAPObject)1 UserProfile (org.keycloak.userprofile.UserProfile)1 UserProfileProvider (org.keycloak.userprofile.UserProfileProvider)1 ValidationException (org.keycloak.userprofile.ValidationException)1