remove User Fed SPI

This commit is contained in:
Bill Burke 2016-11-23 16:06:44 -05:00
parent fad33bc50f
commit ccbd8e8c70
85 changed files with 505 additions and 2891 deletions

View file

@ -78,7 +78,7 @@ public class SecretQuestionCredentialProvider implements CredentialProvider, Cre
creds.get(0).setValue(credInput.getValue());
session.userCredentialManager().updateCredential(realm, user, creds.get(0));
}
session.getUserCache().evict(realm, user);
session.userCache().evict(realm, user);
return true;
}
@ -86,7 +86,7 @@ public class SecretQuestionCredentialProvider implements CredentialProvider, Cre
public void disableCredentialType(RealmModel realm, UserModel user, String credentialType) {
if (!SECRET_QUESTION.equals(credentialType)) return;
session.userCredentialManager().disableCredentialType(realm, user, credentialType);
session.getUserCache().evict(realm, user);
session.userCache().evict(realm, user);
}

View file

@ -1,26 +0,0 @@
Example User Federation Provider
===================================================
This is an example of user federation backed by a simple properties file. This properties file only contains username/password
key pairs. To deploy, build this directory then take the jar and copy it to providers directory. Alternatively you can deploy as a module by running:
KEYCLOAK_HOME/bin/jboss-cli.sh --command="module add --name=org.keycloak.examples.userprops --resources=target/federation-properties-example.jar --dependencies=org.keycloak.keycloak-core,org.keycloak.keycloak-server-spi,org.keycloak.keycloak-server-spi-private"
Then registering the provider by editing `standalone/configuration/standalone.xml` and adding the module to the providers element:
<providers>
...
<provider>module:org.keycloak.examples.userprops</provider>
</providers>
You will then have to restart the authentication server.
The ClasspathPropertiesFederationProvider is an example of a readonly provider. If you go to the Users/Federation
page of the admin console you will see this provider listed under "classpath-properties. To configure this provider you
specify a classpath to a properties file in the "path" field of the admin page for this plugin. This example includes
a "test-users.properties" within the JAR that you can use as the variable.
The FilePropertiesFederationProvider is an example of a writable provider. It synchronizes changes made to
username and password with the properties file. If you go to the Users/Federation page of the admin console you will
see this provider listed under "file-properties". To configure this provider you specify a fully qualified file path to
a properties file in the "path" field of the admin page for this plugin.

View file

@ -1,152 +0,0 @@
/*
* 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.examples.federation.properties;
import org.keycloak.Config;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.KeycloakSessionTask;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderFactory;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserFederationSyncResult;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserProvider;
import org.keycloak.models.utils.KeycloakModelUtils;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public abstract class BasePropertiesFederationFactory implements UserFederationProviderFactory {
static final Set<String> configOptions = new HashSet<String>();
protected ConcurrentHashMap<String, Properties> files = new ConcurrentHashMap<String, Properties>();
static {
configOptions.add("path");
}
@Override
public UserFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model) {
// first get the path to our properties file from the stored configuration of this provider instance.
String path = model.getConfig().get("path");
if (path == null) {
throw new IllegalStateException("Path attribute not configured for provider");
}
// see if we already loaded the config file
Properties props = files.get(path);
if (props != null) return createProvider(session, model, props);
props = new Properties();
InputStream is = getPropertiesFileStream(path);
try {
props.load(is);
is.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
// remember the properties file for next time
files.put(path, props);
return createProvider(session, model, props);
}
protected abstract InputStream getPropertiesFileStream(String path);
protected abstract BasePropertiesFederationProvider createProvider(KeycloakSession session, UserFederationProviderModel model, Properties props);
/**
* List the configuration options to render and display in the admin console's generic management page for this
* plugin
*
* @return
*/
@Override
public Set<String> getConfigurationOptions() {
return configOptions;
}
@Override
public UserFederationProvider create(KeycloakSession session) {
return null;
}
/**
* You can import additional plugin configuration from standalone.xml here.
*
* @param config
*/
@Override
public void init(Config.Scope config) {
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
@Override
public void close() {
}
@Override
public UserFederationSyncResult syncAllUsers(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel model) {
final UserFederationSyncResult syncResult = new UserFederationSyncResult();
KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
@Override
public void run(KeycloakSession session) {
RealmModel realm = session.realms().getRealm(realmId);
BasePropertiesFederationProvider federationProvider = (BasePropertiesFederationProvider)getInstance(session, model);
Set<String> allUsernames = federationProvider.getProperties().stringPropertyNames();
UserProvider localProvider = session.userStorage();
for (String username : allUsernames) {
UserModel localUser = localProvider.getUserByUsername(username, realm);
if (localUser == null) {
// New user, let's import him
UserModel imported = federationProvider.getUserByUsername(realm, username);
if (imported != null) {
syncResult.increaseAdded();
}
}
}
}
});
return syncResult;
}
@Override
public UserFederationSyncResult syncChangedUsers(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel model, Date lastSync) {
return syncAllUsers(sessionFactory, realmId, model);
}
}

View file

@ -1,184 +0,0 @@
/*
* 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.examples.federation.properties;
import org.keycloak.credential.CredentialInput;
import org.keycloak.models.CredentialValidationOutput;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public abstract class BasePropertiesFederationProvider implements UserFederationProvider {
protected static final Set<String> supportedCredentialTypes = new HashSet<String>();
protected KeycloakSession session;
protected Properties properties;
protected UserFederationProviderModel model;
public BasePropertiesFederationProvider(KeycloakSession session, UserFederationProviderModel model, Properties properties) {
this.session = session;
this.model = model;
this.properties = properties;
}
static
{
supportedCredentialTypes.add(UserCredentialModel.PASSWORD);
}
public KeycloakSession getSession() {
return session;
}
public Properties getProperties() {
return properties;
}
public UserFederationProviderModel getModel() {
return model;
}
@Override
public UserModel getUserByUsername(RealmModel realm, String username) {
String password = properties.getProperty(username);
if (password != null) {
UserModel userModel = session.userStorage().addUser(realm, username);
userModel.setEnabled(true);
userModel.setFederationLink(model.getId());
return userModel;
}
return null;
}
@Override
public UserModel getUserByEmail(RealmModel realm, String email) {
return null;
}
/**
* We only search for Usernames as that is all that is stored in the properties file. Not that if the user
* does exist in the properties file, we only import it if the user hasn't been imported already.
*
* @param attributes
* @param realm
* @param maxResults
* @return
*/
@Override
public List<UserModel> searchByAttributes(Map<String, String> attributes, RealmModel realm, int maxResults) {
String username = attributes.get(USERNAME);
if (username != null) {
// make sure user isn't already in storage
if (session.userStorage().getUserByUsername(username, realm) == null) {
// user is not already imported, so let's import it until local storage.
UserModel user = getUserByUsername(realm, username);
if (user != null) {
List<UserModel> list = new ArrayList<UserModel>(1);
list.add(user);
return list;
}
}
}
return Collections.emptyList();
}
@Override
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
return Collections.emptyList();
}
@Override
public void preRemove(RealmModel realm) {
// complete We don't care about the realm being removed
}
@Override
public void preRemove(RealmModel realm, RoleModel role) {
// complete we dont'care if a role is removed
}
@Override
public void preRemove(RealmModel realm, GroupModel group) {
// complete we dont'care if a role is removed
}
/**
* See if the user is still in the properties file
*
* @param local
* @return
*/
@Override
public boolean isValid(RealmModel realm, UserModel local) {
return properties.containsKey(local.getUsername());
}
@Override
public Set<String> getSupportedCredentialTypes() {
return supportedCredentialTypes;
}
@Override
public boolean isValid(RealmModel realm, UserModel user, CredentialInput input) {
if (!supportsCredentialType(input.getType()) || !(input instanceof UserCredentialModel)) return false;
UserCredentialModel cred = (UserCredentialModel)input;
String password = properties.getProperty(user.getUsername());
if (password == null) return false;
return password.equals(cred.getValue());
}
@Override
public boolean isConfiguredFor(RealmModel realm, UserModel user, String credentialType) {
return getSupportedCredentialTypes().contains(credentialType);
}
@Override
public boolean supportsCredentialType(String credentialType) {
return getSupportedCredentialTypes().contains(credentialType);
}
@Override
public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel credential) {
return CredentialValidationOutput.failed();
}
@Override
public void close() {
}
}

View file

@ -1,118 +0,0 @@
/*
* 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.examples.federation.properties;
import org.keycloak.credential.CredentialInput;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.Properties;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class FilePropertiesFederationProvider extends BasePropertiesFederationProvider {
public FilePropertiesFederationProvider(KeycloakSession session, Properties properties, UserFederationProviderModel model) {
super(session, model, properties);
}
/**
* Keycloak will call this method if it finds an imported UserModel. Here we proxy the UserModel with
* a Writable proxy which will synchronize updates to username and password back to the properties file
*
* @param local
* @return
*/
@Override
public UserModel validateAndProxy(RealmModel realm, UserModel local) {
if (isValid(realm, local)) {
return new WritableUserModelProxy(local, this);
} else {
return null;
}
}
/**
* Adding new users is supported
*
* @return
*/
@Override
public boolean synchronizeRegistrations() {
return true;
}
public void save() {
String path = getModel().getConfig().get("path");
try {
FileOutputStream fos = new FileOutputStream(path);
properties.store(fos, "");
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Update the properties file with the new user.
*
* @param realm
* @param user
* @return
*/
@Override
public UserModel register(RealmModel realm, UserModel user) {
synchronized (properties) {
properties.setProperty(user.getUsername(), "");
save();
}
return validateAndProxy(realm, user);
}
@Override
public boolean removeUser(RealmModel realm, UserModel user) {
synchronized (properties) {
if (properties.remove(user.getUsername()) == null) return false;
save();
return true;
}
}
@Override
public boolean updateCredential(RealmModel realm, UserModel user, CredentialInput input) {
return false;
}
@Override
public void disableCredentialType(RealmModel realm, UserModel user, String credentialType) {
}
@Override
public Set<String> getDisableableCredentialTypes(RealmModel realm, UserModel user) {
return Collections.EMPTY_SET;
}
}

View file

@ -1,65 +0,0 @@
/*
* 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.examples.federation.properties;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.UserModelDelegate;
import java.util.Properties;
/**
* Proxy that will synchronize password updates to the properties file.
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class WritableUserModelProxy extends UserModelDelegate {
protected FilePropertiesFederationProvider provider;
public WritableUserModelProxy(UserModel delegate, FilePropertiesFederationProvider provider) {
super(delegate);
this.provider = provider;
}
/**
* Updates the properties file if the username changes. If you have a more complex user storage, you can
* override other methods on UserModel to synchronize updates back to your external storage.
*
* @param username
*/
@Override
public void setUsername(String username) {
if (delegate.getUsername().equals(username)) return;
delegate.setUsername(username);
Properties properties = provider.getProperties();
synchronized (properties) {
if (properties.containsKey(username)) {
throw new IllegalStateException("Can't change username to existing user");
}
String password = (String) properties.remove(username);
if (password == null) {
throw new IllegalStateException("User doesn't exist");
}
properties.setProperty(username, password);
provider.save();
}
}
}

View file

@ -1,19 +0,0 @@
#
# 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.
#
org.keycloak.examples.federation.properties.ClasspathPropertiesFederationFactory
org.keycloak.examples.federation.properties.FilePropertiesFederationFactory

View file

@ -33,10 +33,10 @@
<modules>
<module>event-listener-sysout</module>
<module>event-store-mem</module>
<module>federation-provider</module>
<module>authenticator</module>
<module>rest</module>
<module>domain-extension</module>
<module>user-storage-simple</module>
<module>user-storage-jpa</module>
</modules>
</project>

View file

@ -0,0 +1,19 @@
Example User Federation Provider
===================================================
This is an example of user storage backed by a simple properties file. This properties file only contains username/password
key pairs. To deploy this provider you must have Keycloak running in standalone or standalone-ha mode. Then type the follow maven command:
mvn clean install wildfly:deploy
The ClasspathPropertiesStorageProvider is an example of a readonly provider. If you go to the Users/Federation
page of the admin console you will see this provider listed under "classpath-properties. To configure this provider you
specify a classpath to a properties file in the "path" field of the admin page for this plugin. This example includes
a "test-users.properties" within the JAR that you can use as the variable.
The FilePropertiesStorageProvider is an example of a writable provider. It synchronizes changes made to
username and password with the properties file. If you go to the Users/Federation page of the admin console you will
see this provider listed under "file-properties". To configure this provider you specify a fully qualified file path to
a properties file in the "path" field of the admin page for this plugin.

View file

@ -23,11 +23,11 @@
<version>2.4.1.Final-SNAPSHOT</version>
</parent>
<name>Properties Authentication Provider Example</name>
<name>UserStorageProvider Simple Example</name>
<description/>
<modelVersion>4.0.0</modelVersion>
<artifactId>federation-properties-example</artifactId>
<artifactId>user-storage-properties-example</artifactId>
<packaging>jar</packaging>
<dependencies>
@ -41,11 +41,6 @@
<artifactId>keycloak-server-spi</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-server-spi-private</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
@ -54,6 +49,23 @@
</dependencies>
<build>
<finalName>federation-properties-example</finalName>
<finalName>user-storage-properties-example</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<configuration>
<skip>false</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,69 @@
/*
* 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.examples.federation.properties;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.storage.UserStorageProviderFactory;
import org.keycloak.storage.UserStorageProviderModel;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public abstract class BasePropertiesStorageFactory<T extends BasePropertiesStorageProvider> implements UserStorageProviderFactory<T> {
protected ConcurrentHashMap<String, Properties> files = new ConcurrentHashMap<String, Properties>();
@Override
public T create(KeycloakSession session, ComponentModel model) {
// first get the path to our properties file from the stored configuration of this provider instance.
String path = model.getConfig().getFirst("path");
if (path == null) {
throw new IllegalStateException("Path attribute not configured for provider");
}
// see if we already loaded the config file
Properties props = files.get(path);
if (props != null) return (T)createProvider(session, new UserStorageProviderModel(model), props);
props = new Properties();
InputStream is = getPropertiesFileStream(path);
if (is != null) {
try {
props.load(is);
is.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
// remember the properties file for next time
files.put(path, props);
return (T)createProvider(session, new UserStorageProviderModel(model), props);
}
protected abstract InputStream getPropertiesFileStream(String path);
protected abstract BasePropertiesStorageProvider createProvider(KeycloakSession session, UserStorageProviderModel model, Properties props);
}

View file

@ -0,0 +1,138 @@
/*
* 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.examples.federation.properties;
import org.keycloak.credential.CredentialInput;
import org.keycloak.credential.CredentialInputValidator;
import org.keycloak.credential.CredentialModel;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.storage.StorageId;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.user.UserLookupProvider;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public abstract class BasePropertiesStorageProvider implements
UserStorageProvider,
UserLookupProvider,
CredentialInputValidator
{
public static final String UNSET_PASSWORD="#$!-UNSET-PASSWORD";
protected KeycloakSession session;
protected Properties properties;
protected UserStorageProviderModel model;
// map of loaded users in this transaction
protected Map<String, UserModel> loadedUsers = new HashMap<>();
public BasePropertiesStorageProvider(KeycloakSession session, UserStorageProviderModel model, Properties properties) {
this.session = session;
this.model = model;
this.properties = properties;
}
public KeycloakSession getSession() {
return session;
}
public Properties getProperties() {
return properties;
}
@Override
public UserModel getUserByUsername(String username, RealmModel realm) {
UserModel adapter = loadedUsers.get(username);
if (adapter == null) {
String password = properties.getProperty(username);
if (password != null) {
adapter = createAdapter(realm, username);
loadedUsers.put(username, adapter);
}
}
return adapter;
}
@Override
public UserModel getUserById(String id, RealmModel realm) {
StorageId storageId = new StorageId(id);
String username = storageId.getExternalId();
return getUserByUsername(username, realm);
}
protected abstract UserModel createAdapter(RealmModel realm, String username);
@Override
public UserModel getUserByEmail(String email, RealmModel realm) {
return null;
}
@Override
public void preRemove(RealmModel realm) {
// complete We don't care about the realm being removed
}
@Override
public void preRemove(RealmModel realm, RoleModel role) {
// complete we dont'care if a role is removed
}
@Override
public void preRemove(RealmModel realm, GroupModel group) {
// complete we dont'care if a role is removed
}
@Override
public boolean isValid(RealmModel realm, UserModel user, CredentialInput input) {
if (!supportsCredentialType(input.getType()) || !(input instanceof UserCredentialModel)) return false;
UserCredentialModel cred = (UserCredentialModel)input;
String password = properties.getProperty(user.getUsername());
if (password == null || password.equals(UNSET_PASSWORD)) return false;
return password.equals(cred.getValue());
}
@Override
public boolean isConfiguredFor(RealmModel realm, UserModel user, String credentialType) {
String password = properties.getProperty(user.getUsername());
return credentialType.equals(CredentialModel.PASSWORD) && password != null && !password.equals(UNSET_PASSWORD);
}
@Override
public boolean supportsCredentialType(String credentialType) {
return credentialType.equals(CredentialModel.PASSWORD);
}
@Override
public void close() {
}
}

View file

@ -18,22 +18,40 @@
package org.keycloak.examples.federation.properties;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.provider.ProviderConfigurationBuilder;
import org.keycloak.storage.UserStorageProviderModel;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ClasspathPropertiesFederationFactory extends BasePropertiesFederationFactory {
public class ClasspathPropertiesStorageFactory extends BasePropertiesStorageFactory<ClasspathPropertiesStorageProvider> {
public static final String PROVIDER_NAME = "classpath-properties";
protected static final List<ProviderConfigProperty> configProperties;
static {
configProperties = ProviderConfigurationBuilder.create()
.property().name("path")
.type(ProviderConfigProperty.STRING_TYPE)
.label("Classpath")
.helpText("Classpath of properties file")
.add().build();
}
@Override
protected BasePropertiesFederationProvider createProvider(KeycloakSession session, UserFederationProviderModel model, Properties props) {
return new ClasspathPropertiesFederationProvider(session, model, props);
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
protected BasePropertiesStorageProvider createProvider(KeycloakSession session, UserStorageProviderModel model, Properties props) {
return new ClasspathPropertiesStorageProvider(session, model, props);
}
protected InputStream getPropertiesFileStream(String path) {

View file

@ -18,73 +18,45 @@
package org.keycloak.examples.federation.properties;
import org.keycloak.credential.CredentialInput;
import org.keycloak.credential.CredentialInputUpdater;
import org.keycloak.credential.CredentialModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.storage.ReadOnlyException;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.adapter.AbstractUserAdapter;
import java.util.Collections;
import java.util.Properties;
import java.util.Set;
/**
* Creates a read-only user. Implements CredentialInputUpdater so that passwords cannot be updated
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ClasspathPropertiesFederationProvider extends BasePropertiesFederationProvider {
public class ClasspathPropertiesStorageProvider extends BasePropertiesStorageProvider implements CredentialInputUpdater {
public ClasspathPropertiesFederationProvider(KeycloakSession session, UserFederationProviderModel model, Properties properties) {
public ClasspathPropertiesStorageProvider(KeycloakSession session, UserStorageProviderModel model, Properties properties) {
super(session, model, properties);
}
/**
* Keycloak will call this method if it finds an imported UserModel. Here we proxy the UserModel with
* a Readonly proxy which will barf if password is updated.
*
* @param local
* @return
*/
@Override
public UserModel validateAndProxy(RealmModel realm, UserModel local) {
if (isValid(realm, local)) {
return new ReadonlyUserModelProxy(local);
} else {
return null;
}
}
/**
* The properties file is readonly so don't suppport registration.
*
* @return
*/
@Override
public boolean synchronizeRegistrations() {
return false;
}
/**
* The properties file is readonly so don't suppport registration.
*
* @return
*/
@Override
public UserModel register(RealmModel realm, UserModel user) {
throw new IllegalStateException("Registration not supported");
}
/**
* The properties file is readonly so don't removing a user
*
* @return
*/
@Override
public boolean removeUser(RealmModel realm, UserModel user) {
throw new IllegalStateException("Remove not supported");
protected UserModel createAdapter(RealmModel realm, String username) {
return new AbstractUserAdapter(session, realm, model) {
@Override
public String getUsername() {
return username;
}
};
}
@Override
public boolean updateCredential(RealmModel realm, UserModel user, CredentialInput input) {
if (input.getType().equals(CredentialModel.PASSWORD)) throw new ReadOnlyException("user is read only for this update");
return false;
}

View file

@ -18,30 +18,48 @@
package org.keycloak.examples.federation.properties;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.provider.ProviderConfigurationBuilder;
import org.keycloak.storage.UserStorageProviderModel;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class FilePropertiesFederationFactory extends BasePropertiesFederationFactory {
public class FilePropertiesStorageFactory extends BasePropertiesStorageFactory<FilePropertiesStorageProvider> {
public static final String PROVIDER_NAME = "file-properties";
protected static final List<ProviderConfigProperty> configProperties;
static {
configProperties = ProviderConfigurationBuilder.create()
.property().name("path")
.type(ProviderConfigProperty.STRING_TYPE)
.label("Path")
.helpText("File path to properties file")
.add().build();
}
@Override
protected BasePropertiesFederationProvider createProvider(KeycloakSession session, UserFederationProviderModel model, Properties props) {
return new FilePropertiesFederationProvider(session, props, model);
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
protected BasePropertiesStorageProvider createProvider(KeycloakSession session, UserStorageProviderModel model, Properties props) {
return new FilePropertiesStorageProvider(session, props, model);
}
protected InputStream getPropertiesFileStream(String path) {
try {
return new FileInputStream(path);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
return null;
}
}

View file

@ -0,0 +1,134 @@
/*
* 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.examples.federation.properties;
import org.keycloak.credential.CredentialInput;
import org.keycloak.credential.CredentialInputUpdater;
import org.keycloak.credential.CredentialModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.storage.ReadOnlyException;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.adapter.AbstractUserAdapterFederatedStorage;
import org.keycloak.storage.user.UserRegistrationProvider;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class FilePropertiesStorageProvider extends BasePropertiesStorageProvider implements
UserRegistrationProvider,
CredentialInputUpdater
{
public FilePropertiesStorageProvider(KeycloakSession session, Properties properties, UserStorageProviderModel model) {
super(session, model, properties);
}
public void save() {
String path = model.getConfig().getFirst("path");
try {
FileOutputStream fos = new FileOutputStream(path);
properties.store(fos, "");
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public boolean removeUser(RealmModel realm, UserModel user) {
synchronized (properties) {
if (properties.remove(user.getUsername()) == null) return false;
save();
return true;
}
}
@Override
protected UserModel createAdapter(RealmModel realm, String username) {
return new AbstractUserAdapterFederatedStorage(session, realm, model) {
@Override
public String getUsername() {
return username;
}
@Override
public void setUsername(String username) {
throw new ReadOnlyException("Cannot edit username");
}
};
}
@Override
public UserModel addUser(RealmModel realm, String username) {
synchronized (properties) {
properties.setProperty(username, UNSET_PASSWORD);
save();
}
return createAdapter(realm, username);
}
@Override
public void grantToAllUsers(RealmModel realm, RoleModel role) {
// unsupported
}
@Override
public boolean updateCredential(RealmModel realm, UserModel user, CredentialInput input) {
if (!(input instanceof UserCredentialModel)) return false;
UserCredentialModel cred = (UserCredentialModel)input;
if (!cred.getType().equals(CredentialModel.PASSWORD)) return false;
synchronized (properties) {
properties.setProperty(user.getUsername(), cred.getValue());
save();
}
return true;
}
@Override
public void disableCredentialType(RealmModel realm, UserModel user, String credentialType) {
if (!credentialType.equals(CredentialModel.PASSWORD)) return;
synchronized (properties) {
properties.setProperty(user.getUsername(), UNSET_PASSWORD);
save();
}
}
private static final Set<String> disableableTypes = new HashSet<>();
static {
disableableTypes.add(CredentialModel.PASSWORD);
}
@Override
public Set<String> getDisableableCredentialTypes(RealmModel realm, UserModel user) {
return disableableTypes;
}
}

View file

@ -0,0 +1,2 @@
org.keycloak.examples.federation.properties.ClasspathPropertiesStorageFactory
org.keycloak.examples.federation.properties.FilePropertiesStorageFactory

View file

@ -20,9 +20,6 @@ package org.keycloak.federation.kerberos;
import org.keycloak.common.constants.KerberosConstants;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProvider.EditMode;
/**

View file

@ -33,8 +33,6 @@ import org.keycloak.models.ModelReadOnlyException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserManager;
import org.keycloak.storage.UserStorageProvider;
@ -44,8 +42,6 @@ import org.keycloak.storage.user.UserLookupProvider;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

View file

@ -21,28 +21,19 @@ import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.common.constants.KerberosConstants;
import org.keycloak.component.ComponentModel;
import org.keycloak.component.ComponentValidationException;
import org.keycloak.federation.kerberos.impl.KerberosServerSubjectAuthenticator;
import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator;
import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderFactory;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserFederationSyncResult;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.provider.ProviderConfigurationBuilder;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderFactory;
import org.keycloak.storage.UserStorageProviderModel;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;
/**
* Factory for standalone Kerberos federation provider. Standalone means that it's not backed by LDAP. For Kerberos backed by LDAP (like MS AD or ApacheDS environment)

View file

@ -596,7 +596,7 @@ public class LDAPStorageProvider implements UserStorageProvider,
logger.warnf("User with username [%s] aready exists and is linked to provider [%s] but is not valid. Stale LDAP_ID on local user is: %s",
username, model.getName(), user.getFirstAttribute(LDAPConstants.LDAP_ID));
logger.warn("Will re-create user");
session.getUserCache().evict(realm, user);
session.userCache().evict(realm, user);
new UserManager(session).removeUser(realm, user, session.userLocalStorage());
}
}

View file

@ -495,7 +495,7 @@ public class LDAPStorageProviderFactory implements UserStorageProviderFactory<LD
if (username != null) {
UserModel existing = session.userLocalStorage().getUserByUsername(username, currentRealm);
if (existing != null) {
session.getUserCache().evict(currentRealm, existing);
session.userCache().evict(currentRealm, existing);
session.userLocalStorage().removeUser(currentRealm, existing);
}
}

View file

@ -19,7 +19,6 @@ package org.keycloak.storage.ldap;
import org.keycloak.component.ComponentModel;
import org.keycloak.component.ComponentValidationException;
import org.keycloak.mappers.FederationConfigValidationException;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.ModelException;
import org.keycloak.models.RealmModel;
@ -268,7 +267,7 @@ public class LDAPUtils {
* Validate configured customFilter matches the requested format
*
* @param customFilter
* @throws FederationConfigValidationException
* @throws ComponentValidationException
*/
public static void validateCustomLdapFilter(String customFilter) throws ComponentValidationException {
if (customFilter != null) {

View file

@ -24,15 +24,11 @@ import org.keycloak.credential.CredentialInputValidator;
import org.keycloak.credential.CredentialModel;
import org.keycloak.federation.sssd.api.Sssd;
import org.keycloak.federation.sssd.impl.PAMAuthenticator;
import org.keycloak.models.CredentialValidationOutput;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelReadOnlyException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.models.UserManager;
@ -40,9 +36,7 @@ import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.user.UserLookupProvider;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

View file

@ -24,18 +24,10 @@ import org.keycloak.federation.sssd.api.Sssd;
import org.keycloak.federation.sssd.impl.PAMAuthenticator;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderFactory;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserFederationSyncResult;
import org.keycloak.provider.EnvironmentDependentProviderFactory;
import org.keycloak.storage.UserStorageProviderFactory;
import org.keycloak.storage.UserStorageProviderModel;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
/**
* @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>
* @version $Revision: 1 $

View file

@ -35,8 +35,6 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredActionProviderModel;
import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.cache.CachedRealmModel;
import org.keycloak.models.cache.infinispan.entities.CachedRealm;
import org.keycloak.storage.UserStorageProvider;
@ -1244,7 +1242,7 @@ public class RealmAdapter implements CachedRealmModel {
if (parentId != null && !parentId.equals(getId())) {
ComponentModel parent = getComponent(parentId);
if (parent != null && UserStorageProvider.class.getName().equals(parent.getProviderType())) {
session.getUserCache().evict(this);
session.userCache().evict(this);
}
}
}

View file

@ -32,7 +32,6 @@ import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserProvider;
import org.keycloak.models.cache.CachedUserModel;
@ -53,9 +52,7 @@ import org.keycloak.storage.StorageId;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
@ -852,12 +849,6 @@ public class UserCacheSession implements UserCache {
}
@Override
public void preRemove(RealmModel realm, UserFederationProviderModel link) {
addRealmInvalidation(realm.getId()); // easier to just invalidate whole realm
getDelegate().preRemove(realm, link);
}
@Override
public void preRemove(RealmModel realm, ClientModel client) {
addRealmInvalidation(realm.getId()); // easier to just invalidate whole realm

View file

@ -23,7 +23,6 @@ import org.keycloak.component.ComponentModel;
import org.keycloak.credential.CredentialModel;
import org.keycloak.credential.UserCredentialStore;
import org.keycloak.models.ClientModel;
import org.keycloak.models.CredentialValidationOutput;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
@ -34,8 +33,6 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredActionProviderModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserProvider;
import org.keycloak.models.jpa.entities.CredentialAttributeEntity;
@ -383,12 +380,6 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
.setParameter("realmId", realm.getId()).executeUpdate();
}
@Override
public void preRemove(RealmModel realm, UserFederationProviderModel link) {
String linkId = link.getId();
removeUserDataByLink(realm, linkId);
}
public void removeUserDataByLink(RealmModel realm, String linkId) {
int num = em.createNamedQuery("deleteUserRoleMappingsByRealmAndLink")
.setParameter("realmId", realm.getId())

View file

@ -31,7 +31,6 @@ import org.keycloak.models.GroupModel;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.ModelException;
import org.keycloak.models.OTPPolicy;
import org.keycloak.models.PasswordPolicy;
@ -39,9 +38,6 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredActionProviderModel;
import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserFederationProviderCreationEventImpl;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.jpa.entities.AuthenticationExecutionEntity;
import org.keycloak.models.jpa.entities.AuthenticationFlowEntity;
import org.keycloak.models.jpa.entities.AuthenticatorConfigEntity;
@ -58,8 +54,6 @@ import org.keycloak.models.jpa.entities.RealmEntity;
import org.keycloak.models.jpa.entities.RequiredActionProviderEntity;
import org.keycloak.models.jpa.entities.RequiredCredentialEntity;
import org.keycloak.models.jpa.entities.RoleEntity;
import org.keycloak.models.jpa.entities.UserFederationMapperEntity;
import org.keycloak.models.jpa.entities.UserFederationProviderEntity;
import org.keycloak.models.utils.ComponentUtil;
import org.keycloak.models.utils.KeycloakModelUtils;
@ -68,7 +62,6 @@ import javax.persistence.TypedQuery;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@ -1214,18 +1207,6 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
return mapping;
}
protected UserFederationMapperModel entityToModel(UserFederationMapperEntity entity) {
UserFederationMapperModel mapper = new UserFederationMapperModel();
mapper.setId(entity.getId());
mapper.setName(entity.getName());
mapper.setFederationProviderId(entity.getFederationProvider().getId());
mapper.setFederationMapperType(entity.getFederationMapperType());
Map<String, String> config = new HashMap<String, String>();
if (entity.getConfig() != null) config.putAll(entity.getConfig());
mapper.setConfig(config);
return mapper;
}
@Override
public AuthenticationFlowModel getBrowserFlow() {
String flowId = realm.getBrowserFlow();

View file

@ -30,18 +30,11 @@ import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.storage.StorageId;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.federated.UserAttributeFederatedStorage;
import org.keycloak.storage.federated.UserBrokerLinkFederatedStorage;
import org.keycloak.storage.federated.UserConsentFederatedStorage;
import org.keycloak.storage.federated.UserFederatedStorageProvider;
import org.keycloak.storage.federated.UserGroupMembershipFederatedStorage;
import org.keycloak.storage.federated.UserRequiredActionsFederatedStorage;
import org.keycloak.storage.federated.UserRoleMappingsFederatedStorage;
import org.keycloak.storage.jpa.entity.BrokerLinkEntity;
import org.keycloak.storage.jpa.entity.FederatedUser;
import org.keycloak.storage.jpa.entity.FederatedUserAttributeEntity;
@ -794,38 +787,6 @@ public class JpaUserFederatedStorageProvider implements
.setParameter("realmId", realm.getId()).executeUpdate();
}
@Override
public void preRemove(RealmModel realm, UserFederationProviderModel link) {
int num = em.createNamedQuery("deleteFederatedUserRoleMappingsByRealmAndLink")
.setParameter("realmId", realm.getId())
.setParameter("link", link.getId())
.executeUpdate();
num = em.createNamedQuery("deleteFederatedUserRequiredActionsByRealmAndLink")
.setParameter("realmId", realm.getId())
.setParameter("link", link.getId())
.executeUpdate();
num = em.createNamedQuery("deleteBrokerLinkByRealmAndLink")
.setParameter("realmId", realm.getId())
.setParameter("link", link.getId())
.executeUpdate();
num = em.createNamedQuery("deleteFederatedCredentialAttributeByRealmAndLink")
.setParameter("realmId", realm.getId())
.setParameter("link", link.getId())
.executeUpdate();
num = em.createNamedQuery("deleteFederatedUserCredentialsByRealmAndLink")
.setParameter("realmId", realm.getId())
.setParameter("link", link.getId())
.executeUpdate();
num = em.createNamedQuery("deleteUserFederatedAttributesByRealmAndLink")
.setParameter("realmId", realm.getId())
.setParameter("link", link.getId())
.executeUpdate();
num = em.createNamedQuery("deleteFederatedUsersByRealmAndLink")
.setParameter("realmId", realm.getId())
.setParameter("link", link.getId())
.executeUpdate();
}
@Override
public void preRemove(RealmModel realm, RoleModel role) {
em.createNamedQuery("deleteFederatedUserRoleMappingsByRole").setParameter("roleId", role.getId()).executeUpdate();

View file

@ -28,7 +28,6 @@ import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.credential.CredentialModel;
import org.keycloak.credential.UserCredentialStore;
import org.keycloak.models.ClientModel;
import org.keycloak.models.CredentialValidationOutput;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
@ -39,8 +38,6 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredActionProviderModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserManager;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserProvider;
@ -457,17 +454,6 @@ public class MongoUserProvider implements UserProvider, UserCredentialStore {
getMongoStore().removeEntities(MongoUserEntity.class, query, true, invocationContext);
}
@Override
public void preRemove(RealmModel realm, UserFederationProviderModel link) {
// Remove all users linked with federationProvider and their consents
DBObject query = new QueryBuilder()
.and("realmId").is(realm.getId())
.and("federationLink").is(link.getId())
.get();
getMongoStore().removeEntities(MongoUserEntity.class, query, true, invocationContext);
}
@Override
public void preRemove(RealmModel realm, ClientModel client) {
// Remove all role mappings and consents mapped to all roles of this client

View file

@ -32,7 +32,6 @@ import org.keycloak.models.GroupModel;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.ModelException;
import org.keycloak.models.OTPPolicy;
import org.keycloak.models.PasswordPolicy;
@ -41,9 +40,6 @@ import org.keycloak.models.RealmProvider;
import org.keycloak.models.RequiredActionProviderModel;
import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserFederationProviderCreationEventImpl;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.mongo.keycloak.entities.AuthenticationExecutionEntity;
import org.keycloak.models.mongo.keycloak.entities.AuthenticationFlowEntity;
import org.keycloak.models.mongo.keycloak.entities.AuthenticatorConfigEntity;
@ -56,15 +52,12 @@ import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
import org.keycloak.models.mongo.keycloak.entities.RequiredActionProviderEntity;
import org.keycloak.models.mongo.keycloak.entities.RequiredCredentialEntity;
import org.keycloak.models.mongo.keycloak.entities.UserFederationMapperEntity;
import org.keycloak.models.mongo.keycloak.entities.UserFederationProviderEntity;
import org.keycloak.models.utils.ComponentUtil;
import org.keycloak.models.utils.KeycloakModelUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;

View file

@ -33,27 +33,18 @@ import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.mongo.keycloak.entities.CredentialEntity;
import org.keycloak.models.mongo.keycloak.entities.FederatedIdentityEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.storage.StorageId;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.federated.UserAttributeFederatedStorage;
import org.keycloak.storage.federated.UserBrokerLinkFederatedStorage;
import org.keycloak.storage.federated.UserConsentFederatedStorage;
import org.keycloak.storage.federated.UserFederatedStorageProvider;
import org.keycloak.storage.federated.UserGroupMembershipFederatedStorage;
import org.keycloak.storage.federated.UserRequiredActionsFederatedStorage;
import org.keycloak.storage.federated.UserRoleMappingsFederatedStorage;
import org.keycloak.storage.mongo.entity.FederatedUser;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@ -220,11 +211,6 @@ public class MongoUserFederatedStorageProvider implements
getMongoStore().removeEntities(FederatedUser.class, query, true, invocationContext);
}
@Override
public void preRemove(RealmModel realm, UserFederationProviderModel link) {
}
@Override
public void preRemove(RealmModel realm, GroupModel group) {
DBObject query = new QueryBuilder()

View file

@ -1,47 +0,0 @@
/*
* 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.mappers;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class FederationConfigValidationException extends Exception {
private Object[] parameters;
public FederationConfigValidationException(String message) {
super(message);
}
public FederationConfigValidationException(String message, Throwable cause) {
super(message, cause);
}
public FederationConfigValidationException(String message, Object ... parameters) {
super(message);
this.parameters = parameters;
}
public Object[] getParameters() {
return parameters;
}
public void setParameters(Object[] parameters) {
this.parameters = parameters;
}
}

View file

@ -1,65 +0,0 @@
/*
* 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.mappers;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationSyncResult;
import org.keycloak.models.UserModel;
import org.keycloak.provider.Provider;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface UserFederationMapper extends Provider {
/**
* Sync data from federated storage to Keycloak. It's useful just if mapper needs some data preloaded from federated storage (For example
* load roles from federated provider and sync them to Keycloak database)
*
* Applicable just if sync is supported (see UserFederationMapperFactory.getSyncConfig() )
*
* @see UserFederationMapperFactory#getSyncConfig()
* @param mapperModel
* @param federationProvider
* @param session
* @param realm
*/
UserFederationSyncResult syncDataFromFederationProviderToKeycloak(UserFederationMapperModel mapperModel, UserFederationProvider federationProvider, KeycloakSession session, RealmModel realm);
/**
* Sync data from Keycloak back to federated storage
*
* @see UserFederationMapperFactory#getSyncConfig()
* @param mapperModel
* @param federationProvider
* @param session
* @param realm
*/
UserFederationSyncResult syncDataFromKeycloakToFederationProvider(UserFederationMapperModel mapperModel, UserFederationProvider federationProvider, KeycloakSession session, RealmModel realm);
/**
* Return empty list if doesn't support storing of groups
*/
List<UserModel> getGroupMembers(UserFederationMapperModel mapperModel, UserFederationProvider federationProvider, RealmModel realm, GroupModel group, int firstResult, int maxResults);
}

View file

@ -1,69 +0,0 @@
/*
* 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.mappers;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.provider.ConfiguredProvider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.representations.idm.UserFederationMapperSyncConfigRepresentation;
import java.util.Map;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface UserFederationMapperFactory extends ProviderFactory<UserFederationMapper>, ConfiguredProvider {
/**
* Refers to providerName (type) of the federated provider, which this mapper can be used for. For example "ldap" or "kerberos"
*
* @return providerName
*/
String getFederationProviderType();
String getDisplayCategory();
String getDisplayType();
/**
* Specifies if mapper supports sync data from federated storage to keycloak and viceversa.
* Also specifies messages to be displayed in admin console UI (For example "Sync roles from LDAP" etc)
*
* @return syncConfig representation
*/
UserFederationMapperSyncConfigRepresentation getSyncConfig();
/**
* Called when instance of mapperModel is created for this factory through admin endpoint
*
* @param realm
* @param fedProviderModel
* @param mapperModel
* @throws FederationConfigValidationException if configuration provided in mapperModel is not valid
*/
void validateConfig(RealmModel realm, UserFederationProviderModel fedProviderModel, UserFederationMapperModel mapperModel) throws FederationConfigValidationException;
/**
* Used to detect what are default values for ProviderConfigProperties specified during mapper creation
*
* @return
*/
Map<String, String> getDefaultConfig(UserFederationProviderModel providerModel);
}

View file

@ -1,48 +0,0 @@
/*
* 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.mappers;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class UserFederationMapperSpi implements Spi {
@Override
public String getName() {
return "userFederationMapper";
}
@Override
public Class<? extends Provider> getProviderClass() {
return UserFederationMapper.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return UserFederationMapperFactory.class;
}
@Override
public boolean isInternal() {
return true;
}
}

View file

@ -1,50 +0,0 @@
/*
* 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.models;
import org.keycloak.provider.ProviderEvent;
import org.keycloak.provider.ProviderEventListener;
/**
* Provides "onProviderModelCreated" callback invoked when UserFederationProviderModel for this factory implementation is created in realm
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public abstract class UserFederationEventAwareProviderFactory implements UserFederationProviderFactory {
@Override
public void postInit(KeycloakSessionFactory factory) {
factory.register(new ProviderEventListener() {
@Override
public void onEvent(ProviderEvent event) {
if (event instanceof RealmModel.UserFederationProviderCreationEvent) {
RealmModel.UserFederationProviderCreationEvent fedCreationEvent = (RealmModel.UserFederationProviderCreationEvent)event;
UserFederationProviderModel providerModel = fedCreationEvent.getCreatedFederationProvider();
if (providerModel.getProviderName().equals(getId())) {
onProviderModelCreated(fedCreationEvent.getRealm(), providerModel);
}
}
}
});
}
public abstract void onProviderModelCreated(RealmModel realm, UserFederationProviderModel createdProviderModel);
}

View file

@ -1,42 +0,0 @@
/*
* 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.models;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class UserFederationProviderCreationEventImpl implements RealmModel.UserFederationProviderCreationEvent {
private final UserFederationProviderModel createdFederationProvider;
private final RealmModel realm;
public UserFederationProviderCreationEventImpl(RealmModel realm, UserFederationProviderModel createdFederationProvider) {
this.realm = realm;
this.createdFederationProvider = createdFederationProvider;
}
@Override
public UserFederationProviderModel getCreatedFederationProvider() {
return createdFederationProvider;
}
@Override
public RealmModel getRealm() {
return realm;
}
}

View file

@ -1,49 +0,0 @@
/*
* 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.models;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class UserFederationSpi implements Spi {
@Override
public boolean isInternal() {
return true;
}
@Override
public String getName() {
return "userFederation";
}
@Override
public Class<? extends Provider> getProviderClass() {
return UserFederationProvider.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return UserFederationProviderFactory.class;
}
}

View file

@ -1,37 +0,0 @@
/*
* 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.models;
import org.keycloak.mappers.FederationConfigValidationException;
/**
* TODO: Merge with UserFederationProviderFactory and add "default" method validateConfig with empty body once we move to source level 1.8
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface UserFederationValidatingProviderFactory extends UserFederationProviderFactory {
/**
* Called when instance of mapperModel is created for this factory through admin endpoint
*
* @param realm
* @param providerModel
* @throws FederationConfigValidationException if configuration provided in mapperModel is not valid
*/
void validateConfig(RealmModel realm, UserFederationProviderModel providerModel) throws FederationConfigValidationException;
}

View file

@ -22,11 +22,8 @@ import org.keycloak.broker.social.SocialIdentityProviderFactory;
import org.keycloak.common.util.Base64Url;
import org.keycloak.common.util.CertificateUtils;
import org.keycloak.common.util.KeyUtils;
import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.common.util.PemUtils;
import org.keycloak.component.ComponentFactory;
import org.keycloak.component.ComponentModel;
import org.keycloak.keys.KeyProvider;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.AuthenticationFlowModel;
import org.keycloak.models.ClientModel;
@ -38,19 +35,12 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.KeycloakSessionTask;
import org.keycloak.models.KeycloakTransaction;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.ScopeContainerModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderFactory;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.representations.idm.CertificateRepresentation;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.transaction.JtaTransactionManagerLookup;
@ -61,20 +51,15 @@ import javax.transaction.SystemException;
import javax.transaction.Transaction;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.StreamSupport;
/**
* Set of helper methods, which are useful in various model implementations.
@ -259,29 +244,6 @@ public final class KeycloakModelUtils {
// USER FEDERATION RELATED STUFF
/**
* Ensure that displayName of myProvider (if not null) is unique and there is no other provider with same displayName in the list.
*
* @param displayName to check for duplications
* @param myProvider provider, which is excluded from the list (if present)
* @param federationProviders
* @throws ModelDuplicateException if there is other provider with same displayName
*/
public static void ensureUniqueDisplayName(String displayName, UserFederationProviderModel myProvider, List<UserFederationProviderModel> federationProviders) throws ModelDuplicateException {
if (displayName != null) {
for (UserFederationProviderModel federationProvider : federationProviders) {
if (myProvider != null && (myProvider.equals(federationProvider) || (myProvider.getId() != null && myProvider.getId().equals(federationProvider.getId())))) {
continue;
}
if (displayName.equals(federationProvider.getDisplayName())) {
throw new ModelDuplicateException("There is already existing federation provider with display name: " + displayName);
}
}
}
}
public static UserStorageProviderModel findUserStorageProviderByName(String displayName, RealmModel realm) {
if (displayName == null) {
@ -329,41 +291,6 @@ public final class KeycloakModelUtils {
}
public static UserFederationMapperModel createUserFederationMapperModel(String name, String federationProviderId, String mapperType, String... config) {
UserFederationMapperModel mapperModel = new UserFederationMapperModel();
mapperModel.setName(name);
mapperModel.setFederationProviderId(federationProviderId);
mapperModel.setFederationMapperType(mapperType);
Map<String, String> configMap = new HashMap<>();
String key = null;
for (String configEntry : config) {
if (key == null) {
key = configEntry;
} else {
configMap.put(key, configEntry);
key = null;
}
}
if (key != null) {
throw new IllegalStateException("Invalid count of arguments for config. Maybe mistake?");
}
mapperModel.setConfig(configMap);
return mapperModel;
}
public static UserFederationProviderFactory getFederationProviderFactory(KeycloakSession session, UserFederationProviderModel model) {
return (UserFederationProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(UserFederationProvider.class, model.getProviderName());
}
public static UserFederationProvider getFederationProviderInstance(KeycloakSession session, UserFederationProviderModel model) {
UserFederationProviderFactory factory = getFederationProviderFactory(session, model);
return factory.getInstance(session, model);
}
// END USER FEDERATION RELATED STUFF
public static String toLowerCaseSafe(String str) {

View file

@ -52,8 +52,6 @@ import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.provider.ProviderConfigProperty;
@ -78,8 +76,6 @@ import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RequiredActionProviderRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserConsentRepresentation;
import org.keycloak.representations.idm.UserFederationMapperRepresentation;
import org.keycloak.representations.idm.UserFederationProviderRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.representations.idm.UserSessionRepresentation;
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
@ -574,19 +570,6 @@ public class ModelToRepresentation {
return rep;
}
public static UserFederationProviderRepresentation toRepresentation(UserFederationProviderModel model) {
UserFederationProviderRepresentation rep = new UserFederationProviderRepresentation();
rep.setId(model.getId());
rep.setConfig(model.getConfig());
rep.setProviderName(model.getProviderName());
rep.setPriority(model.getPriority());
rep.setDisplayName(model.getDisplayName());
rep.setFullSyncPeriod(model.getFullSyncPeriod());
rep.setChangedSyncPeriod(model.getChangedSyncPeriod());
rep.setLastSync(model.getLastSync());
return rep;
}
public static IdentityProviderRepresentation toRepresentation(RealmModel realm, IdentityProviderModel identityProviderModel) {
IdentityProviderRepresentation providerRep = new IdentityProviderRepresentation();

View file

@ -62,8 +62,6 @@ import org.keycloak.models.RoleModel;
import org.keycloak.models.ScopeContainerModel;
import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.idm.ApplicationRepresentation;
@ -113,7 +111,6 @@ import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -367,11 +364,9 @@ public class RepresentationToModel {
mapperConvertSet.put(LDAPConstants.LDAP_PROVIDER, "org.keycloak.storage.ldap.mappers.LDAPStorageMapper");
List<UserFederationProviderModel> providerModels = null;
Map<String, ComponentModel> userStorageModels = new HashMap<>();
if (rep.getUserFederationProviders() != null) {
providerModels = new LinkedList<>();
for (UserFederationProviderRepresentation fedRep : rep.getUserFederationProviders()) {
if (convertSet.contains(fedRep.getProviderName())) {
ComponentModel component = convertFedProviderToComponent(newRealm.getId(), fedRep);
@ -869,22 +864,6 @@ public class RepresentationToModel {
// Basic realm stuff
private static List<UserFederationProviderModel> convertFederationProviders(List<UserFederationProviderRepresentation> providers) {
List<UserFederationProviderModel> result = new ArrayList<UserFederationProviderModel>();
for (UserFederationProviderRepresentation representation : providers) {
UserFederationProviderModel model = convertFederationProvider(representation);
result.add(model);
}
return result;
}
private static UserFederationProviderModel convertFederationProvider(UserFederationProviderRepresentation representation) {
return new UserFederationProviderModel(representation.getId(), representation.getProviderName(),
representation.getConfig(), representation.getPriority(), representation.getDisplayName(),
representation.getFullSyncPeriod(), representation.getChangedSyncPeriod(), representation.getLastSync());
}
public static ComponentModel convertFedProviderToComponent(String realmId, UserFederationProviderRepresentation fedModel) {
UserStorageProviderModel model = new UserStorageProviderModel();
model.setId(fedModel.getId());
@ -1368,7 +1347,7 @@ public class RepresentationToModel {
convertDeprecatedSocialProviders(userRep);
// Import users just to user storage. Don't federate
UserModel user = session.userStorage().addUser(newRealm, userRep.getId(), userRep.getUsername(), false, false);
UserModel user = session.userLocalStorage().addUser(newRealm, userRep.getId(), userRep.getUsername(), false, false);
user.setEnabled(userRep.isEnabled() != null && userRep.isEnabled());
user.setCreatedTimestamp(userRep.getCreatedTimestamp());
user.setEmail(userRep.getEmail());
@ -1400,7 +1379,7 @@ public class RepresentationToModel {
if (userRep.getClientConsents() != null) {
for (UserConsentRepresentation consentRep : userRep.getClientConsents()) {
UserConsentModel consentModel = toModel(newRealm, consentRep);
session.userStorage().addConsent(newRealm, user.getId(), consentModel);
session.users().addConsent(newRealm, user.getId(), consentModel);
}
}
if (userRep.getServiceAccountClientId() != null) {

View file

@ -15,10 +15,8 @@
# limitations under the License.
#
org.keycloak.models.UserFederationSpi
org.keycloak.storage.UserStorageProviderSpi
org.keycloak.storage.federated.UserFederatedStorageProviderSpi
org.keycloak.mappers.UserFederationMapperSpi
org.keycloak.models.RealmSpi
org.keycloak.models.UserSessionSpi
org.keycloak.models.UserSpi

View file

@ -110,10 +110,10 @@ public interface KeycloakSession {
*
* @return may be null if cache is disabled
*/
UserCache getUserCache();
UserCache userCache();
/**
* A cached view of all users in system including deprecated UserFederationProvider SPI
* A cached view of all users in system including users loaded by UserStorageProviders
*
* @return
*/
@ -121,18 +121,18 @@ public interface KeycloakSession {
/**
* Un-cached view of all users in system that does NOT include users available from the deprecated UserFederationProvider SPI.
* Un-cached view of all users in system including users loaded by UserStorageProviders
*
* @return
*/
UserProvider userStorageManager();
UserCredentialManager userCredentialManager();
/**
* A cached view of all users in system that does NOT include users available from the deprecated UserFederationProvider SPI.
* Service that allows you to valid and update credentials for a user
*
* @return
*/
UserProvider userStorage();
UserCredentialManager userCredentialManager();
/**
* Keycloak specific local storage for users. No cache in front, this api talks directly to database configured for Keycloak

View file

@ -67,11 +67,6 @@ public interface RealmModel extends RoleContainerModel {
KeycloakSession getKeycloakSession();
}
interface UserFederationProviderCreationEvent extends ProviderEvent {
UserFederationProviderModel getCreatedFederationProvider();
RealmModel getRealm();
}
String getId();
String getName();

View file

@ -1,314 +0,0 @@
/*
* 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.models;
import org.jboss.logging.Logger;
import org.keycloak.component.ComponentModel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UserFederationManager implements UserProvider {
private static final Logger logger = Logger.getLogger(UserFederationManager.class);
protected KeycloakSession session;
// Set of already validated/proxied federation users during this session. Key is user ID
private Map<String, UserModel> managedUsers = new HashMap<>();
public UserFederationManager(KeycloakSession session) {
this.session = session;
}
@Override
public UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions) {
UserModel user = session.userStorage().addUser(realm, id, username.toLowerCase(), addDefaultRoles, addDefaultRequiredActions);
return user;
}
@Override
public UserModel addUser(RealmModel realm, String username) {
UserModel user = session.userStorage().addUser(realm, username.toLowerCase());
return user;
}
@Override
public boolean removeUser(RealmModel realm, UserModel user) {
return session.userStorage().removeUser(realm, user);
}
@Override
public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel socialLink) {
session.userStorage().addFederatedIdentity(realm, user, socialLink);
}
public void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel) {
session.userStorage().updateFederatedIdentity(realm, federatedUser, federatedIdentityModel);
}
@Override
public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider) {
if (user == null) throw new IllegalStateException("Federated user no longer valid");
return session.userStorage().removeFederatedIdentity(realm, user, socialProvider);
}
@Override
public void addConsent(RealmModel realm, String userId, UserConsentModel consent) {
session.userStorage().addConsent(realm, userId, consent);
}
@Override
public UserConsentModel getConsentByClient(RealmModel realm, String userId, String clientInternalId) {
return session.userStorage().getConsentByClient(realm, userId, clientInternalId);
}
@Override
public List<UserConsentModel> getConsents(RealmModel realm, String userId) {
return session.userStorage().getConsents(realm, userId);
}
@Override
public void updateConsent(RealmModel realm, String userId, UserConsentModel consent) {
session.userStorage().updateConsent(realm, userId, consent);
}
@Override
public boolean revokeConsentForClient(RealmModel realm, String userId, String clientInternalId) {
return session.userStorage().revokeConsentForClient(realm, userId, clientInternalId);
}
@Override
public UserModel getUserById(String id, RealmModel realm) {
UserModel user = session.userStorage().getUserById(id, realm);
return user;
}
@Override
public List<UserModel> getGroupMembers(RealmModel realm, final GroupModel group, int firstResult, int maxResults) {
// Not very effective. For the page X, it is loading also all previous pages 0..X-1 . Improve if needed...
int maxTotal = firstResult + maxResults;
List<UserModel> localMembers = query(new PaginatedQuery() {
@Override
public List<UserModel> query(RealmModel realm, int first, int max) {
return session.userStorage().getGroupMembers(realm, group, first, max);
}
}, realm, 0, maxTotal);
Set<UserModel> result = new LinkedHashSet<>(localMembers);
if (result.size() <= firstResult) {
return Collections.emptyList();
}
int max = Math.min(maxTotal, result.size());
return new ArrayList<>(result).subList(firstResult, max);
}
@Override
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group) {
return getGroupMembers(realm, group, -1, -1);
}
@Override
public UserModel getUserByUsername(String username, RealmModel realm) {
UserModel user = session.userStorage().getUserByUsername(username.toLowerCase(), realm);
return user;
}
@Override
public UserModel getUserByEmail(String email, RealmModel realm) {
UserModel user = session.userStorage().getUserByEmail(email.toLowerCase(), realm);
return user;
}
@Override
public UserModel getUserByFederatedIdentity(FederatedIdentityModel socialLink, RealmModel realm) {
UserModel user = session.userStorage().getUserByFederatedIdentity(socialLink, realm);
return user;
}
@Override
public UserModel getServiceAccount(ClientModel client) {
UserModel user = session.userStorage().getServiceAccount(client);
return user;
}
@Override
public List<UserModel> getUsers(RealmModel realm, boolean includeServiceAccounts) {
return getUsers(realm, 0, Integer.MAX_VALUE - 1, includeServiceAccounts);
}
@Override
public List<UserModel> getUsers(RealmModel realm) {
return getUsers(realm, false);
}
@Override
public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
return getUsers(realm, firstResult, maxResults, false);
}
@Override
public int getUsersCount(RealmModel realm) {
return session.userStorage().getUsersCount(realm);
}
interface PaginatedQuery {
List<UserModel> query(RealmModel realm, int first, int max);
}
protected List<UserModel> query(PaginatedQuery pagedQuery, RealmModel realm, int firstResult, int maxResults) {
List<UserModel> results = new LinkedList<UserModel>();
if (maxResults == 0) return results;
int first = firstResult;
int max = maxResults;
do {
List<UserModel> query = pagedQuery.query(realm, first, max);
if (query == null || query.size() == 0) return results;
int added = 0;
for (UserModel user : query) {
results.add(user);
added++;
}
if (results.size() == maxResults) return results;
if (query.size() < max) return results;
first = query.size();
max -= added;
if (max <= 0) return results;
} while (true);
}
@Override
public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults, final boolean includeServiceAccounts) {
return query(new PaginatedQuery() {
@Override
public List<UserModel> query(RealmModel realm, int first, int max) {
return session.userStorage().getUsers(realm, first, max, includeServiceAccounts);
}
}, realm, firstResult, maxResults);
}
@Override
public List<UserModel> searchForUser(String search, RealmModel realm) {
return searchForUser(search, realm, 0, Integer.MAX_VALUE - 1);
}
@Override
public List<UserModel> searchForUser(final String search, RealmModel realm, int firstResult, int maxResults) {
return query(new PaginatedQuery() {
@Override
public List<UserModel> query(RealmModel realm, int first, int max) {
return session.userStorage().searchForUser(search, realm, first, max);
}
}, realm, firstResult, maxResults);
}
@Override
public List<UserModel> searchForUser(Map<String, String> attributes, RealmModel realm) {
return searchForUser(attributes, realm, 0, Integer.MAX_VALUE - 1);
}
@Override
public List<UserModel> searchForUser(final Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
return query(new PaginatedQuery() {
@Override
public List<UserModel> query(RealmModel realm, int first, int max) {
return session.userStorage().searchForUser(attributes, realm, first, max);
}
}, realm, firstResult, maxResults);
}
@Override
public List<UserModel> searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm) {
return session.userStorage().searchForUserByUserAttribute(attrName, attrValue, realm);
}
@Override
public Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) {
return session.userStorage().getFederatedIdentities(user, realm);
}
@Override
public FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm) {
return session.userStorage().getFederatedIdentity(user, socialProvider, realm);
}
@Override
public void grantToAllUsers(RealmModel realm, RoleModel role) {
// not federation-aware for now
session.userStorage().grantToAllUsers(realm, role);
}
@Override
public void preRemove(RealmModel realm) {
session.userStorage().preRemove(realm);
}
@Override
public void preRemove(RealmModel realm, UserFederationProviderModel model) {
session.userStorage().preRemove(realm, model);
}
@Override
public void preRemove(RealmModel realm, GroupModel group) {
session.userStorage().preRemove(realm, group);
}
@Override
public void preRemove(RealmModel realm, RoleModel role) {
session.userStorage().preRemove(realm, role);
}
@Override
public void preRemove(RealmModel realm, ClientModel client) {
session.userStorage().preRemove(realm, client);
}
@Override
public void preRemove(ProtocolMapperModel protocolMapper) {
session.userStorage().preRemove(protocolMapper);
}
@Override
public void preRemove(RealmModel realm, ComponentModel component) {
session.userStorage().preRemove(realm, component);
}
@Override
public void close() {
}
}

View file

@ -1,103 +0,0 @@
/*
* 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.models;
import java.io.Serializable;
import java.util.Map;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class UserFederationMapperModel implements Serializable {
protected String id;
protected String name;
// Refers to DB ID of federation provider
protected String federationProviderId;
// Refers to ID of UserFederationMapper implementation ( UserFederationMapperFactory.getId )
protected String federationMapperType;
protected Map<String, String> config;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFederationProviderId() {
return federationProviderId;
}
public void setFederationProviderId(String federationProviderId) {
this.federationProviderId = federationProviderId;
}
public String getFederationMapperType() {
return federationMapperType;
}
public void setFederationMapperType(String federationMapperType) {
this.federationMapperType = federationMapperType;
}
public Map<String, String> getConfig() {
return config;
}
public void setConfig(Map<String, String> config) {
this.config = config;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserFederationMapperModel that = (UserFederationMapperModel) o;
if (!id.equals(that.id)) return false;
return true;
}
@Override
public int hashCode() {
return id.hashCode();
}
@Override
public String toString() {
return new StringBuilder(" { name=" + name)
.append(", federationMapperType=" + federationMapperType)
.append(", config=" + config)
.append(" } ").toString();
}
}

View file

@ -1,196 +0,0 @@
/*
* 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.models;
import org.keycloak.credential.CredentialInputUpdater;
import org.keycloak.credential.CredentialInputValidator;
import org.keycloak.provider.Provider;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* SPI for plugging in federation storage. This class is instantiated once per session/request and is closed after
* the session/request is finished.
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Deprecated
public interface UserFederationProvider extends Provider, CredentialInputValidator, CredentialInputUpdater {
public static final String USERNAME = UserModel.USERNAME;
public static final String EMAIL = UserModel.EMAIL;
public static final String FIRST_NAME = UserModel.FIRST_NAME;
public static final String LAST_NAME = UserModel.LAST_NAME;
/**
* Optional type that can be by implementations to describe edit mode of federation storage
*
*/
enum EditMode {
/**
* federation storage is read-only
*/
READ_ONLY,
/**
* federation storage is writable
*
*/
WRITABLE,
/**
* updates to user are stored locally and not synced with federation storage.
*
*/
UNSYNCED
}
/**
* Gives the provider an option to validate if user still exists in federation backend and then proxy UserModel loaded from local storage.
* This method is called whenever a UserModel is pulled from Keycloak local storage.
* For example, the LDAP provider proxies the UserModel and does on-demand synchronization with
* LDAP whenever UserModel update methods are invoked. It also overrides UserModel.updateCredential for the
* credential types it supports
*
* @param realm
* @param local
* @return null if user is no longer valid or proxy object otherwise
*/
UserModel validateAndProxy(RealmModel realm, UserModel local);
/**
* Should user registrations be synchronized with this provider?
* FYI, only one provider will be chosen (by priority) to have this synchronization
*
* @return
*/
boolean synchronizeRegistrations();
/**
* Called if this federation provider has priority and supports synchronized registrations.
*
* @param realm
* @param user
* @return
*/
UserModel register(RealmModel realm, UserModel user);
boolean removeUser(RealmModel realm, UserModel user);
/**
* Keycloak will search for user in local storage first. If it can't find the UserModel is local storage,
* it will call this method. You are required to import the returned UserModel into local storage.
*
* @param realm
* @param username
* @return
*/
UserModel getUserByUsername(RealmModel realm, String username);
/**
* Keycloak will search for user in local storage first. If it can't find the UserModel is local storage,
* it will call this method. You are required to import the returned UserModel into local storage.
*
* @param realm
* @param email
* @return
*/
UserModel getUserByEmail(RealmModel realm, String email);
/**
* Keycloak does not search in local storage first before calling this method. The implementation must check
* to see if user is already in local storage (KeycloakSession.userStorage()) before doing an import.
* Currently only attributes USERNAME, EMAIL, FIRST_NAME and LAST_NAME will be used.
*
* @param attributes
* @param realm
* @return
*/
List<UserModel> searchByAttributes(Map<String, String> attributes, RealmModel realm, int maxResults);
/**
* Return group members from federation storage. Useful if info about group memberships is stored in the federation storage.
* Return empty list if your federation provider doesn't support storing user-group memberships
*
* @param realm
* @param group
* @param firstResult
* @param maxResults
* @return
*/
List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults);
/**
* called whenever a Realm is removed
*
* @param realm
*/
void preRemove(RealmModel realm);
/**
* called before a role is removed.
*
* @param realm
* @param role
*/
void preRemove(RealmModel realm, RoleModel role);
/**
* called before a role is removed.
*
* @param realm
* @param group
*/
void preRemove(RealmModel realm, GroupModel group);
/**
* Is the Keycloak UserModel still valid and/or existing in federated storage? Keycloak may call this method
* in various user operations. The local storage may be deleted if this method returns false.
*
* @param realm
* @param local
* @return
*/
boolean isValid(RealmModel realm, UserModel local);
/**
* What UserCredentialModel types should be handled by this provider? This is called in scenarios when we don't know user,
* who is going to authenticate (For example Kerberos authentication).
*
* @return
*/
Set<String> getSupportedCredentialTypes();
/**
* Validate credentials of unknown user. The authenticated user is recognized based on provided credentials and returned back in CredentialValidationOutput
* @param realm
* @param credential
* @return
*/
CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel credential);
/**
* This method is called at the end of requests.
*
*/
void close();
}

View file

@ -1,84 +0,0 @@
/*
* 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.models;
import org.keycloak.provider.ProviderFactory;
import java.util.Date;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface UserFederationProviderFactory extends ProviderFactory<UserFederationProvider> {
/**
* called per Keycloak transaction.
*
* @param session
* @param model
* @return
*/
UserFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model);
/**
* Config options to display in generic admin console page for federation
*
* @return
*/
Set<String> getConfigurationOptions();
/**
* This is the name of the provider and will be showed in the admin console as an option.
*
* @return
*/
@Override
String getId();
/**
* Sync all users from the provider storage to Keycloak storage. Alternatively can update existing users or remove keycloak users, which are no longer
* available in federation storage (depends on the implementation)
*
* @param sessionFactory
* @param realmId
* @param model
* @return result with count of added/updated/removed users
*/
UserFederationSyncResult syncAllUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model);
/**
* Sync just changed (added / updated / removed) users from the provider storage to Keycloak storage. This is useful in case
* that your storage supports "changelogs" (Tracking what users changed since specified date). It's implementation specific to
* decide what exactly will be changed
*
* @param sessionFactory
* @param realmId
* @param model
* @param lastSync
*/
UserFederationSyncResult syncChangedUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model, Date lastSync);
/**
* This method is never called and is only an artifact of ProviderFactory. Returning null with no implementation is recommended.
* @param session
* @return
*/
@Override
UserFederationProvider create(KeycloakSession session);
}

View file

@ -1,119 +0,0 @@
/*
* 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.models;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* Stored configuration of a User Federation provider instance.
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
* @author <a href="mailto:bburke@redhat.com">Bill Burke</a>
*/
public class UserFederationProviderModel implements Serializable {
private String id;
private String providerName;
private Map<String, String> config = new HashMap<String, String>();
private int priority;
private String displayName;
private int fullSyncPeriod = -1; // In seconds. -1 means that periodic full sync is disabled
private int changedSyncPeriod = -1; // In seconds. -1 means that periodic changed sync is disabled
private int lastSync; // Date when last sync was done for this provider
public UserFederationProviderModel() {}
public UserFederationProviderModel(String id, String providerName, Map<String, String> config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync) {
this.id = id;
this.providerName = providerName;
if (config != null) {
this.config.putAll(config);
}
this.priority = priority;
this.displayName = displayName;
this.fullSyncPeriod = fullSyncPeriod;
this.changedSyncPeriod = changedSyncPeriod;
this.lastSync = lastSync;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getProviderName() {
return providerName;
}
public void setProviderName(String providerName) {
this.providerName = providerName;
}
public Map<String, String> getConfig() {
return config;
}
public void setConfig(Map<String, String> config) {
this.config = config;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public int getFullSyncPeriod() {
return fullSyncPeriod;
}
public void setFullSyncPeriod(int fullSyncPeriod) {
this.fullSyncPeriod = fullSyncPeriod;
}
public int getChangedSyncPeriod() {
return changedSyncPeriod;
}
public void setChangedSyncPeriod(int changedSyncPeriod) {
this.changedSyncPeriod = changedSyncPeriod;
}
public int getLastSync() {
return lastSync;
}
public void setLastSync(int lastSync) {
this.lastSync = lastSync;
}
}

View file

@ -1,124 +0,0 @@
/*
* 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.models;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class UserFederationSyncResult {
private boolean ignored;
private int added;
private int updated;
private int removed;
private int failed;
public boolean isIgnored() {
return ignored;
}
public void setIgnored(boolean ignored) {
this.ignored = ignored;
}
public int getAdded() {
return added;
}
public void setAdded(int added) {
this.added = added;
}
public int getUpdated() {
return updated;
}
public void setUpdated(int updated) {
this.updated = updated;
}
public int getRemoved() {
return removed;
}
public void setRemoved(int removed) {
this.removed = removed;
}
public int getFailed() {
return failed;
}
public void setFailed(int failed) {
this.failed = failed;
}
public void increaseAdded() {
added++;
}
public void increaseUpdated() {
updated++;
}
public void increaseRemoved() {
removed++;
}
public void increaseFailed() {
failed++;
}
public void add(UserFederationSyncResult other) {
added += other.added;
updated += other.updated;
removed += other.removed;
failed += other.failed;
}
public String getStatus() {
if (ignored) {
return "Synchronization ignored as it's already in progress";
} else {
String status = String.format("%d imported users, %d updated users", added, updated);
if (removed > 0) {
status += String.format(", %d removed users", removed);
}
if (failed != 0) {
status += String.format(", %d users failed sync! See server log for more details", failed);
}
return status;
}
}
@Override
public String toString() {
return String.format("UserFederationSyncResult [ %s ]", getStatus());
}
public static UserFederationSyncResult empty() {
return new UserFederationSyncResult();
}
public static UserFederationSyncResult ignored() {
UserFederationSyncResult result = new UserFederationSyncResult();
result.setIgnored(true);
return result;
}
}

View file

@ -67,8 +67,6 @@ public interface UserProvider extends Provider,
UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions);
void preRemove(RealmModel realm);
void preRemove(RealmModel realm, UserFederationProviderModel link);
void preRemove(RealmModel realm, RoleModel role);
void preRemove(RealmModel realm, GroupModel group);

View file

@ -14,27 +14,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.examples.federation.properties;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.UserModelDelegate;
package org.keycloak.storage;
/**
* Readonly proxy for a UserModel that prevents passwords from being updated.
* Thrown when UserStorageProvider UserModel adapter is read-only
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ReadonlyUserModelProxy extends UserModelDelegate {
public ReadonlyUserModelProxy(UserModel delegate) {
super(delegate);
public class ReadOnlyException extends RuntimeException {
public ReadOnlyException(String message) {
super(message);
}
@Override
public void setUsername(String username) {
throw new IllegalStateException("Username is readonly");
}
}

View file

@ -27,6 +27,7 @@ import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.DefaultRoles;
import org.keycloak.models.utils.RoleUtils;
import org.keycloak.storage.ReadOnlyException;
import org.keycloak.storage.StorageId;
import java.util.Collections;
@ -49,11 +50,6 @@ import java.util.Set;
* @version $Revision: 1 $
*/
public abstract class AbstractUserAdapter implements UserModel {
public static class ReadOnlyException extends RuntimeException {
public ReadOnlyException(String message) {
super(message);
}
}
protected KeycloakSession session;
protected RealmModel realm;
protected ComponentModel storageProviderModel;

View file

@ -23,7 +23,6 @@ import org.keycloak.models.GroupModel;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.Provider;
@ -47,8 +46,6 @@ public interface UserFederatedStorageProvider extends Provider,
void preRemove(RealmModel realm);
void preRemove(RealmModel realm, UserFederationProviderModel link);
void preRemove(RealmModel realm, GroupModel group);
void preRemove(RealmModel realm, RoleModel role);

View file

@ -30,7 +30,6 @@ import org.keycloak.models.ClientModel;
import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationManager;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserProvider;
import org.keycloak.representations.idm.authorization.ResourceOwnerRepresentation;

View file

@ -102,7 +102,7 @@ public class OTPCredentialProvider implements CredentialProvider, CredentialInpu
} else {
getCredentialStore().updateCredential(realm, user, model);
}
session.getUserCache().evict(realm, user);
session.userCache().evict(realm, user);
return true;
@ -138,7 +138,7 @@ public class OTPCredentialProvider implements CredentialProvider, CredentialInpu
}
if (disableTOTP || disableHOTP) {
session.getUserCache().evict(realm, user);
session.userCache().evict(realm, user);
}
}

View file

@ -27,7 +27,6 @@ import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.cache.CachedUserModel;
import org.keycloak.models.cache.OnUserCache;
import org.keycloak.policy.HashAlgorithmPasswordPolicyProviderFactory;
import org.keycloak.policy.PasswordPolicyManagerProvider;
import org.keycloak.policy.PolicyError;
@ -99,7 +98,7 @@ public class PasswordCredentialProvider implements CredentialProvider, Credentia
newPassword.setCreatedDate(createdDate);
hash.encode(cred.getValue(), policy, newPassword);
getCredentialStore().createCredential(realm, user, newPassword);
session.getUserCache().evict(realm, user);
session.userCache().evict(realm, user);
return true;
}
@ -213,7 +212,7 @@ public class PasswordCredentialProvider implements CredentialProvider, Credentia
hash.encode(cred.getValue(), policy, password);
getCredentialStore().updateCredential(realm, user, password);
session.getUserCache().evict(realm, user);
session.userCache().evict(realm, user);
return true;
}

View file

@ -21,19 +21,14 @@ import org.keycloak.models.CredentialValidationOutput;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserCredentialManager;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.cache.CachedUserModel;
import org.keycloak.models.cache.OnUserCache;
import org.keycloak.models.utils.CredentialValidation;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.storage.StorageId;
import org.keycloak.storage.UserStorageManager;
import org.keycloak.storage.UserStorageProvider;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;

View file

@ -44,7 +44,6 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserFederationManager;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserProvider;
import org.keycloak.models.utils.ModelToRepresentation;

View file

@ -27,14 +27,12 @@ import org.keycloak.models.KeycloakTransactionManager;
import org.keycloak.models.KeyManager;
import org.keycloak.models.RealmProvider;
import org.keycloak.models.UserCredentialManager;
import org.keycloak.models.UserFederationManager;
import org.keycloak.models.UserProvider;
import org.keycloak.models.UserSessionProvider;
import org.keycloak.models.cache.CacheRealmProvider;
import org.keycloak.models.cache.UserCache;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.scripting.ScriptingProvider;
import org.keycloak.storage.UserStorageManager;
import org.keycloak.storage.federated.UserFederatedStorageProvider;
@ -60,7 +58,6 @@ public class DefaultKeycloakSession implements KeycloakSession {
private UserStorageManager userStorageManager;
private UserCredentialStoreManager userCredentialStorageManager;
private UserSessionProvider sessionProvider;
private UserFederationManager federationManager;
private UserFederatedStorageProvider userFederatedStorageProvider;
private KeycloakContext context;
private KeyManager keyManager;
@ -68,7 +65,6 @@ public class DefaultKeycloakSession implements KeycloakSession {
public DefaultKeycloakSession(DefaultKeycloakSessionFactory factory) {
this.factory = factory;
this.transactionManager = new DefaultKeycloakTransactionManager(this);
federationManager = new UserFederationManager(this);
context = new DefaultKeycloakContext(this);
}
@ -86,17 +82,8 @@ public class DefaultKeycloakSession implements KeycloakSession {
}
}
private UserProvider getUserProvider() {
UserCache cache = getProvider(UserCache.class);
if (cache != null) {
return cache;
} else {
return getProvider(UserProvider.class);
}
}
@Override
public UserCache getUserCache() {
public UserCache userCache() {
return getProvider(UserCache.class);
}
@ -151,17 +138,19 @@ public class DefaultKeycloakSession implements KeycloakSession {
}
@Override
public UserCredentialManager userCredentialManager() {
if (userCredentialStorageManager == null) userCredentialStorageManager = new UserCredentialStoreManager(this);
return userCredentialStorageManager;
public UserProvider users() {
UserCache cache = getProvider(UserCache.class);
if (cache != null) {
return cache;
} else {
return userStorageManager();
}
}
@Override
public UserProvider userStorage() {
if (userModel == null) {
userModel = getUserProvider();
}
return userModel;
public UserCredentialManager userCredentialManager() {
if (userCredentialStorageManager == null) userCredentialStorageManager = new UserCredentialStoreManager(this);
return userCredentialStorageManager;
}
public <T extends Provider> T getProvider(Class<T> clazz) {
@ -239,11 +228,6 @@ public class DefaultKeycloakSession implements KeycloakSession {
return model;
}
@Override
public UserFederationManager users() {
return federationManager;
}
@Override
public UserSessionProvider sessions() {
if (sessionProvider == null) {

View file

@ -156,7 +156,7 @@ public class ClientManager {
logger.debugf("Creating service account user '%s'", username);
// Don't use federation for service account user
UserModel user = realmManager.getSession().userStorage().addUser(client.getRealm(), username);
UserModel user = realmManager.getSession().userLocalStorage().addUser(client.getRealm(), username);
user.setEnabled(true);
user.setEmail(username + "@placeholder.org");
user.setServiceAccountClientLink(client.getId());

View file

@ -31,7 +31,6 @@ import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RealmProvider;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionProvider;
import org.keycloak.models.session.UserSessionPersisterProvider;

View file

@ -21,7 +21,6 @@ import org.jboss.logging.Logger;
import org.keycloak.common.util.reflections.Types;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.CredentialValidationOutput;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
@ -31,16 +30,12 @@ import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserManager;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserProvider;
import org.keycloak.models.cache.CachedUserModel;
import org.keycloak.models.cache.OnUserCache;
import org.keycloak.storage.federated.UserFederatedStorageProvider;
import org.keycloak.credential.CredentialAuthentication;
import org.keycloak.storage.user.ImportSynchronization;
import org.keycloak.storage.user.ImportedUserValidation;
import org.keycloak.storage.user.UserLookupProvider;
import org.keycloak.storage.user.UserQueryProvider;
@ -248,7 +243,7 @@ public class UserStorageManager implements UserProvider, OnUserCache {
if (user == null || user.getFederationLink() == null) return user;
UserStorageProvider provider = getStorageProvider(session, realm, user.getFederationLink());
if (provider != null && provider instanceof ImportedUserValidation) {
UserModel validated = ((ImportedUserValidation)provider).validate(realm, user);
UserModel validated = ((ImportedUserValidation) provider).validate(realm, user);
if (validated == null) {
deleteInvalidUser(realm, user);
return null;
@ -256,6 +251,11 @@ public class UserStorageManager implements UserProvider, OnUserCache {
return validated;
}
} else if (provider == null) {
// remove linked user with unknown storage provider.
logger.debugf("Removed user with federation link of unknown storage provider '%s'", user.getUsername());
deleteInvalidUser(realm, user);
return null;
} else {
return user;
}
@ -265,7 +265,7 @@ public class UserStorageManager implements UserProvider, OnUserCache {
protected void deleteInvalidUser(final RealmModel realm, final UserModel user) {
String userId = user.getId();
String userName = user.getUsername();
session.getUserCache().evict(realm, user);
session.userCache().evict(realm, user);
runJobInTransaction(session.getKeycloakSessionFactory(), new KeycloakSessionTask() {
@Override
@ -321,11 +321,13 @@ public class UserStorageManager implements UserProvider, OnUserCache {
@Override
public UserModel getUserByEmail(String email, RealmModel realm) {
UserModel user = localStorage().getUserByEmail(email, realm);
if (user != null) return user;
if (user != null) {
return importValidation(realm, user);
}
for (UserLookupProvider provider : getStorageProviders(session, realm, UserLookupProvider.class)) {
user = provider.getUserByEmail(email, realm);
if (user != null) {
return importValidation(realm, user);
return user;
}
}
return null;
@ -562,12 +564,6 @@ public class UserStorageManager implements UserProvider, OnUserCache {
}
}
@Override
public void preRemove(RealmModel realm, UserFederationProviderModel model) {
if (getFederatedStorage() != null) getFederatedStorage().preRemove(realm, model);
localStorage().preRemove(realm, model);
}
@Override
public void preRemove(RealmModel realm, GroupModel group) {
localStorage().preRemove(realm, group);

View file

@ -19,24 +19,19 @@ package org.keycloak.testsuite.federation;
import org.keycloak.component.ComponentModel;
import org.keycloak.credential.CredentialInput;
import org.keycloak.credential.CredentialInputUpdater;
import org.keycloak.credential.CredentialInputValidator;
import org.keycloak.credential.CredentialModel;
import org.keycloak.models.CredentialValidationOutput;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserModel;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.user.UserLookupProvider;
import org.keycloak.storage.user.UserQueryProvider;
import org.keycloak.storage.user.UserRegistrationProvider;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

View file

@ -22,11 +22,6 @@ import org.keycloak.Config;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderFactory;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserFederationSyncResult;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.provider.ProviderConfigurationBuilder;
@ -37,10 +32,8 @@ import org.keycloak.storage.user.SynchronizationResult;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
/**

View file

@ -32,18 +32,13 @@ import org.keycloak.events.admin.AdminEventQuery;
import org.keycloak.events.admin.AuthDetails;
import org.keycloak.events.admin.OperationType;
import org.keycloak.events.admin.ResourceType;
import org.keycloak.keys.KeyProvider;
import org.keycloak.keys.KeyProviderFactory;
import org.keycloak.models.AuthenticationFlowModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RealmProvider;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderFactory;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserProvider;
import org.keycloak.models.UserSessionModel;
@ -54,7 +49,6 @@ import org.keycloak.representations.idm.AuthDetailsRepresentation;
import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
import org.keycloak.representations.idm.EventRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resource.RealmResourceProvider;
import org.keycloak.storage.UserStorageProvider;

View file

@ -22,7 +22,7 @@ import org.jboss.logging.Logger;
import org.keycloak.common.constants.GenericConstants;
import org.keycloak.common.constants.KerberosConstants;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.storage.UserStorageProvider;
import java.io.File;
import java.io.FileInputStream;
@ -83,7 +83,7 @@ public class LDAPTestConfiguration {
DEFAULT_VALUES.put(LDAPConstants.BATCH_SIZE_FOR_SYNC, String.valueOf(LDAPConstants.DEFAULT_BATCH_SIZE_FOR_SYNC));
DEFAULT_VALUES.put(LDAPConstants.USERNAME_LDAP_ATTRIBUTE, null);
DEFAULT_VALUES.put(LDAPConstants.USER_OBJECT_CLASSES, null);
DEFAULT_VALUES.put(LDAPConstants.EDIT_MODE, UserFederationProvider.EditMode.READ_ONLY.toString());
DEFAULT_VALUES.put(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.READ_ONLY.toString());
DEFAULT_VALUES.put(KerberosConstants.ALLOW_KERBEROS_AUTHENTICATION, "false");
DEFAULT_VALUES.put(KerberosConstants.KERBEROS_REALM, "KEYCLOAK.ORG");

View file

@ -1,373 +0,0 @@
/*
* 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.testsuite.adapter.federation;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.client.params.AuthPolicy;
import org.apache.http.impl.client.DefaultHttpClient;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.graphene.page.Page;
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.keycloak.adapters.HttpClientBuilder;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.common.constants.KerberosConstants;
import org.keycloak.events.Details;
import org.keycloak.federation.kerberos.CommonKerberosConfig;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserFederationProviderRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest;
import org.keycloak.testsuite.adapter.page.KerberosPortal;
import org.keycloak.testsuite.adapter.servlet.KerberosCredDelegServlet;
import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.auth.page.AuthRealm;
import org.keycloak.testsuite.auth.page.account.ChangePassword;
import org.keycloak.testsuite.util.LDAPTestConfiguration;
import org.keycloak.util.ldap.KerberosEmbeddedServer;
import org.keycloak.util.ldap.LDAPEmbeddedServer;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import java.security.Principal;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import static org.keycloak.testsuite.util.IOUtil.loadRealm;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public abstract class AbstractKerberosAdapterTest extends AbstractServletsAdapterTest {
protected static LDAPTestConfiguration ldapTestConfiguration;
protected KeycloakSPNegoSchemeFactory spnegoSchemeFactory;
protected ResteasyClient client;
protected static LDAPEmbeddedServer ldapEmbeddedServer;
@Rule
public AssertEvents events = new AssertEvents(this);
@Page
protected ChangePassword changePasswordPage;
@Page
protected KerberosPortal kerberosPortal;
protected abstract String getConnectionPropertiesLocation();
protected abstract CommonKerberosConfig getKerberosConfig(UserStorageProviderModel model);
@Deployment(name = KerberosPortal.DEPLOYMENT_NAME)
protected static WebArchive kerberosPortal() {
return servletDeployment(KerberosPortal.DEPLOYMENT_NAME, "keycloak.json", KerberosCredDelegServlet.class);
}
@Override
public void addAdapterTestRealms(List<RealmRepresentation> testRealms) {
testRealms.add(loadRealm("/adapter-test/kerberosrealm.json"));
}
@Before
public void before() throws Exception {
testRealmPage.setAuthRealm(AuthRealm.TEST);
changePasswordPage.setAuthRealm(testRealmPage);
// Global kerberos configuration
ldapTestConfiguration = LDAPTestConfiguration.readConfiguration(getConnectionPropertiesLocation());
String krb5ConfPath = LDAPTestConfiguration.getResource("test-krb5.conf");
log.info("Krb5.conf file location is: " + krb5ConfPath);
System.setProperty("java.security.krb5.conf", krb5ConfPath);
if (ldapTestConfiguration.isStartEmbeddedLdapServer() && ldapEmbeddedServer == null) {
ldapEmbeddedServer = createServer();
ldapEmbeddedServer.init();
ldapEmbeddedServer.start();
}
UserStorageProviderModel model = new UserStorageProviderModel();
model.setConfig(AbstractKerberosStandaloneAdapterTest.toComponentConfig(ldapTestConfiguration.getLDAPConfig()));
spnegoSchemeFactory = new KeycloakSPNegoSchemeFactory(getKerberosConfig(model));
initHttpClient(true);
removeAllUsers();
}
@After
public void after() {
client.close();
client = null;
}
@AfterClass
public static void afterClass() {
try {
if (ldapEmbeddedServer != null) {
ldapEmbeddedServer.stop();
ldapEmbeddedServer = null;
}
ldapTestConfiguration = null;
} catch (Exception e) {
throw new RuntimeException("Error tearDown Embedded LDAP server.", e);
}
}
@Test
public void spnegoNotAvailableTest() throws Exception {
initHttpClient(false);
String kcLoginPageLocation = client.target(kerberosPortal.getInjectedUrl().toString()).request().get().getLocation().toString();
Response response = client.target(kcLoginPageLocation).request().get();
Assert.assertEquals(401, response.getStatus());
Assert.assertEquals(KerberosConstants.NEGOTIATE, response.getHeaderString(HttpHeaders.WWW_AUTHENTICATE));
String responseText = response.readEntity(String.class);
responseText.contains("Log in to test");
response.close();
}
protected void spnegoLoginTestImpl() throws Exception {
Response spnegoResponse = spnegoLogin("hnelson", "secret");
Assert.assertEquals(302, spnegoResponse.getStatus());
List<UserRepresentation> users = testRealmResource().users().search("hnelson", 0, 1);
String userId = users.get(0).getId();
events.expectLogin()
.client("kerberos-app")
.user(userId)
.detail(Details.REDIRECT_URI, kerberosPortal.toString())
//.detail(Details.AUTH_METHOD, "spnego")
.detail(Details.USERNAME, "hnelson")
.assertEvent();
String location = spnegoResponse.getLocation().toString();
driver.navigate().to(location);
String pageSource = driver.getPageSource();
Assert.assertTrue(
pageSource.contains("Kerberos Test") && pageSource.contains("Kerberos servlet secured content"));
spnegoResponse.close();
events.clear();
}
// KEYCLOAK-2102
@Test
public void spnegoCaseInsensitiveTest() throws Exception {
Response spnegoResponse = spnegoLogin(ldapTestConfiguration.isCaseSensitiveLogin() ? "MyDuke" : "myduke", "theduke");
Assert.assertEquals(302, spnegoResponse.getStatus());
List<UserRepresentation> users = testRealmResource().users().search("myduke", 0, 1);
String userId = users.get(0).getId();
events.expectLogin()
.client("kerberos-app")
.user(userId)
.detail(Details.REDIRECT_URI, kerberosPortal.toString())
//.detail(Details.AUTH_METHOD, "spnego")
.detail(Details.USERNAME, "myduke")
.assertEvent();
String location = spnegoResponse.getLocation().toString();
driver.navigate().to(location);
String pageSource = driver.getPageSource();
Assert.assertTrue(
pageSource.contains("Kerberos Test") && pageSource.contains("Kerberos servlet secured content"));
spnegoResponse.close();
events.clear();
}
@Test
public void usernamePasswordLoginTest() throws Exception {
// Change editMode to READ_ONLY
updateProviderEditMode(UserFederationProvider.EditMode.READ_ONLY);
// Login with username/password from kerberos
changePasswordPage.navigateTo();
testRealmLoginPage.isCurrent();
testRealmLoginPage.form().login("jduke", "theduke");
changePasswordPage.isCurrent();
// Bad existing password
changePasswordPage.changePasswords("theduke-invalid", "newPass", "newPass");
Assert.assertTrue(driver.getPageSource().contains("Invalid existing password."));
// Change password is not possible as editMode is READ_ONLY
changePasswordPage.changePasswords("theduke", "newPass", "newPass");
Assert.assertTrue(
driver.getPageSource().contains("You can't update your password as your account is read only"));
// Change editMode to UNSYNCED
updateProviderEditMode(UserFederationProvider.EditMode.UNSYNCED);
// Successfully change password now
changePasswordPage.changePasswords("theduke", "newPass", "newPass");
Assert.assertTrue(driver.getPageSource().contains("Your password has been updated."));
changePasswordPage.logOut();
// Login with old password doesn't work, but with new password works
testRealmLoginPage.form().login("jduke", "theduke");
testRealmLoginPage.isCurrent();
testRealmLoginPage.form().login("jduke", "newPass");
changePasswordPage.isCurrent();
changePasswordPage.logOut();
// Assert SPNEGO login still with the old password as mode is unsynced
events.clear();
Response spnegoResponse = spnegoLogin("jduke", "theduke");
Assert.assertEquals(302, spnegoResponse.getStatus());
UserRepresentation user = ApiUtil.findUserByUsername(testRealmResource(), "jduke");
events.expectLogin()
.client("kerberos-app")
.user(user != null ? user.getId() : null)
.detail(Details.REDIRECT_URI, kerberosPortal.toString())
//.detail(Details.AUTH_METHOD, "spnego")
.detail(Details.USERNAME, "jduke")
.assertEvent();
spnegoResponse.close();
}
protected Response spnegoLogin(String username, String password) {
kerberosPortal.navigateTo();
Response res = client.target(kerberosPortal.getInjectedUrl().toString()).request().get();
String kcLoginPageLocation = res.getLocation().toString();
if (driver.manage().getCookieNamed("OAuth_Token_Request_State") != null) {
kcLoginPageLocation = res.getLocation().toString().replaceFirst("state=.*&", "state=" + driver.manage().getCookieNamed("OAuth_Token_Request_State").getValue() + "&");
}
// Request for SPNEGO login sent with Resteasy client
spnegoSchemeFactory.setCredentials(username, password);
Response response = client.target(kcLoginPageLocation).request().get();
if (response.getStatus() == 302) {
if (response.getLocation() == null)
return response;
String uri = response.getLocation().toString();
if (uri.contains("login-actions/required-action")) {
response = client.target(uri).request().get();
}
}
return response;
}
protected void initHttpClient(boolean useSpnego) {
if (client != null) {
after();
}
DefaultHttpClient httpClient = (DefaultHttpClient) new HttpClientBuilder().build();
httpClient.getAuthSchemes().register(AuthPolicy.SPNEGO, spnegoSchemeFactory);
if (useSpnego) {
Credentials fake = new Credentials() {
public String getPassword() {
return null;
}
public Principal getUserPrincipal() {
return null;
}
};
httpClient.getCredentialsProvider().setCredentials(
new AuthScope(null, -1, null),
fake);
}
ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient);
client = new ResteasyClientBuilder().httpEngine(engine).build();
}
protected void removeAllUsers() {
RealmResource realm = testRealmResource();
List<UserRepresentation> users = realm.users().search("", 0, Integer.MAX_VALUE);
for (UserRepresentation user : users) {
if (!user.getUsername().equals(AssertEvents.DEFAULT_USERNAME)) {
realm.users().get(user.getId()).remove();
}
}
Assert.assertEquals(1, realm.users().search("", 0, Integer.MAX_VALUE).size());
}
protected void assertUser(String expectedUsername, String expectedEmail, String expectedFirstname,
String expectedLastname, boolean updateProfileActionExpected) {
try {
UserRepresentation user = ApiUtil.findUserByUsername(testRealmResource(), expectedUsername);
Assert.assertNotNull(user);
Assert.assertEquals(expectedEmail, user.getEmail());
Assert.assertEquals(expectedFirstname, user.getFirstName());
Assert.assertEquals(expectedLastname, user.getLastName());
if (updateProfileActionExpected) {
Assert.assertEquals(UserModel.RequiredAction.UPDATE_PROFILE.toString(),
user.getRequiredActions().iterator().next());
} else {
Assert.assertTrue(user.getRequiredActions().isEmpty());
}
} finally {
}
}
protected void updateProviderEditMode(UserFederationProvider.EditMode editMode) {
RealmResource realm = testRealmResource();
RealmRepresentation realmRepresentation = realm.toRepresentation();
UserFederationProviderRepresentation kerberosProviderRepresentation = realmRepresentation
.getUserFederationProviders().get(0);
kerberosProviderRepresentation.getConfig().put(LDAPConstants.EDIT_MODE, editMode.toString());
realm.update(realmRepresentation);
}
public RealmResource testRealmResource() {
return adminClient.realm("test");
}
public Map<String, String> getConfig() {
return ldapTestConfiguration.getLDAPConfig();
}
protected static LDAPEmbeddedServer createServer() {
Properties defaultProperties = new Properties();
defaultProperties.setProperty(LDAPEmbeddedServer.PROPERTY_DSF, LDAPEmbeddedServer.DSF_INMEMORY);
defaultProperties.setProperty(LDAPEmbeddedServer.PROPERTY_LDIF_FILE, "classpath:kerberos/users-kerberos.ldif");
return new KerberosEmbeddedServer(defaultProperties);
}
@Override
public void setDefaultPageUriParameters() {
super.setDefaultPageUriParameters();
testRealmPage.setAuthRealm(AuthRealm.TEST);
}
}

View file

@ -1,122 +0,0 @@
/*
* 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.testsuite.adapter.federation;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.keycloak.common.constants.KerberosConstants;
import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.federation.kerberos.CommonKerberosConfig;
import org.keycloak.federation.kerberos.KerberosConfig;
import org.keycloak.federation.kerberos.KerberosFederationProviderFactory;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.representations.idm.ComponentRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserFederationProviderRepresentation;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
import javax.ws.rs.core.Response;
import java.util.Arrays;
import java.util.Map;
/**
* Test of KerberosFederationProvider (Kerberos not backed by LDAP)
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public abstract class AbstractKerberosStandaloneAdapterTest extends AbstractKerberosAdapterTest {
public static MultivaluedHashMap<String, String> toComponentConfig(Map<String, String> ldapConfig) {
MultivaluedHashMap<String, String> config = new MultivaluedHashMap<>();
for (Map.Entry<String, String> entry : ldapConfig.entrySet()) {
config.add(entry.getKey(), entry.getValue());
}
return config;
}
protected static final String PROVIDER_CONFIG_LOCATION = "kerberos-standalone-connection.properties";
@Before
public void init() throws Exception{
RealmRepresentation realmRepresentation = testRealmResource().toRepresentation();
Map<String,String> ldapConfig = getConfig();
ComponentRepresentation component = new ComponentRepresentation();
component.setName("kerberos-standalone");
component.setParentId(realmRepresentation.getId());
component.setProviderId(KerberosFederationProviderFactory.PROVIDER_NAME);
component.setProviderType(UserStorageProvider.class.getName());
component.setConfig(toComponentConfig(ldapConfig));
component.getConfig().putSingle("priority", "0");
testRealmResource().components().add(component);
realmRepresentation.setEventsEnabled(true);
testRealmResource().update(realmRepresentation);
}
@Override
protected CommonKerberosConfig getKerberosConfig(UserStorageProviderModel model) {
return new KerberosConfig(model);
}
@Override
protected String getConnectionPropertiesLocation() {
return PROVIDER_CONFIG_LOCATION;
}
@Test
public void spnegoLoginTest() throws Exception {
spnegoLoginTestImpl();
// Assert user was imported and hasn't any required action on him
assertUser("hnelson", "hnelson@" + getConfig().get(KerberosConstants.KERBEROS_REALM).toLowerCase(), null, null, false);
}
@Test
@Override
public void usernamePasswordLoginTest() throws Exception {
super.usernamePasswordLoginTest();
}
@Test
public void updateProfileEnabledTest() throws Exception {
// Switch updateProfileOnFirstLogin to on
RealmRepresentation realm = testRealmResource().toRepresentation();
UserFederationProviderRepresentation kerberosProviderRepresentation = realm.getUserFederationProviders().get(0);
kerberosProviderRepresentation.getConfig().put(KerberosConstants.UPDATE_PROFILE_FIRST_LOGIN, "true");
testRealmResource().update(realm);
// Assert update profile page is displayed
Response spnegoResponse = spnegoLogin("hnelson", "secret");
Assert.assertEquals(200, spnegoResponse.getStatus());
String responseText = spnegoResponse.readEntity(String.class);
Assert.assertTrue(responseText.contains("You need to update your user profile to activate your account."));
Assert.assertTrue(responseText.contains("hnelson@" + getConfig().get(KerberosConstants.KERBEROS_REALM).toLowerCase()));
spnegoResponse.close();
// Assert user was imported and has required action on him
assertUser("hnelson", "hnelson@" + getConfig().get(KerberosConstants.KERBEROS_REALM).toLowerCase(), null, null, true);
// Switch updateProfileOnFirstLogin to off
kerberosProviderRepresentation = realm.getUserFederationProviders().get(0);
kerberosProviderRepresentation.getConfig().put(KerberosConstants.UPDATE_PROFILE_FIRST_LOGIN, "false");
testRealmResource().update(realm);
}
}

View file

@ -25,11 +25,8 @@ import org.keycloak.admin.client.resource.ClientTemplateResource;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.common.constants.KerberosConstants;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.Constants;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.utils.DefaultAuthenticationFlows;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
@ -38,14 +35,12 @@ import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
import org.keycloak.representations.idm.ClientMappingsRepresentation;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ClientTemplateRepresentation;
import org.keycloak.representations.idm.ComponentExportRepresentation;
import org.keycloak.representations.idm.ComponentRepresentation;
import org.keycloak.representations.idm.FederatedIdentityRepresentation;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserFederationMapperRepresentation;
import org.keycloak.representations.idm.UserFederationProviderRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
@ -53,7 +48,6 @@ import org.keycloak.representations.idm.authorization.ResourceRepresentation;
import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.ldap.mappers.FullNameLDAPStorageMapper;
import org.keycloak.storage.ldap.mappers.FullNameLDAPStorageMapperFactory;
import org.keycloak.storage.ldap.mappers.LDAPStorageMapper;

View file

@ -26,7 +26,6 @@ import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.keycloak.services.Urls;
@ -47,7 +46,6 @@ import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.net.URI;
import java.util.HashMap;
import java.util.Set;
import static org.junit.Assert.assertEquals;

View file

@ -39,8 +39,6 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper;
@ -345,14 +343,14 @@ public abstract class AbstractKerberosTest {
RealmManager manager = new RealmManager(session);
RealmModel appRealm = manager.getRealm("test");
List<UserModel> users = session.userStorage().getUsers(appRealm, true);
List<UserModel> users = session.users().getUsers(appRealm, true);
for (UserModel user : users) {
if (!user.getUsername().equals(AssertEvents.DEFAULT_USERNAME)) {
session.userStorage().removeUser(appRealm, user);
session.users().removeUser(appRealm, user);
}
}
Assert.assertEquals(1, session.userStorage().getUsers(appRealm, true).size());
Assert.assertEquals(1, session.users().getUsers(appRealm, true).size());
} finally {
keycloakRule.stopSession(session, true);
}

View file

@ -32,11 +32,9 @@ import org.keycloak.federation.kerberos.KerberosConfig;
import org.keycloak.federation.kerberos.KerberosFederationProviderFactory;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.federation.storage.ldap.LDAPTestUtils;
import org.keycloak.testsuite.rule.KerberosRule;

View file

@ -20,7 +20,7 @@ package org.keycloak.testsuite.federation.ldap;
import org.jboss.logging.Logger;
import org.keycloak.common.constants.KerberosConstants;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.storage.UserStorageProvider;
import java.io.File;
import java.io.InputStream;
@ -79,7 +79,7 @@ public class LDAPTestConfiguration {
DEFAULT_VALUES.put(LDAPConstants.BATCH_SIZE_FOR_SYNC, String.valueOf(LDAPConstants.DEFAULT_BATCH_SIZE_FOR_SYNC));
DEFAULT_VALUES.put(LDAPConstants.USERNAME_LDAP_ATTRIBUTE, null);
DEFAULT_VALUES.put(LDAPConstants.USER_OBJECT_CLASSES, null);
DEFAULT_VALUES.put(LDAPConstants.EDIT_MODE, UserFederationProvider.EditMode.READ_ONLY.toString());
DEFAULT_VALUES.put(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.READ_ONLY.toString());
DEFAULT_VALUES.put(KerberosConstants.ALLOW_KERBEROS_AUTHENTICATION, "false");
DEFAULT_VALUES.put(KerberosConstants.KERBEROS_REALM, "KEYCLOAK.ORG");

View file

@ -24,12 +24,8 @@ import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.rules.TestRule;
import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.component.ComponentModel;
import org.keycloak.events.Details;
import org.keycloak.federation.kerberos.CommonKerberosConfig;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.ldap.LDAPStorageProviderFactory;

View file

@ -315,7 +315,7 @@ public class LDAPSyncTest {
// Remove all users from model
for (UserModel user : session.userLocalStorage().getUsers(testRealm, true)) {
System.out.println("trying to delete user: " + user.getUsername());
session.getUserCache().evict(testRealm, user);
session.userCache().evict(testRealm, user);
session.userLocalStorage().removeUser(testRealm, user);
}

View file

@ -22,8 +22,6 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.KeycloakSessionTask;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserFederationSyncResult;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.provider.ProviderConfigProperty;
@ -34,7 +32,6 @@ import org.keycloak.testsuite.federation.DummyUserFederationProviderFactory;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@ -93,13 +90,13 @@ public class SyncDummyUserFederationProviderFactory extends DummyUserFederationP
// KEYCLOAK-2412 : Just remove and add some users for testing purposes
for (int i = 0; i < 10; i++) {
String username = "dummyuser-" + i;
UserModel user = session.userStorage().getUserByUsername(username, realm);
UserModel user = session.userLocalStorage().getUserByUsername(username, realm);
if (user != null) {
session.userStorage().removeUser(realm, user);
session.userLocalStorage().removeUser(realm, user);
}
user = session.userStorage().addUser(realm, username);
user = session.userLocalStorage().addUser(realm, username);
}
logger.infof("Finished sync of changed users. Waiting now for %d seconds", waitTime);

View file

@ -24,12 +24,9 @@ import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import org.keycloak.common.util.Time;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserFederationSyncResult;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.UserStorageSyncManager;
import org.keycloak.storage.UserStorageProvider;
@ -39,8 +36,6 @@ import org.keycloak.testsuite.federation.DummyUserFederationProviderFactory;
import org.keycloak.testsuite.rule.KeycloakRule;
import org.keycloak.timer.TimerProvider;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**

View file

@ -36,10 +36,6 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderFactory;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.DefaultAuthenticationFlows;
import org.keycloak.models.utils.KeycloakModelUtils;

View file

@ -20,16 +20,11 @@ package org.keycloak.testsuite.util.cli;
import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.services.managers.UserStorageSyncManager;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.testsuite.federation.DummyUserFederationProviderFactory;
import org.keycloak.testsuite.federation.sync.SyncDummyUserFederationProviderFactory;
import java.util.HashMap;
import java.util.Map;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/