KEYCLOAK-1385 Introduce end-of-line normalization
This commit is contained in:
1 parent
be8aa93cca
commit
1642ac2394
888 files changed
+110680
-110660
No files matched your search
+135
-135
@@ -1,135 +1,135 @@
|
||||
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 keycloak-server.json 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);
|
||||
}
|
||||
}
|
||||
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 keycloak-server.json 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);
|
||||
}
|
||||
}
|
||||
+173
-173
@@ -1,173 +1,173 @@
|
||||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
import org.keycloak.models.CredentialValidationOutput;
|
||||
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 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
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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());
|
||||
}
|
||||
|
||||
/**
|
||||
* hardcoded to only return PASSWORD
|
||||
*
|
||||
* @param user
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Set<String> getSupportedCredentialTypes(UserModel user) {
|
||||
return supportedCredentialTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getSupportedCredentialTypes() {
|
||||
return supportedCredentialTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
|
||||
for (UserCredentialModel cred : input) {
|
||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
String password = properties.getProperty(user.getUsername());
|
||||
if (password == null) return false;
|
||||
return password.equals(cred.getValue());
|
||||
} else {
|
||||
return false; // invalid cred type
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
|
||||
for (UserCredentialModel cred : input) {
|
||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
String password = properties.getProperty(user.getUsername());
|
||||
if (password == null) return false;
|
||||
return password.equals(cred.getValue());
|
||||
} else {
|
||||
return false; // invalid cred type
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel credential) {
|
||||
return CredentialValidationOutput.failed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
}
|
||||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
import org.keycloak.models.CredentialValidationOutput;
|
||||
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 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
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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());
|
||||
}
|
||||
|
||||
/**
|
||||
* hardcoded to only return PASSWORD
|
||||
*
|
||||
* @param user
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Set<String> getSupportedCredentialTypes(UserModel user) {
|
||||
return supportedCredentialTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getSupportedCredentialTypes() {
|
||||
return supportedCredentialTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
|
||||
for (UserCredentialModel cred : input) {
|
||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
String password = properties.getProperty(user.getUsername());
|
||||
if (password == null) return false;
|
||||
return password.equals(cred.getValue());
|
||||
} else {
|
||||
return false; // invalid cred type
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
|
||||
for (UserCredentialModel cred : input) {
|
||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
String password = properties.getProperty(user.getUsername());
|
||||
if (password == null) return false;
|
||||
return password.equals(cred.getValue());
|
||||
} else {
|
||||
return false; // invalid cred type
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel credential) {
|
||||
return CredentialValidationOutput.failed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
}
|
||||
+37
-37
@@ -1,37 +1,37 @@
|
||||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ClasspathPropertiesFederationFactory extends BasePropertiesFederationFactory {
|
||||
|
||||
public static final String PROVIDER_NAME = "classpath-properties";
|
||||
|
||||
@Override
|
||||
protected BasePropertiesFederationProvider createProvider(KeycloakSession session, UserFederationProviderModel model, Properties props) {
|
||||
return new ClasspathPropertiesFederationProvider(session, model, props);
|
||||
}
|
||||
|
||||
protected InputStream getPropertiesFileStream(String path) {
|
||||
InputStream is = getClass().getClassLoader().getResourceAsStream(path);
|
||||
if (is == null) {
|
||||
throw new IllegalStateException("Path not found for properties file");
|
||||
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_NAME;
|
||||
}
|
||||
}
|
||||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ClasspathPropertiesFederationFactory extends BasePropertiesFederationFactory {
|
||||
|
||||
public static final String PROVIDER_NAME = "classpath-properties";
|
||||
|
||||
@Override
|
||||
protected BasePropertiesFederationProvider createProvider(KeycloakSession session, UserFederationProviderModel model, Properties props) {
|
||||
return new ClasspathPropertiesFederationProvider(session, model, props);
|
||||
}
|
||||
|
||||
protected InputStream getPropertiesFileStream(String path) {
|
||||
InputStream is = getClass().getClassLoader().getResourceAsStream(path);
|
||||
if (is == null) {
|
||||
throw new IllegalStateException("Path not found for properties file");
|
||||
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_NAME;
|
||||
}
|
||||
}
|
||||
+66
-66
@@ -1,66 +1,66 @@
|
||||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ClasspathPropertiesFederationProvider extends BasePropertiesFederationProvider {
|
||||
|
||||
public ClasspathPropertiesFederationProvider(KeycloakSession session, UserFederationProviderModel 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");
|
||||
}
|
||||
|
||||
}
|
||||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ClasspathPropertiesFederationProvider extends BasePropertiesFederationProvider {
|
||||
|
||||
public ClasspathPropertiesFederationProvider(KeycloakSession session, UserFederationProviderModel 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");
|
||||
}
|
||||
|
||||
}
|
||||
+42
-42
@@ -1,42 +1,42 @@
|
||||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class FilePropertiesFederationFactory extends BasePropertiesFederationFactory {
|
||||
|
||||
public static final String PROVIDER_NAME = "file-properties";
|
||||
|
||||
@Override
|
||||
protected BasePropertiesFederationProvider createProvider(KeycloakSession session, UserFederationProviderModel model, Properties props) {
|
||||
return new FilePropertiesFederationProvider(session, props, model);
|
||||
}
|
||||
protected InputStream getPropertiesFileStream(String path) {
|
||||
try {
|
||||
return new FileInputStream(path);
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Name of the provider. This will show up under the "Add Provider" select box on the Federation page in the
|
||||
* admin console
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_NAME;
|
||||
}
|
||||
}
|
||||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class FilePropertiesFederationFactory extends BasePropertiesFederationFactory {
|
||||
|
||||
public static final String PROVIDER_NAME = "file-properties";
|
||||
|
||||
@Override
|
||||
protected BasePropertiesFederationProvider createProvider(KeycloakSession session, UserFederationProviderModel model, Properties props) {
|
||||
return new FilePropertiesFederationProvider(session, props, model);
|
||||
}
|
||||
protected InputStream getPropertiesFileStream(String path) {
|
||||
try {
|
||||
return new FileInputStream(path);
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Name of the provider. This will show up under the "Add Provider" select box on the Federation page in the
|
||||
* admin console
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_NAME;
|
||||
}
|
||||
}
|
||||
+86
-86
@@ -1,86 +1,86 @@
|
||||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
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.Properties;
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
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.Properties;
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
+40
-40
@@ -1,40 +1,40 @@
|
||||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.UserModelDelegate;
|
||||
|
||||
/**
|
||||
* Readonly proxy for a UserModel that prevents passwords from being updated.
|
||||
*
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ReadonlyUserModelProxy extends UserModelDelegate {
|
||||
|
||||
public ReadonlyUserModelProxy(UserModel delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUsername(String username) {
|
||||
throw new IllegalStateException("Username is readonly");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredentialDirectly(UserCredentialValueModel cred) {
|
||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
throw new IllegalStateException("Passwords are readonly");
|
||||
}
|
||||
super.updateCredentialDirectly(cred);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredential(UserCredentialModel cred) {
|
||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
throw new IllegalStateException("Passwords are readonly");
|
||||
}
|
||||
super.updateCredential(cred);
|
||||
}
|
||||
}
|
||||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.UserModelDelegate;
|
||||
|
||||
/**
|
||||
* Readonly proxy for a UserModel that prevents passwords from being updated.
|
||||
*
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ReadonlyUserModelProxy extends UserModelDelegate {
|
||||
|
||||
public ReadonlyUserModelProxy(UserModel delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUsername(String username) {
|
||||
throw new IllegalStateException("Username is readonly");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredentialDirectly(UserCredentialValueModel cred) {
|
||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
throw new IllegalStateException("Passwords are readonly");
|
||||
}
|
||||
super.updateCredentialDirectly(cred);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredential(UserCredentialModel cred) {
|
||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
throw new IllegalStateException("Passwords are readonly");
|
||||
}
|
||||
super.updateCredential(cred);
|
||||
}
|
||||
}
|
||||
+72
-72
@@ -1,72 +1,72 @@
|
||||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredentialDirectly(UserCredentialValueModel cred) {
|
||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
throw new IllegalStateException("Shouldn't be using this method");
|
||||
}
|
||||
super.updateCredentialDirectly(cred);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredential(UserCredentialModel cred) {
|
||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
synchronized (provider.getProperties()) {
|
||||
if (!provider.getProperties().containsKey(delegate.getUsername())) {
|
||||
throw new IllegalStateException("no user of that in properties file");
|
||||
}
|
||||
provider.getProperties().setProperty(delegate.getUsername(), cred.getValue());
|
||||
provider.save();
|
||||
}
|
||||
} else {
|
||||
super.updateCredential(cred);
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.keycloak.examples.federation.properties;
|
||||
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredentialDirectly(UserCredentialValueModel cred) {
|
||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
throw new IllegalStateException("Shouldn't be using this method");
|
||||
}
|
||||
super.updateCredentialDirectly(cred);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCredential(UserCredentialModel cred) {
|
||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
synchronized (provider.getProperties()) {
|
||||
if (!provider.getProperties().containsKey(delegate.getUsername())) {
|
||||
throw new IllegalStateException("no user of that in properties file");
|
||||
}
|
||||
provider.getProperties().setProperty(delegate.getUsername(), cred.getValue());
|
||||
provider.save();
|
||||
}
|
||||
} else {
|
||||
super.updateCredential(cred);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
org.keycloak.examples.federation.properties.ClasspathPropertiesFederationFactory
|
||||
org.keycloak.examples.federation.properties.ClasspathPropertiesFederationFactory
|
||||
org.keycloak.examples.federation.properties.FilePropertiesFederationFactory
|
||||
@@ -1,3 +1,3 @@
|
||||
#
|
||||
#Sun Aug 03 10:52:57 EDT 2014
|
||||
belichick=superbowl
|
||||
#
|
||||
#Sun Aug 03 10:52:57 EDT 2014
|
||||
belichick=superbowl
|
||||
Reference in new issue
Block a user