fixes for new user fed spi
This commit is contained in:
parent
a19469aba5
commit
7e5a5f79cf
24 changed files with 320 additions and 156 deletions
|
@ -16,6 +16,40 @@ import java.util.Set;
|
|||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
*
|
||||
* Some notes on how this works:
|
||||
|
||||
* This implementation manages optimistic locking and version checks itself. The reason is Infinispan just does behave
|
||||
* the way we need it to. Not saying Infinispan is bad, just that we have specific caching requirements!
|
||||
*
|
||||
* This is an invalidation cache implementation and requires to caches:
|
||||
* Cache 1 is an Invalidation Cache
|
||||
* Cache 2 is a local-only revision number cache.
|
||||
*
|
||||
*
|
||||
* Each node in the cluster maintains its own revision number cache for each entry in the main invalidation cache. This revision
|
||||
* cache holds the version counter for each cached entity.
|
||||
*
|
||||
* Cache listeners do not receive a @CacheEntryInvalidated event if that node does not have an entry for that item. So, consider the following.
|
||||
|
||||
1. Node 1 gets current counter for user. There currently isn't one as this user isn't cached.
|
||||
2. Node 1 reads user from DB
|
||||
3. Node 2 updates user
|
||||
4. Node 2 calls cache.remove(user). This does not result in an invalidation listener event to node 1!
|
||||
5. node 1 checks version counter, checks pass. Stale entry is cached.
|
||||
|
||||
The issue is that Node 1 doesn't have an entry for the user, so it never receives an invalidation listener event from Node 2 thus it can't bump the version. So, when node 1 goes to cache the user it is stale as the version number was never bumped.
|
||||
|
||||
So how is this issue fixed? here is pseudo code:
|
||||
|
||||
1. Node 1 calls cacheManager.getCurrentRevision() to get the current local version counter of that User
|
||||
2. Node 1 getCurrentRevision() pulls current counter for that user
|
||||
3. Node 1 getCurrentRevision() adds a "invalidation.key.userid" to invalidation cache. Its just a marker. nothing else
|
||||
4. Node 2 update user
|
||||
5. Node 2 does a cache.remove(user) cache.remove(invalidation.key.userid)
|
||||
6. Node 1 receives invalidation event for invalidation.key.userid. Bumps the version counter for that user
|
||||
7. node 1 version check fails, it doesn't cache the user
|
||||
*
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
|
|
|
@ -29,6 +29,8 @@ import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
|||
@Ignore
|
||||
public class ClusteredCacheBehaviorTest {
|
||||
public EmbeddedCacheManager createManager() {
|
||||
System.setProperty("java.net.preferIPv4Stack", "true");
|
||||
System.setProperty("jgroups.tcp.port", "53715");
|
||||
GlobalConfigurationBuilder gcb = new GlobalConfigurationBuilder();
|
||||
|
||||
boolean clustered = true;
|
||||
|
@ -36,7 +38,8 @@ public class ClusteredCacheBehaviorTest {
|
|||
boolean allowDuplicateJMXDomains = true;
|
||||
|
||||
if (clustered) {
|
||||
gcb.transport().defaultTransport();
|
||||
gcb = gcb.clusteredDefault();
|
||||
gcb.transport().clusterName("test-clustering");
|
||||
}
|
||||
gcb.globalJmxStatistics().allowDuplicateDomains(allowDuplicateJMXDomains);
|
||||
|
||||
|
|
|
@ -149,8 +149,8 @@ public class JpaUserFederatedStorageProvider implements
|
|||
|
||||
@Override
|
||||
public String getUserByFederatedIdentity(FederatedIdentityModel link, RealmModel realm) {
|
||||
TypedQuery<String> query = em.createNamedQuery("findBrokerLinkByUserAndProvider", String.class)
|
||||
.setParameter("realmid", realm.getId())
|
||||
TypedQuery<String> query = em.createNamedQuery("findUserByBrokerLinkAndRealm", String.class)
|
||||
.setParameter("realmId", realm.getId())
|
||||
.setParameter("identityProvider", link.getIdentityProvider())
|
||||
.setParameter("brokerUserId", link.getUserId());
|
||||
List<String> results = query.getResultList();
|
||||
|
@ -180,15 +180,16 @@ public class JpaUserFederatedStorageProvider implements
|
|||
|
||||
@Override
|
||||
public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider) {
|
||||
BrokerLinkEntity entity = getBrokerLinkEntity(user, socialProvider);
|
||||
BrokerLinkEntity entity = getBrokerLinkEntity(realm, user, socialProvider);
|
||||
if (entity == null) return false;
|
||||
em.remove(entity);
|
||||
return true;
|
||||
}
|
||||
|
||||
private BrokerLinkEntity getBrokerLinkEntity(UserModel user, String socialProvider) {
|
||||
private BrokerLinkEntity getBrokerLinkEntity(RealmModel realm, UserModel user, String socialProvider) {
|
||||
TypedQuery<BrokerLinkEntity> query = em.createNamedQuery("findBrokerLinkByUserAndProvider", BrokerLinkEntity.class)
|
||||
.setParameter("userId", user.getId())
|
||||
.setParameter("realmId", realm.getId())
|
||||
.setParameter("identityProvider", socialProvider);
|
||||
List<BrokerLinkEntity> results = query.getResultList();
|
||||
return results.size() > 0 ? results.get(0) : null;
|
||||
|
@ -196,7 +197,7 @@ public class JpaUserFederatedStorageProvider implements
|
|||
|
||||
@Override
|
||||
public void updateFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel model) {
|
||||
BrokerLinkEntity entity = getBrokerLinkEntity(user, model.getIdentityProvider());
|
||||
BrokerLinkEntity entity = getBrokerLinkEntity(realm, user, model.getIdentityProvider());
|
||||
if (entity == null) return;
|
||||
entity.setBrokerUserName(model.getUserName());
|
||||
entity.setBrokerUserId(model.getUserId());
|
||||
|
@ -221,7 +222,7 @@ public class JpaUserFederatedStorageProvider implements
|
|||
|
||||
@Override
|
||||
public FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm) {
|
||||
BrokerLinkEntity entity = getBrokerLinkEntity(user, socialProvider);
|
||||
BrokerLinkEntity entity = getBrokerLinkEntity(realm, user, socialProvider);
|
||||
if (entity == null) return null;
|
||||
return new FederatedIdentityModel(entity.getIdentityProvider(), entity.getBrokerUserId(), entity.getBrokerUserName(), entity.getToken());
|
||||
}
|
||||
|
@ -239,6 +240,7 @@ public class JpaUserFederatedStorageProvider implements
|
|||
consentEntity.setId(KeycloakModelUtils.generateId());
|
||||
consentEntity.setUserId(user.getId());
|
||||
consentEntity.setClientId(clientId);
|
||||
consentEntity.setRealmId(realm.getId());
|
||||
consentEntity.setStorageProviderId(StorageId.resolveProviderId(user));
|
||||
em.persist(consentEntity);
|
||||
em.flush();
|
||||
|
@ -588,7 +590,7 @@ public class JpaUserFederatedStorageProvider implements
|
|||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm) {
|
||||
int num = em.createNamedQuery("deleteUserConsentRolesByRealm")
|
||||
int num = em.createNamedQuery("deleteFederatedUserConsentRolesByRealm")
|
||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||
num = em.createNamedQuery("deleteFederatedUserConsentProtMappersByRealm")
|
||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||
|
|
|
@ -21,6 +21,7 @@ import javax.persistence.Column;
|
|||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
|
@ -32,7 +33,7 @@ import java.io.Serializable;
|
|||
*/
|
||||
@NamedQueries({
|
||||
@NamedQuery(name= "findBrokerLinkByUser", query="select link from BrokerLinkEntity link where link.userId = :userId"),
|
||||
@NamedQuery(name= "findBrokerLinkByUserAndProvider", query="select link from BrokerLinkEntity link where link.userId = :userId and link.identityProvider = :identityProvider"),
|
||||
@NamedQuery(name= "findBrokerLinkByUserAndProvider", query="select link from BrokerLinkEntity link where link.userId = :userId and link.identityProvider = :identityProvider and link.realmId = :realmId"),
|
||||
@NamedQuery(name= "findUserByBrokerLinkAndRealm", query="select link.userId from BrokerLinkEntity link where link.realmId = :realmId and link.identityProvider = :identityProvider and link.brokerUserId = :brokerUserId"),
|
||||
@NamedQuery(name= "deleteBrokerLinkByStorageProvider", query="delete from BrokerLinkEntity social where social.storageProviderId = :storageProviderId"),
|
||||
@NamedQuery(name= "deleteBrokerLinkByRealm", query="delete from BrokerLinkEntity social where social.realmId = :realmId"),
|
||||
|
@ -45,6 +46,7 @@ import java.io.Serializable;
|
|||
public class BrokerLinkEntity {
|
||||
|
||||
@Id
|
||||
@Column(name = "USER_ID")
|
||||
private String userId;
|
||||
|
||||
@Id
|
||||
|
|
|
@ -39,12 +39,12 @@ import java.util.Collection;
|
|||
@UniqueConstraint(columnNames = {"USER_ID", "CLIENT_ID"})
|
||||
})
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="userFederatedConsentByUserAndClient", query="select consent from UserConsentEntity consent where consent.userId = :userId and consent.clientId = :clientId"),
|
||||
@NamedQuery(name="userFederatedConsentsByUser", query="select consent from UserConsentEntity consent where consent.userId = :userId"),
|
||||
@NamedQuery(name="deleteFederatedUserConsentsByRealm", query="delete from UserConsentEntity consent where consent.realmId=:realmId"),
|
||||
@NamedQuery(name="userFederatedConsentByUserAndClient", query="select consent from FederatedUserConsentEntity consent where consent.userId = :userId and consent.clientId = :clientId"),
|
||||
@NamedQuery(name="userFederatedConsentsByUser", query="select consent from FederatedUserConsentEntity consent where consent.userId = :userId"),
|
||||
@NamedQuery(name="deleteFederatedUserConsentsByRealm", query="delete from FederatedUserConsentEntity consent where consent.realmId=:realmId"),
|
||||
@NamedQuery(name="deleteFederatedUserConsentsByStorageProvider", query="delete from FederatedUserConsentEntity e where e.storageProviderId=:storageProviderId"),
|
||||
@NamedQuery(name="deleteFederatedUserConsentsByUser", query="delete from UserConsentEntity consent where consent.userId = :userId and consent.realmId = :realmId"),
|
||||
@NamedQuery(name="deleteFederatedUserConsentsByClient", query="delete from UserConsentEntity consent where consent.clientId = :clientId"),
|
||||
@NamedQuery(name="deleteFederatedUserConsentsByUser", query="delete from FederatedUserConsentEntity consent where consent.userId = :userId and consent.realmId = :realmId"),
|
||||
@NamedQuery(name="deleteFederatedUserConsentsByClient", query="delete from FederatedUserConsentEntity consent where consent.clientId = :clientId"),
|
||||
})
|
||||
public class FederatedUserConsentEntity {
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ import java.io.Serializable;
|
|||
@NamedQueries({
|
||||
@NamedQuery(name="feduserMemberOf", query="select m from FederatedUserGroupMembershipEntity m where m.userId = :userId and m.groupId = :groupId"),
|
||||
@NamedQuery(name="feduserGroupMembership", query="select m from FederatedUserGroupMembershipEntity m where m.userId = :userId"),
|
||||
@NamedQuery(name="fedgroupMembership", query="select g.user from FederatedUserGroupMembershipEntity g where g.groupId = :groupId"),
|
||||
@NamedQuery(name="fedgroupMembership", query="select g.userId from FederatedUserGroupMembershipEntity g where g.groupId = :groupId"),
|
||||
@NamedQuery(name="feduserGroupIds", query="select m.groupId from FederatedUserGroupMembershipEntity m where m.userId = :userId"),
|
||||
@NamedQuery(name="deleteFederatedUserGroupMembershipByRealm", query="delete from FederatedUserGroupMembershipEntity mapping where mapping.realmId=:realmId"),
|
||||
@NamedQuery(name="deleteFederatedUserGroupMembershipByStorageProvider", query="delete from FederatedUserGroupMembershipEntity e where e.storageProviderId=:storageProviderId"),
|
||||
|
@ -50,6 +50,7 @@ import java.io.Serializable;
|
|||
public class FederatedUserGroupMembershipEntity {
|
||||
|
||||
@Id
|
||||
@Column(name = "USER_ID")
|
||||
protected String userId;
|
||||
|
||||
@Id
|
||||
|
|
|
@ -36,7 +36,7 @@ import java.io.Serializable;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="getFederatedUserRequiredActionsByUser", query="select action from FederatedUserRequiredActionEntity action where action.userId = :userId and attr.realmId=:realmId"),
|
||||
@NamedQuery(name="getFederatedUserRequiredActionsByUser", query="select action from FederatedUserRequiredActionEntity action where action.userId = :userId and action.realmId=:realmId"),
|
||||
@NamedQuery(name="deleteFederatedUserRequiredActionsByRealm", query="delete from FederatedUserRequiredActionEntity action where action.realmId=:realmId"),
|
||||
@NamedQuery(name="deleteFederatedUserRequiredActionsByStorageProvider", query="delete from FederatedUserRequiredActionEntity e where e.storageProviderId=:storageProviderId"),
|
||||
@NamedQuery(name="deleteFederatedUserRequiredActionsByRealmAndLink", query="delete from FederatedUserRequiredActionEntity action where action.userId IN (select u.id from UserEntity u where u.realmId=:realmId and u.federationLink=:link)")
|
||||
|
|
|
@ -48,6 +48,7 @@ import java.io.Serializable;
|
|||
public class FederatedUserRoleMappingEntity {
|
||||
|
||||
@Id
|
||||
@Column(name = "USER_ID")
|
||||
protected String userId;
|
||||
|
||||
@Id
|
||||
|
|
|
@ -17,131 +17,178 @@
|
|||
-->
|
||||
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
|
||||
<changeSet author="mposolda@redhat.com" id="1.8.0">
|
||||
<changeSet author="bburke@redhat.com" id="2.1.0">
|
||||
|
||||
<addColumn tableName="IDENTITY_PROVIDER">
|
||||
<column name="POST_BROKER_LOGIN_FLOW_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="true"/>
|
||||
<createTable tableName="BROKER_LINK">
|
||||
<column name="IDENTITY_PROVIDER" type="VARCHAR(255)">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
</addColumn>
|
||||
<createTable tableName="CLIENT_TEMPLATE">
|
||||
<column name="ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
<column name="STORAGE_PROVIDER_ID" type="VARCHAR(255)">
|
||||
</column>
|
||||
<column name="NAME" type="VARCHAR(255)"/>
|
||||
<column name="REALM_ID" type="VARCHAR(36)"/>
|
||||
<column name="DESCRIPTION" type="VARCHAR(255)"/>
|
||||
<column name="PROTOCOL" type="VARCHAR(255)"/>
|
||||
<column name="FULL_SCOPE_ALLOWED" type="BOOLEAN" defaultValueBoolean="false">
|
||||
<constraints nullable="false"/>
|
||||
<column name="REALM_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="CONSENT_REQUIRED" type="BOOLEAN" defaultValueBoolean="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="STANDARD_FLOW_ENABLED" type="BOOLEAN" defaultValueBoolean="true">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="IMPLICIT_FLOW_ENABLED" type="BOOLEAN" defaultValueBoolean="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="DIRECT_ACCESS_GRANTS_ENABLED" type="BOOLEAN" defaultValueBoolean="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="SERVICE_ACCOUNTS_ENABLED" type="BOOLEAN" defaultValueBoolean="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="FRONTCHANNEL_LOGOUT" type="BOOLEAN" defaultValueBoolean="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="BEARER_ONLY" type="BOOLEAN" defaultValueBoolean="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="PUBLIC_CLIENT" type="BOOLEAN" defaultValueBoolean="false">
|
||||
<constraints nullable="false"/>
|
||||
<column name="BROKER_USER_ID" type="VARCHAR(255)" />
|
||||
<column name="BROKER_USERNAME" type="VARCHAR(255)" />
|
||||
<column name="TOKEN" type="TEXT" />
|
||||
<column name="USER_ID" type="VARCHAR(255)">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
</createTable>
|
||||
<createTable tableName="CLIENT_TEMPLATE_ATTRIBUTES">
|
||||
<column name="TEMPLATE_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
<createTable tableName="FED_USER_ATTRIBUTE">
|
||||
<column name="ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="VALUE" type="VARCHAR(2048)"/>
|
||||
<column name="NAME" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="USER_ID" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="REALM_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="STORAGE_PROVIDER_ID" type="VARCHAR(36)"/>
|
||||
<column name="VALUE" type="VARCHAR(2024)"/>
|
||||
</createTable>
|
||||
<createTable tableName="TEMPLATE_SCOPE_MAPPING">
|
||||
<column name="TEMPLATE_ID" type="VARCHAR(36)">
|
||||
<createTable tableName="FED_USER_CONSENT">
|
||||
<column name="ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="CLIENT_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="USER_ID" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="REALM_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="STORAGE_PROVIDER_ID" type="VARCHAR(36)"/>
|
||||
</createTable>
|
||||
<createTable tableName="FED_USER_CONSENT_ROLE">
|
||||
<column name="USER_CONSENT_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="ROLE_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
|
||||
|
||||
|
||||
<dropNotNullConstraint tableName="PROTOCOL_MAPPER" columnName="CLIENT_ID" columnDataType="VARCHAR(36)"/>
|
||||
<addColumn tableName="CLIENT">
|
||||
<column name="CLIENT_TEMPLATE_ID" type="VARCHAR(36)">
|
||||
<createTable tableName="FED_USER_CONSENT_PROT_MAPPER">
|
||||
<column name="USER_CONSENT_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="PROTOCOL_MAPPER_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<createTable tableName="FED_USER_CREDENTIAL">
|
||||
<column name="ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="DEVICE" type="VARCHAR(255)"/>
|
||||
<column name="HASH_ITERATIONS" type="INT"/>
|
||||
<column name="SALT" type="BLOB(16)"/>
|
||||
<column name="TYPE" type="VARCHAR(255)"/>
|
||||
<column name="VALUE" type="VARCHAR(255)"/>
|
||||
<column name="CREATED_DATE" type="BIGINT"/>
|
||||
<column name="COUNTER" type="INT" defaultValueNumeric="0">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="USE_TEMPLATE_CONFIG" type="BOOLEAN" defaultValueBoolean="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="USE_TEMPLATE_SCOPE" type="BOOLEAN" defaultValueBoolean="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="USE_TEMPLATE_MAPPERS" type="BOOLEAN" defaultValueBoolean="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
<addColumn tableName="PROTOCOL_MAPPER">
|
||||
<column name="CLIENT_TEMPLATE_ID" type="VARCHAR(36)">
|
||||
<column name="DIGITS" type="INT" defaultValueNumeric="6">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
<createTable tableName="REALM_CLIENT_TEMPLATE">
|
||||
<column name="CLIENT_TEMPLATE_ID" type="VARCHAR(36)">
|
||||
<column name="PERIOD" type="INT" defaultValueNumeric="30">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="ALGORITHM" type="VARCHAR(36)" defaultValue="HmacSHA1">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="USER_ID" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="REALM_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="STORAGE_PROVIDER_ID" type="VARCHAR(36)"/>
|
||||
</createTable>
|
||||
<createTable tableName="FED_USER_GROUP_MEMBERSHIP">
|
||||
<column name="GROUP_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="USER_ID" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="REALM_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="STORAGE_PROVIDER_ID" type="VARCHAR(36)"/>
|
||||
</createTable>
|
||||
<createTable tableName="FED_USER_REQUIRED_ACTION">
|
||||
<column name="REQUIRED_ACTION" type="VARCHAR(255)" defaultValue=" ">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="USER_ID" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="REALM_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="STORAGE_PROVIDER_ID" type="VARCHAR(36)"/>
|
||||
</createTable>
|
||||
<createTable tableName="FED_USER_ROLE_MAPPING">
|
||||
<column name="ROLE_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="USER_ID" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="REALM_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="STORAGE_PROVIDER_ID" type="VARCHAR(36)"/>
|
||||
</createTable>
|
||||
|
||||
<addPrimaryKey columnNames="ID" constraintName="PK_CLI_TEMPLATE" tableName="CLIENT_TEMPLATE"/>
|
||||
<addUniqueConstraint columnNames="REALM_ID,NAME" constraintName="UK_CLI_TEMPLATE" tableName="CLIENT_TEMPLATE"/>
|
||||
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="CLIENT_TEMPLATE" constraintName="FK_REALM_CLI_TMPLT" referencedColumnNames="ID" referencedTableName="REALM"/>
|
||||
<addForeignKeyConstraint baseColumnNames="CLIENT_TEMPLATE_ID" baseTableName="PROTOCOL_MAPPER" constraintName="FK_CLI_TMPLT_MAPPER" referencedColumnNames="ID" referencedTableName="CLIENT_TEMPLATE"/>
|
||||
<addForeignKeyConstraint baseColumnNames="CLIENT_TEMPLATE_ID" baseTableName="CLIENT" constraintName="FK_CLI_TMPLT_CLIENT" referencedColumnNames="ID" referencedTableName="CLIENT_TEMPLATE"/>
|
||||
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="REALM_CLIENT_TEMPLATE" constraintName="FK_RLM_CLI_TMPLT_RLM" referencedColumnNames="ID" referencedTableName="REALM"/>
|
||||
<addForeignKeyConstraint baseColumnNames="CLIENT_TEMPLATE_ID" baseTableName="REALM_CLIENT_TEMPLATE" constraintName="FK_RLM_CLI_TMPLT_CLI" referencedColumnNames="ID" referencedTableName="CLIENT_TEMPLATE"/>
|
||||
<addPrimaryKey columnNames="TEMPLATE_ID, ROLE_ID" constraintName="PK_TEMPLATE_SCOPE" tableName="TEMPLATE_SCOPE_MAPPING"/>
|
||||
<addForeignKeyConstraint baseColumnNames="TEMPLATE_ID" baseTableName="TEMPLATE_SCOPE_MAPPING" constraintName="FK_TEMPL_SCOPE_TEMPL" referencedColumnNames="ID" referencedTableName="CLIENT_TEMPLATE"/>
|
||||
<addForeignKeyConstraint baseColumnNames="ROLE_ID" baseTableName="TEMPLATE_SCOPE_MAPPING" constraintName="FK_TEMPL_SCOPE_ROLE" referencedColumnNames="ID" referencedTableName="KEYCLOAK_ROLE"/>
|
||||
<addPrimaryKey columnNames="TEMPLATE_ID, NAME" constraintName="PK_CL_TMPL_ATTR" tableName="CLIENT_TEMPLATE_ATTRIBUTES"/>
|
||||
<addForeignKeyConstraint baseColumnNames="TEMPLATE_ID" baseTableName="CLIENT_TEMPLATE_ATTRIBUTES" constraintName="FK_CL_TEMPL_ATTR_TEMPL" referencedColumnNames="ID" referencedTableName="CLIENT_TEMPLATE"/>
|
||||
<createTable tableName="STORAGE_PROVIDER_CONFIG">
|
||||
<column name="STORAGE_PROVIDER_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="VALUE" type="VARCHAR(255)"/>
|
||||
<column name="NAME" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<createTable tableName="STORAGE_PROVIDER">
|
||||
<column name="ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="DISPLAY_NAME" type="VARCHAR(255)"/>
|
||||
<column name="PRIORITY" type="INT"/>
|
||||
<column name="PROVIDER_NAME" type="VARCHAR(255)"/>
|
||||
<column name="REALM_ID" type="VARCHAR(36)"/>
|
||||
</createTable>
|
||||
|
||||
<update tableName="CREDENTIAL">
|
||||
<column name="ALGORITHM" type="VARCHAR(36)" value="pbkdf2" />
|
||||
<where>TYPE in ('password-history', 'password') AND ALGORITHM is NULL</where>
|
||||
</update>
|
||||
|
||||
|
||||
|
||||
<addPrimaryKey columnNames="IDENTITY_PROVIDER, USER_ID" constraintName="CONSTR_BROKER_LINK_PK" tableName="BROKER_LINK" />
|
||||
<addPrimaryKey columnNames="ID" constraintName="CONSTR_FED_USER_ATTR_PK" tableName="FED_USER_ATTRIBUTE"/>
|
||||
<addPrimaryKey columnNames="ID" constraintName="CONSTR_FED_USER_CONSENT_PK" tableName="FED_USER_CONSENT"/>
|
||||
<addPrimaryKey columnNames="USER_CONSENT_ID, ROLE_ID" constraintName="CONSTR_USER_CONSENT_ROLE_PK" tableName="FED_USER_CONSENT_ROLE"/>
|
||||
<addPrimaryKey columnNames="USER_CONSENT_ID, PROTOCOL_MAPPER_ID" constraintName="CONSTR_USER_CONSENT_PROT_MAP_PK" tableName="FED_USER_CONSENT_PROT_MAPPER"/>
|
||||
<!--
|
||||
<addForeignKeyConstraint baseColumnNames="USER_CONSENT_ID" baseTableName="FED_USER_CONSENT_ROLE" constraintName="FK_FED_GRNTCSNT_ROLE_GR" referencedColumnNames="ID" referencedTableName="FED_USER_CONSENT"/>
|
||||
<addForeignKeyConstraint baseColumnNames="USER_CONSENT_ID" baseTableName="FED_USER_CONSENT_PROT_MAPPER" constraintName="FK_FED_GRNTCSNT_PRM_GR" referencedColumnNames="ID" referencedTableName="FED_USER_CONSENT"/>
|
||||
-->
|
||||
<addPrimaryKey columnNames="ID" constraintName="CONSTR_FED_USER_CRED_PK" tableName="FED_USER_CREDENTIAL"/>
|
||||
<addPrimaryKey columnNames="GROUP_ID, USER_ID" constraintName="CONSTR_FED_USER_GROUP" tableName="FED_USER_GROUP_MEMBERSHIP"/>
|
||||
<addPrimaryKey columnNames="ROLE_ID, USER_ID" constraintName="CONSTR_FED_USER_ROLE" tableName="FED_USER_ROLE_MAPPING"/>
|
||||
<addPrimaryKey columnNames="REQUIRED_ACTION, USER_ID" constraintName="CONSTR_FED_REQUIRED_ACTION" tableName="FED_USER_REQUIRED_ACTION"/>
|
||||
|
||||
<addPrimaryKey columnNames="ID" constraintName="CONSTR_STORAGE_PROVIDER_PK" tableName="STORAGE_PROVIDER"/>
|
||||
<addPrimaryKey columnNames="STORAGE_PROVIDER_ID, NAME" constraintName="CONSTR_STORAGE_CONFIG" tableName="STORAGE_PROVIDER_CONFIG"/>
|
||||
<!--
|
||||
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="STORAGE_PROVIDER" constraintName="FK_STORAGE_PROVIDER_REALM" referencedColumnNames="ID" referencedTableName="REALM"/>
|
||||
-->
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="1.8.0-2" author="keycloak">
|
||||
<dropDefaultValue tableName="CREDENTIAL" columnName="ALGORITHM" columnDataType="VARCHAR(36)"/>
|
||||
|
||||
<update tableName="CREDENTIAL">
|
||||
<column name="ALGORITHM" type="VARCHAR(36)" value="pbkdf2" />
|
||||
<where>TYPE in ('password-history', 'password') AND ALGORITHM = 'HmacSHA1'</where>
|
||||
</update>
|
||||
|
||||
<!-- Sybase specific hacks -->
|
||||
<modifySql dbms="sybase">
|
||||
<regExpReplace replace=".*(SET DEFAULT NULL)" with="SELECT 1" />
|
||||
</modifySql>
|
||||
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
|
@ -32,6 +32,7 @@
|
|||
<include file="META-INF/jpa-changelog-1.9.0.xml"/>
|
||||
<include file="META-INF/jpa-changelog-1.9.1.xml"/>
|
||||
<include file="META-INF/jpa-changelog-1.9.2.xml"/>
|
||||
<include file="META-INF/jpa-changelog-2.1.0.xml"/>
|
||||
|
||||
<include file="META-INF/jpa-changelog-authz-master.xml"/>
|
||||
</databaseChangeLog>
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
<class>org.keycloak.models.jpa.entities.RealmEntity</class>
|
||||
<class>org.keycloak.models.jpa.entities.RealmAttributeEntity</class>
|
||||
<class>org.keycloak.models.jpa.entities.RequiredCredentialEntity</class>
|
||||
<class>org.keycloak.models.jpa.entities.StorageProviderEntity</class>
|
||||
<class>org.keycloak.models.jpa.entities.UserFederationProviderEntity</class>
|
||||
<class>org.keycloak.models.jpa.entities.UserFederationMapperEntity</class>
|
||||
<class>org.keycloak.models.jpa.entities.RoleEntity</class>
|
||||
|
@ -64,6 +65,17 @@
|
|||
<class>org.keycloak.authorization.jpa.entities.ResourceEntity</class>
|
||||
<class>org.keycloak.authorization.jpa.entities.ScopeEntity</class>
|
||||
<class>org.keycloak.authorization.jpa.entities.PolicyEntity</class>
|
||||
|
||||
<!-- User Federation Storage -->
|
||||
<class>org.keycloak.storage.jpa.entity.BrokerLinkEntity</class>
|
||||
<class>org.keycloak.storage.jpa.entity.FederatedUserAttributeEntity</class>
|
||||
<class>org.keycloak.storage.jpa.entity.FederatedUserConsentEntity</class>
|
||||
<class>org.keycloak.storage.jpa.entity.FederatedUserConsentRoleEntity</class>
|
||||
<class>org.keycloak.storage.jpa.entity.FederatedUserConsentProtocolMapperEntity</class>
|
||||
<class>org.keycloak.storage.jpa.entity.FederatedUserCredentialEntity</class>
|
||||
<class>org.keycloak.storage.jpa.entity.FederatedUserGroupMembershipEntity</class>
|
||||
<class>org.keycloak.storage.jpa.entity.FederatedUserRequiredActionEntity</class>
|
||||
<class>org.keycloak.storage.jpa.entity.FederatedUserRoleMappingEntity</class>
|
||||
|
||||
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
org.keycloak.storage.jpa.JpaUserFederatedStorageProviderFactory
|
|
@ -209,7 +209,8 @@ public class MongoUserProvider implements UserProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
|
||||
public List<UserModel>
|
||||
searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
|
||||
search = search.trim();
|
||||
Pattern caseInsensitivePattern = Pattern.compile("(?i:" + search + ")");
|
||||
|
||||
|
|
|
@ -47,10 +47,6 @@ public interface UserProvider extends Provider, UserLookupProvider, UserQueryPro
|
|||
UserModel getServiceAccount(ClientModel client);
|
||||
List<UserModel> getUsers(RealmModel realm, boolean includeServiceAccounts);
|
||||
List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults, boolean includeServiceAccounts);
|
||||
List<UserModel> searchForUser(String search, RealmModel realm);
|
||||
|
||||
// Searching by UserModel.attribute (not property)
|
||||
List<UserModel> searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm);
|
||||
|
||||
void preRemove(RealmModel realm);
|
||||
|
||||
|
|
|
@ -41,4 +41,9 @@ public interface UserQueryProvider {
|
|||
|
||||
List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults);
|
||||
List<UserModel> getGroupMembers(RealmModel realm, GroupModel group);
|
||||
|
||||
List<UserModel> searchForUser(String search, RealmModel realm);
|
||||
|
||||
// Searching by UserModel.attribute (not property)
|
||||
List<UserModel> searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm);
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ public class StorageProviderSpi implements Spi {
|
|||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "userFederation";
|
||||
return "storage";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -43,6 +43,7 @@ import org.keycloak.storage.federated.UserFederatedStorageProvider;
|
|||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
@ -152,43 +153,77 @@ public class UserStorageManager implements UserProvider {
|
|||
|
||||
@Override
|
||||
public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel socialLink) {
|
||||
getFederatedStorage().addFederatedIdentity(realm, user, socialLink);
|
||||
if (StorageId.isLocalStorage(user)) {
|
||||
localStorage().addFederatedIdentity(realm, user, socialLink);
|
||||
} else {
|
||||
getFederatedStorage().addFederatedIdentity(realm, user, socialLink);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel) {
|
||||
getFederatedStorage().updateFederatedIdentity(realm, federatedUser, federatedIdentityModel);
|
||||
if (StorageId.isLocalStorage(federatedUser)) {
|
||||
localStorage().updateFederatedIdentity(realm, federatedUser, federatedIdentityModel);
|
||||
|
||||
} else {
|
||||
getFederatedStorage().updateFederatedIdentity(realm, federatedUser, federatedIdentityModel);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider) {
|
||||
return getFederatedStorage().removeFederatedIdentity(realm, user, socialProvider);
|
||||
if (StorageId.isLocalStorage(user)) {
|
||||
return localStorage().removeFederatedIdentity(realm, user, socialProvider);
|
||||
} else {
|
||||
return getFederatedStorage().removeFederatedIdentity(realm, user, socialProvider);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
|
||||
getFederatedStorage().addConsent(realm, user, consent);
|
||||
if (StorageId.isLocalStorage(user)) {
|
||||
localStorage().addConsent(realm, user, consent);
|
||||
} else {
|
||||
getFederatedStorage().addConsent(realm, user, consent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserConsentModel getConsentByClient(RealmModel realm, UserModel user, String clientInternalId) {
|
||||
return getFederatedStorage().getConsentByClient(realm, user, clientInternalId);
|
||||
if (StorageId.isLocalStorage(user)) {
|
||||
return localStorage().getConsentByClient(realm, user, clientInternalId);
|
||||
} else {
|
||||
return getFederatedStorage().getConsentByClient(realm, user, clientInternalId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserConsentModel> getConsents(RealmModel realm, UserModel user) {
|
||||
return getFederatedStorage().getConsents(realm, user);
|
||||
if (StorageId.isLocalStorage(user)) {
|
||||
return localStorage().getConsents(realm, user);
|
||||
|
||||
} else {
|
||||
return getFederatedStorage().getConsents(realm, user);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
|
||||
getFederatedStorage().updateConsent(realm, user, consent);
|
||||
if (StorageId.isLocalStorage(user)) {
|
||||
localStorage().updateConsent(realm, user, consent);
|
||||
} else {
|
||||
getFederatedStorage().updateConsent(realm, user, consent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean revokeConsentForClient(RealmModel realm, UserModel user, String clientInternalId) {
|
||||
return getFederatedStorage().revokeConsentForClient(realm, user, clientInternalId);
|
||||
if (StorageId.isLocalStorage(user)) {
|
||||
return localStorage().revokeConsentForClient(realm, user, clientInternalId);
|
||||
} else {
|
||||
return getFederatedStorage().revokeConsentForClient(realm, user, clientInternalId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -334,24 +369,10 @@ public class UserStorageManager implements UserProvider {
|
|||
|
||||
@Override
|
||||
public List<UserModel> searchForUser(final String search, final RealmModel realm, int firstResult, int maxResults) {
|
||||
final Map<String, String> attributes = new HashMap<String, String>();
|
||||
int spaceIndex = search.lastIndexOf(' ');
|
||||
if (spaceIndex > -1) {
|
||||
String firstName = search.substring(0, spaceIndex).trim();
|
||||
String lastName = search.substring(spaceIndex).trim();
|
||||
attributes.put(UserModel.FIRST_NAME, firstName);
|
||||
attributes.put(UserModel.LAST_NAME, lastName);
|
||||
} else if (search.indexOf('@') > -1) {
|
||||
attributes.put(UserModel.USERNAME, search.trim().toLowerCase());
|
||||
attributes.put(UserModel.EMAIL, search.trim().toLowerCase());
|
||||
} else {
|
||||
attributes.put(UserModel.LAST_NAME, search.trim());
|
||||
attributes.put(UserModel.USERNAME, search.trim().toLowerCase());
|
||||
}
|
||||
return query(new PaginatedQuery() {
|
||||
return query(new PaginatedQuery() {
|
||||
@Override
|
||||
public List<UserModel> query(UserQueryProvider provider, int first, int max) {
|
||||
return provider.searchForUserByAttributes(attributes, realm, first, max);
|
||||
return provider.searchForUser(search, realm, first, max);
|
||||
}
|
||||
}, realm, firstResult, maxResults);
|
||||
}
|
||||
|
@ -372,26 +393,32 @@ public class UserStorageManager implements UserProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm) {
|
||||
Map<String, String> attributes = new HashMap<>();
|
||||
attributes.put(attrName, attrValue);
|
||||
return searchForUserByAttributes(attributes, realm);
|
||||
public List<UserModel> searchForUserByUserAttribute(final String attrName, final String attrValue, RealmModel realm) {
|
||||
return query(new PaginatedQuery() {
|
||||
@Override
|
||||
public List<UserModel> query(UserQueryProvider provider, int first, int max) {
|
||||
return provider.searchForUserByUserAttribute(attrName, attrValue, realm);
|
||||
}
|
||||
}, realm,0, Integer.MAX_VALUE - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) {
|
||||
if (user == null) throw new IllegalStateException("Federated user no longer valid");
|
||||
Set<FederatedIdentityModel> set = new HashSet<>();
|
||||
if (StorageId.isLocalStorage(user)) {
|
||||
return localStorage().getFederatedIdentities(user, realm);
|
||||
set.addAll(localStorage().getFederatedIdentities(user, realm));
|
||||
}
|
||||
return getFederatedStorage().getFederatedIdentities(user, realm);
|
||||
set.addAll(getFederatedStorage().getFederatedIdentities(user, realm));
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm) {
|
||||
if (user == null) throw new IllegalStateException("Federated user no longer valid");
|
||||
if (StorageId.isLocalStorage(user)) {
|
||||
return localStorage().getFederatedIdentity(user, socialProvider, realm);
|
||||
FederatedIdentityModel model = localStorage().getFederatedIdentity(user, socialProvider, realm);
|
||||
if (model != null) return model;
|
||||
}
|
||||
return getFederatedStorage().getFederatedIdentity(user, socialProvider, realm);
|
||||
}
|
||||
|
@ -430,6 +457,7 @@ public class UserStorageManager implements UserProvider {
|
|||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, UserFederationProviderModel model) {
|
||||
getFederatedStorage().preRemove(realm, model);
|
||||
localStorage().preRemove(realm, model);
|
||||
}
|
||||
|
||||
|
@ -454,11 +482,14 @@ public class UserStorageManager implements UserProvider {
|
|||
@Override
|
||||
public void preRemove(RealmModel realm, ClientModel client) {
|
||||
localStorage().preRemove(realm, client);
|
||||
getFederatedStorage().preRemove(realm, client);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(ProtocolMapperModel protocolMapper) {
|
||||
localStorage().preRemove(protocolMapper);
|
||||
getFederatedStorage().preRemove(protocolMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#
|
||||
|
||||
org.keycloak.models.UserFederationSpi
|
||||
org.keycloak.storage.StorageProviderSpi
|
||||
org.keycloak.storage.federated.UserFederatedStorageProviderSpi
|
||||
org.keycloak.mappers.UserFederationMapperSpi
|
||||
org.keycloak.models.RealmSpi
|
||||
|
|
|
@ -42,6 +42,7 @@ public class DefaultKeycloakSession implements KeycloakSession {
|
|||
private ScriptingProvider scriptingProvider;
|
||||
private UserSessionProvider sessionProvider;
|
||||
private UserFederationManager federationManager;
|
||||
private UserFederatedStorageProvider userFederatedStorageProvider;
|
||||
private KeycloakContext context;
|
||||
|
||||
public DefaultKeycloakSession(DefaultKeycloakSessionFactory factory) {
|
||||
|
@ -91,7 +92,10 @@ public class DefaultKeycloakSession implements KeycloakSession {
|
|||
|
||||
@Override
|
||||
public UserFederatedStorageProvider userFederatedStorage() {
|
||||
return null;
|
||||
if (userFederatedStorageProvider == null) {
|
||||
userFederatedStorageProvider = getProvider(UserFederatedStorageProvider.class);
|
||||
}
|
||||
return userFederatedStorageProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -154,7 +154,11 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory {
|
|||
|
||||
@Override
|
||||
public <T extends Provider> ProviderFactory<T> getProviderFactory(Class<T> clazz, String id) {
|
||||
return factoriesMap.get(clazz).get(id);
|
||||
Map<String, ProviderFactory> map = factoriesMap.get(clazz);
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
return map.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -23,6 +23,10 @@
|
|||
"provider": "${keycloak.user.provider:jpa}"
|
||||
},
|
||||
|
||||
"userFederatedStorage": {
|
||||
"provider": "${keycloak.userFederatedStorage.provider:jpa}"
|
||||
},
|
||||
|
||||
"userSessionPersister": {
|
||||
"provider": "${keycloak.userSessionPersister.provider:jpa}"
|
||||
},
|
||||
|
|
|
@ -72,7 +72,9 @@ public abstract class AbstractKeycloakIdentityProviderTest extends AbstractIdent
|
|||
|
||||
@Test
|
||||
public void testDisabledUser() {
|
||||
KeycloakSession session = brokerServerRule.startSession();
|
||||
setUpdateProfileFirstLogin(session.realms().getRealmByName("realm-with-broker"), IdentityProviderRepresentation.UPFLM_OFF);
|
||||
brokerServerRule.stopSession(session, true);
|
||||
|
||||
driver.navigate().to("http://localhost:8081/test-app");
|
||||
loginPage.clickSocial(getProviderId());
|
||||
|
@ -81,7 +83,7 @@ public abstract class AbstractKeycloakIdentityProviderTest extends AbstractIdent
|
|||
driver.navigate().to("http://localhost:8081/test-app/logout");
|
||||
|
||||
try {
|
||||
KeycloakSession session = brokerServerRule.startSession();
|
||||
session = brokerServerRule.startSession();
|
||||
session.users().getUserByUsername("test-user", session.realms().getRealmByName("realm-with-broker")).setEnabled(false);
|
||||
brokerServerRule.stopSession(session, true);
|
||||
|
||||
|
@ -93,7 +95,7 @@ public abstract class AbstractKeycloakIdentityProviderTest extends AbstractIdent
|
|||
assertTrue(errorPage.isCurrent());
|
||||
assertEquals("Account is disabled, contact admin.", errorPage.getError());
|
||||
} finally {
|
||||
KeycloakSession session = brokerServerRule.startSession();
|
||||
session = brokerServerRule.startSession();
|
||||
session.users().getUserByUsername("test-user", session.realms().getRealmByName("realm-with-broker")).setEnabled(true);
|
||||
brokerServerRule.stopSession(session, true);
|
||||
}
|
||||
|
@ -101,7 +103,9 @@ public abstract class AbstractKeycloakIdentityProviderTest extends AbstractIdent
|
|||
|
||||
@Test
|
||||
public void testTemporarilyDisabledUser() {
|
||||
KeycloakSession session = brokerServerRule.startSession();
|
||||
setUpdateProfileFirstLogin(session.realms().getRealmByName("realm-with-broker"), IdentityProviderRepresentation.UPFLM_OFF);
|
||||
brokerServerRule.stopSession(session, true);
|
||||
|
||||
driver.navigate().to("http://localhost:8081/test-app");
|
||||
loginPage.clickSocial(getProviderId());
|
||||
|
@ -109,7 +113,7 @@ public abstract class AbstractKeycloakIdentityProviderTest extends AbstractIdent
|
|||
driver.navigate().to("http://localhost:8081/test-app/logout");
|
||||
|
||||
try {
|
||||
KeycloakSession session = brokerServerRule.startSession();
|
||||
session = brokerServerRule.startSession();
|
||||
RealmModel brokerRealm = session.realms().getRealmByName("realm-with-broker");
|
||||
brokerRealm.setBruteForceProtected(true);
|
||||
brokerRealm.setFailureFactor(2);
|
||||
|
@ -129,7 +133,7 @@ public abstract class AbstractKeycloakIdentityProviderTest extends AbstractIdent
|
|||
assertTrue(errorPage.isCurrent());
|
||||
assertEquals("Account is disabled, contact admin.", errorPage.getError());
|
||||
} finally {
|
||||
KeycloakSession session = brokerServerRule.startSession();
|
||||
session = brokerServerRule.startSession();
|
||||
RealmModel brokerRealm = session.realms().getRealmByName("realm-with-broker");
|
||||
brokerRealm.setBruteForceProtected(false);
|
||||
brokerRealm.setFailureFactor(0);
|
||||
|
|
|
@ -170,4 +170,14 @@ public class OIDCKeyCloakServerBrokerBasicTest extends AbstractKeycloakIdentityP
|
|||
public void testAccountManagementLinkIdentity() {
|
||||
super.testAccountManagementLinkIdentity();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithLinkedFederationProvider() throws Exception {
|
||||
super.testWithLinkedFederationProvider();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccountManagementLinkedIdentityAlreadyExists() {
|
||||
super.testAccountManagementLinkedIdentityAlreadyExists();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
|||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p %t [%c] %m%n
|
||||
|
||||
log4j.logger.org.keycloak=info
|
||||
log4j.logger.org.keycloak=debug
|
||||
|
||||
# Enable to view events
|
||||
# log4j.logger.org.keycloak.events=debug
|
||||
|
|
Loading…
Reference in a new issue