Refactoring of Authentication SPI and Picketlink to use ProviderSessions
Refactoring of ProviderSessionFactory to support dependencies between components Calling lifecycle methods Removing KeycloakRegistry
This commit is contained in:
parent
0d00db281a
commit
5aefe52ccc
74 changed files with 690 additions and 315 deletions
|
@ -3,6 +3,8 @@ package org.keycloak.audit.log;
|
|||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.audit.AuditListener;
|
||||
import org.keycloak.audit.AuditListenerFactory;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.provider.ProviderSessionFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
|
@ -14,7 +16,7 @@ public class JBossLoggingAuditListenerFactory implements AuditListenerFactory {
|
|||
private static final Logger logger = Logger.getLogger("org.keycloak.audit");
|
||||
|
||||
@Override
|
||||
public AuditListener create() {
|
||||
public AuditListener create(ProviderSession providerSession) {
|
||||
return new JBossLoggingAuditListener(logger);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ package org.keycloak.audit.jpa;
|
|||
|
||||
import org.keycloak.audit.AuditProvider;
|
||||
import org.keycloak.audit.AuditProviderFactory;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.provider.ProviderSessionFactory;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.Persistence;
|
||||
|
@ -15,7 +17,7 @@ public class JpaAuditProviderFactory implements AuditProviderFactory {
|
|||
private EntityManagerFactory emf;
|
||||
|
||||
@Override
|
||||
public AuditProvider create() {
|
||||
public AuditProvider create(ProviderSession providerSession) {
|
||||
return new JpaAuditProvider(emf.createEntityManager());
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@ import com.mongodb.MongoClient;
|
|||
import com.mongodb.WriteConcern;
|
||||
import org.keycloak.audit.AuditProvider;
|
||||
import org.keycloak.audit.AuditProviderFactory;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.provider.ProviderSessionFactory;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
|
@ -22,7 +24,7 @@ public class MongoAuditProviderFactory implements AuditProviderFactory {
|
|||
private DB db;
|
||||
|
||||
@Override
|
||||
public AuditProvider create() {
|
||||
public AuditProvider create(ProviderSession providerSession) {
|
||||
return new MongoAuditProvider(db.getCollection("audit"));
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ public abstract class AbstractAuditProviderTest {
|
|||
factory = loader.find(getProviderId());
|
||||
factory.init();
|
||||
|
||||
provider = factory.create();
|
||||
provider = factory.create(null);
|
||||
}
|
||||
|
||||
protected abstract String getProviderId();
|
||||
|
@ -58,7 +58,7 @@ public abstract class AbstractAuditProviderTest {
|
|||
provider.onEvent(create("event", "realmId", "clientId", "userId2", "127.0.0.1", "error"));
|
||||
|
||||
provider.close();
|
||||
provider = factory.create();
|
||||
provider = factory.create(null);
|
||||
|
||||
Assert.assertEquals(5, provider.createQuery().client("clientId").getResultList().size());
|
||||
Assert.assertEquals(5, provider.createQuery().realm("realmId").getResultList().size());
|
||||
|
@ -84,7 +84,7 @@ public abstract class AbstractAuditProviderTest {
|
|||
provider.onEvent(create(System.currentTimeMillis() - 30000, "event", "realmId2", "clientId", "userId", "127.0.0.1", "error"));
|
||||
|
||||
provider.close();
|
||||
provider = factory.create();
|
||||
provider = factory.create(null);
|
||||
|
||||
provider.clear("realmId");
|
||||
|
||||
|
@ -100,7 +100,7 @@ public abstract class AbstractAuditProviderTest {
|
|||
provider.onEvent(create(System.currentTimeMillis() - 30000, "event", "realmId2", "clientId", "userId", "127.0.0.1", "error"));
|
||||
|
||||
provider.close();
|
||||
provider = factory.create();
|
||||
provider = factory.create(null);
|
||||
|
||||
provider.clear("realmId", System.currentTimeMillis() - 10000);
|
||||
|
||||
|
|
|
@ -4,11 +4,12 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.provider.Provider;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public interface AuthenticationProvider {
|
||||
public interface AuthenticationProvider extends Provider {
|
||||
|
||||
String getName();
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package org.keycloak.authentication;
|
||||
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public interface AuthenticationProviderFactory extends ProviderFactory<AuthenticationProvider> {
|
||||
}
|
|
@ -10,6 +10,7 @@ import org.keycloak.models.AuthenticationLinkModel;
|
|||
import org.keycloak.models.AuthenticationProviderModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.util.ProviderLoader;
|
||||
|
||||
/**
|
||||
|
@ -27,8 +28,8 @@ public class AuthenticationProviderManager {
|
|||
private final RealmModel realm;
|
||||
private final Map<String, AuthenticationProvider> delegates;
|
||||
|
||||
public static AuthenticationProviderManager getManager(RealmModel realm) {
|
||||
Iterable<AuthenticationProvider> providers = load();
|
||||
public static AuthenticationProviderManager getManager(RealmModel realm, ProviderSession providerSession) {
|
||||
Iterable<AuthenticationProvider> providers = providerSession.getAllProviders(AuthenticationProvider.class);
|
||||
|
||||
Map<String, AuthenticationProvider> providersMap = new HashMap<String, AuthenticationProvider>();
|
||||
for (AuthenticationProvider provider : providers) {
|
||||
|
@ -38,10 +39,6 @@ public class AuthenticationProviderManager {
|
|||
return new AuthenticationProviderManager(realm, providersMap);
|
||||
}
|
||||
|
||||
public static Iterable<AuthenticationProvider> load() {
|
||||
return ProviderLoader.load(AuthenticationProvider.class);
|
||||
}
|
||||
|
||||
public AuthenticationProviderManager(RealmModel realm, Map<String, AuthenticationProvider> delegates) {
|
||||
this.realm = realm;
|
||||
this.delegates = delegates;
|
||||
|
|
|
@ -70,6 +70,10 @@ public abstract class AbstractModelAuthenticationProvider implements Authenticat
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
protected abstract RealmModel getRealm(RealmModel currentRealm, Map<String, String> config) throws AuthenticationProviderException;
|
||||
|
||||
protected AuthUser createAuthenticatedUserInstance(UserModel user) {
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.keycloak.models.KeycloakSession;
|
|||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.authentication.AuthProviderConstants;
|
||||
import org.keycloak.authentication.AuthenticationProviderException;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
|
||||
/**
|
||||
* AbstractModelAuthenticationProvider, which delegates authentication operations to different (external) realm
|
||||
|
@ -17,6 +18,9 @@ import org.keycloak.authentication.AuthenticationProviderException;
|
|||
*/
|
||||
public class ExternalModelAuthenticationProvider extends AbstractModelAuthenticationProvider {
|
||||
|
||||
public ExternalModelAuthenticationProvider(ProviderSession providerSession) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return AuthProviderConstants.PROVIDER_NAME_EXTERNAL_MODEL;
|
||||
|
@ -34,6 +38,7 @@ public class ExternalModelAuthenticationProvider extends AbstractModelAuthentica
|
|||
throw new AuthenticationProviderException("Option '" + AuthProviderConstants.EXTERNAL_REALM_ID + "' not specified in configuration");
|
||||
}
|
||||
|
||||
// TODO: This won't be needed when KeycloakSession is available from ProviderSession
|
||||
KeycloakSession session = ResteasyProviderFactory.getContextData(KeycloakSession.class);
|
||||
if (session == null) {
|
||||
throw new AuthenticationProviderException("KeycloakSession not available");
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package org.keycloak.authentication.model;
|
||||
|
||||
import org.keycloak.authentication.AuthProviderConstants;
|
||||
import org.keycloak.authentication.AuthenticationProvider;
|
||||
import org.keycloak.authentication.AuthenticationProviderFactory;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.provider.ProviderSessionFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class ExternalModelAuthenticationProviderFactory implements AuthenticationProviderFactory {
|
||||
|
||||
@Override
|
||||
public AuthenticationProvider create(ProviderSession providerSession) {
|
||||
return new ExternalModelAuthenticationProvider(providerSession);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return AuthProviderConstants.PROVIDER_NAME_EXTERNAL_MODEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean lazyLoad() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package org.keycloak.authentication.model;
|
||||
|
||||
import org.keycloak.authentication.AuthProviderConstants;
|
||||
import org.keycloak.authentication.AuthenticationProvider;
|
||||
import org.keycloak.authentication.AuthenticationProviderFactory;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class ModelAuthenticationProviderFactory implements AuthenticationProviderFactory {
|
||||
|
||||
@Override
|
||||
public AuthenticationProvider create(ProviderSession providerSession) {
|
||||
return new ModelAuthenticationProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return AuthProviderConstants.PROVIDER_NAME_MODEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean lazyLoad() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
org.keycloak.authentication.model.ModelAuthenticationProvider
|
||||
org.keycloak.authentication.model.ExternalModelAuthenticationProvider
|
|
@ -0,0 +1,2 @@
|
|||
org.keycloak.authentication.model.ModelAuthenticationProviderFactory
|
||||
org.keycloak.authentication.model.ExternalModelAuthenticationProviderFactory
|
|
@ -31,6 +31,12 @@
|
|||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-picketlink-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
|
|
|
@ -12,7 +12,7 @@ import org.keycloak.authentication.AuthProviderConstants;
|
|||
import org.keycloak.authentication.AuthUser;
|
||||
import org.keycloak.authentication.AuthenticationProvider;
|
||||
import org.keycloak.authentication.AuthenticationProviderException;
|
||||
import org.keycloak.picketlink.PartitionManagerProvider;
|
||||
import org.keycloak.picketlink.IdentityManagerProvider;
|
||||
import org.keycloak.util.ProviderLoader;
|
||||
import org.picketlink.idm.IdentityManagementException;
|
||||
import org.picketlink.idm.IdentityManager;
|
||||
|
@ -32,6 +32,12 @@ public class PicketlinkAuthenticationProvider implements AuthenticationProvider
|
|||
|
||||
private static final Logger logger = Logger.getLogger(PicketlinkAuthenticationProvider.class);
|
||||
|
||||
private final IdentityManagerProvider identityManagerProvider;
|
||||
|
||||
public PicketlinkAuthenticationProvider(IdentityManagerProvider identityManagerProvider) {
|
||||
this.identityManagerProvider = identityManagerProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return AuthProviderConstants.PROVIDER_NAME_PICKETLINK;
|
||||
|
@ -107,28 +113,12 @@ public class PicketlinkAuthenticationProvider implements AuthenticationProvider
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
public IdentityManager getIdentityManager(RealmModel realm) throws AuthenticationProviderException {
|
||||
IdentityManager identityManager = ResteasyProviderFactory.getContextData(IdentityManager.class);
|
||||
if (identityManager == null) {
|
||||
Iterable<PartitionManagerProvider> providers = ProviderLoader.load(PartitionManagerProvider.class);
|
||||
|
||||
// TODO: Priority?
|
||||
PartitionManager partitionManager = null;
|
||||
for (PartitionManagerProvider provider : providers) {
|
||||
partitionManager = provider.getPartitionManager(realm);
|
||||
if (partitionManager != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (partitionManager == null) {
|
||||
throw new AuthenticationProviderException("Not able to locate PartitionManager with any PartitionManagerProvider");
|
||||
}
|
||||
|
||||
identityManager = partitionManager.createIdentityManager();
|
||||
ResteasyProviderFactory.pushContext(IdentityManager.class, identityManager);
|
||||
}
|
||||
return identityManager;
|
||||
return identityManagerProvider.getIdentityManager(realm);
|
||||
}
|
||||
|
||||
private AuthenticationProviderException convertIDMException(IdentityManagementException ie) {
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package org.keycloak.authentication.picketlink;
|
||||
|
||||
import org.keycloak.authentication.AuthProviderConstants;
|
||||
import org.keycloak.authentication.AuthenticationProvider;
|
||||
import org.keycloak.authentication.AuthenticationProviderFactory;
|
||||
import org.keycloak.picketlink.IdentityManagerProvider;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class PicketlinkAuthenticationProviderFactory implements AuthenticationProviderFactory {
|
||||
|
||||
@Override
|
||||
public AuthenticationProvider create(ProviderSession providerSession) {
|
||||
return new PicketlinkAuthenticationProvider(providerSession.getProvider(IdentityManagerProvider.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return AuthProviderConstants.PROVIDER_NAME_PICKETLINK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean lazyLoad() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
package org.keycloak.picketlink;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.picketlink.idm.PartitionManager;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public interface PartitionManagerProvider {
|
||||
|
||||
PartitionManager getPartitionManager(RealmModel realm);
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package org.keycloak.picketlink.impl;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.picketlink.PartitionManagerProvider;
|
||||
import org.keycloak.util.KeycloakRegistry;
|
||||
import org.picketlink.idm.PartitionManager;
|
||||
|
||||
/**
|
||||
* Obtains {@link PartitionManager} instances from shared {@link PartitionManagerRegistry} and uses realm configuration for it
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class RealmPartitionManagerProvider implements PartitionManagerProvider {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(RealmPartitionManagerProvider.class);
|
||||
|
||||
@Override
|
||||
public PartitionManager getPartitionManager(RealmModel realm) {
|
||||
KeycloakRegistry registry = ResteasyProviderFactory.getContextData(KeycloakRegistry.class) ;
|
||||
if (registry == null) {
|
||||
logger.warn("KeycloakRegistry not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
PartitionManagerRegistry partitionManagerRegistry = registry.getService(PartitionManagerRegistry.class);
|
||||
if (partitionManagerRegistry == null) {
|
||||
partitionManagerRegistry = new PartitionManagerRegistry();
|
||||
partitionManagerRegistry = registry.putServiceIfAbsent(PartitionManagerRegistry.class, partitionManagerRegistry);
|
||||
logger.info("Pushed PartitionManagerRegistry component");
|
||||
}
|
||||
|
||||
return partitionManagerRegistry.getPartitionManager(realm);
|
||||
}
|
||||
}
|
|
@ -1 +1 @@
|
|||
org.keycloak.authentication.picketlink.PicketlinkAuthenticationProvider
|
||||
org.keycloak.authentication.picketlink.PicketlinkAuthenticationProviderFactory
|
|
@ -1 +0,0 @@
|
|||
org.keycloak.picketlink.impl.RealmPartitionManagerProvider
|
|
@ -5,7 +5,7 @@ package org.keycloak.provider;
|
|||
*/
|
||||
public interface ProviderFactory<T extends Provider> {
|
||||
|
||||
public T create();
|
||||
public T create(ProviderSession providerSession);
|
||||
|
||||
public void init();
|
||||
|
||||
|
|
|
@ -68,12 +68,12 @@ public class ProviderFactoryLoader<T extends Provider> implements Iterable<Provi
|
|||
}
|
||||
|
||||
@Override
|
||||
public synchronized T create() {
|
||||
public synchronized T create(ProviderSession providerSession) {
|
||||
if (!initialized) {
|
||||
factory.init();
|
||||
initialized = true;
|
||||
}
|
||||
return factory.create();
|
||||
return factory.create(providerSession);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -82,9 +82,11 @@ public class ProviderFactoryLoader<T extends Provider> implements Iterable<Provi
|
|||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
public synchronized void close() {
|
||||
if (initialized) {
|
||||
factory.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
package org.keycloak.services;
|
||||
|
||||
import org.keycloak.provider.Provider;
|
||||
package org.keycloak.provider;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -15,6 +13,8 @@ public interface ProviderSession {
|
|||
|
||||
<T extends Provider> Set<String> listProviderIds(Class<T> clazz);
|
||||
|
||||
<T extends Provider> Set<T> getAllProviders(Class<T> clazz);
|
||||
|
||||
void close();
|
||||
|
||||
}
|
|
@ -1,11 +1,5 @@
|
|||
package org.keycloak.services;
|
||||
package org.keycloak.provider;
|
||||
|
||||
import org.keycloak.provider.Provider;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
import org.keycloak.provider.ProviderFactoryLoader;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
|
@ -1,29 +0,0 @@
|
|||
package org.keycloak.util;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* Set of services shared for whole Keycloak server
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class KeycloakRegistry {
|
||||
|
||||
private final ConcurrentMap<Class<?>, Object> services = new ConcurrentHashMap<Class<?>, Object>();
|
||||
|
||||
public <T> void putService(Class<T> type, T object) {
|
||||
services.put(type, object);
|
||||
}
|
||||
|
||||
public <T> T putServiceIfAbsent(Class<T> type, T object) {
|
||||
// Put only if absent and always return the version from registry
|
||||
services.putIfAbsent(type, object);
|
||||
return (T) services.get(type);
|
||||
}
|
||||
|
||||
public <T> T getService(Class<T> type) {
|
||||
return (T) services.get(type);
|
||||
}
|
||||
}
|
|
@ -18,6 +18,8 @@ public class Config {
|
|||
public static final String AUDIT_EXPIRATION_SCHEDULE_KEY = "keycloak.audit.expirationSchedule";
|
||||
public static final String AUDIT_EXPIRATION_SCHEDULE_DEFAULT = String.valueOf(TimeUnit.MINUTES.toMillis(15));
|
||||
|
||||
public static final String PICKETLINK_PROVIDER_KEY = "keycloak.picketlink";
|
||||
|
||||
public static final String THEME_BASE_KEY = "keycloak.theme.base";
|
||||
public static final String THEME_BASE_DEFAULT = "base";
|
||||
public static final String THEME_DEFAULT_KEY = "keycloak.theme.default";
|
||||
|
@ -68,6 +70,14 @@ public class Config {
|
|||
System.setProperty(TIMER_PROVIDER_KEY, provider);
|
||||
}
|
||||
|
||||
public static String getIdentityManagerProvider() {
|
||||
return System.getProperty(PICKETLINK_PROVIDER_KEY, "realm");
|
||||
}
|
||||
|
||||
public static void setIdentityManagerProvider(String provider) {
|
||||
System.setProperty(PICKETLINK_PROVIDER_KEY, provider);
|
||||
}
|
||||
|
||||
public static String getThemeDir() {
|
||||
String themeDir = System.getProperty(THEME_DIR_KEY);
|
||||
if (themeDir == null && System.getProperties().containsKey(JBOSS_SERVER_CONFIG_DIR_KEY)) {
|
||||
|
|
|
@ -65,7 +65,7 @@ public class MongoStoreImpl implements MongoStore {
|
|||
mapperRegistry.addDBObjectMapper(converter);
|
||||
}
|
||||
|
||||
// Specific converter for ArrayList is added just for performance purposes to avoid recursive converter lookup (most of list impl will be ArrayList)
|
||||
// Specific converter for ArrayList is added just for performance purposes to avoid recursive converter lookup (most of list idm will be ArrayList)
|
||||
mapperRegistry.addAppObjectMapper(new ListMapper(mapperRegistry, ArrayList.class));
|
||||
mapperRegistry.addAppObjectMapper(new ListMapper(mapperRegistry, List.class));
|
||||
mapperRegistry.addDBObjectMapper(new BasicDBListMapper(mapperRegistry));
|
||||
|
|
|
@ -18,7 +18,7 @@ import org.keycloak.models.mongo.keycloak.entities.RoleEntity;
|
|||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
/**
|
||||
* Wrapper around RoleData object, which will persist wrapped object after each set operation (compatibility with picketlink based impl)
|
||||
* Wrapper around RoleData object, which will persist wrapped object after each set operation (compatibility with picketlink based idm)
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
|
|
|
@ -11,7 +11,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Wrapper around UserData object, which will persist wrapped object after each set operation (compatibility with picketlink based impl)
|
||||
* Wrapper around UserData object, which will persist wrapped object after each set operation (compatibility with picketlink based idm)
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
|
|
|
@ -7,7 +7,7 @@ package org.keycloak.models.mongo.keycloak.config;
|
|||
*/
|
||||
public class MongoClientProviderHolder {
|
||||
|
||||
// Just use static object for now. Default impl is SystemPropsMongoClientProvider
|
||||
// Just use static object for now. Default idm is SystemPropsMongoClientProvider
|
||||
private static MongoClientProvider instance = new SystemPropertiesMongoClientProvider();
|
||||
|
||||
public static MongoClientProvider getInstance() {
|
||||
|
|
|
@ -39,6 +39,30 @@
|
|||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-picketlink-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-picketlink-realm</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-timer-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-timer-basic</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
|
|
|
@ -17,7 +17,7 @@ import javax.naming.directory.DirContext;
|
|||
import javax.naming.directory.InitialDirContext;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.picketlink.impl.LdapConstants;
|
||||
import org.keycloak.picketlink.idm.LdapConstants;
|
||||
import org.picketbox.test.ldap.AbstractLDAPTest;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package org.keycloak.model.test;
|
||||
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.authentication.picketlink.PicketlinkAuthenticationProvider;
|
||||
import org.keycloak.util.KeycloakRegistry;
|
||||
import org.keycloak.picketlink.IdentityManagerProvider;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.picketlink.idm.IdentityManager;
|
||||
import org.picketlink.idm.credential.Password;
|
||||
import org.picketlink.idm.model.basic.BasicModel;
|
||||
|
@ -14,16 +14,10 @@ import org.picketlink.idm.model.basic.User;
|
|||
*/
|
||||
public class LdapTestUtils {
|
||||
|
||||
public static void setLdapPassword(RealmModel realm, String username, String password) {
|
||||
// TODO: Workaround... should be improved once we have KeycloakSession with available application-scoped components
|
||||
KeycloakRegistry registry = ResteasyProviderFactory.getContextData(KeycloakRegistry.class);
|
||||
if (registry == null) {
|
||||
ResteasyProviderFactory.pushContext(KeycloakRegistry.class, new KeycloakRegistry());
|
||||
}
|
||||
|
||||
public static void setLdapPassword(ProviderSession providerSession, RealmModel realm, String username, String password) {
|
||||
// Update password directly in ldap. It's workaround, but LDIF import doesn't seem to work on windows for ApacheDS
|
||||
try {
|
||||
IdentityManager identityManager = new PicketlinkAuthenticationProvider().getIdentityManager(realm);
|
||||
IdentityManager identityManager = new PicketlinkAuthenticationProvider(providerSession.getProvider(IdentityManagerProvider.class)).getIdentityManager(realm);
|
||||
User user = BasicModel.getUser(identityManager, username);
|
||||
identityManager.updateCredential(user, new Password(password.toCharArray()));
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -12,6 +12,8 @@ import org.junit.Before;
|
|||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.provider.ProviderSessionFactory;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.services.managers.ApplianceBootstrap;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
|
@ -26,6 +28,8 @@ public class AbstractModelTest {
|
|||
protected KeycloakSessionFactory factory;
|
||||
protected KeycloakSession identitySession;
|
||||
protected RealmManager realmManager;
|
||||
protected ProviderSessionFactory providerSessionFactory;
|
||||
protected ProviderSession providerSession;
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
|
@ -34,13 +38,18 @@ public class AbstractModelTest {
|
|||
identitySession.getTransaction().begin();
|
||||
realmManager = new RealmManager(identitySession);
|
||||
|
||||
providerSessionFactory = KeycloakApplication.createProviderSessionFactory();
|
||||
providerSession = providerSessionFactory.createSession();
|
||||
|
||||
new ApplianceBootstrap().bootstrap(identitySession, "/auth");
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() throws Exception {
|
||||
identitySession.getTransaction().commit();
|
||||
providerSession.close();
|
||||
identitySession.close();
|
||||
providerSessionFactory.close();
|
||||
factory.close();
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ public class AuthProvidersExternalModelTest extends AbstractModelTest {
|
|||
credential.setValue("password");
|
||||
realm1.updateCredential(john, credential);
|
||||
|
||||
am = new AuthenticationManager();
|
||||
am = new AuthenticationManager(providerSession);
|
||||
}
|
||||
|
||||
|
||||
|
@ -119,7 +119,7 @@ public class AuthProvidersExternalModelTest extends AbstractModelTest {
|
|||
ResteasyProviderFactory.pushContext(KeycloakSession.class, identitySession);
|
||||
|
||||
// Change credential via realm2 and validate that they are changed also in realm1
|
||||
AuthenticationProviderManager authProviderManager = AuthenticationProviderManager.getManager(realm2);
|
||||
AuthenticationProviderManager authProviderManager = AuthenticationProviderManager.getManager(realm2, providerSession);
|
||||
try {
|
||||
Assert.assertTrue(authProviderManager.updatePassword(john, "password-updated"));
|
||||
} catch (AuthenticationProviderException ape) {
|
||||
|
|
|
@ -22,7 +22,6 @@ import org.keycloak.services.managers.AuthenticationManager;
|
|||
import org.keycloak.authentication.AuthProviderConstants;
|
||||
import org.keycloak.authentication.AuthenticationProviderException;
|
||||
import org.keycloak.authentication.AuthenticationProviderManager;
|
||||
import org.keycloak.util.KeycloakRegistry;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
|
@ -52,7 +51,7 @@ public class AuthProvidersLDAPTest extends AbstractModelTest {
|
|||
realm.addRequiredCredential(CredentialRepresentation.PASSWORD);
|
||||
this.embeddedServer.setupLdapInRealm(realm);
|
||||
|
||||
am = new AuthenticationManager();
|
||||
am = new AuthenticationManager(providerSession);
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -70,12 +69,8 @@ public class AuthProvidersLDAPTest extends AbstractModelTest {
|
|||
public void testLdapAuthentication() {
|
||||
MultivaluedMap<String, String> formData = AuthProvidersExternalModelTest.createFormData("john", "password");
|
||||
|
||||
try {
|
||||
// this is needed for Picketlink model provider
|
||||
ResteasyProviderFactory.pushContext(KeycloakRegistry.class, new KeycloakRegistry());
|
||||
|
||||
// Set password of user in LDAP
|
||||
LdapTestUtils.setLdapPassword(realm, "john", "password");
|
||||
LdapTestUtils.setLdapPassword(providerSession, realm, "john", "password");
|
||||
|
||||
// Verify that user doesn't exists in realm2 and can't authenticate here
|
||||
Assert.assertEquals(AuthenticationManager.AuthenticationStatus.INVALID_USER, am.authenticateForm(null, realm, formData));
|
||||
|
@ -97,19 +92,12 @@ public class AuthProvidersLDAPTest extends AbstractModelTest {
|
|||
AuthenticationLinkModel authLink = realm.getAuthenticationLink(john);
|
||||
Assert.assertNotNull(authLink);
|
||||
Assert.assertEquals(authLink.getAuthProvider(), AuthProviderConstants.PROVIDER_NAME_PICKETLINK);
|
||||
} finally {
|
||||
ResteasyProviderFactory.clearContextData();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLdapInvalidAuthentication() {
|
||||
setupAuthenticationProviders();
|
||||
|
||||
try {
|
||||
ResteasyProviderFactory.pushContext(KeycloakRegistry.class, new KeycloakRegistry());
|
||||
|
||||
// Add some user and password to realm
|
||||
UserModel realmUser = realm.addUser("realmUser");
|
||||
realmUser.setEnabled(true);
|
||||
|
@ -139,9 +127,6 @@ public class AuthProvidersLDAPTest extends AbstractModelTest {
|
|||
realmUser.setEnabled(true);
|
||||
formData = AuthProvidersExternalModelTest.createFormData("realmUser", "pass");
|
||||
Assert.assertEquals(AuthenticationManager.AuthenticationStatus.SUCCESS, am.authenticateForm(null, realm, formData));
|
||||
} finally {
|
||||
ResteasyProviderFactory.clearContextData();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -149,18 +134,14 @@ public class AuthProvidersLDAPTest extends AbstractModelTest {
|
|||
// Add ldap
|
||||
setupAuthenticationProviders();
|
||||
|
||||
try {
|
||||
// this is needed for ldap provider
|
||||
ResteasyProviderFactory.pushContext(KeycloakRegistry.class, new KeycloakRegistry());
|
||||
|
||||
LdapTestUtils.setLdapPassword(realm, "john", "password");
|
||||
LdapTestUtils.setLdapPassword(providerSession, realm, "john", "password");
|
||||
|
||||
// First authenticate successfully to sync john into realm
|
||||
MultivaluedMap<String, String> formData = AuthProvidersExternalModelTest.createFormData("john", "password");
|
||||
Assert.assertEquals(AuthenticationManager.AuthenticationStatus.SUCCESS, am.authenticateForm(null, realm, formData));
|
||||
|
||||
// Change credential and validate that user can authenticate
|
||||
AuthenticationProviderManager authProviderManager = AuthenticationProviderManager.getManager(realm);
|
||||
AuthenticationProviderManager authProviderManager = AuthenticationProviderManager.getManager(realm, providerSession);
|
||||
|
||||
UserModel john = realm.getUser("john");
|
||||
try {
|
||||
|
@ -187,9 +168,6 @@ public class AuthProvidersLDAPTest extends AbstractModelTest {
|
|||
}
|
||||
formData = AuthProvidersExternalModelTest.createFormData("john", "password-updated2");
|
||||
Assert.assertEquals(AuthenticationManager.AuthenticationStatus.INVALID_CREDENTIALS, am.authenticateForm(null, realm, formData));
|
||||
} finally {
|
||||
ResteasyProviderFactory.clearContextData();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -143,7 +143,7 @@ public class AuthenticationManagerTest extends AbstractModelTest {
|
|||
realm.addRequiredCredential(CredentialRepresentation.PASSWORD);
|
||||
realm.setAuthenticationProviders(Arrays.asList(AuthenticationProviderModel.DEFAULT_PROVIDER));
|
||||
|
||||
am = new AuthenticationManager();
|
||||
am = new AuthenticationManager(providerSession);
|
||||
|
||||
user = realm.addUser("test");
|
||||
user.setEnabled(true);
|
||||
|
|
55
picketlink/keycloak-picketlink-api/pom.xml
Normal file
55
picketlink/keycloak-picketlink-api/pom.xml
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-picketlink</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.0-beta-1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-picketlink-api</artifactId>
|
||||
<name>Keycloak Picketlink API</name>
|
||||
<description />
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-model-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.picketlink</groupId>
|
||||
<artifactId>picketlink-idm-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,13 @@
|
|||
package org.keycloak.picketlink;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.provider.Provider;
|
||||
import org.picketlink.idm.IdentityManager;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public interface IdentityManagerProvider extends Provider {
|
||||
|
||||
IdentityManager getIdentityManager(RealmModel realm);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package org.keycloak.picketlink;
|
||||
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public interface IdentityManagerProviderFactory extends ProviderFactory<IdentityManagerProvider> {
|
||||
}
|
66
picketlink/keycloak-picketlink-realm/pom.xml
Normal file
66
picketlink/keycloak-picketlink-realm/pom.xml
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-picketlink</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.0-beta-1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-picketlink-realm</artifactId>
|
||||
<name>Keycloak Picketlink Realm</name>
|
||||
<description />
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-model-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-picketlink-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.picketlink</groupId>
|
||||
<artifactId>picketlink-idm-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.picketlink</groupId>
|
||||
<artifactId>picketlink-idm-impl</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.picketlink.impl;
|
||||
package org.keycloak.picketlink.idm;
|
||||
|
||||
import org.picketlink.idm.IdentityManager;
|
||||
import org.picketlink.idm.ldap.internal.LDAPPlainTextPasswordCredentialHandler;
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.picketlink.impl;
|
||||
package org.keycloak.picketlink.idm;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
@ -1,10 +1,12 @@
|
|||
package org.keycloak.picketlink.impl;
|
||||
package org.keycloak.picketlink.realm;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.picketlink.idm.LDAPAgentIgnoreCredentialHandler;
|
||||
import org.keycloak.picketlink.idm.LdapConstants;
|
||||
import org.picketlink.idm.PartitionManager;
|
||||
import org.picketlink.idm.config.IdentityConfigurationBuilder;
|
||||
import org.picketlink.idm.internal.DefaultPartitionManager;
|
|
@ -0,0 +1,28 @@
|
|||
package org.keycloak.picketlink.realm;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.picketlink.IdentityManagerProvider;
|
||||
import org.picketlink.idm.IdentityManager;
|
||||
import org.picketlink.idm.PartitionManager;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class RealmIdentityManagerProvider implements IdentityManagerProvider {
|
||||
|
||||
private final PartitionManagerRegistry partitionManagerRegistry;
|
||||
|
||||
public RealmIdentityManagerProvider(PartitionManagerRegistry partitionManagerRegistry) {
|
||||
this.partitionManagerRegistry = partitionManagerRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdentityManager getIdentityManager(RealmModel realm) {
|
||||
PartitionManager partitionManager = partitionManagerRegistry.getPartitionManager(realm);
|
||||
return partitionManager.createIdentityManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package org.keycloak.picketlink.realm;
|
||||
|
||||
import org.keycloak.picketlink.IdentityManagerProvider;
|
||||
import org.keycloak.picketlink.IdentityManagerProviderFactory;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.picketlink.idm.PartitionManager;
|
||||
|
||||
/**
|
||||
* Obtains {@link PartitionManager} instances from shared {@link PartitionManagerRegistry} and uses realm configuration for it
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class RealmIdentityManagerProviderFactory implements IdentityManagerProviderFactory {
|
||||
|
||||
private PartitionManagerRegistry partitionManagerRegistry;
|
||||
|
||||
@Override
|
||||
public IdentityManagerProvider create(ProviderSession providerSession) {
|
||||
return new RealmIdentityManagerProvider(partitionManagerRegistry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
partitionManagerRegistry = new PartitionManagerRegistry();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "realm";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean lazyLoad() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.keycloak.picketlink.realm.RealmIdentityManagerProviderFactory
|
24
picketlink/pom.xml
Normal file
24
picketlink/pom.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.0-beta-1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<artifactId>keycloak-picketlink</artifactId>
|
||||
<name>Keycloak Picketlink</name>
|
||||
<description />
|
||||
|
||||
<modules>
|
||||
<module>keycloak-picketlink-api</module>
|
||||
<module>keycloak-picketlink-realm</module>
|
||||
</modules>
|
||||
|
||||
|
||||
</project>
|
1
pom.xml
1
pom.xml
|
@ -91,6 +91,7 @@
|
|||
<module>core-jaxrs</module>
|
||||
<module>model</module>
|
||||
<module>integration</module>
|
||||
<module>picketlink</module>
|
||||
<module>services</module>
|
||||
<module>social</module>
|
||||
<module>forms</module>
|
||||
|
|
|
@ -152,6 +152,16 @@
|
|||
<artifactId>keycloak-timer-basic</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-picketlink-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-picketlink-realm</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
|
|
|
@ -87,6 +87,12 @@
|
|||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-picketlink-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
|
|
|
@ -2,8 +2,10 @@ package org.keycloak.services;
|
|||
|
||||
import org.keycloak.provider.Provider;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -29,7 +31,7 @@ public class DefaultProviderSession implements ProviderSession {
|
|||
if (provider == null) {
|
||||
ProviderFactory<T> providerFactory = factory.getProviderFactory(clazz, id);
|
||||
if (providerFactory != null) {
|
||||
provider = providerFactory.create();
|
||||
provider = providerFactory.create(this);
|
||||
providers.put(hash, provider);
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +42,16 @@ public class DefaultProviderSession implements ProviderSession {
|
|||
return factory.providerIds(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Provider> Set<T> getAllProviders(Class<T> clazz) {
|
||||
Set<String> providerIds = listProviderIds(clazz);
|
||||
Set<T> providers = new HashSet<T>();
|
||||
for (String providerId : providerIds) {
|
||||
providers.add(getProvider(clazz, providerId));
|
||||
}
|
||||
return providers;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
for (Provider p : providers.values()) {
|
||||
p.close();
|
||||
|
|
|
@ -3,6 +3,8 @@ package org.keycloak.services;
|
|||
import org.keycloak.provider.Provider;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
import org.keycloak.provider.ProviderFactoryLoader;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.provider.ProviderSessionFactory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
|
|
@ -4,9 +4,8 @@ import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
|||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.models.KeycloakTransaction;
|
||||
import org.keycloak.services.ProviderSession;
|
||||
import org.keycloak.services.ProviderSessionFactory;
|
||||
import org.keycloak.util.KeycloakRegistry;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.provider.ProviderSessionFactory;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
|
@ -33,9 +32,7 @@ public class KeycloakSessionServletFilter implements Filter {
|
|||
|
||||
ResteasyProviderFactory.pushContext(ProviderSession.class, providerSession);
|
||||
|
||||
KeycloakRegistry registry = (KeycloakRegistry)servletRequest.getServletContext().getAttribute(KeycloakRegistry.class.getName());
|
||||
ResteasyProviderFactory.pushContext(KeycloakRegistry.class, registry);
|
||||
KeycloakSessionFactory factory = registry.getService(KeycloakSessionFactory.class);
|
||||
KeycloakSessionFactory factory = (KeycloakSessionFactory) servletRequest.getServletContext().getAttribute(KeycloakSessionFactory.class.getName());
|
||||
if (factory == null) throw new ServletException("Factory was null");
|
||||
KeycloakSession session = factory.createSession();
|
||||
ResteasyProviderFactory.pushContext(KeycloakSession.class, session);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package org.keycloak.services.listeners;
|
||||
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.util.KeycloakRegistry;
|
||||
import org.keycloak.provider.ProviderSessionFactory;
|
||||
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
|
@ -17,10 +17,13 @@ public class KeycloakSessionDestroyListener implements ServletContextListener {
|
|||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce) {
|
||||
KeycloakRegistry registry = (KeycloakRegistry)sce.getServletContext().getAttribute(KeycloakRegistry.class.getName());
|
||||
KeycloakSessionFactory factory = registry.getService(KeycloakSessionFactory.class);
|
||||
if (factory != null) {
|
||||
factory.close();
|
||||
ProviderSessionFactory providerSessionFactory = (ProviderSessionFactory) sce.getServletContext().getAttribute(ProviderSessionFactory.class.getName());
|
||||
KeycloakSessionFactory kcSessionFactory = (KeycloakSessionFactory) sce.getServletContext().getAttribute(KeycloakSessionFactory.class.getName());
|
||||
if (providerSessionFactory != null) {
|
||||
providerSessionFactory.close();
|
||||
}
|
||||
if (kcSessionFactory != null) {
|
||||
kcSessionFactory.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.keycloak.models.ApplicationModel;
|
|||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
|
||||
import javax.ws.rs.BadRequestException;
|
||||
|
@ -26,12 +27,13 @@ import java.net.URI;
|
|||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class AppAuthManager extends AuthenticationManager {
|
||||
protected static Logger logger = Logger.getLogger(AuthenticationManager.class);
|
||||
protected static Logger logger = Logger.getLogger(AppAuthManager.class);
|
||||
|
||||
private String cookieName;
|
||||
private TokenManager tokenManager;
|
||||
|
||||
public AppAuthManager(String cookieName, TokenManager tokenManager) {
|
||||
public AppAuthManager(ProviderSession providerSession, String cookieName, TokenManager tokenManager) {
|
||||
super(providerSession);
|
||||
this.cookieName = cookieName;
|
||||
this.tokenManager = tokenManager;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import org.keycloak.audit.AuditListener;
|
|||
import org.keycloak.audit.AuditProvider;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.services.ClientConnection;
|
||||
import org.keycloak.services.ProviderSession;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.keycloak.models.RealmModel;
|
|||
import org.keycloak.models.RequiredCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.services.ClientConnection;
|
||||
|
@ -42,9 +43,11 @@ public class AuthenticationManager {
|
|||
public static final String KEYCLOAK_IDENTITY_COOKIE = "KEYCLOAK_IDENTITY";
|
||||
public static final String KEYCLOAK_REMEMBER_ME = "KEYCLOAK_REMEMBER_ME";
|
||||
|
||||
protected ProviderSession providerSession;
|
||||
protected BruteForceProtector protector;
|
||||
|
||||
public AuthenticationManager() {
|
||||
public AuthenticationManager(ProviderSession providerSession) {
|
||||
this.providerSession = providerSession;
|
||||
}
|
||||
|
||||
public AuthenticationManager(BruteForceProtector protector) {
|
||||
|
@ -222,7 +225,7 @@ public class AuthenticationManager {
|
|||
protected AuthenticationStatus authenticateInternal(RealmModel realm, MultivaluedMap<String, String> formData, String username) {
|
||||
UserModel user = KeycloakModelUtils.findUserByNameOrEmail(realm, username);
|
||||
if (user == null) {
|
||||
AuthUser authUser = AuthenticationProviderManager.getManager(realm).getUser(username);
|
||||
AuthUser authUser = AuthenticationProviderManager.getManager(realm, providerSession).getUser(username);
|
||||
if (authUser != null) {
|
||||
// Create new user and link him with authentication provider
|
||||
user = realm.addUser(authUser.getUsername());
|
||||
|
@ -269,7 +272,7 @@ public class AuthenticationManager {
|
|||
} else {
|
||||
logger.debug("validating password for user: " + username);
|
||||
|
||||
AuthProviderStatus authStatus = AuthenticationProviderManager.getManager(realm).validatePassword(user, password);
|
||||
AuthProviderStatus authStatus = AuthenticationProviderManager.getManager(realm, providerSession).validatePassword(user, password);
|
||||
if (authStatus == AuthProviderStatus.INVALID_CREDENTIALS) {
|
||||
logger.debug("invalid password for user: " + username);
|
||||
return AuthenticationStatus.INVALID_CREDENTIALS;
|
||||
|
|
|
@ -45,7 +45,7 @@ import org.keycloak.models.UserCredentialModel;
|
|||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.TimeBasedOTP;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.services.ProviderSession;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.services.managers.AppAuthManager;
|
||||
import org.keycloak.services.managers.Auth;
|
||||
import org.keycloak.services.managers.ModelToRepresentation;
|
||||
|
@ -137,7 +137,7 @@ public class AccountService {
|
|||
this.realm = realm;
|
||||
this.application = application;
|
||||
this.audit = audit;
|
||||
this.authManager = new AppAuthManager(KEYCLOAK_ACCOUNT_IDENTITY_COOKIE, tokenManager);
|
||||
this.authManager = new AppAuthManager(providers, KEYCLOAK_ACCOUNT_IDENTITY_COOKIE, tokenManager);
|
||||
this.socialRequestManager = socialRequestManager;
|
||||
}
|
||||
|
||||
|
@ -339,7 +339,7 @@ public class AccountService {
|
|||
return account.setError(Messages.INVALID_PASSWORD_CONFIRM).createResponse(AccountPages.PASSWORD);
|
||||
}
|
||||
|
||||
AuthenticationProviderManager authProviderManager = AuthenticationProviderManager.getManager(realm);
|
||||
AuthenticationProviderManager authProviderManager = AuthenticationProviderManager.getManager(realm, providers);
|
||||
if (Validation.isEmpty(password)) {
|
||||
return account.setError(Messages.MISSING_PASSWORD).createResponse(AccountPages.PASSWORD);
|
||||
} else if (authProviderManager.validatePassword(user, password) != AuthProviderStatus.SUCCESS) {
|
||||
|
|
|
@ -6,6 +6,8 @@ import org.keycloak.audit.AuditListener;
|
|||
import org.keycloak.audit.AuditListenerFactory;
|
||||
import org.keycloak.audit.AuditProvider;
|
||||
import org.keycloak.audit.AuditProviderFactory;
|
||||
import org.keycloak.authentication.AuthenticationProvider;
|
||||
import org.keycloak.authentication.AuthenticationProviderFactory;
|
||||
import org.keycloak.models.Config;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
|
@ -14,15 +16,16 @@ import org.keycloak.models.RealmModel;
|
|||
import org.keycloak.provider.ProviderFactory;
|
||||
import org.keycloak.provider.ProviderFactoryLoader;
|
||||
import org.keycloak.services.DefaultProviderSessionFactory;
|
||||
import org.keycloak.services.ProviderSessionFactory;
|
||||
import org.keycloak.timer.TimerProvider;
|
||||
import org.keycloak.timer.TimerProviderFactory;
|
||||
import org.keycloak.util.KeycloakRegistry;
|
||||
import org.keycloak.picketlink.IdentityManagerProvider;
|
||||
import org.keycloak.picketlink.IdentityManagerProviderFactory;
|
||||
import org.keycloak.provider.ProviderSessionFactory;
|
||||
import org.keycloak.services.managers.ApplianceBootstrap;
|
||||
import org.keycloak.services.managers.SocialRequestManager;
|
||||
import org.keycloak.services.managers.TokenManager;
|
||||
import org.keycloak.services.resources.admin.AdminService;
|
||||
import org.keycloak.models.utils.ModelProviderUtils;
|
||||
import org.keycloak.timer.TimerProvider;
|
||||
import org.keycloak.timer.TimerProviderFactory;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.ws.rs.core.Application;
|
||||
|
@ -45,19 +48,17 @@ public class KeycloakApplication extends Application {
|
|||
protected Set<Class<?>> classes = new HashSet<Class<?>>();
|
||||
|
||||
protected KeycloakSessionFactory factory;
|
||||
protected ProviderSessionFactory providerSessionFactory;
|
||||
protected String contextPath;
|
||||
|
||||
public KeycloakApplication(@Context ServletContext context) {
|
||||
this.factory = createSessionFactory();
|
||||
this.contextPath = context.getContextPath();
|
||||
KeycloakRegistry registry = new KeycloakRegistry();
|
||||
registry.putService(KeycloakSessionFactory.class, factory);
|
||||
context.setAttribute(KeycloakRegistry.class.getName(), registry);
|
||||
this.providerSessionFactory = createProviderSessionFactory();
|
||||
context.setAttribute(KeycloakSessionFactory.class.getName(), factory);
|
||||
//classes.add(KeycloakSessionCleanupFilter.class);
|
||||
|
||||
DefaultProviderSessionFactory providerSessionFactory = createProviderSessionFactory();
|
||||
|
||||
context.setAttribute(ProviderSessionFactory.class.getName(), providerSessionFactory);
|
||||
context.setAttribute(ProviderSessionFactory.class.getName(), this.providerSessionFactory);
|
||||
|
||||
TokenManager tokenManager = new TokenManager();
|
||||
SocialRequestManager socialRequestManager = new SocialRequestManager();
|
||||
|
@ -110,6 +111,9 @@ public class KeycloakApplication extends Application {
|
|||
factory.registerLoader(AuditProvider.class, ProviderFactoryLoader.create(AuditProviderFactory.class), Config.getAuditProvider());
|
||||
factory.registerLoader(AuditListener.class, ProviderFactoryLoader.create(AuditListenerFactory.class));
|
||||
factory.registerLoader(TimerProvider.class, ProviderFactoryLoader.create(TimerProviderFactory.class), Config.getTimerProvider());
|
||||
factory.registerLoader(IdentityManagerProvider.class, ProviderFactoryLoader.create(IdentityManagerProviderFactory.class), Config.getIdentityManagerProvider());
|
||||
factory.registerLoader(AuthenticationProvider.class, ProviderFactoryLoader.create(AuthenticationProviderFactory.class));
|
||||
factory.init();
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
@ -120,7 +124,7 @@ public class KeycloakApplication extends Application {
|
|||
log.error("Can't setup schedule tasks, no timer provider found");
|
||||
return;
|
||||
}
|
||||
TimerProvider timer = timerFactory.create();
|
||||
TimerProvider timer = timerFactory.create(null);
|
||||
|
||||
final ProviderFactory<AuditProvider> auditFactory = providerSessionFactory.getProviderFactory(AuditProvider.class);
|
||||
if (auditFactory != null) {
|
||||
|
@ -128,7 +132,7 @@ public class KeycloakApplication extends Application {
|
|||
@Override
|
||||
public void run() {
|
||||
KeycloakSession keycloakSession = keycloakSessionFactory.createSession();
|
||||
AuditProvider audit = providerSessionFactory.getProviderFactory(AuditProvider.class).create();
|
||||
AuditProvider audit = providerSessionFactory.getProviderFactory(AuditProvider.class).create(null);
|
||||
try {
|
||||
for (RealmModel realm : keycloakSession.getRealms()) {
|
||||
if (realm.isAuditEnabled() && realm.getAuditExpiration() > 0) {
|
||||
|
@ -152,6 +156,10 @@ public class KeycloakApplication extends Application {
|
|||
return factory;
|
||||
}
|
||||
|
||||
public ProviderSessionFactory getProviderSessionFactory() {
|
||||
return providerSessionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Class<?>> getClasses() {
|
||||
return classes;
|
||||
|
|
|
@ -2,20 +2,18 @@ package org.keycloak.services.resources;
|
|||
|
||||
import org.jboss.resteasy.logging.Logger;
|
||||
import org.keycloak.audit.Audit;
|
||||
import org.keycloak.audit.AuditListener;
|
||||
import org.keycloak.audit.AuditProvider;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.services.ClientConnection;
|
||||
import org.keycloak.services.ProviderSession;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.services.managers.AuditManager;
|
||||
import org.keycloak.services.managers.AuthenticationManager;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.managers.SocialRequestManager;
|
||||
import org.keycloak.services.managers.TokenManager;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.NotFoundException;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
|
@ -24,8 +22,6 @@ import javax.ws.rs.core.Context;
|
|||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -70,7 +66,8 @@ public class RealmsResource {
|
|||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel realm = locateRealm(name, realmManager);
|
||||
Audit audit = new AuditManager(realm, providers, clientConnection).createAudit();
|
||||
TokenService tokenService = new TokenService(realm, tokenManager, audit);
|
||||
AuthenticationManager authManager = new AuthenticationManager(providers);
|
||||
TokenService tokenService = new TokenService(realm, tokenManager, audit, authManager);
|
||||
resourceContext.initResource(tokenService);
|
||||
return tokenService;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.keycloak.models.UserCredentialModel;
|
|||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserModel.RequiredAction;
|
||||
import org.keycloak.models.utils.TimeBasedOTP;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.services.email.EmailException;
|
||||
import org.keycloak.services.email.EmailSender;
|
||||
|
@ -84,7 +85,8 @@ public class RequiredActionsService {
|
|||
@Context
|
||||
protected Providers providers;
|
||||
|
||||
protected AuthenticationManager authManager = new AuthenticationManager();
|
||||
@Context
|
||||
protected ProviderSession providerSession;
|
||||
|
||||
private TokenManager tokenManager;
|
||||
|
||||
|
@ -200,7 +202,7 @@ public class RequiredActionsService {
|
|||
}
|
||||
|
||||
try {
|
||||
boolean updateSuccessful = AuthenticationProviderManager.getManager(realm).updatePassword(user, passwordNew);
|
||||
boolean updateSuccessful = AuthenticationProviderManager.getManager(realm, providerSession).updatePassword(user, passwordNew);
|
||||
if (!updateSuccessful) {
|
||||
return loginForms.setError("Password update failed").createResponse(RequiredAction.UPDATE_PASSWORD);
|
||||
}
|
||||
|
@ -285,6 +287,8 @@ public class RequiredActionsService {
|
|||
String redirect = uriInfo.getQueryParameters().getFirst(OAuth2Constants.REDIRECT_URI);
|
||||
String clientId = uriInfo.getQueryParameters().getFirst(OAuth2Constants.CLIENT_ID);
|
||||
|
||||
AuthenticationManager authManager = new AuthenticationManager(providerSession);
|
||||
|
||||
ClientModel client = realm.findClient(clientId);
|
||||
if (client == null) {
|
||||
return Flows.oauth(realm, request, uriInfo, authManager, tokenManager).forwardToSecurityFailure(
|
||||
|
@ -392,6 +396,9 @@ public class RequiredActionsService {
|
|||
accessCode.setExpiration(Time.currentTime() + realm.getAccessCodeLifespan());
|
||||
|
||||
audit.success();
|
||||
|
||||
AuthenticationManager authManager = new AuthenticationManager(providerSession);
|
||||
|
||||
return Flows.oauth(realm, request, uriInfo, authManager, tokenManager).redirectAccessCode(accessCode,
|
||||
accessCode.getState(), accessCode.getRedirectUri());
|
||||
}
|
||||
|
|
|
@ -25,8 +25,6 @@ import org.jboss.resteasy.logging.Logger;
|
|||
import org.jboss.resteasy.spi.HttpRequest;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.audit.Audit;
|
||||
import org.keycloak.audit.AuditListener;
|
||||
import org.keycloak.audit.AuditProvider;
|
||||
import org.keycloak.audit.Details;
|
||||
import org.keycloak.audit.Errors;
|
||||
import org.keycloak.audit.Events;
|
||||
|
@ -39,7 +37,7 @@ import org.keycloak.models.SocialLinkModel;
|
|||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.services.ClientConnection;
|
||||
import org.keycloak.services.ProviderSession;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.services.managers.AuditManager;
|
||||
import org.keycloak.services.managers.AuthenticationManager;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
|
@ -57,7 +55,6 @@ import org.keycloak.social.SocialProviderConfig;
|
|||
import org.keycloak.social.SocialProviderException;
|
||||
import org.keycloak.social.SocialUser;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
|
@ -72,7 +69,6 @@ import javax.ws.rs.core.UriBuilder;
|
|||
import javax.ws.rs.core.UriInfo;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
@ -110,8 +106,6 @@ public class SocialResource {
|
|||
|
||||
private TokenManager tokenManager;
|
||||
|
||||
private AuthenticationManager authManager = new AuthenticationManager();
|
||||
|
||||
public SocialResource(TokenManager tokenManager, SocialRequestManager socialRequestManager) {
|
||||
this.tokenManager = tokenManager;
|
||||
this.socialRequestManager = socialRequestManager;
|
||||
|
@ -135,6 +129,7 @@ public class SocialResource {
|
|||
.detail(Details.RESPONSE_TYPE, "code")
|
||||
.detail(Details.AUTH_METHOD, "social@" + provider.getId());
|
||||
|
||||
AuthenticationManager authManager = new AuthenticationManager(providers);
|
||||
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
|
||||
|
||||
if (!realm.isEnabled()) {
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.keycloak.models.RequiredCredentialModel;
|
|||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.AccessTokenResponse;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
|
@ -79,7 +80,7 @@ public class TokenService {
|
|||
protected RealmModel realm;
|
||||
protected TokenManager tokenManager;
|
||||
private Audit audit;
|
||||
protected AuthenticationManager authManager = new AuthenticationManager();
|
||||
protected AuthenticationManager authManager;
|
||||
|
||||
@Context
|
||||
protected Providers providers;
|
||||
|
@ -99,16 +100,19 @@ public class TokenService {
|
|||
protected KeycloakTransaction transaction;
|
||||
@Context
|
||||
protected ClientConnection clientConnection;
|
||||
@Context
|
||||
protected ProviderSession providerSession;
|
||||
|
||||
@Context
|
||||
protected ResourceContext resourceContext;
|
||||
|
||||
private ResourceAdminManager resourceAdminManager = new ResourceAdminManager();
|
||||
|
||||
public TokenService(RealmModel realm, TokenManager tokenManager, Audit audit) {
|
||||
public TokenService(RealmModel realm, TokenManager tokenManager, Audit audit, AuthenticationManager authManager) {
|
||||
this.realm = realm;
|
||||
this.tokenManager = tokenManager;
|
||||
this.audit = audit;
|
||||
this.authManager = authManager;
|
||||
}
|
||||
|
||||
public static UriBuilder tokenServiceBaseUrl(UriInfo uriInfo) {
|
||||
|
@ -383,7 +387,7 @@ public class TokenService {
|
|||
return Flows.forms(realm, request, uriInfo).setError(error).setFormData(formData).createRegistration();
|
||||
}
|
||||
|
||||
AuthenticationProviderManager authenticationProviderManager = AuthenticationProviderManager.getManager(realm);
|
||||
AuthenticationProviderManager authenticationProviderManager = AuthenticationProviderManager.getManager(realm, providerSession);
|
||||
|
||||
// Validate that user with this username doesn't exist in realm or any authentication provider
|
||||
if (realm.getUser(username) != null || authenticationProviderManager.getUser(username) != null) {
|
||||
|
@ -406,7 +410,7 @@ public class TokenService {
|
|||
boolean passwordUpdateSuccessful;
|
||||
String passwordUpdateError = null;
|
||||
try {
|
||||
passwordUpdateSuccessful = AuthenticationProviderManager.getManager(realm).updatePassword(user, formData.getFirst("password"));
|
||||
passwordUpdateSuccessful = AuthenticationProviderManager.getManager(realm, providerSession).updatePassword(user, formData.getFirst("password"));
|
||||
passwordUpdateError = "Password update failed";
|
||||
} catch (AuthenticationProviderException ape) {
|
||||
passwordUpdateSuccessful = false;
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.keycloak.models.KeycloakSession;
|
|||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.services.managers.AppAuthManager;
|
||||
import org.keycloak.services.managers.Auth;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
|
@ -69,13 +70,16 @@ public class AdminService {
|
|||
@Context
|
||||
protected Providers providers;
|
||||
|
||||
@Context
|
||||
protected ProviderSession providerSession;
|
||||
|
||||
protected String adminPath = "/admin/index.html";
|
||||
protected AppAuthManager authManager;
|
||||
protected TokenManager tokenManager;
|
||||
|
||||
public AdminService(TokenManager tokenManager) {
|
||||
this.tokenManager = tokenManager;
|
||||
this.authManager = new AppAuthManager("KEYCLOAK_ADMIN_CONSOLE_IDENTITY", tokenManager);
|
||||
this.authManager = new AppAuthManager(providerSession, "KEYCLOAK_ADMIN_CONSOLE_IDENTITY", tokenManager);
|
||||
}
|
||||
|
||||
public static UriBuilder adminApiUrl(UriInfo uriInfo) {
|
||||
|
|
|
@ -11,7 +11,7 @@ import org.keycloak.models.RealmModel;
|
|||
import org.keycloak.representations.adapters.action.SessionStats;
|
||||
import org.keycloak.representations.idm.RealmAuditRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.services.ProviderSession;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.services.managers.ModelToRepresentation;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.managers.ResourceAdminManager;
|
||||
|
|
|
@ -3,7 +3,7 @@ package org.keycloak.services.resources.admin;
|
|||
import org.keycloak.audit.AuditListener;
|
||||
import org.keycloak.freemarker.Theme;
|
||||
import org.keycloak.freemarker.ThemeProvider;
|
||||
import org.keycloak.services.ProviderSession;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.social.SocialProvider;
|
||||
import org.keycloak.authentication.AuthenticationProvider;
|
||||
import org.keycloak.authentication.AuthenticationProviderManager;
|
||||
|
@ -59,7 +59,7 @@ public class ServerInfoAdminResource {
|
|||
|
||||
private void setAuthProviders(ServerInfoRepresentation info) {
|
||||
info.authProviders = new HashMap<String, List<String>>();
|
||||
Iterable<AuthenticationProvider> authProviders = AuthenticationProviderManager.load();
|
||||
Iterable<AuthenticationProvider> authProviders = providers.getAllProviders(AuthenticationProvider.class);
|
||||
for (AuthenticationProvider authProvider : authProviders) {
|
||||
info.authProviders.put(authProvider.getName(), authProvider.getAvailableOptions());
|
||||
}
|
||||
|
|
|
@ -170,6 +170,16 @@
|
|||
<artifactId>keycloak-authentication-model</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-picketlink-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-picketlink-realm</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
|
@ -186,7 +196,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.picketlink</groupId>
|
||||
<artifactId>picketlink-idm-impl</artifactId>
|
||||
<artifactId>picketlink-idm-idm</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.picketlink</groupId>
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.jboss.resteasy.logging.Logger;
|
|||
import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer;
|
||||
import org.jboss.resteasy.spi.ResteasyDeployment;
|
||||
import org.keycloak.models.Config;
|
||||
import org.keycloak.provider.ProviderSessionFactory;
|
||||
import org.keycloak.services.filters.ClientConnectionFilter;
|
||||
import org.keycloak.theme.DefaultLoginThemeProvider;
|
||||
import org.keycloak.services.tmp.TmpAdminRedirectServlet;
|
||||
|
@ -173,6 +174,8 @@ public class KeycloakServer {
|
|||
|
||||
private KeycloakSessionFactory factory;
|
||||
|
||||
private ProviderSessionFactory providerSessionFactory;
|
||||
|
||||
private UndertowJaxrsServer server;
|
||||
|
||||
public KeycloakServer() {
|
||||
|
@ -187,6 +190,10 @@ public class KeycloakServer {
|
|||
return factory;
|
||||
}
|
||||
|
||||
public ProviderSessionFactory getProviderSessionFactory() {
|
||||
return providerSessionFactory;
|
||||
}
|
||||
|
||||
public UndertowJaxrsServer getServer() {
|
||||
return server;
|
||||
}
|
||||
|
@ -275,6 +282,7 @@ public class KeycloakServer {
|
|||
server.deploy(di);
|
||||
|
||||
factory = ((KeycloakApplication) deployment.getApplication()).getFactory();
|
||||
providerSessionFactory = ((KeycloakApplication) deployment.getApplication()).getProviderSessionFactory();
|
||||
|
||||
setupDevConfig();
|
||||
|
||||
|
@ -295,6 +303,7 @@ public class KeycloakServer {
|
|||
}
|
||||
|
||||
public void stop() {
|
||||
providerSessionFactory.close();
|
||||
factory.close();
|
||||
server.stop();
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.keycloak.models.ClientModel;
|
|||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.testsuite.rule.KeycloakRule;
|
||||
|
@ -165,7 +166,7 @@ public class AssertEvents implements TestRule, AuditListenerFactory {
|
|||
}
|
||||
|
||||
@Override
|
||||
public AuditListener create() {
|
||||
public AuditListener create(ProviderSession providerSession) {
|
||||
return new AuditListener() {
|
||||
@Override
|
||||
public void onEvent(Event event) {
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.keycloak.testsuite.pages.AccountUpdateProfilePage;
|
|||
import org.keycloak.testsuite.pages.AppPage;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
import org.keycloak.testsuite.pages.RegisterPage;
|
||||
import org.keycloak.testsuite.rule.AbstractKeycloakRule;
|
||||
import org.keycloak.testsuite.rule.KeycloakRule;
|
||||
import org.keycloak.testsuite.rule.LDAPRule;
|
||||
import org.keycloak.testsuite.rule.WebResource;
|
||||
|
@ -62,7 +63,7 @@ public class AuthProvidersIntegrationTest {
|
|||
|
||||
// Configure LDAP
|
||||
ldapRule.getEmbeddedServer().setupLdapInRealm(appRealm);
|
||||
LdapTestUtils.setLdapPassword(appRealm, "john", "password");
|
||||
LdapTestUtils.setLdapPassword(providerSession, appRealm, "john", "password");
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ package org.keycloak.testsuite.rule;
|
|||
import org.keycloak.models.Config;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.testsuite.ApplicationServlet;
|
||||
|
||||
|
@ -58,6 +59,7 @@ public class KeycloakRule extends AbstractKeycloakRule {
|
|||
|
||||
public void configure(KeycloakSetup configurer) {
|
||||
KeycloakSession session = server.getKeycloakSessionFactory().createSession();
|
||||
ProviderSession providerSession = server.getProviderSessionFactory().createSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
try {
|
||||
|
@ -66,17 +68,21 @@ public class KeycloakRule extends AbstractKeycloakRule {
|
|||
RealmModel adminstrationRealm = manager.getRealm(Config.getAdminRealm());
|
||||
RealmModel appRealm = manager.getRealm("test");
|
||||
|
||||
configurer.providerSession = providerSession;
|
||||
configurer.config(manager, adminstrationRealm, appRealm);
|
||||
|
||||
session.getTransaction().commit();
|
||||
} finally {
|
||||
providerSession.close();
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
|
||||
public interface KeycloakSetup {
|
||||
public abstract static class KeycloakSetup {
|
||||
|
||||
void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm);
|
||||
protected ProviderSession providerSession;
|
||||
|
||||
public abstract void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -161,7 +161,7 @@
|
|||
<!--
|
||||
<dependency>
|
||||
<groupId>org.picketlink</groupId>
|
||||
<artifactId>picketlink-idm-impl</artifactId>
|
||||
<artifactId>picketlink-idm-idm</artifactId>
|
||||
<version>${picketlink.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.keycloak.timer.basic;
|
||||
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.timer.TimerProvider;
|
||||
import org.keycloak.timer.TimerProviderFactory;
|
||||
|
||||
|
@ -13,7 +14,7 @@ public class BasicTimerProviderFactory implements TimerProviderFactory {
|
|||
private Timer timer;
|
||||
|
||||
@Override
|
||||
public TimerProvider create() {
|
||||
public TimerProvider create(ProviderSession providerSession) {
|
||||
return new BasicTimerProvider(timer);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue