[KEYCLOAK-7907] Migrate model package from old testsuite

This commit is contained in:
Martin Bartos RH 2019-03-01 11:09:21 +01:00 committed by Marek Posolda
parent 845275ef0f
commit bec5d676e7
17 changed files with 3224 additions and 2520 deletions

View file

@ -0,0 +1,272 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.model;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.TargetsContainer;
import org.jboss.logging.Logger;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Assert;
import org.junit.Test;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.models.*;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.testsuite.AbstractTestRealmKeycloakTest;
import org.keycloak.testsuite.arquillian.annotation.ModelTest;
import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
import static org.keycloak.testsuite.arquillian.DeploymentTargetModifier.AUTH_SERVER_CURRENT;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ConcurrentTransactionsTest extends AbstractTestRealmKeycloakTest {
@Deployment
@TargetsContainer(AUTH_SERVER_CURRENT)
public static WebArchive deploy() {
return RunOnServerDeployment.create(UserResource.class, UserSessionProviderOfflineTest.class)
.addPackages(true,
"org.keycloak.testsuite",
"org.keycloak.testsuite.model");
}
private static final Logger logger = Logger.getLogger(ConcurrentTransactionsTest.class);
@Test
@ModelTest
public void persistClient(KeycloakSession session) {
final ClientModel[] client = {null};
AtomicReference<String> clientDBIdAtomic = new AtomicReference<>();
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionSetup) -> {
RealmModel realm = sessionSetup.realms().getRealm("test");
sessionSetup.users().addUser(realm, "user1").setEmail("user1@localhost");
sessionSetup.users().addUser(realm, "user2").setEmail("user2@localhost");
realm = sessionSetup.realms().createRealm("original");
client[0] = sessionSetup.realms().addClient(realm, "client");
client[0].setSecret("old");
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession session1) -> {
String clientDBId = client[0].getId();
clientDBIdAtomic.set(clientDBId);
final KeycloakSessionFactory sessionFactory = session1.getKeycloakSessionFactory();
final CountDownLatch transactionsCounter = new CountDownLatch(2);
final CountDownLatch readLatch = new CountDownLatch(1);
final CountDownLatch updateLatch = new CountDownLatch(1);
Thread thread1 = new Thread(() -> {
KeycloakModelUtils.runJobInTransaction(sessionFactory, session11 -> {
try {
KeycloakSession currentSession = session11;
// Wait until transaction in both threads started
transactionsCounter.countDown();
logger.info("transaction1 started");
transactionsCounter.await();
// Read client
RealmModel realm1 = currentSession.realms().getRealmByName("original");
ClientModel client1 = currentSession.realms().getClientByClientId("client", realm1);
logger.info("transaction1: Read client finished");
readLatch.countDown();
// Wait until thread2 updates client and commits
updateLatch.await();
logger.info("transaction1: Going to read client again");
client1 = currentSession.realms().getClientByClientId("client", realm1);
logger.info("transaction1: secret: " + client1.getSecret());
} catch (Exception e) {
throw new RuntimeException(e);
}
});
});
Thread thread2 = new Thread(() -> {
KeycloakModelUtils.runJobInTransaction(sessionFactory, session22 -> {
try {
KeycloakSession currentSession = session22;
// Wait until transaction in both threads started
transactionsCounter.countDown();
logger.info("transaction2 started");
transactionsCounter.await();
readLatch.await();
logger.info("transaction2: Going to update client secret");
RealmModel realm12 = currentSession.realms().getRealmByName("original");
ClientModel client12 = currentSession.realms().getClientByClientId("client", realm12);
client12.setSecret("new");
} catch (Exception e) {
throw new RuntimeException(e);
}
});
logger.info("transaction2: commited");
updateLatch.countDown();
});
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info("after thread join");
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession session2) -> {
RealmModel realm = session2.realms().getRealmByName("original");
String clientDBId = clientDBIdAtomic.get();
ClientModel clientFromCache = session2.realms().getClientById(clientDBId, realm);
ClientModel clientFromDB = session2.getProvider(RealmProvider.class).getClientById(clientDBId, realm);
logger.info("SECRET FROM DB : " + clientFromDB.getSecret());
logger.info("SECRET FROM CACHE : " + clientFromCache.getSecret());
Assert.assertEquals("new", clientFromDB.getSecret());
Assert.assertEquals("new", clientFromCache.getSecret());
session2.sessions().removeUserSessions(realm);
tearDownRealm(session2, "user1", "user2");
});
}
// KEYCLOAK-3296 , KEYCLOAK-3494
@Test
@ModelTest
public void removeUserAttribute(KeycloakSession session) throws Exception {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionSet) -> {
RealmModel realm = sessionSet.realms().createRealm("original");
UserModel john = sessionSet.users().addUser(realm, "john");
john.setSingleAttribute("foo", "val1");
UserModel john2 = sessionSet.users().addUser(realm, "john2");
john2.setAttribute("foo", Arrays.asList("val1", "val2"));
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession session2) -> {
final KeycloakSessionFactory sessionFactory = session2.getKeycloakSessionFactory();
AtomicReference<Exception> reference = new AtomicReference<>();
final CountDownLatch readAttrLatch = new CountDownLatch(2);
Runnable runnable = () -> {
try {
KeycloakModelUtils.runJobInTransaction(sessionFactory, session1 -> {
try {
// Read user attribute
RealmModel realm = session1.realms().getRealmByName("original");
UserModel john = session1.users().getUserByUsername("john", realm);
String attrVal = john.getFirstAttribute("foo");
UserModel john2 = session1.users().getUserByUsername("john2", realm);
String attrVal2 = john2.getFirstAttribute("foo");
// Wait until it's read in both threads
readAttrLatch.countDown();
readAttrLatch.await();
// KEYCLOAK-3296 : Remove user attribute in both threads
john.removeAttribute("foo");
// KEYCLOAK-3494 : Set single attribute in both threads
john2.setSingleAttribute("foo", "bar");
} catch (Exception e) {
throw new RuntimeException(e);
}
});
} catch (Exception e) {
reference.set(e);
throw new RuntimeException(e);
} finally {
readAttrLatch.countDown();
}
};
Thread thread1 = new Thread(runnable);
Thread thread2 = new Thread(runnable);
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info("removeUserAttribute: after thread join");
if (reference.get() != null) {
Assert.fail("Exception happened in some of threads. Details: " + reference.get().getMessage());
}
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionTearDown) -> {
tearDownRealm(sessionTearDown, "john", "john2");
});
}
private void tearDownRealm(KeycloakSession session, String user1, String user2) {
KeycloakSession currentSession = session;
RealmModel realm = currentSession.realms().getRealmByName("original");
UserModel realmUser1 = currentSession.users().getUserByUsername(user1, realm);
UserModel realmUser2 = currentSession.users().getUserByUsername(user2, realm);
UserManager um = new UserManager(currentSession);
if (realmUser1 != null) {
um.removeUser(realm, realmUser1);
}
if (realmUser2 != null) {
um.removeUser(realm, realmUser2);
}
assert (currentSession.realms().removeRealm(realm.getId()));
}
@Override
public void configureTestRealm(RealmRepresentation testRealm) {
}
}

View file

@ -17,10 +17,14 @@
package org.keycloak.testsuite.model;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.TargetsContainer;
import org.jboss.logging.Logger;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.KeycloakSessionTask;
@ -28,15 +32,30 @@ import org.keycloak.models.dblock.DBLockManager;
import org.keycloak.models.dblock.DBLockProvider;
import org.keycloak.models.dblock.DBLockProviderFactory;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.testsuite.AbstractTestRealmKeycloakTest;
import org.keycloak.testsuite.arquillian.annotation.ModelTest;
import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import static org.keycloak.testsuite.arquillian.DeploymentTargetModifier.AUTH_SERVER_CURRENT;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class DBLockTest extends AbstractModelTest {
public class DBLockTest extends AbstractTestRealmKeycloakTest {
@Deployment
@TargetsContainer(AUTH_SERVER_CURRENT)
public static WebArchive deploy() {
return RunOnServerDeployment.create(UserResource.class, DBLockTest.class)
.addPackages(true,
"org.keycloak.testsuite",
"org.keycloak.testsuite.model");
}
private static final Logger log = Logger.getLogger(DBLockTest.class);
@ -48,66 +67,65 @@ public class DBLockTest extends AbstractModelTest {
private static final int LOCK_RECHECK_MILLIS = 10;
@Before
@Override
public void before() throws Exception {
super.before();
// Set timeouts for testing
DBLockManager lockManager = new DBLockManager(session);
DBLockProviderFactory lockFactory = lockManager.getDBLockFactory();
lockFactory.setTimeouts(LOCK_RECHECK_MILLIS, LOCK_TIMEOUT_MILLIS);
testingClient.server().run(session -> {
// Set timeouts for testing
DBLockManager lockManager = new DBLockManager(session);
DBLockProviderFactory lockFactory = lockManager.getDBLockFactory();
lockFactory.setTimeouts(LOCK_RECHECK_MILLIS, LOCK_TIMEOUT_MILLIS);
// Drop lock table, just to simulate racing threads for create lock table and insert lock record into it.
lockManager.getDBLock().destroyLockInfo();
// Drop lock table, just to simulate racing threads for create lock table and insert lock record into it.
lockManager.getDBLock().destroyLockInfo();
});
commit();
}
@Test
public void testLockConcurrently() throws Exception {
long startupTime = System.currentTimeMillis();
@ModelTest
public void testLockConcurrently(KeycloakSession session) throws Exception {
final Semaphore semaphore = new Semaphore();
final KeycloakSessionFactory sessionFactory = realmManager.getSession().getKeycloakSessionFactory();
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionLC) -> {
long startupTime = System.currentTimeMillis();
List<Thread> threads = new LinkedList<>();
for (int i=0 ; i<THREADS_COUNT ; i++) {
Thread thread = new Thread() {
final Semaphore semaphore = new Semaphore();
final KeycloakSessionFactory sessionFactory = sessionLC.getKeycloakSessionFactory();
@Override
public void run() {
for (int i=0 ; i<ITERATIONS_PER_THREAD ; i++) {
List<Thread> threads = new LinkedList<>();
for (int i = 0; i < THREADS_COUNT; i++) {
Thread thread = new Thread(() -> {
for (int j = 0; j < ITERATIONS_PER_THREAD; j++) {
try {
KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
@Override
public void run(KeycloakSession session) {
lock(session, semaphore);
}
});
KeycloakModelUtils.runJobInTransaction(sessionFactory, session1 ->
lock(session1, semaphore));
} catch (RuntimeException e) {
semaphore.setException(e);
throw e;
}
}
});
threads.add(thread);
}
for (Thread thread : threads) {
thread.start();
}
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
threads.add(thread);
}
long took = (System.currentTimeMillis() - startupTime);
log.infof("DBLockTest executed in %d ms with total counter %d. THREADS_COUNT=%d, ITERATIONS_PER_THREAD=%d", took, semaphore.getTotal(), THREADS_COUNT, ITERATIONS_PER_THREAD);
for (Thread thread : threads) {
thread.start();
}
for (Thread thread : threads) {
thread.join();
}
long took = (System.currentTimeMillis() - startupTime);
log.infof("DBLockTest executed in %d ms with total counter %d. THREADS_COUNT=%d, ITERATIONS_PER_THREAD=%d", took, semaphore.getTotal(), THREADS_COUNT, ITERATIONS_PER_THREAD);
Assert.assertEquals(semaphore.getTotal(), THREADS_COUNT * ITERATIONS_PER_THREAD);
Assert.assertNull(semaphore.getException());
Assert.assertEquals(semaphore.getTotal(), THREADS_COUNT * ITERATIONS_PER_THREAD);
Assert.assertNull(semaphore.getException());
});
}
private void lock(KeycloakSession session, Semaphore semaphore) {
@ -124,6 +142,9 @@ public class DBLockTest extends AbstractModelTest {
}
}
@Override
public void configureTestRealm(RealmRepresentation testRealm) {
}
// Ensure just one thread is allowed to run at the same time
private class Semaphore {
@ -167,7 +188,7 @@ public class DBLockTest extends AbstractModelTest {
}
}
}

View file

@ -57,7 +57,7 @@ public class ImportTest extends AbstractTestRealmKeycloakTest {
@Deployment
@TargetsContainer(AUTH_SERVER_CURRENT)
public static WebArchive deploy() {
return RunOnServerDeployment.create(UserResource.class, AbstractLDAPTest.class)
return RunOnServerDeployment.create(UserResource.class, ImportTest.class)
.addPackages(true,
"org.keycloak.testsuite",
"org.keycloak.testsuite.model");

View file

@ -0,0 +1,192 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.model;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.TargetsContainer;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Assert;
import org.junit.Test;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.models.*;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.testsuite.AbstractTestRealmKeycloakTest;
import org.keycloak.testsuite.arquillian.annotation.ModelTest;
import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
import java.util.concurrent.atomic.AtomicReference;
import static org.keycloak.testsuite.arquillian.DeploymentTargetModifier.AUTH_SERVER_CURRENT;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class MultipleRealmsTest extends AbstractTestRealmKeycloakTest {
@Deployment
@TargetsContainer(AUTH_SERVER_CURRENT)
public static WebArchive deploy() {
return RunOnServerDeployment.create(UserResource.class, MultipleRealmsTest.class)
.addPackages(true,
"org.keycloak.testsuite",
"org.keycloak.testsuite.model");
}
public static void createObjects(KeycloakSession session, RealmModel realm) {
ClientModel app1 = realm.addClient("app1");
realm.addClient("app2");
session.users().addUser(realm, "user1");
session.users().addUser(realm, "user2");
realm.addRole("role1");
realm.addRole("role2");
app1.addRole("app1Role1");
app1.addScopeMapping(realm.getRole("role1"));
realm.addClient("cl1");
}
@Test
@ModelTest
public void testUsers(KeycloakSession session) {
AtomicReference<UserModel> r1user1Atomic = new AtomicReference<>();
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionTestUser1) -> {
KeycloakSession currentSession = sessionTestUser1;
RealmModel realm1 = currentSession.realms().createRealm("id1", "realm1");
RealmModel realm2 = currentSession.realms().createRealm("id2", "realm2");
createObjects(currentSession, realm1);
createObjects(currentSession, realm2);
UserModel r1user1 = currentSession.users().getUserByUsername("user1", realm1);
UserModel r2user1 = currentSession.users().getUserByUsername("user1", realm2);
r1user1Atomic.set(r1user1);
Assert.assertEquals(r1user1.getUsername(), r2user1.getUsername());
Assert.assertNotEquals(r1user1.getId(), r2user1.getId());
// Test password
currentSession.userCredentialManager().updateCredential(realm1, r1user1, UserCredentialModel.password("pass1"));
currentSession.userCredentialManager().updateCredential(realm2, r2user1, UserCredentialModel.password("pass2"));
Assert.assertTrue(currentSession.userCredentialManager().isValid(realm1, r1user1, UserCredentialModel.password("pass1")));
Assert.assertFalse(currentSession.userCredentialManager().isValid(realm1, r1user1, UserCredentialModel.password("pass2")));
Assert.assertFalse(currentSession.userCredentialManager().isValid(realm2, r2user1, UserCredentialModel.password("pass1")));
Assert.assertTrue(currentSession.userCredentialManager().isValid(realm2, r2user1, UserCredentialModel.password("pass2")));
// Test searching
Assert.assertEquals(2, currentSession.users().searchForUser("user", realm1).size());
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionTestUser2) -> {
KeycloakSession currentSession = sessionTestUser2;
RealmModel realm1 = currentSession.realms().getRealm("id1");
RealmModel realm2 = currentSession.realms().getRealm("id2");
UserModel r1user1 = r1user1Atomic.get();
currentSession.users().removeUser(realm1, r1user1);
UserModel user2 = currentSession.users().getUserByUsername("user2", realm1);
currentSession.users().removeUser(realm1, user2);
Assert.assertEquals(0, currentSession.users().searchForUser("user", realm1).size());
Assert.assertEquals(2, currentSession.users().searchForUser("user", realm2).size());
UserModel user1 = currentSession.users().getUserByUsername("user1", realm1);
UserModel user1a = currentSession.users().getUserByUsername("user1", realm2);
UserManager um = new UserManager(session);
if (user1 != null) {
um.removeUser(realm1, user1);
}
if (user1a != null) {
um.removeUser(realm2, user1a);
}
currentSession.realms().removeRealm("id1");
currentSession.realms().removeRealm("id2");
});
}
@Test
@ModelTest
public void testGetById(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionById) -> {
KeycloakSession currentSession = sessionById;
RealmModel realm1 = currentSession.realms().createRealm("id1", "realm1");
RealmModel realm2 = currentSession.realms().createRealm("id2", "realm2");
createObjects(currentSession, realm1);
createObjects(currentSession, realm2);
Assert.assertEquals(realm1, currentSession.realms().getRealm("id1"));
Assert.assertEquals(realm1, currentSession.realms().getRealmByName("realm1"));
Assert.assertEquals(realm2, currentSession.realms().getRealm("id2"));
Assert.assertEquals(realm2, currentSession.realms().getRealmByName("realm2"));
ClientModel r1app1 = realm1.getClientByClientId("app1");
Assert.assertNotNull(realm1.getClientByClientId("app2"));
Assert.assertNotNull(realm2.getClientByClientId("app1"));
Assert.assertNotNull(realm2.getClientByClientId("app2"));
Assert.assertEquals(r1app1, realm1.getClientById(r1app1.getId()));
Assert.assertNull(realm2.getClientById(r1app1.getId()));
ClientModel r2cl1 = realm2.getClientByClientId("cl1");
Assert.assertEquals(r2cl1.getId(), realm2.getClientById(r2cl1.getId()).getId());
Assert.assertNull(realm1.getClientByClientId(r2cl1.getId()));
RoleModel r1App1Role = r1app1.getRole("app1Role1");
Assert.assertEquals(r1App1Role, realm1.getRoleById(r1App1Role.getId()));
Assert.assertNull(realm2.getRoleById(r1App1Role.getId()));
RoleModel r2Role1 = realm2.getRole("role2");
Assert.assertNull(realm1.getRoleById(r2Role1.getId()));
Assert.assertEquals(r2Role1, realm2.getRoleById(r2Role1.getId()));
UserModel user1 = currentSession.users().getUserByUsername("user1", realm1);
UserModel user1a = currentSession.users().getUserByUsername("user1", realm2);
UserManager um = new UserManager(currentSession);
if (user1 != null) {
um.removeUser(realm1, user1);
}
if (user1a != null) {
um.removeUser(realm2, user1a);
}
currentSession.realms().removeRealm("id1");
currentSession.realms().removeRealm("id2");
});
}
@Override
public void configureTestRealm(RealmRepresentation testRealm) {
}
}

View file

@ -0,0 +1,411 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.model;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.TargetsContainer;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.*;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.storage.client.ClientStorageProviderModel;
import org.keycloak.testsuite.AbstractTestRealmKeycloakTest;
import org.keycloak.testsuite.arquillian.annotation.ModelTest;
import org.keycloak.testsuite.federation.HardcodedClientStorageProviderFactory;
import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import static org.keycloak.testsuite.arquillian.DeploymentTargetModifier.AUTH_SERVER_CURRENT;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class UserConsentModelTest extends AbstractTestRealmKeycloakTest {
private static ComponentModel clientStorageComponent;
@Deployment
@TargetsContainer(AUTH_SERVER_CURRENT)
public static WebArchive deploy() {
return RunOnServerDeployment.create(UserResource.class, UserConsentModelTest.class)
.addPackages(true,
"org.keycloak.testsuite",
"org.keycloak.testsuite.model");
}
@Before
public void before() {
testingClient.server().run(session -> {
setupEnv(session);
});
}
@After
public void after() {
testingClient.server().run(session -> {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = realmManager.getRealmByName("original");
if (realm != null) {
session.sessions().removeUserSessions(realm);
UserModel user = session.users().getUserByUsername("user", realm);
UserModel user1 = session.users().getUserByUsername("user1", realm);
UserModel user2 = session.users().getUserByUsername("user2", realm);
UserModel user3 = session.users().getUserByUsername("user3", realm);
UserManager um = new UserManager(session);
if (user != null) {
um.removeUser(realm, user);
}
if (user1 != null) {
um.removeUser(realm, user1);
}
if (user2 != null) {
um.removeUser(realm, user2);
}
if (user3 != null) {
um.removeUser(realm, user3);
}
realmManager.removeRealm(realm);
}
});
}
public static void setupEnv(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionEnv) -> {
KeycloakSession currentSession = sessionEnv;
RealmManager realmManager = new RealmManager(currentSession);
RealmModel realm = realmManager.createRealm("original");
ClientModel fooClient = realm.addClient("foo-client");
ClientModel barClient = realm.addClient("bar-client");
ClientScopeModel fooScope = realm.addClientScope("foo");
fooScope.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
ClientScopeModel barScope = realm.addClientScope("bar");
fooScope.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
UserModel john = currentSession.users().addUser(realm, "john");
UserModel mary = currentSession.users().addUser(realm, "mary");
UserConsentModel johnFooGrant = new UserConsentModel(fooClient);
johnFooGrant.addGrantedClientScope(fooScope);
realmManager.getSession().users().addConsent(realm, john.getId(), johnFooGrant);
UserConsentModel johnBarGrant = new UserConsentModel(barClient);
johnBarGrant.addGrantedClientScope(barScope);
// Update should fail as grant doesn't yet exists
try {
realmManager.getSession().users().updateConsent(realm, john.getId(), johnBarGrant);
Assert.fail("Not expected to end here");
} catch (ModelException expected) {
}
realmManager.getSession().users().addConsent(realm, john.getId(), johnBarGrant);
UserConsentModel maryFooGrant = new UserConsentModel(fooClient);
maryFooGrant.addGrantedClientScope(fooScope);
realmManager.getSession().users().addConsent(realm, mary.getId(), maryFooGrant);
ClientStorageProviderModel clientStorage = new ClientStorageProviderModel();
clientStorage.setProviderId(HardcodedClientStorageProviderFactory.PROVIDER_ID);
clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.CLIENT_ID, "hardcoded-client");
clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.REDIRECT_URI, "http://localhost:8081/*");
clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.CONSENT, "true");
clientStorage.setParentId(realm.getId());
clientStorageComponent = realm.addComponentModel(clientStorage);
ClientModel hardcodedClient = currentSession.realms().getClientByClientId("hardcoded-client", realm);
Assert.assertNotNull(hardcodedClient);
UserConsentModel maryHardcodedGrant = new UserConsentModel(hardcodedClient);
realmManager.getSession().users().addConsent(realm, mary.getId(), maryHardcodedGrant);
});
}
@Test
@ModelTest
public void basicConsentTest(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCT) -> {
KeycloakSession currentSession = sessionCT;
RealmModel realm = currentSession.realms().getRealm("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
ClientModel barClient = realm.getClientByClientId("bar-client");
UserModel john = currentSession.users().getUserByUsername("john", realm);
UserModel mary = currentSession.users().getUserByUsername("mary", realm);
UserConsentModel johnFooConsent = currentSession.users().getConsentByClient(realm, john.getId(), fooClient.getId());
Assert.assertEquals(johnFooConsent.getGrantedClientScopes().size(), 1);
Assert.assertTrue(isClientScopeGranted(realm, "foo", johnFooConsent));
Assert.assertNotNull("Created Date should be set", johnFooConsent.getCreatedDate());
Assert.assertNotNull("Last Updated Date should be set", johnFooConsent.getLastUpdatedDate());
UserConsentModel johnBarConsent = currentSession.users().getConsentByClient(realm, john.getId(), barClient.getId());
Assert.assertEquals(johnBarConsent.getGrantedClientScopes().size(), 1);
Assert.assertTrue(isClientScopeGranted(realm, "bar", johnBarConsent));
Assert.assertNotNull("Created Date should be set", johnBarConsent.getCreatedDate());
Assert.assertNotNull("Last Updated Date should be set", johnBarConsent.getLastUpdatedDate());
UserConsentModel maryConsent = currentSession.users().getConsentByClient(realm, mary.getId(), fooClient.getId());
Assert.assertEquals(maryConsent.getGrantedClientScopes().size(), 1);
Assert.assertTrue(isClientScopeGranted(realm, "foo", maryConsent));
Assert.assertNotNull("Created Date should be set", maryConsent.getCreatedDate());
Assert.assertNotNull("Last Updated Date should be set", maryConsent.getLastUpdatedDate());
ClientModel hardcodedClient = currentSession.realms().getClientByClientId("hardcoded-client", realm);
UserConsentModel maryHardcodedConsent = currentSession.users().getConsentByClient(realm, mary.getId(), hardcodedClient.getId());
Assert.assertEquals(maryHardcodedConsent.getGrantedClientScopes().size(), 0);
Assert.assertNotNull("Created Date should be set", maryHardcodedConsent.getCreatedDate());
Assert.assertNotNull("Last Updated Date should be set", maryHardcodedConsent.getLastUpdatedDate());
Assert.assertNull(currentSession.users().getConsentByClient(realm, mary.getId(), barClient.getId()));
Assert.assertNull(currentSession.users().getConsentByClient(realm, john.getId(), hardcodedClient.getId()));
});
}
@Test
@ModelTest
public void getAllConsentTest(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionACT) -> {
KeycloakSession currentSession = sessionACT;
RealmModel realm = currentSession.realms().getRealm("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
UserModel john = currentSession.users().getUserByUsername("john", realm);
UserModel mary = currentSession.users().getUserByUsername("mary", realm);
List<UserConsentModel> johnConsents = currentSession.users().getConsents(realm, john.getId());
Assert.assertEquals(2, johnConsents.size());
ClientModel hardcodedClient = currentSession.realms().getClientByClientId("hardcoded-client", realm);
List<UserConsentModel> maryConsents = currentSession.users().getConsents(realm, mary.getId());
Assert.assertEquals(2, maryConsents.size());
UserConsentModel maryConsent = maryConsents.get(0);
UserConsentModel maryHardcodedConsent = maryConsents.get(1);
if (maryConsents.get(0).getClient().getId().equals(hardcodedClient.getId())) {
maryConsent = maryConsents.get(1);
maryHardcodedConsent = maryConsents.get(0);
}
Assert.assertEquals(maryConsent.getClient().getId(), fooClient.getId());
Assert.assertEquals(maryConsent.getGrantedClientScopes().size(), 1);
Assert.assertTrue(isClientScopeGranted(realm, "foo", maryConsent));
Assert.assertEquals(maryHardcodedConsent.getClient().getId(), hardcodedClient.getId());
Assert.assertEquals(maryHardcodedConsent.getGrantedClientScopes().size(), 0);
});
}
@Test
@ModelTest
public void updateWithClientScopeRemovalTest(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession removalTestSession1) -> {
KeycloakSession currentSession = removalTestSession1;
RealmModel realm = currentSession.realms().getRealm("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
UserModel john = currentSession.users().getUserByUsername("john", realm);
UserConsentModel johnConsent = currentSession.users().getConsentByClient(realm, john.getId(), fooClient.getId());
Assert.assertEquals(1, johnConsent.getGrantedClientScopes().size());
// Remove foo protocol mapper from johnConsent
ClientScopeModel fooScope = KeycloakModelUtils.getClientScopeByName(realm, "foo");
johnConsent.getGrantedClientScopes().remove(fooScope);
currentSession.users().updateConsent(realm, john.getId(), johnConsent);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession removalTestSession2) -> {
KeycloakSession currentSession = removalTestSession2;
RealmModel realm = currentSession.realms().getRealm("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
UserModel john = currentSession.users().getUserByUsername("john", realm);
UserConsentModel johnConsent = currentSession.users().getConsentByClient(realm, john.getId(), fooClient.getId());
Assert.assertEquals(johnConsent.getGrantedClientScopes().size(), 0);
Assert.assertTrue("Created date should be less than last updated date", johnConsent.getCreatedDate() < johnConsent.getLastUpdatedDate());
});
}
@Test
@ModelTest
public void revokeTest(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionRT1) -> {
KeycloakSession currentSession = sessionRT1;
RealmModel realm = currentSession.realms().getRealm("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
UserModel john = currentSession.users().getUserByUsername("john", realm);
UserModel mary = currentSession.users().getUserByUsername("mary", realm);
currentSession.users().revokeConsentForClient(realm, john.getId(), fooClient.getId());
ClientModel hardcodedClient = currentSession.realms().getClientByClientId("hardcoded-client", realm);
currentSession.users().revokeConsentForClient(realm, mary.getId(), hardcodedClient.getId());
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionRT2) -> {
KeycloakSession currentSession = sessionRT2;
RealmModel realm = currentSession.realms().getRealm("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
ClientModel hardcodedClient = currentSession.realms().getClientByClientId("hardcoded-client", realm);
UserModel john = currentSession.users().getUserByUsername("john", realm);
Assert.assertNull(currentSession.users().getConsentByClient(realm, john.getId(), fooClient.getId()));
UserModel mary = currentSession.users().getUserByUsername("mary", realm);
Assert.assertNull(currentSession.users().getConsentByClient(realm, mary.getId(), hardcodedClient.getId()));
});
}
@Test
@ModelTest
public void deleteUserTest(KeycloakSession session) {
// Validate user deleted without any referential constraint errors
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionUT) -> {
KeycloakSession currentSession = sessionUT;
RealmModel realm = currentSession.realms().getRealm("original");
UserModel john = currentSession.users().getUserByUsername("john", realm);
currentSession.users().removeUser(realm, john);
UserModel mary = currentSession.users().getUserByUsername("mary", realm);
currentSession.users().removeUser(realm, mary);
});
}
@Test
@ModelTest
public void deleteClientScopeTest(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionST1) -> {
KeycloakSession currentSession = sessionST1;
RealmModel realm = currentSession.realms().getRealm("original");
ClientScopeModel fooScope = KeycloakModelUtils.getClientScopeByName(realm, "foo");
realm.removeClientScope(fooScope.getId());
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionST2) -> {
KeycloakSession currentSession = sessionST2;
RealmModel realm = currentSession.realms().getRealm("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
UserModel john = currentSession.users().getUserByUsername("john", realm);
UserConsentModel johnConsent = currentSession.users().getConsentByClient(realm, john.getId(), fooClient.getId());
Assert.assertEquals(johnConsent.getGrantedClientScopes().size(), 0);
});
}
@Test
@ModelTest
public void deleteClientTest(KeycloakSession session) {
AtomicReference<String> barClientID = new AtomicReference<>();
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionDCT1) -> {
KeycloakSession currentSession = sessionDCT1;
RealmModel realm = currentSession.realms().getRealm("original");
ClientModel barClient = realm.getClientByClientId("bar-client");
barClientID.set(barClient.getId());
realm.removeClient(barClient.getId());
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionDCT2) -> {
KeycloakSession currentSession = sessionDCT2;
RealmModel realm = currentSession.realms().getRealm("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
Assert.assertNull(realm.getClientByClientId("bar-client"));
UserModel john = currentSession.users().getUserByUsername("john", realm);
ClientModel barClient = realm.getClientByClientId("bar-client");
UserConsentModel johnFooConsent = currentSession.users().getConsentByClient(realm, john.getId(), fooClient.getId());
Assert.assertEquals(johnFooConsent.getGrantedClientScopes().size(), 1);
Assert.assertTrue(isClientScopeGranted(realm, "foo", johnFooConsent));
Assert.assertNull(currentSession.users().getConsentByClient(realm, john.getId(), barClientID.get()));
});
}
@Test
@ModelTest
public void deleteClientStorageTest(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCST1) -> {
KeycloakSession currentSession = sessionCST1;
RealmModel realm = currentSession.realms().getRealm("original");
realm.removeComponent(clientStorageComponent);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCST2) -> {
KeycloakSession currentSession = sessionCST2;
RealmModel realm = currentSession.realms().getRealm("original");
ClientModel hardcodedClient = currentSession.realms().getClientByClientId("hardcoded-client", realm);
Assert.assertNull(hardcodedClient);
UserModel mary = currentSession.users().getUserByUsername("mary", realm);
List<UserConsentModel> maryConsents = currentSession.users().getConsents(realm, mary.getId());
Assert.assertEquals(1, maryConsents.size());
});
}
private boolean isClientScopeGranted(RealmModel realm, String scopeName, UserConsentModel consentModel) {
ClientScopeModel clientScope = KeycloakModelUtils.getClientScopeByName(realm, scopeName);
return consentModel.isClientScopeGranted(clientScope);
}
@Override
public void configureTestRealm(RealmRepresentation testRealm) {
}
}

View file

@ -0,0 +1,420 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.model;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.TargetsContainer;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.*;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.client.ClientStorageProviderModel;
import org.keycloak.testsuite.AbstractTestRealmKeycloakTest;
import org.keycloak.testsuite.arquillian.annotation.ModelTest;
import org.keycloak.testsuite.federation.HardcodedClientStorageProviderFactory;
import org.keycloak.testsuite.federation.UserMapStorageFactory;
import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import static org.keycloak.testsuite.arquillian.DeploymentTargetModifier.AUTH_SERVER_CURRENT;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class UserConsentWithUserStorageModelTest extends AbstractTestRealmKeycloakTest {
@Deployment
@TargetsContainer(AUTH_SERVER_CURRENT)
public static WebArchive deploy() {
return RunOnServerDeployment.create(UserResource.class, UserConsentWithUserStorageModelTest.class)
.addPackages(true,
"org.keycloak.testsuite",
"org.keycloak.testsuite.model");
}
private static ComponentModel clientStorageComponent;
@Before
public void before() {
testingClient.server().run(currentSession -> {
setupEnv(currentSession);
});
}
@After
public void after() {
testingClient.server().run(session -> {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = realmManager.getRealmByName("original");
if (realm != null) {
session.sessions().removeUserSessions(realm);
UserModel user = session.users().getUserByUsername("user", realm);
UserModel user1 = session.users().getUserByUsername("user1", realm);
UserModel user2 = session.users().getUserByUsername("user2", realm);
UserModel user3 = session.users().getUserByUsername("user3", realm);
UserManager um = new UserManager(session);
if (user != null) {
um.removeUser(realm, user);
}
if (user1 != null) {
um.removeUser(realm, user1);
}
if (user2 != null) {
um.removeUser(realm, user2);
}
if (user3 != null) {
um.removeUser(realm, user3);
}
realmManager.removeRealm(realm);
}
});
}
public static void setupEnv(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionSetUpEnv) -> {
KeycloakSession currentSession = sessionSetUpEnv;
RealmManager realmManager = new RealmManager(currentSession);
RealmModel realm = realmManager.createRealm("original");
UserStorageProviderModel model = new UserStorageProviderModel();
model.setName("memory");
model.setPriority(0);
model.setProviderId(UserMapStorageFactory.PROVIDER_ID);
model.setParentId(realm.getId());
realm.addComponentModel(model);
ClientModel fooClient = realm.addClient("foo-client");
ClientModel barClient = realm.addClient("bar-client");
ClientScopeModel fooScope = realm.addClientScope("foo");
fooScope.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
ClientScopeModel barScope = realm.addClientScope("bar");
fooScope.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
UserModel john = currentSession.users().addUser(realm, "john");
UserModel mary = currentSession.users().addUser(realm, "mary");
UserConsentModel johnFooGrant = new UserConsentModel(fooClient);
johnFooGrant.addGrantedClientScope(fooScope);
realmManager.getSession().users().addConsent(realm, john.getId(), johnFooGrant);
UserConsentModel johnBarGrant = new UserConsentModel(barClient);
johnBarGrant.addGrantedClientScope(barScope);
// Update should fail as grant doesn't yet exists
try {
currentSession.users().updateConsent(realm, john.getId(), johnBarGrant);
Assert.fail("Not expected to end here");
} catch (ModelException expected) {
}
realmManager.getSession().users().addConsent(realm, john.getId(), johnBarGrant);
UserConsentModel maryFooGrant = new UserConsentModel(fooClient);
maryFooGrant.addGrantedClientScope(fooScope);
realmManager.getSession().users().addConsent(realm, mary.getId(), maryFooGrant);
ClientStorageProviderModel clientStorage = new ClientStorageProviderModel();
clientStorage.setProviderId(HardcodedClientStorageProviderFactory.PROVIDER_ID);
clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.CLIENT_ID, "hardcoded-client");
clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.REDIRECT_URI, "http://localhost:8081/*");
clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.CONSENT, "true");
clientStorage.setParentId(realm.getId());
clientStorageComponent = realm.addComponentModel(clientStorage);
ClientModel hardcodedClient = currentSession.realms().getClientByClientId("hardcoded-client", realm);
Assert.assertNotNull(hardcodedClient);
UserConsentModel maryHardcodedGrant = new UserConsentModel(hardcodedClient);
realmManager.getSession().users().addConsent(realm, mary.getId(), maryHardcodedGrant);
});
}
@Test
@ModelTest
public void basicConsentTest(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession currentSessionCT) -> {
KeycloakSession currentSession = currentSessionCT;
RealmModel realm = currentSession.realms().getRealmByName("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
ClientModel barClient = realm.getClientByClientId("bar-client");
UserModel john = currentSessionCT.users().getUserByUsername("john", realm);
UserModel mary = currentSessionCT.users().getUserByUsername("mary", realm);
UserConsentModel johnFooConsent = currentSession.users().getConsentByClient(realm, john.getId(), fooClient.getId());
Assert.assertEquals(johnFooConsent.getGrantedClientScopes().size(), 1);
Assert.assertTrue(isClientScopeGranted(realm, "foo", johnFooConsent));
Assert.assertNotNull("Created Date should be set", johnFooConsent.getCreatedDate());
Assert.assertNotNull("Last Updated Date should be set", johnFooConsent.getLastUpdatedDate());
UserConsentModel johnBarConsent = currentSession.users().getConsentByClient(realm, john.getId(), barClient.getId());
Assert.assertEquals(johnBarConsent.getGrantedClientScopes().size(), 1);
Assert.assertTrue(isClientScopeGranted(realm, "bar", johnBarConsent));
Assert.assertNotNull("Created Date should be set", johnBarConsent.getCreatedDate());
Assert.assertNotNull("Last Updated Date should be set", johnBarConsent.getLastUpdatedDate());
UserConsentModel maryConsent = currentSession.users().getConsentByClient(realm, mary.getId(), fooClient.getId());
Assert.assertEquals(maryConsent.getGrantedClientScopes().size(), 1);
Assert.assertTrue(isClientScopeGranted(realm, "foo", maryConsent));
Assert.assertNotNull("Created Date should be set", maryConsent.getCreatedDate());
Assert.assertNotNull("Last Updated Date should be set", maryConsent.getLastUpdatedDate());
ClientModel hardcodedClient = currentSessionCT.realms().getClientByClientId("hardcoded-client", realm);
UserConsentModel maryHardcodedConsent = currentSession.users().getConsentByClient(realm, mary.getId(), hardcodedClient.getId());
Assert.assertEquals(maryHardcodedConsent.getGrantedClientScopes().size(), 0);
Assert.assertNotNull("Created Date should be set", maryHardcodedConsent.getCreatedDate());
Assert.assertNotNull("Last Updated Date should be set", maryHardcodedConsent.getLastUpdatedDate());
Assert.assertNull(currentSession.users().getConsentByClient(realm, mary.getId(), barClient.getId()));
Assert.assertNull(currentSession.users().getConsentByClient(realm, john.getId(), hardcodedClient.getId()));
});
}
@Test
@ModelTest
public void getAllConsentTest(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession currentSessionACT) -> {
KeycloakSession currentSession = currentSessionACT;
RealmModel realm = currentSession.realms().getRealmByName("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
UserModel john = currentSessionACT.users().getUserByUsername("john", realm);
UserModel mary = currentSessionACT.users().getUserByUsername("mary", realm);
List<UserConsentModel> johnConsents = currentSession.users().getConsents(realm, john.getId());
Assert.assertEquals(2, johnConsents.size());
ClientModel hardcodedClient = currentSessionACT.realms().getClientByClientId("hardcoded-client", realm);
List<UserConsentModel> maryConsents = currentSession.users().getConsents(realm, mary.getId());
Assert.assertEquals(2, maryConsents.size());
UserConsentModel maryConsent = maryConsents.get(0);
UserConsentModel maryHardcodedConsent = maryConsents.get(1);
if (maryConsents.get(0).getClient().getId().equals(hardcodedClient.getId())) {
maryConsent = maryConsents.get(1);
maryHardcodedConsent = maryConsents.get(0);
}
Assert.assertEquals(maryConsent.getClient().getId(), fooClient.getId());
Assert.assertEquals(maryConsent.getGrantedClientScopes().size(), 1);
Assert.assertTrue(isClientScopeGranted(realm, "foo", maryConsent));
Assert.assertEquals(maryHardcodedConsent.getClient().getId(), hardcodedClient.getId());
Assert.assertEquals(maryHardcodedConsent.getGrantedClientScopes().size(), 0);
});
}
@Test
@ModelTest
public void updateWithClientScopeRemovalTest(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionScopeRemoval1) -> {
KeycloakSession currentSession = sessionScopeRemoval1;
RealmModel realm = currentSession.realms().getRealmByName("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
UserModel john = currentSession.users().getUserByUsername("john", realm);
UserConsentModel johnConsent = currentSession.users().getConsentByClient(realm, john.getId(), fooClient.getId());
Assert.assertEquals(1, johnConsent.getGrantedClientScopes().size());
// Remove foo protocol mapper from johnConsent
ClientScopeModel fooScope = KeycloakModelUtils.getClientScopeByName(realm, "foo");
johnConsent.getGrantedClientScopes().remove(fooScope);
currentSession.users().updateConsent(realm, john.getId(), johnConsent);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionScopeRemoval2) -> {
KeycloakSession currentSession = sessionScopeRemoval2;
RealmModel realm = currentSession.realms().getRealmByName("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
UserModel john = currentSession.users().getUserByUsername("john", realm);
UserConsentModel johnConsent = currentSession.users().getConsentByClient(realm, john.getId(), fooClient.getId());
Assert.assertEquals(johnConsent.getGrantedClientScopes().size(), 0);
Assert.assertTrue("Created date should be less than last updated date", johnConsent.getCreatedDate() < johnConsent.getLastUpdatedDate());
});
}
@Test
@ModelTest
public void revokeTest(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionRevoke1) -> {
KeycloakSession currentSession = sessionRevoke1;
RealmModel realm = currentSession.realms().getRealmByName("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
UserModel john = currentSession.users().getUserByUsername("john", realm);
UserModel mary = currentSession.users().getUserByUsername("mary", realm);
currentSession.users().revokeConsentForClient(realm, john.getId(), fooClient.getId());
ClientModel hardcodedClient = currentSession.realms().getClientByClientId("hardcoded-client", realm);
currentSession.users().revokeConsentForClient(realm, mary.getId(), hardcodedClient.getId());
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionRevoke2) -> {
KeycloakSession currentSession = sessionRevoke2;
RealmModel realm = currentSession.realms().getRealmByName("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
ClientModel hardcodedClient = currentSession.realms().getClientByClientId("hardcoded-client", realm);
UserModel john = currentSession.users().getUserByUsername("john", realm);
Assert.assertNull(currentSession.users().getConsentByClient(realm, john.getId(), fooClient.getId()));
UserModel mary = currentSession.users().getUserByUsername("mary", realm);
Assert.assertNull(currentSession.users().getConsentByClient(realm, mary.getId(), hardcodedClient.getId()));
});
}
@Test
@ModelTest
public void deleteUserTest(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionDelete) -> {
// Validate user deleted without any referential constraint errors
KeycloakSession currentSession = sessionDelete;
RealmModel realm = currentSession.realms().getRealmByName("original");
UserModel john = currentSession.users().getUserByUsername("john", realm);
currentSession.users().removeUser(realm, john);
UserModel mary = currentSession.users().getUserByUsername("mary", realm);
currentSession.users().removeUser(realm, mary);
});
}
@Test
@ModelTest
public void deleteClientScopeTest(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesDelClScope1) -> {
KeycloakSession currentSession = sesDelClScope1;
RealmModel realm = currentSession.realms().getRealmByName("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
ClientScopeModel fooScope = KeycloakModelUtils.getClientScopeByName(realm, "foo");
realm.removeClientScope(fooScope.getId());
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesDelClScope2) -> {
KeycloakSession currentSession = sesDelClScope2;
RealmModel realm = currentSession.realms().getRealmByName("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
UserModel john = currentSession.users().getUserByUsername("john", realm);
UserConsentModel johnConsent = currentSession.users().getConsentByClient(realm, john.getId(), fooClient.getId());
Assert.assertEquals(johnConsent.getGrantedClientScopes().size(), 0);
});
}
@Test
@ModelTest
public void deleteClientTest(KeycloakSession session) {
AtomicReference<String> barClientID = new AtomicReference<>();
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesDelClient1) -> {
KeycloakSession currentSession = sesDelClient1;
RealmManager realmManager = new RealmManager(currentSession);
RealmModel realm = realmManager.getRealmByName("original");
ClientModel barClient = realm.getClientByClientId("bar-client");
barClientID.set(barClient.getId());
realm.removeClient(barClient.getId());
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesDelClient2) -> {
KeycloakSession currentSession = sesDelClient2;
RealmManager realmManager = new RealmManager(currentSession);
RealmModel realm = realmManager.getRealm("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
Assert.assertNull(realm.getClientByClientId("bar-client"));
UserModel john = realmManager.getSession().users().getUserByUsername("john", realm);
UserConsentModel johnFooConsent = realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId());
Assert.assertEquals(johnFooConsent.getGrantedClientScopes().size(), 1);
Assert.assertTrue(isClientScopeGranted(realm, "foo", johnFooConsent));
Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john.getId(), barClientID.get()));
});
}
@Test
@ModelTest
public void deleteClientStorageTest(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesDelClientStore1) -> {
KeycloakSession currentSession = sesDelClientStore1;
RealmModel realm = currentSession.realms().getRealmByName("original");
realm.removeComponent(clientStorageComponent);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesDelClientStore2) -> {
KeycloakSession currentSession = sesDelClientStore2;
RealmModel realm = currentSession.realms().getRealmByName("original");
ClientModel hardcodedClient = currentSession.realms().getClientByClientId("hardcoded-client", realm);
Assert.assertNull(hardcodedClient);
UserModel mary = currentSession.users().getUserByUsername("mary", realm);
List<UserConsentModel> maryConsents = currentSession.users().getConsents(realm, mary.getId());
Assert.assertEquals(1, maryConsents.size());
});
}
private boolean isClientScopeGranted(RealmModel realm, String scopeName, UserConsentModel consentModel) {
ClientScopeModel clientScope = KeycloakModelUtils.getClientScopeByName(realm, scopeName);
return consentModel.isClientScopeGranted(clientScope);
}
@Override
public void configureTestRealm(RealmRepresentation testRealm) {
}
}

View file

@ -0,0 +1,615 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.model;
import com.google.common.collect.ImmutableMap;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.TargetsContainer;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.models.*;
import org.keycloak.models.UserModel.RequiredAction;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.managers.ClientManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.testsuite.AbstractTestRealmKeycloakTest;
import org.keycloak.testsuite.arquillian.annotation.ModelTest;
import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.Assert.assertNotNull;
import static org.keycloak.testsuite.arquillian.DeploymentTargetModifier.AUTH_SERVER_CURRENT;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class UserModelTest extends AbstractTestRealmKeycloakTest {
@Deployment
@TargetsContainer(AUTH_SERVER_CURRENT)
public static WebArchive deploy() {
return RunOnServerDeployment.create(UserResource.class, UserModelTest.class)
.addPackages(true,
"org.keycloak.testsuite",
"org.keycloak.testsuite.model",
"com.google.common");
}
@After
public void after() {
testingClient.server().run(session -> {
RealmModel realm = session.realms().getRealmByName("original");
if (realm != null) {
session.sessions().removeUserSessions(realm);
UserModel user = session.users().getUserByUsername("user", realm);
UserModel user1 = session.users().getUserByUsername("user1", realm);
UserModel user2 = session.users().getUserByUsername("user2", realm);
UserModel user3 = session.users().getUserByUsername("user3", realm);
UserManager um = new UserManager(session);
if (user != null) {
um.removeUser(realm, user);
}
if (user1 != null) {
um.removeUser(realm, user1);
}
if (user2 != null) {
um.removeUser(realm, user2);
}
if (user3 != null) {
um.removeUser(realm, user3);
}
session.realms().removeRealm(realm.getId());
}
});
}
@Test
@ModelTest
public void persistUser(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesPersistUser) -> {
KeycloakSession currentSession = sesPersistUser;
RealmModel realm = currentSession.realms().createRealm("original");
UserModel user = currentSession.users().addUser(realm, "user");
user.setFirstName("first-name");
user.setLastName("last-name");
user.setEmail("email");
assertNotNull(user.getCreatedTimestamp());
// test that timestamp is current with 10s tollerance
Assert.assertTrue((System.currentTimeMillis() - user.getCreatedTimestamp()) < 10000);
user.addRequiredAction(RequiredAction.CONFIGURE_TOTP);
user.addRequiredAction(RequiredAction.UPDATE_PASSWORD);
RealmModel searchRealm = currentSession.realms().getRealm(realm.getId());
UserModel persisted = currentSession.users().getUserByUsername("user", searchRealm);
assertEquals(user, persisted);
searchRealm = currentSession.realms().getRealm(realm.getId());
UserModel persisted2 = currentSession.users().getUserById(user.getId(), searchRealm);
assertEquals(user, persisted2);
Map<String, String> attributes = new HashMap<>();
attributes.put(UserModel.LAST_NAME, "last-name");
List<UserModel> search = currentSession.users().searchForUser(attributes, realm);
Assert.assertEquals(search.size(), 1);
Assert.assertEquals(search.get(0).getUsername(), "user");
attributes.clear();
attributes.put(UserModel.EMAIL, "email");
search = currentSession.users().searchForUser(attributes, realm);
Assert.assertEquals(search.size(), 1);
Assert.assertEquals(search.get(0).getUsername(), "user");
attributes.clear();
attributes.put(UserModel.LAST_NAME, "last-name");
attributes.put(UserModel.EMAIL, "email");
search = currentSession.users().searchForUser(attributes, realm);
Assert.assertEquals(search.size(), 1);
Assert.assertEquals(search.get(0).getUsername(), "user");
});
}
@Test
@ModelTest
public void webOriginSetTest(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesWebOrigin) -> {
KeycloakSession currentSession = sesWebOrigin;
RealmModel realm = currentSession.realms().createRealm("original");
ClientModel client = realm.addClient("user");
Assert.assertTrue(client.getWebOrigins().isEmpty());
client.addWebOrigin("origin-1");
Assert.assertEquals(1, client.getWebOrigins().size());
client.addWebOrigin("origin-2");
Assert.assertEquals(2, client.getWebOrigins().size());
client.removeWebOrigin("origin-2");
Assert.assertEquals(1, client.getWebOrigins().size());
client.removeWebOrigin("origin-1");
Assert.assertTrue(client.getWebOrigins().isEmpty());
client = realm.addClient("oauthclient2");
Assert.assertTrue(client.getWebOrigins().isEmpty());
client.addWebOrigin("origin-1");
Assert.assertEquals(1, client.getWebOrigins().size());
client.addWebOrigin("origin-2");
Assert.assertEquals(2, client.getWebOrigins().size());
client.removeWebOrigin("origin-2");
Assert.assertEquals(1, client.getWebOrigins().size());
client.removeWebOrigin("origin-1");
Assert.assertTrue(client.getWebOrigins().isEmpty());
});
}
@Test
@ModelTest
public void testUserRequiredActions(KeycloakSession session) throws Exception {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesUserReqActions) -> {
KeycloakSession currentSession = sesUserReqActions;
RealmModel realm = currentSession.realms().createRealm("original");
UserModel user = currentSession.users().addUser(realm, "user");
Assert.assertTrue(user.getRequiredActions().isEmpty());
user.addRequiredAction(RequiredAction.CONFIGURE_TOTP);
String id = realm.getId();
realm = currentSession.realms().getRealm(id);
user = currentSession.users().getUserByUsername("user", realm);
Assert.assertEquals(1, user.getRequiredActions().size());
Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.CONFIGURE_TOTP.name()));
user.addRequiredAction(RequiredAction.CONFIGURE_TOTP);
user = currentSession.users().getUserByUsername("user", realm);
Assert.assertEquals(1, user.getRequiredActions().size());
Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.CONFIGURE_TOTP.name()));
user.addRequiredAction(RequiredAction.VERIFY_EMAIL.name());
user = currentSession.users().getUserByUsername("user", realm);
Assert.assertEquals(2, user.getRequiredActions().size());
Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.CONFIGURE_TOTP.name()));
Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.VERIFY_EMAIL.name()));
user.removeRequiredAction(RequiredAction.CONFIGURE_TOTP.name());
user = currentSession.users().getUserByUsername("user", realm);
Assert.assertEquals(1, user.getRequiredActions().size());
Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.VERIFY_EMAIL.name()));
user.removeRequiredAction(RequiredAction.VERIFY_EMAIL.name());
user = currentSession.users().getUserByUsername("user", realm);
Assert.assertTrue(user.getRequiredActions().isEmpty());
});
}
@Test
@ModelTest
public void testUserMultipleAttributes(KeycloakSession session) throws Exception {
AtomicReference<List<String>> attrValsAtomic = new AtomicReference<>();
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesMultipleAtr1) -> {
KeycloakSession currentSession = sesMultipleAtr1;
RealmModel realm = currentSession.realms().createRealm("original");
UserModel user = currentSession.users().addUser(realm, "user");
currentSession.users().addUser(realm, "user-noattrs");
user.setSingleAttribute("key1", "value1");
List<String> attrVals = new ArrayList<>(Arrays.asList("val21", "val22"));
attrValsAtomic.set(attrVals);
user.setAttribute("key2", attrVals);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesMultipleAtr2) -> {
KeycloakSession currentSession = sesMultipleAtr2;
RealmModel realm = currentSession.realms().getRealmByName("original");
// Test read attributes
UserModel user = currentSession.users().getUserByUsername("user", realm);
List<String> attrVals = attrValsAtomic.get();
attrVals = user.getAttribute("key1");
Assert.assertEquals(1, attrVals.size());
Assert.assertEquals("value1", attrVals.get(0));
Assert.assertEquals("value1", user.getFirstAttribute("key1"));
attrVals = user.getAttribute("key2");
Assert.assertEquals(2, attrVals.size());
Assert.assertTrue(attrVals.contains("val21"));
Assert.assertTrue(attrVals.contains("val22"));
attrVals = user.getAttribute("key3");
Assert.assertTrue(attrVals.isEmpty());
Assert.assertNull(user.getFirstAttribute("key3"));
Map<String, List<String>> allAttrVals = user.getAttributes();
Assert.assertEquals(2, allAttrVals.size());
Assert.assertEquals(allAttrVals.get("key1"), user.getAttribute("key1"));
Assert.assertEquals(allAttrVals.get("key2"), user.getAttribute("key2"));
// Test remove and rewrite attribute
user.removeAttribute("key1");
user.setSingleAttribute("key2", "val23");
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesMultipleAtr3) -> {
KeycloakSession currentSession = sesMultipleAtr3;
RealmModel realm = currentSession.realms().getRealmByName("original");
UserModel user = currentSession.users().getUserByUsername("user", realm);
Assert.assertNull(user.getFirstAttribute("key1"));
List<String> attrVals = attrValsAtomic.get();
attrVals = user.getAttribute("key2");
Assert.assertEquals(1, attrVals.size());
Assert.assertEquals("val23", attrVals.get(0));
});
}
// KEYCLOAK-3494
@Test
@ModelTest
public void testUpdateUserAttribute(KeycloakSession session) throws Exception {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesUpdateAtr1) -> {
KeycloakSession currentSession = sesUpdateAtr1;
RealmModel realm = currentSession.realms().createRealm("original");
UserModel user = currentSession.users().addUser(realm, "user");
user.setSingleAttribute("key1", "value1");
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesUpdateAtr2) -> {
KeycloakSession currentSession = sesUpdateAtr2;
RealmModel realm = currentSession.realms().getRealmByName("original");
UserModel user = currentSession.users().getUserByUsername("user", realm);
// Update attribute
List<String> attrVals = new ArrayList<>(Arrays.asList("val2"));
user.setAttribute("key1", attrVals);
Map<String, List<String>> allAttrVals = user.getAttributes();
// Ensure same transaction is able to see updated value
Assert.assertEquals(1, allAttrVals.size());
Assert.assertEquals(allAttrVals.get("key1"), Arrays.asList("val2"));
});
}
// KEYCLOAK-3608
@Test
@ModelTest
public void testUpdateUserSingleAttribute(KeycloakSession session) {
AtomicReference<Map<String, List<String>>> expectedAtomic = new AtomicReference<>();
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesUpdateUserSingleAtr) -> {
KeycloakSession currentSession = sesUpdateUserSingleAtr;
RealmModel realm = currentSession.realms().createRealm("original");
Map<String, List<String>> expected = ImmutableMap.of(
"key1", Arrays.asList("value3"),
"key2", Arrays.asList("value2"));
expectedAtomic.set(expected);
UserModel user = currentSession.users().addUser(realm, "user");
user.setSingleAttribute("key1", "value1");
user.setSingleAttribute("key2", "value2");
// Overwrite the first attribute
user.setSingleAttribute("key1", "value3");
Assert.assertEquals(expected, user.getAttributes());
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesUpdateUserSingleAtr2) -> {
KeycloakSession currentSession = sesUpdateUserSingleAtr2;
RealmModel realm = currentSession.realms().getRealmByName("original");
Map<String, List<String>> expected = expectedAtomic.get();
Assert.assertEquals(expected, currentSession.users().getUserByUsername("user", realm).getAttributes());
});
}
@Test
@ModelTest
public void testSearchByString(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesSearchString1) -> {
KeycloakSession currentSession = sesSearchString1;
RealmModel realm = currentSession.realms().createRealm("original");
currentSession.users().addUser(realm, "user1");
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesSearchString1) -> {
KeycloakSession currentSession = sesSearchString1;
RealmModel realm = currentSession.realms().getRealmByName("original");
UserModel user1 = currentSession.users().getUserByUsername("user1", realm);
List<UserModel> users = currentSession.users().searchForUser("user", realm, 0, 7);
Assert.assertTrue(users.contains(user1));
});
}
@Test
@ModelTest
public void testSearchByUserAttribute(KeycloakSession session) throws Exception {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesSearchAtr1) -> {
KeycloakSession currentSession = sesSearchAtr1;
RealmModel realm = currentSession.realms().createRealm("original");
UserModel user1 = currentSession.users().addUser(realm, "user1");
UserModel user2 = currentSession.users().addUser(realm, "user2");
UserModel user3 = currentSession.users().addUser(realm, "user3");
RealmModel otherRealm = currentSession.realms().createRealm("other");
UserModel otherRealmUser = currentSession.users().addUser(otherRealm, "user1");
user1.setSingleAttribute("key1", "value1");
user1.setSingleAttribute("key2", "value21");
user2.setSingleAttribute("key1", "value1");
user2.setSingleAttribute("key2", "value22");
user3.setSingleAttribute("key2", "value21");
otherRealmUser.setSingleAttribute("key2", "value21");
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesSearchAtr2) -> {
KeycloakSession currentSession = sesSearchAtr2;
RealmModel realm = currentSession.realms().getRealmByName("original");
UserModel user1 = currentSession.users().getUserByUsername("user1", realm);
UserModel user2 = currentSession.users().getUserByUsername("user2", realm);
UserModel user3 = currentSession.users().getUserByUsername("user3", realm);
List<UserModel> users = currentSession.users().searchForUserByUserAttribute("key1", "value1", realm);
Assert.assertEquals(2, users.size());
Assert.assertTrue(users.contains(user1));
Assert.assertTrue(users.contains(user2));
users = currentSession.users().searchForUserByUserAttribute("key2", "value21", realm);
Assert.assertEquals(2, users.size());
Assert.assertTrue(users.contains(user1));
Assert.assertTrue(users.contains(user3));
users = currentSession.users().searchForUserByUserAttribute("key2", "value22", realm);
Assert.assertEquals(1, users.size());
Assert.assertTrue(users.contains(user2));
users = currentSession.users().searchForUserByUserAttribute("key3", "value3", realm);
Assert.assertEquals(0, users.size());
});
}
@Test
@ModelTest
public void testServiceAccountLink(KeycloakSession session) throws Exception {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesServiceLink1) -> {
KeycloakSession currentSession = sesServiceLink1;
RealmModel realm = currentSession.realms().createRealm("original");
ClientModel client = realm.addClient("foo");
UserModel user1 = currentSession.users().addUser(realm, "user1");
user1.setFirstName("John");
user1.setLastName("Doe");
UserModel user2 = currentSession.users().addUser(realm, "user2");
user2.setFirstName("John");
user2.setLastName("Doe");
// Search
Assert.assertNull(currentSession.users().getServiceAccount(client));
List<UserModel> users = currentSession.users().searchForUser("John Doe", realm);
Assert.assertEquals(2, users.size());
Assert.assertTrue(users.contains(user1));
Assert.assertTrue(users.contains(user2));
// Link service account
user1.setServiceAccountClientLink(client.getId());
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesServiceLink2) -> {
KeycloakSession currentSession = sesServiceLink2;
RealmModel realm = currentSession.realms().getRealmByName("original");
UserModel user1 = currentSession.users().getUserByUsername("user1", realm);
UserModel user2 = currentSession.users().getUserByUsername("user2", realm);
// Search and assert service account user not found
ClientModel client = realm.getClientByClientId("foo");
UserModel searched = currentSession.users().getServiceAccount(client);
Assert.assertEquals(searched, user1);
List<UserModel> users = currentSession.users().searchForUser("John Doe", realm);
Assert.assertEquals(1, users.size());
Assert.assertFalse(users.contains(user1));
Assert.assertTrue(users.contains(user2));
users = currentSession.users().getUsers(realm, false);
Assert.assertEquals(1, users.size());
Assert.assertFalse(users.contains(user1));
Assert.assertTrue(users.contains(user2));
users = currentSession.users().getUsers(realm, true);
Assert.assertEquals(2, users.size());
Assert.assertTrue(users.contains(user1));
Assert.assertTrue(users.contains(user2));
Assert.assertEquals(2, currentSession.users().getUsersCount(realm, true));
Assert.assertEquals(1, currentSession.users().getUsersCount(realm, false));
// Remove client
RealmManager realmMgr = new RealmManager(currentSession);
ClientManager clientMgr = new ClientManager(realmMgr);
clientMgr.removeClient(realm, client);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesServiceLink3) -> {
KeycloakSession currentSession = sesServiceLink3;
RealmModel realm = currentSession.realms().getRealmByName("original");
// Assert service account removed as well
Assert.assertNull(currentSession.users().getUserByUsername("user1", realm));
});
}
@Test
@ModelTest
public void testGrantToAll(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesGrantToAll1) -> {
KeycloakSession currentSession = sesGrantToAll1;
if (currentSession.realms().getRealm("realm1") != null)
currentSession.realms().removeRealm("realm1");
RealmModel realm1 = currentSession.realms().createRealm("realm1");
realm1.addRole("role1");
currentSession.users().addUser(realm1, "user1");
currentSession.users().addUser(realm1, "user2");
if (currentSession.realms().getRealm("realm2") != null)
currentSession.realms().removeRealm("realm2");
RealmModel realm2 = currentSession.realms().createRealm("realm2");
currentSession.users().addUser(realm2, "user1");
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesGrantToAll2) -> {
KeycloakSession currentSession = sesGrantToAll2;
RealmModel realm1 = currentSession.realms().getRealmByName("realm1");
RoleModel role1 = realm1.getRole("role1");
currentSession.users().grantToAllUsers(realm1, role1);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesGrantToAll2) -> {
KeycloakSession currentSession = sesGrantToAll2;
RealmModel realm1 = currentSession.realms().getRealmByName("realm1");
RoleModel role1 = realm1.getRole("role1");
UserModel user1 = currentSession.users().getUserByUsername("user1", realm1);
UserModel user2 = currentSession.users().getUserByUsername("user2", realm1);
Assert.assertTrue(user1.hasRole(role1));
Assert.assertTrue(user2.hasRole(role1));
RealmModel realm2 = currentSession.realms().getRealmByName("realm2");
UserModel realm2User1 = currentSession.users().getUserByUsername("user1", realm2);
Assert.assertFalse(realm2User1.hasRole(role1));
currentSession.realms().removeRealm(realm1.getId());
currentSession.realms().removeRealm(realm2.getId());
});
}
@Test
@ModelTest
public void testUserNotBefore(KeycloakSession session) throws Exception {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesUserNotBefore1) -> {
KeycloakSession currentSession = sesUserNotBefore1;
RealmModel realm = currentSession.realms().createRealm("original");
UserModel user1 = currentSession.users().addUser(realm, "user1");
currentSession.users().setNotBeforeForUser(realm, user1, 10);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesUserNotBefore2) -> {
KeycloakSession currentSession = sesUserNotBefore2;
RealmModel realm = currentSession.realms().getRealmByName("original");
UserModel user1 = currentSession.users().getUserByUsername("user1", realm);
int notBefore = currentSession.users().getNotBeforeOfUser(realm, user1);
Assert.assertEquals(10, notBefore);
// Try to update
currentSession.users().setNotBeforeForUser(realm, user1, 20);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesUserNotBefore3) -> {
KeycloakSession currentSession = sesUserNotBefore3;
RealmModel realm = currentSession.realms().getRealmByName("original");
UserModel user1 = currentSession.users().getUserByUsername("user1", realm);
int notBefore = currentSession.users().getNotBeforeOfUser(realm, user1);
Assert.assertEquals(20, notBefore);
});
}
public static void assertEquals(UserModel expected, UserModel actual) {
Assert.assertEquals(expected.getUsername(), actual.getUsername());
Assert.assertEquals(expected.getCreatedTimestamp(), actual.getCreatedTimestamp());
Assert.assertEquals(expected.getFirstName(), actual.getFirstName());
Assert.assertEquals(expected.getLastName(), actual.getLastName());
String[] expectedRequiredActions = expected.getRequiredActions().toArray(new String[expected.getRequiredActions().size()]);
Arrays.sort(expectedRequiredActions);
String[] actualRequiredActions = actual.getRequiredActions().toArray(new String[actual.getRequiredActions().size()]);
Arrays.sort(actualRequiredActions);
Assert.assertArrayEquals(expectedRequiredActions, actualRequiredActions);
}
@Override
public void configureTestRealm(RealmRepresentation testRealm) {
}
}

View file

@ -0,0 +1,611 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.model;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.TargetsContainer;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.*;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.common.util.Time;
import org.keycloak.models.*;
import org.keycloak.models.session.UserSessionPersisterProvider;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.managers.ClientManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.testsuite.AbstractTestRealmKeycloakTest;
import org.keycloak.testsuite.arquillian.annotation.ModelTest;
import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicReferenceArray;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.keycloak.testsuite.arquillian.DeploymentTargetModifier.AUTH_SERVER_CURRENT;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class UserSessionPersisterProviderTest extends AbstractTestRealmKeycloakTest {
@Deployment
@TargetsContainer(AUTH_SERVER_CURRENT)
public static WebArchive deploy() {
return RunOnServerDeployment.create(UserResource.class, UserSessionPersisterProvider.class)
.addPackages(true,
"org.keycloak.testsuite",
"org.keycloak.testsuite.model");
}
@Before
public void before() {
testingClient.server().run(session -> {
initStuff(session);
});
}
public static void initStuff(KeycloakSession session) {
RealmModel realm = session.realms().getRealm("test");
session.users().addUser(realm, "user1").setEmail("user1@localhost");
session.users().addUser(realm, "user2").setEmail("user2@localhost");
}
@After
public void after() {
testingClient.server().run(session -> {
RealmModel realm = session.realms().getRealm("test");
session.sessions().removeUserSessions(realm);
UserModel user1 = session.users().getUserByUsername("user1", realm);
UserModel user2 = session.users().getUserByUsername("user2", realm);
UserManager um = new UserManager(session);
if (user1 != null) {
um.removeUser(realm, user1);
}
if (user2 != null) {
um.removeUser(realm, user2);
}
});
}
@Test
@ModelTest
public void testPersistenceWithLoad(KeycloakSession session) {
int started = Time.currentTime();
UserSessionModel[][] origSessions = new UserSessionModel[1][1];
final UserSessionModel[] userSession = new UserSessionModel[1];
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionWL) -> {
// Create some sessions in infinispan
origSessions[0] = createSessions(sessionWL);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionWL22) -> {
// Persist 3 created userSessions and clientSessions as offline
RealmModel realm = sessionWL22.realms().getRealm("test");
ClientModel testApp = realm.getClientByClientId("test-app");
List<UserSessionModel> userSessions = sessionWL22.sessions().getUserSessions(realm, testApp);
for (UserSessionModel userSessionLooper : userSessions) {
persistUserSession(sessionWL22, userSessionLooper, true);
}
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionWL2) -> {
// Persist 1 online session
RealmModel realm = sessionWL2.realms().getRealm("test");
userSession[0] = sessionWL2.sessions().getUserSession(realm, origSessions[0][0].getId());
persistUserSession(sessionWL2, userSession[0], false);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionWL3) -> {// Assert online session
RealmModel realm = sessionWL3.realms().getRealm("test");
List<UserSessionModel> loadedSessions = loadPersistedSessionsPaginated(sessionWL3, false, 1, 1, 1);
UserSessionProviderTest.assertSession(loadedSessions.get(0), sessionWL3.users().getUserByUsername("user1", realm), "127.0.0.1", started, started, "test-app", "third-party");
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionWL4) -> {
// Assert offline sessions
RealmModel realm = sessionWL4.realms().getRealm("test");
List<UserSessionModel> loadedSessions = loadPersistedSessionsPaginated(sessionWL4, true, 2, 2, 3);
UserSessionProviderTest.assertSessions(loadedSessions, origSessions[0]);
assertSessionLoaded(loadedSessions, origSessions[0][0].getId(), sessionWL4.users().getUserByUsername("user1", realm), "127.0.0.1", started, started, "test-app", "third-party");
assertSessionLoaded(loadedSessions, origSessions[0][1].getId(), sessionWL4.users().getUserByUsername("user1", realm), "127.0.0.2", started, started, "test-app");
assertSessionLoaded(loadedSessions, origSessions[0][2].getId(), sessionWL4.users().getUserByUsername("user2", realm), "127.0.0.3", started, started, "test-app");
});
}
@Test
@ModelTest
public void testUpdateAndRemove(KeycloakSession session) {
int started = Time.currentTime();
AtomicReference<UserSessionModel[]> origSessionsAt = new AtomicReference<>();
AtomicReference<List<UserSessionModel>> loadedSessionsAt = new AtomicReference<>();
AtomicReference<UserSessionModel> userSessionAt = new AtomicReference<>();
AtomicReference<UserSessionModel> persistedSessionAt = new AtomicReference<>();
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesUpdateRemove1) -> {
KeycloakSession currentSession = sesUpdateRemove1;
// Create some sessions in infinispan
UserSessionModel[] origSessions = createSessions(currentSession);
origSessionsAt.set(origSessions);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesUpdateRemove2) -> {
KeycloakSession currentSession = sesUpdateRemove2;
RealmModel realm = currentSession.realms().getRealm("test");
UserSessionModel[] origSessions = origSessionsAt.get();
// Persist 1 offline session
UserSessionModel userSession = currentSession.sessions().getUserSession(realm, origSessions[1].getId());
userSessionAt.set(userSession);
persistUserSession(currentSession, userSession, true);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesUpdateRemove3) -> {
KeycloakSession currentSession = sesUpdateRemove3;
RealmModel realm = currentSession.realms().getRealm("test");
UserSessionPersisterProvider persister = currentSession.getProvider(UserSessionPersisterProvider.class);
// Load offline session
List<UserSessionModel> loadedSessions = loadPersistedSessionsPaginated(currentSession, true, 10, 1, 1);
loadedSessionsAt.set(loadedSessions);
UserSessionModel persistedSession = loadedSessions.get(0);
persistedSessionAt.set(persistedSession);
UserSessionProviderTest.assertSession(persistedSession, currentSession.users().getUserByUsername("user1", realm), "127.0.0.2", started, started, "test-app");
// create new clientSession
AuthenticatedClientSessionModel clientSession = createClientSession(currentSession, realm.getClientByClientId("third-party"), currentSession.sessions().getUserSession(realm, persistedSession.getId()),
"http://redirect", "state");
persister.createClientSession(clientSession, true);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesUpdateRemove4) -> {
KeycloakSession currentSession = sesUpdateRemove4;
RealmModel realm = currentSession.realms().getRealm("test");
UserSessionPersisterProvider persister = currentSession.getProvider(UserSessionPersisterProvider.class);
UserSessionModel userSession = userSessionAt.get();
// Remove clientSession
persister.removeClientSession(userSession.getId(), realm.getClientByClientId("third-party").getId(), true);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesUpdateRemove5) -> {
KeycloakSession currentSession = sesUpdateRemove5;
RealmModel realm = currentSession.realms().getRealm("test");
UserSessionPersisterProvider persister = currentSession.getProvider(UserSessionPersisterProvider.class);
List<UserSessionModel> loadedSessions = loadedSessionsAt.get();
UserSessionModel persistedSession = persistedSessionAt.get();
// Assert clientSession removed
loadedSessions = loadPersistedSessionsPaginated(currentSession, true, 10, 1, 1);
persistedSession = loadedSessions.get(0);
UserSessionProviderTest.assertSession(persistedSession, currentSession.users().getUserByUsername("user1", realm), "127.0.0.2", started, started, "test-app");
// Remove userSession
persister.removeUserSession(persistedSession.getId(), true);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sesUpdateRemove6) -> {
KeycloakSession currentSession = sesUpdateRemove6;
// Assert nothing found
loadPersistedSessionsPaginated(currentSession, true, 10, 0, 0);
});
}
@Test
@ModelTest
public void testOnRealmRemoved(KeycloakSession session) {
AtomicReference<String> userSessionID = new AtomicReference<>();
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionRR1) -> {
KeycloakSession currentSession = sessionRR1;
RealmModel fooRealm = currentSession.realms().createRealm("foo", "foo");
fooRealm.addClient("foo-app");
currentSession.users().addUser(fooRealm, "user3");
UserSessionModel userSession = currentSession.sessions().createUserSession(fooRealm, currentSession.users().getUserByUsername("user3", fooRealm), "user3", "127.0.0.1", "form", true, null, null);
userSessionID.set(userSession.getId());
createClientSession(currentSession, fooRealm.getClientByClientId("foo-app"), userSession, "http://redirect", "state");
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionRR2) -> {
KeycloakSession currentSession = sessionRR2;
// Persist offline session
RealmModel fooRealm = currentSession.realms().getRealm("foo");
UserSessionModel userSession = currentSession.sessions().getUserSession(fooRealm, userSessionID.get());
persistUserSession(currentSession, userSession, true);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionRR3) -> {
KeycloakSession currentSession = sessionRR3;
// Assert session was persisted
loadPersistedSessionsPaginated(currentSession, true, 10, 1, 1);
// Remove realm
RealmManager realmMgr = new RealmManager(currentSession);
realmMgr.removeRealm(realmMgr.getRealm("foo"));
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionRR4) -> {
KeycloakSession currentSession = sessionRR4;
// Assert nothing loaded
loadPersistedSessionsPaginated(currentSession, true, 10, 0, 0);
});
}
@Test
@ModelTest
public void testOnClientRemoved(KeycloakSession session) {
int started = Time.currentTime();
AtomicReference<String> userSessionID = new AtomicReference<>();
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCR1) -> {
KeycloakSession currentSession = sessionCR1;
RealmModel fooRealm = currentSession.realms().createRealm("foo", "foo");
fooRealm.addClient("foo-app");
fooRealm.addClient("bar-app");
currentSession.users().addUser(fooRealm, "user3");
UserSessionModel userSession = currentSession.sessions().createUserSession(fooRealm, currentSession.users().getUserByUsername("user3", fooRealm), "user3", "127.0.0.1", "form", true, null, null);
userSessionID.set(userSession.getId());
createClientSession(currentSession, fooRealm.getClientByClientId("foo-app"), userSession, "http://redirect", "state");
createClientSession(currentSession, fooRealm.getClientByClientId("bar-app"), userSession, "http://redirect", "state");
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCR2) -> {
KeycloakSession currentSession = sessionCR2;
RealmModel fooRealm = currentSession.realms().getRealm("foo");
// Persist offline session
UserSessionModel userSession = currentSession.sessions().getUserSession(fooRealm, userSessionID.get());
persistUserSession(currentSession, userSession, true);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCR3) -> {
KeycloakSession currentSession = sessionCR3;
RealmManager realmMgr = new RealmManager(currentSession);
ClientManager clientMgr = new ClientManager(realmMgr);
RealmModel fooRealm = realmMgr.getRealm("foo");
// Assert session was persisted with both clientSessions
UserSessionModel persistedSession = loadPersistedSessionsPaginated(currentSession, true, 10, 1, 1).get(0);
UserSessionProviderTest.assertSession(persistedSession, currentSession.users().getUserByUsername("user3", fooRealm), "127.0.0.1", started, started, "foo-app", "bar-app");
// Remove foo-app client
ClientModel client = fooRealm.getClientByClientId("foo-app");
clientMgr.removeClient(fooRealm, client);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCR4) -> {
KeycloakSession currentSession = sessionCR4;
RealmManager realmMgr = new RealmManager(currentSession);
ClientManager clientMgr = new ClientManager(realmMgr);
RealmModel fooRealm = realmMgr.getRealm("foo");
// Assert just one bar-app clientSession persisted now
UserSessionModel persistedSession = loadPersistedSessionsPaginated(currentSession, true, 10, 1, 1).get(0);
UserSessionProviderTest.assertSession(persistedSession, currentSession.users().getUserByUsername("user3", fooRealm), "127.0.0.1", started, started, "bar-app");
// Remove bar-app client
ClientModel client = fooRealm.getClientByClientId("bar-app");
clientMgr.removeClient(fooRealm, client);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCR5) -> {
KeycloakSession currentSession = sessionCR5;
// Assert loading still works - last userSession is still there, but no clientSession on it
loadPersistedSessionsPaginated(currentSession, true, 10, 1, 1);
// Cleanup
RealmManager realmMgr = new RealmManager(currentSession);
realmMgr.removeRealm(realmMgr.getRealm("foo"));
});
}
@Test
@ModelTest
public void testOnUserRemoved(KeycloakSession session) {
int started = Time.currentTime();
AtomicReference<UserSessionModel[]> origSessionsAt = new AtomicReference<>();
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionOR1) -> {
KeycloakSession currentSession = sessionOR1;
// Create some sessions in infinispan
UserSessionModel[] origSessions = createSessions(currentSession);
origSessionsAt.set(origSessions);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionOR2) -> {
KeycloakSession currentSession = sessionOR2;
RealmModel realm = currentSession.realms().getRealm("test");
UserSessionModel[] origSessions = origSessionsAt.get();
// Persist 2 offline sessions of 2 users
UserSessionModel userSession1 = currentSession.sessions().getUserSession(realm, origSessions[1].getId());
UserSessionModel userSession2 = currentSession.sessions().getUserSession(realm, origSessions[2].getId());
persistUserSession(currentSession, userSession1, true);
persistUserSession(currentSession, userSession2, true);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionOR3) -> {
KeycloakSession currentSession = sessionOR3;
RealmModel realm = currentSession.realms().getRealm("test");
// Load offline sessions
loadPersistedSessionsPaginated(currentSession, true, 10, 1, 2);
// Properly delete user and assert his offlineSession removed
UserModel user1 = currentSession.users().getUserByUsername("user1", realm);
new UserManager(currentSession).removeUser(realm, user1);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionOR4) -> {
KeycloakSession currentSession = sessionOR4;
RealmModel realm = currentSession.realms().getRealm("test");
UserSessionPersisterProvider persister = currentSession.getProvider(UserSessionPersisterProvider.class);
Assert.assertEquals(1, persister.getUserSessionsCount(true));
List<UserSessionModel> loadedSessions = loadPersistedSessionsPaginated(currentSession, true, 10, 1, 1);
UserSessionModel persistedSession = loadedSessions.get(0);
UserSessionProviderTest.assertSession(persistedSession, currentSession.users().getUserByUsername("user2", realm), "127.0.0.3", started, started, "test-app");
// KEYCLOAK-2431 Assert that userSessionPersister is resistent even to situation, when users are deleted "directly".
// No exception will happen. However session will be still there
UserModel user2 = currentSession.users().getUserByUsername("user2", realm);
currentSession.users().removeUser(realm, user2);
loadedSessions = loadPersistedSessionsPaginated(currentSession, true, 10, 1, 1);
// Cleanup
UserSessionModel userSession = loadedSessions.get(0);
currentSession.sessions().removeUserSession(realm, userSession);
persister.removeUserSession(userSession.getId(), userSession.isOffline());
});
}
// KEYCLOAK-1999
@Test
@ModelTest
public void testNoSessions(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionNS) -> {
UserSessionPersisterProvider persister = sessionNS.getProvider(UserSessionPersisterProvider.class);
List<UserSessionModel> sessions = persister.loadUserSessions(0, 1, true, 0, "abc");
Assert.assertEquals(0, sessions.size());
});
}
@Test
@ModelTest
public void testMoreSessions(KeycloakSession session) {
AtomicReference<List<UserSessionModel>> userSessionsAt = new AtomicReference<>();
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionMS1) -> {
KeycloakSession currentSession = sessionMS1;
RealmModel realm = currentSession.realms().getRealm("test");
// Create 10 userSessions - each having 1 clientSession
List<UserSessionModel> userSessions = new ArrayList<>();
UserModel user = currentSession.users().getUserByUsername("user1", realm);
for (int i = 0; i < 20; i++) {
// Having different offsets for each session (to ensure that lastSessionRefresh is also different)
Time.setOffset(i);
UserSessionModel userSession = currentSession.sessions().createUserSession(realm, user, "user1", "127.0.0.1", "form", true, null, null);
createClientSession(currentSession, realm.getClientByClientId("test-app"), userSession, "http://redirect", "state");
userSessions.add(userSession);
}
userSessionsAt.set(userSessions);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionMS2) -> {
KeycloakSession currentSession = sessionMS2;
RealmModel realm = currentSession.realms().getRealm("test");
List<UserSessionModel> userSessions = userSessionsAt.get();
for (UserSessionModel userSession : userSessions) {
UserSessionModel userSession2 = currentSession.sessions().getUserSession(realm, userSession.getId());
persistUserSession(currentSession, userSession2, true);
}
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionMS3) -> {
KeycloakSession currentSession = sessionMS3;
RealmModel realm = currentSession.realms().getRealm("test");
List<UserSessionModel> loadedSessions = loadPersistedSessionsPaginated(currentSession, true, 2, 10, 20);
UserModel user = currentSession.users().getUserByUsername("user1", realm);
ClientModel testApp = realm.getClientByClientId("test-app");
for (UserSessionModel loadedSession : loadedSessions) {
assertEquals(user.getId(), loadedSession.getUser().getId());
assertEquals("127.0.0.1", loadedSession.getIpAddress());
assertEquals(user.getUsername(), loadedSession.getLoginUsername());
assertEquals(1, loadedSession.getAuthenticatedClientSessions().size());
assertTrue(loadedSession.getAuthenticatedClientSessions().containsKey(testApp.getId()));
}
});
}
@Test
@ModelTest
public void testExpiredSessions(KeycloakSession session) {
UserSessionModel[][] origSessions = {new UserSessionModel[1]};
int started = Time.currentTime();
final UserSessionModel[] userSession1 = {null};
final UserSessionModel[] userSession2 = {null};
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionES) -> {
// Create some sessions in infinispan
UserSessionPersisterProvider persister = sessionES.getProvider(UserSessionPersisterProvider.class);
origSessions[0] = createSessions(sessionES);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionES2) -> {
// Persist 2 offline sessions of 2 users
RealmModel realm = sessionES2.realms().getRealm("test");
UserSessionPersisterProvider persister = sessionES2.getProvider(UserSessionPersisterProvider.class);
userSession1[0] = sessionES2.sessions().getUserSession(realm, origSessions[0][1].getId());
userSession2[0] = sessionES2.sessions().getUserSession(realm, origSessions[0][2].getId());
persistUserSession(sessionES2, userSession1[0], true);
persistUserSession(sessionES2, userSession2[0], true);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionES3) -> {
// Update one of the sessions with lastSessionRefresh of 20 days ahead
int lastSessionRefresh = Time.currentTime() + 1728000;
RealmModel realm = sessionES3.realms().getRealm("test");
UserSessionPersisterProvider persister = sessionES3.getProvider(UserSessionPersisterProvider.class);
persister.updateLastSessionRefreshes(realm, lastSessionRefresh, Collections.singleton(userSession1[0].getId()), true);
// Increase time offset - 40 days
Time.setOffset(3456000);
try {
// Run expiration thread
persister.removeExpired(realm);
// Test the updated session is still in persister. Not updated session is not there anymore
List<UserSessionModel> loadedSessions = loadPersistedSessionsPaginated(sessionES3, true, 10, 1, 1);
UserSessionModel persistedSession = loadedSessions.get(0);
UserSessionProviderTest.assertSession(persistedSession, sessionES3.users().getUserByUsername("user1", realm), "127.0.0.2", started, lastSessionRefresh, "test-app");
} finally {
// Cleanup
Time.setOffset(0);
}
});
}
private AuthenticatedClientSessionModel createClientSession(KeycloakSession session, ClientModel client, UserSessionModel userSession, String redirect, String state) {
RealmModel realm = session.realms().getRealm("test");
AuthenticatedClientSessionModel clientSession = session.sessions().createClientSession(realm, client, userSession);
clientSession.setRedirectUri(redirect);
if (state != null) clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, state);
return clientSession;
}
private UserSessionModel[] createSessions(KeycloakSession session) {
RealmModel realm = session.realms().getRealm("test");
UserSessionModel[] sessions = new UserSessionModel[3];
sessions[0] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "user1", "127.0.0.1", "form", true, null, null);
createClientSession(session, realm.getClientByClientId("test-app"), sessions[0], "http://redirect", "state");
createClientSession(session, realm.getClientByClientId("third-party"), sessions[0], "http://redirect", "state");
sessions[1] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "user1", "127.0.0.2", "form", true, null, null);
createClientSession(session, realm.getClientByClientId("test-app"), sessions[1], "http://redirect", "state");
sessions[2] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user2", realm), "user2", "127.0.0.3", "form", true, null, null);
createClientSession(session, realm.getClientByClientId("test-app"), sessions[2], "http://redirect", "state");
return sessions;
}
private void persistUserSession(KeycloakSession session, UserSessionModel userSession, boolean offline) {
UserSessionPersisterProvider persister = session.getProvider(UserSessionPersisterProvider.class);
persister.createUserSession(userSession, offline);
for (AuthenticatedClientSessionModel clientSession : userSession.getAuthenticatedClientSessions().values()) {
persister.createClientSession(clientSession, offline);
}
}
public static void assertSessionLoaded(List<UserSessionModel> sessions, String id, UserModel user, String ipAddress, int started, int lastRefresh, String... clients) {
for (UserSessionModel session : sessions) {
if (session.getId().equals(id)) {
UserSessionProviderTest.assertSession(session, user, ipAddress, started, lastRefresh, clients);
return;
}
}
Assert.fail("Session with ID " + id + " not found in the list");
}
private List<UserSessionModel> loadPersistedSessionsPaginated(KeycloakSession session, boolean offline, int sessionsPerPage, int expectedPageCount, int expectedSessionsCount) {
UserSessionPersisterProvider persister = session.getProvider(UserSessionPersisterProvider.class);
int count = persister.getUserSessionsCount(offline);
int pageCount = 0;
boolean next = true;
List<UserSessionModel> result = new ArrayList<>();
int lastCreatedOn = 0;
String lastSessionId = "abc";
while (next) {
List<UserSessionModel> sess = persister.loadUserSessions(0, sessionsPerPage, offline, lastCreatedOn, lastSessionId);
if (sess.size() < sessionsPerPage) {
next = false;
// We had at least some session
if (sess.size() > 0) {
pageCount++;
}
} else {
pageCount++;
UserSessionModel lastSession = sess.get(sess.size() - 1);
lastCreatedOn = lastSession.getStarted();
lastSessionId = lastSession.getId();
}
result.addAll(sess);
}
Assert.assertEquals(expectedPageCount, pageCount);
Assert.assertEquals(expectedSessionsCount, result.size());
return result;
}
@Override
public void configureTestRealm(RealmRepresentation testRealm) {
}
}

View file

@ -0,0 +1,636 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.model;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.TargetsContainer;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.common.util.Time;
import org.keycloak.models.*;
import org.keycloak.models.session.UserSessionPersisterProvider;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.managers.ClientManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.UserSessionManager;
import org.keycloak.testsuite.AbstractTestRealmKeycloakTest;
import org.keycloak.testsuite.arquillian.annotation.ModelTest;
import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.keycloak.testsuite.arquillian.DeploymentTargetModifier.AUTH_SERVER_CURRENT;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class UserSessionProviderOfflineTest extends AbstractTestRealmKeycloakTest {
private static KeycloakSession currentSession;
private static RealmModel realm;
private static UserSessionManager sessionManager;
private static UserSessionPersisterProvider persister;
@Deployment
@TargetsContainer(AUTH_SERVER_CURRENT)
public static WebArchive deploy() {
return RunOnServerDeployment.create(UserResource.class, UserSessionProviderOfflineTest.class)
.addPackages(true,
"org.keycloak.testsuite",
"org.keycloak.testsuite.model");
}
@Before
public void before() {
testingClient.server().run(session -> {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionBefore) -> {
reloadState(sessionBefore, true);
persister = sessionBefore.getProvider(UserSessionPersisterProvider.class);
});
});
}
@After
public void after() {
testingClient.server().run(session -> {
RealmModel realm = session.realms().getRealmByName("test");
session.sessions().removeUserSessions(realm);
UserModel user1 = session.users().getUserByUsername("user1", realm);
UserModel user2 = session.users().getUserByUsername("user2", realm);
UserManager um = new UserManager(session);
if (user1 != null) {
um.removeUser(realm, user1);
}
if (user2 != null) {
um.removeUser(realm, user2);
}
});
}
@Test
@ModelTest
public void testOfflineSessionsCrud(KeycloakSession session) {
Map<String, Set<String>> offlineSessions = new HashMap<>();
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCrud) -> {
// Create some online sessions in infinispan
reloadState(sessionCrud);
createSessions(sessionCrud);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCrud2) -> {
currentSession = sessionCrud2;
realm = currentSession.realms().getRealm("test");
sessionManager = new UserSessionManager(currentSession);
persister = currentSession.getProvider(UserSessionPersisterProvider.class);
// Key is userSession ID, values are client UUIDS
// Persist 3 created userSessions and clientSessions as offline
ClientModel testApp = realm.getClientByClientId("test-app");
List<UserSessionModel> userSessions = currentSession.sessions().getUserSessions(realm, testApp);
for (UserSessionModel userSession : userSessions) {
offlineSessions.put(userSession.getId(), createOfflineSessionIncludeClientSessions(currentSession, userSession));
}
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCrud3) -> {
currentSession = sessionCrud3;
realm = currentSession.realms().getRealm("test");
sessionManager = new UserSessionManager(currentSession);
persister = currentSession.getProvider(UserSessionPersisterProvider.class);
// Assert all previously saved offline sessions found
for (Map.Entry<String, Set<String>> entry : offlineSessions.entrySet()) {
UserSessionModel offlineSession = sessionManager.findOfflineUserSession(realm, entry.getKey());
Assert.assertNotNull(offlineSession);
Assert.assertEquals(offlineSession.getAuthenticatedClientSessions().keySet(), entry.getValue());
}
// Find clients with offline token
UserModel user1 = currentSession.users().getUserByUsername("user1", realm);
Set<ClientModel> clients = sessionManager.findClientsWithOfflineToken(realm, user1);
Assert.assertEquals(clients.size(), 2);
for (ClientModel client : clients) {
Assert.assertTrue(client.getClientId().equals("test-app") || client.getClientId().equals("third-party"));
}
UserModel user2 = currentSession.users().getUserByUsername("user2", realm);
clients = sessionManager.findClientsWithOfflineToken(realm, user2);
Assert.assertEquals(clients.size(), 1);
Assert.assertEquals("test-app", clients.iterator().next().getClientId());
// Test count
ClientModel testApp = realm.getClientByClientId("test-app");
ClientModel thirdparty = realm.getClientByClientId("third-party");
Assert.assertEquals(3, currentSession.sessions().getOfflineSessionsCount(realm, testApp));
Assert.assertEquals(1, currentSession.sessions().getOfflineSessionsCount(realm, thirdparty));
// Revoke "test-app" for user1
sessionManager.revokeOfflineToken(user1, testApp);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCrud4) -> {
currentSession = sessionCrud4;
realm = currentSession.realms().getRealm("test");
sessionManager = new UserSessionManager(currentSession);
persister = currentSession.getProvider(UserSessionPersisterProvider.class);
// Assert userSession revoked
ClientModel testApp = realm.getClientByClientId("test-app");
ClientModel thirdparty = realm.getClientByClientId("third-party");
// Still 2 sessions. The count of sessions by client may not be accurate after revoke due the
// performance optimizations (the "127.0.0.1" currentSession still has another client "thirdparty" in it)
Assert.assertEquals(2, currentSession.sessions().getOfflineSessionsCount(realm, testApp));
Assert.assertEquals(1, currentSession.sessions().getOfflineSessionsCount(realm, thirdparty));
List<UserSessionModel> thirdpartySessions = currentSession.sessions().getOfflineUserSessions(realm, thirdparty, 0, 10);
Assert.assertEquals(1, thirdpartySessions.size());
Assert.assertEquals("127.0.0.1", thirdpartySessions.get(0).getIpAddress());
Assert.assertEquals("user1", thirdpartySessions.get(0).getUser().getUsername());
UserModel user1 = currentSession.users().getUserByUsername("user1", realm);
UserModel user2 = currentSession.users().getUserByUsername("user2", realm);
Set<ClientModel> clients = sessionManager.findClientsWithOfflineToken(realm, user1);
Assert.assertEquals(1, clients.size());
Assert.assertEquals("third-party", clients.iterator().next().getClientId());
clients = sessionManager.findClientsWithOfflineToken(realm, user2);
Assert.assertEquals(1, clients.size());
Assert.assertEquals("test-app", clients.iterator().next().getClientId());
// Revoke the second currentSession for user1 too.
sessionManager.revokeOfflineToken(user1, thirdparty);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCrud5) -> {
currentSession = sessionCrud5;
realm = currentSession.realms().getRealm("test");
sessionManager = new UserSessionManager(currentSession);
persister = currentSession.getProvider(UserSessionPersisterProvider.class);
ClientModel testApp = realm.getClientByClientId("test-app");
ClientModel thirdparty = realm.getClientByClientId("third-party");
// Accurate count now. All sessions of user1 cleared
Assert.assertEquals(1, currentSession.sessions().getOfflineSessionsCount(realm, testApp));
Assert.assertEquals(0, currentSession.sessions().getOfflineSessionsCount(realm, thirdparty));
List<UserSessionModel> testAppSessions = currentSession.sessions().getOfflineUserSessions(realm, testApp, 0, 10);
Assert.assertEquals(1, testAppSessions.size());
Assert.assertEquals("127.0.0.3", testAppSessions.get(0).getIpAddress());
Assert.assertEquals("user2", testAppSessions.get(0).getUser().getUsername());
UserModel user1 = currentSession.users().getUserByUsername("user1", realm);
Set<ClientModel> clients = sessionManager.findClientsWithOfflineToken(realm, user1);
Assert.assertEquals(0, clients.size());
});
}
@Test
@ModelTest
public void testOnRealmRemoved(KeycloakSession session) {
AtomicReference<String> userSessionID = new AtomicReference<>();
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionRR1) -> {
currentSession = sessionRR1;
persister = currentSession.getProvider(UserSessionPersisterProvider.class);
RealmModel fooRealm = currentSession.realms().createRealm("foo", "foo");
fooRealm.addClient("foo-app");
currentSession.users().addUser(fooRealm, "user3");
UserSessionModel userSession = currentSession.sessions().createUserSession(fooRealm, currentSession.users().getUserByUsername("user3", fooRealm), "user3", "127.0.0.1", "form", true, null, null);
userSessionID.set(userSession.getId());
createClientSession(currentSession, fooRealm.getClientByClientId("foo-app"), userSession, "http://redirect", "state");
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionRR2) -> {
currentSession = sessionRR2;
sessionManager = new UserSessionManager(currentSession);
// Persist offline session
RealmModel fooRealm = currentSession.realms().getRealm("foo");
UserSessionModel userSession = currentSession.sessions().getUserSession(fooRealm, userSessionID.get());
createOfflineSessionIncludeClientSessions(currentSession, userSession);
UserSessionModel offlineUserSession = sessionManager.findOfflineUserSession(fooRealm, userSession.getId());
Assert.assertEquals(offlineUserSession.getAuthenticatedClientSessions().size(), 1);
AuthenticatedClientSessionModel offlineClientSession = offlineUserSession.getAuthenticatedClientSessions().values().iterator().next();
Assert.assertEquals("foo-app", offlineClientSession.getClient().getClientId());
Assert.assertEquals("user3", offlineClientSession.getUserSession().getUser().getUsername());
// Remove realm
RealmManager realmMgr = new RealmManager(currentSession);
realmMgr.removeRealm(realmMgr.getRealm("foo"));
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionRR3) -> {
currentSession = sessionRR3;
RealmModel fooRealm = currentSession.realms().createRealm("foo", "foo");
fooRealm.addClient("foo-app");
currentSession.users().addUser(fooRealm, "user3");
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionRR4) -> {
currentSession = sessionRR4;
RealmModel fooRealm = currentSession.realms().getRealm("foo");
Assert.assertEquals(0, currentSession.sessions().getOfflineSessionsCount(fooRealm, fooRealm.getClientByClientId("foo-app")));
// Cleanup
RealmManager realmMgr = new RealmManager(currentSession);
realmMgr.removeRealm(realmMgr.getRealm("foo"));
});
}
@Test
@ModelTest
public void testOnClientRemoved(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCR) -> {
try {
int started = Time.currentTime();
AtomicReference<String> userSessionID = new AtomicReference<>();
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCR1) -> {
currentSession = sessionCR1;
sessionManager = new UserSessionManager(currentSession);
persister = currentSession.getProvider(UserSessionPersisterProvider.class);
RealmModel fooRealm = currentSession.realms().createRealm("foo", "foo");
fooRealm.addClient("foo-app");
fooRealm.addClient("bar-app");
currentSession.users().addUser(fooRealm, "user3");
UserSessionModel userSession = currentSession.sessions().createUserSession(fooRealm, currentSession.users().getUserByUsername("user3", fooRealm), "user3", "127.0.0.1", "form", true, null, null);
userSessionID.set(userSession.getId());
createClientSession(currentSession, fooRealm.getClientByClientId("foo-app"), userSession, "http://redirect", "state");
createClientSession(currentSession, fooRealm.getClientByClientId("bar-app"), userSession, "http://redirect", "state");
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCR2) -> {
currentSession = sessionCR2;
// Create offline currentSession
RealmModel fooRealm = currentSession.realms().getRealm("foo");
UserSessionModel userSession = currentSession.sessions().getUserSession(fooRealm, userSessionID.get());
createOfflineSessionIncludeClientSessions(currentSession, userSession);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCR3) -> {
currentSession = sessionCR3;
RealmManager realmMgr = new RealmManager(currentSession);
ClientManager clientMgr = new ClientManager(realmMgr);
RealmModel fooRealm = realmMgr.getRealm("foo");
// Assert currentSession was persisted with both clientSessions
UserSessionModel offlineSession = currentSession.sessions().getOfflineUserSession(fooRealm, userSessionID.get());
assertSession(offlineSession, currentSession.users().getUserByUsername("user3", fooRealm), "127.0.0.1", started, started, "foo-app", "bar-app");
// Remove foo-app client
ClientModel client = fooRealm.getClientByClientId("foo-app");
clientMgr.removeClient(fooRealm, client);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCR4) -> {
currentSession = sessionCR4;
RealmManager realmMgr = new RealmManager(currentSession);
ClientManager clientMgr = new ClientManager(realmMgr);
RealmModel fooRealm = realmMgr.getRealm("foo");
// Assert just one bar-app clientSession persisted now
UserSessionModel offlineSession = currentSession.sessions().getOfflineUserSession(fooRealm, userSessionID.get());
Assert.assertEquals(1, offlineSession.getAuthenticatedClientSessions().size());
Assert.assertEquals("bar-app", offlineSession.getAuthenticatedClientSessions().values().iterator().next().getClient().getClientId());
// Remove bar-app client
ClientModel client = fooRealm.getClientByClientId("bar-app");
clientMgr.removeClient(fooRealm, client);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCR5) -> {
currentSession = sessionCR5;
// Assert nothing loaded - userSession was removed as well because it was last userSession
RealmManager realmMgr = new RealmManager(currentSession);
RealmModel fooRealm = realmMgr.getRealm("foo");
UserSessionModel offlineSession = currentSession.sessions().getOfflineUserSession(fooRealm, userSessionID.get());
Assert.assertEquals(0, offlineSession.getAuthenticatedClientSessions().size());
});
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionTearDown) -> {
currentSession = sessionTearDown;
RealmManager realmMgr = new RealmManager(currentSession);
RealmModel fooRealm = realmMgr.getRealm("foo");
UserModel user3 = currentSession.users().getUserByUsername("user3", fooRealm);
// Remove user3
new UserManager(currentSession).removeUser(fooRealm, user3);
// Cleanup
realmMgr = new RealmManager(currentSession);
realmMgr.removeRealm(realmMgr.getRealm("foo"));
});
}
});
}
@Test
@ModelTest
public void testOnUserRemoved(KeycloakSession session) {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionUR) -> {
try {
int started = Time.currentTime();
AtomicReference<String> userSessionID = new AtomicReference<>();
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionUR1) -> {
currentSession = sessionUR1;
RealmModel fooRealm = currentSession.realms().createRealm("foo", "foo");
fooRealm.addClient("foo-app");
currentSession.users().addUser(fooRealm, "user3");
UserSessionModel userSession = currentSession.sessions().createUserSession(fooRealm, currentSession.users().getUserByUsername("user3", fooRealm), "user3", "127.0.0.1", "form", true, null, null);
userSessionID.set(userSession.getId());
createClientSession(currentSession, fooRealm.getClientByClientId("foo-app"), userSession, "http://redirect", "state");
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionUR2) -> {
currentSession = sessionUR2;
// Create offline session
RealmModel fooRealm = currentSession.realms().getRealm("foo");
UserSessionModel userSession = currentSession.sessions().getUserSession(fooRealm, userSessionID.get());
createOfflineSessionIncludeClientSessions(currentSession, userSession);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionUR3) -> {
currentSession = sessionUR3;
RealmManager realmMgr = new RealmManager(currentSession);
RealmModel fooRealm = realmMgr.getRealm("foo");
UserModel user3 = currentSession.users().getUserByUsername("user3", fooRealm);
// Assert session was persisted with both clientSessions
UserSessionModel offlineSession = currentSession.sessions().getOfflineUserSession(fooRealm, userSessionID.get());
assertSession(offlineSession, user3, "127.0.0.1", started, started, "foo-app");
});
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionTearDown) -> {
currentSession = sessionTearDown;
RealmManager realmMgr = new RealmManager(currentSession);
RealmModel fooRealm = realmMgr.getRealm("foo");
UserModel user3 = currentSession.users().getUserByUsername("user3", fooRealm);
// Remove user3
new UserManager(currentSession).removeUser(fooRealm, user3);
// Cleanup
realmMgr = new RealmManager(currentSession);
realmMgr.removeRealm(realmMgr.getRealm("foo"));
});
}
});
}
@Test
@ModelTest
public void testExpired(KeycloakSession session) {
AtomicReference<UserSessionModel[]> origSessionsAt = new AtomicReference<>();
// Key is userSessionId, value is set of client UUIDS
Map<String, Set<String>> offlineSessions = new HashMap<>();
ClientModel[] testApp = new ClientModel[1];
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionExpired1) -> {
// Create some online sessions in infinispan
currentSession = sessionExpired1;
reloadState(currentSession);
UserSessionModel[] origSessions = createSessions(currentSession);
origSessionsAt.set(origSessions);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionExpired2) -> {
currentSession = sessionExpired2;
realm = currentSession.realms().getRealm("test");
sessionManager = new UserSessionManager(currentSession);
persister = currentSession.getProvider(UserSessionPersisterProvider.class);
// Persist 3 created userSessions and clientSessions as offline
testApp[0] = realm.getClientByClientId("test-app");
List<UserSessionModel> userSessions = currentSession.sessions().getUserSessions(realm, testApp[0]);
for (UserSessionModel userSession : userSessions) {
offlineSessions.put(userSession.getId(), createOfflineSessionIncludeClientSessions(currentSession, userSession));
}
// Assert all previously saved offline sessions found
for (Map.Entry<String, Set<String>> entry : offlineSessions.entrySet()) {
UserSessionModel foundSession = sessionManager.findOfflineUserSession(realm, entry.getKey());
Assert.assertEquals(foundSession.getAuthenticatedClientSessions().keySet(), entry.getValue());
}
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionExpired3) -> {
currentSession = sessionExpired3;
realm = currentSession.realms().getRealm("test");
persister = currentSession.getProvider(UserSessionPersisterProvider.class);
UserSessionModel[] origSessions = origSessionsAt.get();
UserSessionModel session0 = currentSession.sessions().getOfflineUserSession(realm, origSessions[0].getId());
Assert.assertNotNull(session0);
// sessions are in persister too
Assert.assertEquals(3, persister.getUserSessionsCount(true));
Time.setOffset(300);
// Set lastSessionRefresh to currentSession[0] to 0
session0.setLastSessionRefresh(Time.currentTime());
});
try {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionExpired4) -> {
currentSession = sessionExpired4;
realm = currentSession.realms().getRealm("test");
UserSessionModel[] origSessions = origSessionsAt.get();
// Increase timeOffset - 20 days
Time.setOffset(1728000);
UserSessionModel session0 = currentSession.sessions().getOfflineUserSession(realm, origSessions[0].getId());
session0.setLastSessionRefresh(Time.currentTime());
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionExpired5) -> {
currentSession = sessionExpired5;
realm = currentSession.realms().getRealm("test");
persister = currentSession.getProvider(UserSessionPersisterProvider.class);
// Increase timeOffset - 40 days
Time.setOffset(3456000);
// Expire and ensure that all sessions despite session0 were removed
currentSession.sessions().removeExpired(realm);
persister.removeExpired(realm);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionExpired6) -> {
currentSession = sessionExpired6;
realm = currentSession.realms().getRealm("test");
persister = currentSession.getProvider(UserSessionPersisterProvider.class);
UserSessionModel[] origSessions = origSessionsAt.get();
// assert session0 is the only session found
Assert.assertNotNull(currentSession.sessions().getOfflineUserSession(realm, origSessions[0].getId()));
Assert.assertNull(currentSession.sessions().getOfflineUserSession(realm, origSessions[1].getId()));
Assert.assertNull(currentSession.sessions().getOfflineUserSession(realm, origSessions[2].getId()));
Assert.assertEquals(1, persister.getUserSessionsCount(true));
// Expire everything and assert nothing found
Time.setOffset(6000000);
currentSession.sessions().removeExpired(realm);
persister.removeExpired(realm);
});
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionExpired7) -> {
currentSession = sessionExpired7;
realm = currentSession.realms().getRealm("test");
sessionManager = new UserSessionManager(currentSession);
persister = currentSession.getProvider(UserSessionPersisterProvider.class);
for (String userSessionId : offlineSessions.keySet()) {
Assert.assertNull(sessionManager.findOfflineUserSession(realm, userSessionId));
}
Assert.assertEquals(0, persister.getUserSessionsCount(true));
});
} finally {
Time.setOffset(0);
}
}
private static Set<String> createOfflineSessionIncludeClientSessions(KeycloakSession session, UserSessionModel
userSession) {
Set<String> offlineSessions = new HashSet<>();
UserSessionManager localManager = new UserSessionManager(session);
for (AuthenticatedClientSessionModel clientSession : userSession.getAuthenticatedClientSessions().values()) {
localManager.createOrUpdateOfflineSession(clientSession, userSession);
offlineSessions.add(clientSession.getClient().getId());
}
return offlineSessions;
}
public static void assertSession(UserSessionModel session, UserModel user, String ipAddress, int started,
int lastRefresh, String... clients) {
assertEquals(user.getId(), session.getUser().getId());
assertEquals(ipAddress, session.getIpAddress());
assertEquals(user.getUsername(), session.getLoginUsername());
assertEquals("form", session.getAuthMethod());
assertTrue(session.isRememberMe());
assertTrue((session.getStarted() >= started - 1) && (session.getStarted() <= started + 1));
assertTrue((session.getLastSessionRefresh() >= lastRefresh - 1) && (session.getLastSessionRefresh() <= lastRefresh + 1));
String[] actualClients = new String[session.getAuthenticatedClientSessions().size()];
int i = 0;
for (Map.Entry<String, AuthenticatedClientSessionModel> entry : session.getAuthenticatedClientSessions().entrySet()) {
String clientUUID = entry.getKey();
AuthenticatedClientSessionModel clientSession = entry.getValue();
Assert.assertEquals(clientUUID, clientSession.getClient().getId());
actualClients[i] = clientSession.getClient().getClientId();
i++;
}
}
private static AuthenticatedClientSessionModel createClientSession(KeycloakSession sessionParam, ClientModel
client, UserSessionModel userSession, String redirect, String state) {
AuthenticatedClientSessionModel clientSession = sessionParam.sessions().createClientSession(client.getRealm(), client, userSession);
clientSession.setRedirectUri(redirect);
if (state != null) clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, state);
return clientSession;
}
private static UserSessionModel[] createSessions(KeycloakSession session) {
UserSessionModel[] sessions = new UserSessionModel[3];
sessions[0] = session.sessions().createUserSession(realm, currentSession.users().getUserByUsername("user1", realm), "user1", "127.0.0.1", "form", true, null, null);
Set<String> roles = new HashSet<String>();
roles.add("one");
roles.add("two");
Set<String> protocolMappers = new HashSet<String>();
protocolMappers.add("mapper-one");
protocolMappers.add("mapper-two");
createClientSession(session, realm.getClientByClientId("test-app"), sessions[0], "http://redirect", "state");
createClientSession(session, realm.getClientByClientId("third-party"), sessions[0], "http://redirect", "state");
sessions[1] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "user1", "127.0.0.2", "form", true, null, null);
createClientSession(session, realm.getClientByClientId("test-app"), sessions[1], "http://redirect", "state");
sessions[2] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user2", realm), "user2", "127.0.0.3", "form", true, null, null);
createClientSession(session, realm.getClientByClientId("test-app"), sessions[2], "http://redirect", "state");
return sessions;
}
public static void reloadState(KeycloakSession session) {
reloadState(session, false);
}
public static void reloadState(KeycloakSession session, Boolean initialConfig) {
currentSession = session;
realm = currentSession.realms().getRealm("test");
if (initialConfig) {
currentSession.users().addUser(realm, "user1").setEmail("user1@localhost");
currentSession.users().addUser(realm, "user2").setEmail("user2@localhost");
}
sessionManager = new UserSessionManager(currentSession);
persister = currentSession.getProvider(UserSessionPersisterProvider.class);
}
@Override
public void configureTestRealm(RealmRepresentation testRealm) {
}
}

View file

@ -1,158 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.model;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.keycloak.models.ClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.managers.RealmManager;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class CompositeRolesModelTest extends AbstractModelTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Before
@Override
public void before() throws Exception {
super.before();
RealmManager manager = realmManager;
RealmRepresentation rep = AbstractModelTest.loadJson("model/testcomposites.json");
rep.setId("TestComposites");
manager.importRealm(rep);
}
@Test
public void testNoClientID() throws IOException {
RealmManager manager = realmManager;
RealmRepresentation rep = AbstractModelTest.loadJson("model/testrealm-noclient-id.json");
rep.setId("TestNoClientID");
expectedException.expect(RuntimeException.class);
expectedException.expectMessage("Unknown client specification in scope mappings: some-client");
manager.importRealm(rep);
}
@Test
public void testComposites() {
Set<RoleModel> requestedRoles = getRequestedRoles("APP_COMPOSITE_APPLICATION", "APP_COMPOSITE_USER");
Assert.assertEquals(5, requestedRoles.size());
assertContains("APP_COMPOSITE_APPLICATION", "APP_COMPOSITE_ROLE", requestedRoles);
assertContains("APP_COMPOSITE_APPLICATION", "APP_COMPOSITE_CHILD", requestedRoles);
assertContains("APP_COMPOSITE_APPLICATION", "APP_ROLE_2", requestedRoles);
assertContains("APP_ROLE_APPLICATION", "APP_ROLE_1", requestedRoles);
assertContains("realm", "REALM_ROLE_1", requestedRoles);
requestedRoles = getRequestedRoles("APP_COMPOSITE_APPLICATION", "REALM_APP_COMPOSITE_USER");
Assert.assertEquals(4, requestedRoles.size());
assertContains("APP_ROLE_APPLICATION", "APP_ROLE_1", requestedRoles);
requestedRoles = getRequestedRoles("REALM_COMPOSITE_1_APPLICATION", "REALM_COMPOSITE_1_USER");
Assert.assertEquals(1, requestedRoles.size());
assertContains("realm", "REALM_COMPOSITE_1", requestedRoles);
requestedRoles = getRequestedRoles("REALM_COMPOSITE_2_APPLICATION", "REALM_COMPOSITE_1_USER");
Assert.assertEquals(3, requestedRoles.size());
assertContains("realm", "REALM_COMPOSITE_1", requestedRoles);
assertContains("realm", "REALM_COMPOSITE_CHILD", requestedRoles);
assertContains("realm", "REALM_ROLE_4", requestedRoles);
requestedRoles = getRequestedRoles("REALM_ROLE_1_APPLICATION", "REALM_COMPOSITE_1_USER");
Assert.assertEquals(1, requestedRoles.size());
assertContains("realm", "REALM_ROLE_1", requestedRoles);
requestedRoles = getRequestedRoles("REALM_COMPOSITE_1_APPLICATION", "REALM_ROLE_1_USER");
Assert.assertEquals(1, requestedRoles.size());
assertContains("realm", "REALM_ROLE_1", requestedRoles);
}
// Same algorithm as in TokenManager.createAccessCode
private Set<RoleModel> getRequestedRoles(String applicationName, String username) {
Set<RoleModel> requestedRoles = new HashSet<RoleModel>();
RealmModel realm = realmManager.getRealm("TestComposites");
UserModel user = realmManager.getSession().users().getUserByUsername(username, realm);
ClientModel application = realm.getClientByClientId(applicationName);
Set<RoleModel> roleMappings = user.getRoleMappings();
Set<RoleModel> scopeMappings = application.getScopeMappings();
Set<RoleModel> appRoles = application.getRoles();
if (appRoles != null) scopeMappings.addAll(appRoles);
for (RoleModel role : roleMappings) {
if (role.getContainer().equals(application)) requestedRoles.add(role);
for (RoleModel desiredRole : scopeMappings) {
Set<RoleModel> visited = new HashSet<RoleModel>();
applyScope(role, desiredRole, visited, requestedRoles);
}
}
return requestedRoles;
}
private static void applyScope(RoleModel role, RoleModel scope, Set<RoleModel> visited, Set<RoleModel> requested) {
if (visited.contains(scope)) return;
visited.add(scope);
if (role.hasRole(scope)) {
requested.add(scope);
return;
}
if (!scope.isComposite()) return;
for (RoleModel contained : scope.getComposites()) {
applyScope(role, contained, visited, requested);
}
}
private RoleModel getRole(String appName, String roleName) {
RealmModel realm = realmManager.getRealm("TestComposites");
if ("realm".equals(appName)) {
return realm.getRole(roleName);
} else {
return realm.getClientByClientId(appName).getRole(roleName);
}
}
private void assertContains(String appName, String roleName, Set<RoleModel> requestedRoles) {
RoleModel expectedRole = getRole(appName, roleName);
Assert.assertTrue(requestedRoles.contains(expectedRole));
// Check if requestedRole has correct role container
for (RoleModel role : requestedRoles) {
if (role.equals(expectedRole)) {
Assert.assertEquals(role.getContainer(), expectedRole.getContainer());
}
}
}
}

View file

@ -1,234 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.model;
import org.jboss.logging.Logger;
import org.junit.Assert;
import org.junit.Test;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.KeycloakSessionTask;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RealmProvider;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ConcurrentTransactionsTest extends AbstractModelTest {
private static final Logger logger = Logger.getLogger(ConcurrentTransactionsTest.class);
@Test
public void persistClient() throws Exception {
RealmModel realm = realmManager.createRealm("original");
KeycloakSession session = realmManager.getSession();
ClientModel client = session.realms().addClient(realm, "client");
client.setSecret("old");
String clientDBId = client.getId();
final KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
commit();
final CountDownLatch transactionsCounter = new CountDownLatch(2);
final CountDownLatch readLatch = new CountDownLatch(1);
final CountDownLatch updateLatch = new CountDownLatch(1);
Thread thread1 = new Thread() {
@Override
public void run() {
KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
@Override
public void run(KeycloakSession session) {
try {
// Wait until transaction in both threads started
transactionsCounter.countDown();
logger.info("transaction1 started");
transactionsCounter.await();
// Read client
RealmModel realm = session.realms().getRealmByName("original");
ClientModel client = session.realms().getClientByClientId("client", realm);
logger.info("transaction1: Read client finished");
readLatch.countDown();
// Wait until thread2 updates client and commits
updateLatch.await();
logger.info("transaction1: Going to read client again");
client = session.realms().getClientByClientId("client", realm);
logger.info("transaction1: secret: " + client.getSecret());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
@Override
public void run(KeycloakSession session) {
try {
// Wait until transaction in both threads started
transactionsCounter.countDown();
logger.info("transaction2 started");
transactionsCounter.await();
readLatch.await();
logger.info("transaction2: Going to update client secret");
RealmModel realm = session.realms().getRealmByName("original");
ClientModel client = session.realms().getClientByClientId("client", realm);
client.setSecret("new");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
logger.info("transaction2: commited");
updateLatch.countDown();
}
};
thread1.start();
thread2.start();
thread1.join();
thread2.join();
logger.info("after thread join");
commit();
session = realmManager.getSession();
realm = session.realms().getRealmByName("original");
ClientModel clientFromCache = session.realms().getClientById(clientDBId, realm);
ClientModel clientFromDB = session.getProvider(RealmProvider.class).getClientById(clientDBId, realm);
logger.info("SECRET FROM DB : " + clientFromDB.getSecret());
logger.info("SECRET FROM CACHE : " + clientFromCache.getSecret());
Assert.assertEquals("new", clientFromDB.getSecret());
Assert.assertEquals("new", clientFromCache.getSecret());
}
// KEYCLOAK-3296 , KEYCLOAK-3494
@Test
public void removeUserAttribute() throws Exception {
RealmModel realm = realmManager.createRealm("original");
KeycloakSession session = realmManager.getSession();
UserModel john = session.users().addUser(realm, "john");
john.setSingleAttribute("foo", "val1");
UserModel john2 = session.users().addUser(realm, "john2");
john2.setAttribute("foo", Arrays.asList("val1", "val2"));
final KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
commit();
AtomicReference<Exception> reference = new AtomicReference<>();
final CountDownLatch readAttrLatch = new CountDownLatch(2);
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
@Override
public void run(KeycloakSession session) {
try {
// Read user attribute
RealmModel realm = session.realms().getRealmByName("original");
UserModel john = session.users().getUserByUsername("john", realm);
String attrVal = john.getFirstAttribute("foo");
UserModel john2 = session.users().getUserByUsername("john2", realm);
String attrVal2 = john2.getFirstAttribute("foo");
// Wait until it's read in both threads
readAttrLatch.countDown();
readAttrLatch.await();
// KEYCLOAK-3296 : Remove user attribute in both threads
john.removeAttribute("foo");
// KEYCLOAK-3494 : Set single attribute in both threads
john2.setSingleAttribute("foo", "bar");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
} catch (Exception e) {
reference.set(e);
throw new RuntimeException(e);
} finally {
readAttrLatch.countDown();
}
}
};
Thread thread1 = new Thread(runnable);
Thread thread2 = new Thread(runnable);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
logger.info("removeUserAttribute: after thread join");
commit();
if (reference.get() != null) {
Assert.fail("Exception happened in some of threads. Details: " + reference.get().getMessage());
}
}
}

View file

@ -1,122 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.model;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.keycloak.models.ClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class MultipleRealmsTest extends AbstractModelTest {
private RealmModel realm1;
private RealmModel realm2;
@Before
@Override
public void before() throws Exception {
super.before();
realm1 = realmManager.createRealm("id1", "realm1");
realm2 = realmManager.createRealm("id2", "realm2");
createObjects(realm1);
createObjects(realm2);
}
@Test
public void testUsers() {
UserModel r1user1 = session.users().getUserByUsername("user1", realm1);
UserModel r2user1 = session.users().getUserByUsername("user1", realm2);
Assert.assertEquals(r1user1.getUsername(), r2user1.getUsername());
Assert.assertNotEquals(r1user1.getId(), r2user1.getId());
// Test password
session.userCredentialManager().updateCredential(realm1, r1user1, UserCredentialModel.password("pass1"));
session.userCredentialManager().updateCredential(realm2, r2user1, UserCredentialModel.password("pass2"));
Assert.assertTrue(session.userCredentialManager().isValid(realm1, r1user1, UserCredentialModel.password("pass1")));
Assert.assertFalse(session.userCredentialManager().isValid(realm1, r1user1, UserCredentialModel.password("pass2")));
Assert.assertFalse(session.userCredentialManager().isValid(realm2, r2user1, UserCredentialModel.password("pass1")));
Assert.assertTrue(session.userCredentialManager().isValid(realm2, r2user1, UserCredentialModel.password("pass2")));
// Test searching
Assert.assertEquals(2, session.users().searchForUser("user", realm1).size());
commit();
realm1 = model.getRealm("id1");
realm2 = model.getRealm("id2");
session.users().removeUser(realm1, r1user1);
UserModel user2 = session.users().getUserByUsername("user2", realm1);
session.users().removeUser(realm1, user2);
Assert.assertEquals(0, session.users().searchForUser("user", realm1).size());
Assert.assertEquals(2, session.users().searchForUser("user", realm2).size());
}
@Test
public void testGetById() {
Assert.assertEquals(realm1, model.getRealm("id1"));
Assert.assertEquals(realm1, model.getRealmByName("realm1"));
Assert.assertEquals(realm2, model.getRealm("id2"));
Assert.assertEquals(realm2, model.getRealmByName("realm2"));
ClientModel r1app1 = realm1.getClientByClientId("app1");
ClientModel r1app2 = realm1.getClientByClientId("app2");
ClientModel r2app1 = realm2.getClientByClientId("app1");
ClientModel r2app2 = realm2.getClientByClientId("app2");
Assert.assertEquals(r1app1, realm1.getClientById(r1app1.getId()));
Assert.assertNull(realm2.getClientById(r1app1.getId()));
ClientModel r2cl1 = realm2.getClientByClientId("cl1");
Assert.assertEquals(r2cl1.getId(), realm2.getClientById(r2cl1.getId()).getId());
Assert.assertNull(realm1.getClientByClientId(r2cl1.getId()));
RoleModel r1App1Role = r1app1.getRole("app1Role1");
Assert.assertEquals(r1App1Role, realm1.getRoleById(r1App1Role.getId()));
Assert.assertNull(realm2.getRoleById(r1App1Role.getId()));
RoleModel r2Role1 = realm2.getRole("role2");
Assert.assertNull(realm1.getRoleById(r2Role1.getId()));
Assert.assertEquals(r2Role1, realm2.getRoleById(r2Role1.getId()));
}
private void createObjects(RealmModel realm) {
ClientModel app1 = realm.addClient("app1");
realm.addClient("app2");
realmManager.getSession().users().addUser(realm, "user1");
realmManager.getSession().users().addUser(realm, "user2");
realm.addRole("role1");
realm.addRole("role2");
app1.addRole("app1Role1");
app1.addScopeMapping(realm.getRole("role1"));
realm.addClient("cl1");
}
}

View file

@ -1,286 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.model;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.ModelException;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.protocol.oidc.mappers.UserPropertyMapper;
import org.keycloak.storage.client.ClientStorageProviderModel;
import org.keycloak.testsuite.federation.HardcodedClientStorageProviderFactory;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class UserConsentModelTest extends AbstractModelTest {
private ComponentModel clientStorageComponent;
@Before
public void setupEnv() {
RealmModel realm = realmManager.createRealm("original");
ClientModel fooClient = realm.addClient("foo-client");
ClientModel barClient = realm.addClient("bar-client");
ClientScopeModel fooScope = realm.addClientScope("foo");
fooScope.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
ClientScopeModel barScope = realm.addClientScope("bar");
fooScope.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
UserModel john = session.users().addUser(realm, "john");
UserModel mary = session.users().addUser(realm, "mary");
UserConsentModel johnFooGrant = new UserConsentModel(fooClient);
johnFooGrant.addGrantedClientScope(fooScope);
realmManager.getSession().users().addConsent(realm, john.getId(), johnFooGrant);
UserConsentModel johnBarGrant = new UserConsentModel(barClient);
johnBarGrant.addGrantedClientScope(barScope);
// Update should fail as grant doesn't yet exists
try {
realmManager.getSession().users().updateConsent(realm, john.getId(), johnBarGrant);
Assert.fail("Not expected to end here");
} catch (ModelException expected) {
}
realmManager.getSession().users().addConsent(realm, john.getId(), johnBarGrant);
UserConsentModel maryFooGrant = new UserConsentModel(fooClient);
maryFooGrant.addGrantedClientScope(fooScope);
realmManager.getSession().users().addConsent(realm, mary.getId(), maryFooGrant);
ClientStorageProviderModel clientStorage = new ClientStorageProviderModel();
clientStorage.setProviderId(HardcodedClientStorageProviderFactory.PROVIDER_ID);
clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.CLIENT_ID, "hardcoded-client");
clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.REDIRECT_URI, "http://localhost:8081/*");
clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.CONSENT, "true");
clientStorage.setParentId(realm.getId());
clientStorageComponent = realm.addComponentModel(clientStorage);
ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm);
Assert.assertNotNull(hardcodedClient);
UserConsentModel maryHardcodedGrant = new UserConsentModel(hardcodedClient);
realmManager.getSession().users().addConsent(realm, mary.getId(), maryHardcodedGrant);
commit();
}
@Test
public void basicConsentTest() {
RealmModel realm = realmManager.getRealm("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
ClientModel barClient = realm.getClientByClientId("bar-client");
UserModel john = session.users().getUserByUsername("john", realm);
UserModel mary = session.users().getUserByUsername("mary", realm);
UserConsentModel johnFooConsent = realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId());
Assert.assertEquals(johnFooConsent.getGrantedClientScopes().size(), 1);
Assert.assertTrue(isClientScopeGranted(realm, "foo", johnFooConsent));
Assert.assertNotNull("Created Date should be set", johnFooConsent.getCreatedDate());
Assert.assertNotNull("Last Updated Date should be set", johnFooConsent.getLastUpdatedDate());
UserConsentModel johnBarConsent = realmManager.getSession().users().getConsentByClient(realm, john.getId(), barClient.getId());
Assert.assertEquals(johnBarConsent.getGrantedClientScopes().size(), 1);
Assert.assertTrue(isClientScopeGranted(realm, "bar", johnBarConsent));
Assert.assertNotNull("Created Date should be set", johnBarConsent.getCreatedDate());
Assert.assertNotNull("Last Updated Date should be set", johnBarConsent.getLastUpdatedDate());
UserConsentModel maryConsent = realmManager.getSession().users().getConsentByClient(realm, mary.getId(), fooClient.getId());
Assert.assertEquals(maryConsent.getGrantedClientScopes().size(), 1);
Assert.assertTrue(isClientScopeGranted(realm, "foo", maryConsent));
Assert.assertNotNull("Created Date should be set", maryConsent.getCreatedDate());
Assert.assertNotNull("Last Updated Date should be set", maryConsent.getLastUpdatedDate());
ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm);
UserConsentModel maryHardcodedConsent = realmManager.getSession().users().getConsentByClient(realm, mary.getId(), hardcodedClient.getId());
Assert.assertEquals(maryHardcodedConsent.getGrantedClientScopes().size(), 0);
Assert.assertNotNull("Created Date should be set", maryHardcodedConsent.getCreatedDate());
Assert.assertNotNull("Last Updated Date should be set", maryHardcodedConsent.getLastUpdatedDate());
Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, mary.getId(), barClient.getId()));
Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john.getId(), hardcodedClient.getId()));
}
@Test
public void getAllConsentTest() {
RealmModel realm = realmManager.getRealm("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
UserModel john = session.users().getUserByUsername("john", realm);
UserModel mary = session.users().getUserByUsername("mary", realm);
List<UserConsentModel> johnConsents = realmManager.getSession().users().getConsents(realm, john.getId());
Assert.assertEquals(2, johnConsents.size());
ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm);
List<UserConsentModel> maryConsents = realmManager.getSession().users().getConsents(realm, mary.getId());
Assert.assertEquals(2, maryConsents.size());
UserConsentModel maryConsent = maryConsents.get(0);
UserConsentModel maryHardcodedConsent = maryConsents.get(1);
if (maryConsents.get(0).getClient().getId().equals(hardcodedClient.getId())) {
maryConsent = maryConsents.get(1);
maryHardcodedConsent = maryConsents.get(0);
}
Assert.assertEquals(maryConsent.getClient().getId(), fooClient.getId());
Assert.assertEquals(maryConsent.getGrantedClientScopes().size(), 1);
Assert.assertTrue(isClientScopeGranted(realm, "foo", maryConsent));
Assert.assertEquals(maryHardcodedConsent.getClient().getId(), hardcodedClient.getId());
Assert.assertEquals(maryHardcodedConsent.getGrantedClientScopes().size(), 0);
}
@Test
public void updateWithClientScopeRemovalTest() {
RealmModel realm = realmManager.getRealm("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
UserModel john = session.users().getUserByUsername("john", realm);
UserConsentModel johnConsent = realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId());
Assert.assertEquals(1, johnConsent.getGrantedClientScopes().size());
// Remove foo protocol mapper from johnConsent
ClientScopeModel fooScope = KeycloakModelUtils.getClientScopeByName(realm, "foo");
johnConsent.getGrantedClientScopes().remove(fooScope);
realmManager.getSession().users().updateConsent(realm, john.getId(), johnConsent);
commit();
realm = realmManager.getRealm("original");
fooClient = realm.getClientByClientId("foo-client");
john = session.users().getUserByUsername("john", realm);
johnConsent = realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId());
Assert.assertEquals(johnConsent.getGrantedClientScopes().size(), 0);
Assert.assertTrue("Created date should be less than last updated date", johnConsent.getCreatedDate() < johnConsent.getLastUpdatedDate());
}
@Test
public void revokeTest() {
RealmModel realm = realmManager.getRealm("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
UserModel john = session.users().getUserByUsername("john", realm);
UserModel mary = session.users().getUserByUsername("mary", realm);
realmManager.getSession().users().revokeConsentForClient(realm, john.getId(), fooClient.getId());
ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm);
realmManager.getSession().users().revokeConsentForClient(realm, mary.getId(), hardcodedClient.getId());
commit();
realm = realmManager.getRealm("original");
john = session.users().getUserByUsername("john", realm);
Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId()));
mary = session.users().getUserByUsername("mary", realm);
Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, mary.getId(), hardcodedClient.getId()));
}
@Test
public void deleteUserTest() {
// Validate user deleted without any referential constraint errors
RealmModel realm = realmManager.getRealm("original");
UserModel john = session.users().getUserByUsername("john", realm);
session.users().removeUser(realm, john);
UserModel mary = session.users().getUserByUsername("mary", realm);
session.users().removeUser(realm, mary);
}
@Test
public void deleteClientScopeTest() {
RealmModel realm = realmManager.getRealm("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
ClientScopeModel fooScope = KeycloakModelUtils.getClientScopeByName(realm, "foo");
realm.removeClientScope(fooScope.getId());
commit();
realm = realmManager.getRealm("original");
fooClient = realm.getClientByClientId("foo-client");
UserModel john = session.users().getUserByUsername("john", realm);
UserConsentModel johnConsent = realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId());
Assert.assertEquals(johnConsent.getGrantedClientScopes().size(), 0);
}
@Test
public void deleteClientTest() {
RealmModel realm = realmManager.getRealm("original");
ClientModel barClient = realm.getClientByClientId("bar-client");
realm.removeClient(barClient.getId());
commit();
realm = realmManager.getRealm("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
Assert.assertNull(realm.getClientByClientId("bar-client"));
UserModel john = session.users().getUserByUsername("john", realm);
UserConsentModel johnFooConsent = realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId());
Assert.assertEquals(johnFooConsent.getGrantedClientScopes().size(), 1);
Assert.assertTrue(isClientScopeGranted(realm, "foo", johnFooConsent));
Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john.getId(), barClient.getId()));
}
@Test
public void deleteClientStorageTest() {
RealmModel realm = realmManager.getRealm("original");
realm.removeComponent(clientStorageComponent);
commit();
realm = realmManager.getRealm("original");
ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm);
Assert.assertNull(hardcodedClient);
UserModel mary = session.users().getUserByUsername("mary", realm);
List<UserConsentModel> maryConsents = realmManager.getSession().users().getConsents(realm, mary.getId());
Assert.assertEquals(1, maryConsents.size());
}
private boolean isClientScopeGranted(RealmModel realm, String scopeName, UserConsentModel consentModel) {
ClientScopeModel clientScope = KeycloakModelUtils.getClientScopeByName(realm, scopeName);
return consentModel.isClientScopeGranted(clientScope);
}
}

View file

@ -1,296 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.model;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.ModelException;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.protocol.oidc.mappers.UserPropertyMapper;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.client.ClientStorageProviderModel;
import org.keycloak.testsuite.federation.HardcodedClientStorageProviderFactory;
import org.keycloak.testsuite.federation.storage.UserMapStorageFactory;
import org.keycloak.testsuite.federation.storage.UserPropertyFileStorageFactory;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class UserConsentWithUserStorageModelTest extends AbstractModelTest {
private ComponentModel clientStorageComponent;
@Before
public void setupEnv() {
RealmModel realm = realmManager.createRealm("original");
UserStorageProviderModel model = new UserStorageProviderModel();
model.setName("memory");
model.setPriority(0);
model.setProviderId(UserMapStorageFactory.PROVIDER_ID);
model.setParentId(realm.getId());
realm.addComponentModel(model);
ClientModel fooClient = realm.addClient("foo-client");
ClientModel barClient = realm.addClient("bar-client");
ClientScopeModel fooScope = realm.addClientScope("foo");
fooScope.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
ClientScopeModel barScope = realm.addClientScope("bar");
fooScope.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
UserModel john = session.users().addUser(realm, "john");
UserModel mary = session.users().addUser(realm, "mary");
UserConsentModel johnFooGrant = new UserConsentModel(fooClient);
johnFooGrant.addGrantedClientScope(fooScope);
realmManager.getSession().users().addConsent(realm, john.getId(), johnFooGrant);
UserConsentModel johnBarGrant = new UserConsentModel(barClient);
johnBarGrant.addGrantedClientScope(barScope);
// Update should fail as grant doesn't yet exists
try {
realmManager.getSession().users().updateConsent(realm, john.getId(), johnBarGrant);
Assert.fail("Not expected to end here");
} catch (ModelException expected) {
}
realmManager.getSession().users().addConsent(realm, john.getId(), johnBarGrant);
UserConsentModel maryFooGrant = new UserConsentModel(fooClient);
maryFooGrant.addGrantedClientScope(fooScope);
realmManager.getSession().users().addConsent(realm, mary.getId(), maryFooGrant);
ClientStorageProviderModel clientStorage = new ClientStorageProviderModel();
clientStorage.setProviderId(HardcodedClientStorageProviderFactory.PROVIDER_ID);
clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.CLIENT_ID, "hardcoded-client");
clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.REDIRECT_URI, "http://localhost:8081/*");
clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.CONSENT, "true");
clientStorage.setParentId(realm.getId());
clientStorageComponent = realm.addComponentModel(clientStorage);
ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm);
Assert.assertNotNull(hardcodedClient);
UserConsentModel maryHardcodedGrant = new UserConsentModel(hardcodedClient);
realmManager.getSession().users().addConsent(realm, mary.getId(), maryHardcodedGrant);
commit();
}
@Test
public void basicConsentTest() {
RealmModel realm = realmManager.getRealm("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
ClientModel barClient = realm.getClientByClientId("bar-client");
UserModel john = session.users().getUserByUsername("john", realm);
UserModel mary = session.users().getUserByUsername("mary", realm);
UserConsentModel johnFooConsent = realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId());
Assert.assertEquals(johnFooConsent.getGrantedClientScopes().size(), 1);
Assert.assertTrue(isClientScopeGranted(realm, "foo", johnFooConsent));
Assert.assertNotNull("Created Date should be set", johnFooConsent.getCreatedDate());
Assert.assertNotNull("Last Updated Date should be set", johnFooConsent.getLastUpdatedDate());
UserConsentModel johnBarConsent = realmManager.getSession().users().getConsentByClient(realm, john.getId(), barClient.getId());
Assert.assertEquals(johnBarConsent.getGrantedClientScopes().size(), 1);
Assert.assertTrue(isClientScopeGranted(realm, "bar", johnBarConsent));
Assert.assertNotNull("Created Date should be set", johnBarConsent.getCreatedDate());
Assert.assertNotNull("Last Updated Date should be set", johnBarConsent.getLastUpdatedDate());
UserConsentModel maryConsent = realmManager.getSession().users().getConsentByClient(realm, mary.getId(), fooClient.getId());
Assert.assertEquals(maryConsent.getGrantedClientScopes().size(), 1);
Assert.assertTrue(isClientScopeGranted(realm, "foo", maryConsent));
Assert.assertNotNull("Created Date should be set", maryConsent.getCreatedDate());
Assert.assertNotNull("Last Updated Date should be set", maryConsent.getLastUpdatedDate());
ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm);
UserConsentModel maryHardcodedConsent = realmManager.getSession().users().getConsentByClient(realm, mary.getId(), hardcodedClient.getId());
Assert.assertEquals(maryHardcodedConsent.getGrantedClientScopes().size(), 0);
Assert.assertNotNull("Created Date should be set", maryHardcodedConsent.getCreatedDate());
Assert.assertNotNull("Last Updated Date should be set", maryHardcodedConsent.getLastUpdatedDate());
Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, mary.getId(), barClient.getId()));
Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john.getId(), hardcodedClient.getId()));
}
@Test
public void getAllConsentTest() {
RealmModel realm = realmManager.getRealm("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
UserModel john = session.users().getUserByUsername("john", realm);
UserModel mary = session.users().getUserByUsername("mary", realm);
List<UserConsentModel> johnConsents = realmManager.getSession().users().getConsents(realm, john.getId());
Assert.assertEquals(2, johnConsents.size());
ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm);
List<UserConsentModel> maryConsents = realmManager.getSession().users().getConsents(realm, mary.getId());
Assert.assertEquals(2, maryConsents.size());
UserConsentModel maryConsent = maryConsents.get(0);
UserConsentModel maryHardcodedConsent = maryConsents.get(1);
if (maryConsents.get(0).getClient().getId().equals(hardcodedClient.getId())) {
maryConsent = maryConsents.get(1);
maryHardcodedConsent = maryConsents.get(0);
}
Assert.assertEquals(maryConsent.getClient().getId(), fooClient.getId());
Assert.assertEquals(maryConsent.getGrantedClientScopes().size(), 1);
Assert.assertTrue(isClientScopeGranted(realm, "foo", maryConsent));
Assert.assertEquals(maryHardcodedConsent.getClient().getId(), hardcodedClient.getId());
Assert.assertEquals(maryHardcodedConsent.getGrantedClientScopes().size(), 0);
}
@Test
public void updateWithClientScopeRemovalTest() {
RealmModel realm = realmManager.getRealm("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
UserModel john = session.users().getUserByUsername("john", realm);
UserConsentModel johnConsent = realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId());
Assert.assertEquals(1, johnConsent.getGrantedClientScopes().size());
// Remove foo protocol mapper from johnConsent
ClientScopeModel fooScope = KeycloakModelUtils.getClientScopeByName(realm, "foo");
johnConsent.getGrantedClientScopes().remove(fooScope);
realmManager.getSession().users().updateConsent(realm, john.getId(), johnConsent);
commit();
realm = realmManager.getRealm("original");
fooClient = realm.getClientByClientId("foo-client");
john = session.users().getUserByUsername("john", realm);
johnConsent = realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId());
Assert.assertEquals(johnConsent.getGrantedClientScopes().size(), 0);
Assert.assertTrue("Created date should be less than last updated date", johnConsent.getCreatedDate() < johnConsent.getLastUpdatedDate());
}
@Test
public void revokeTest() {
RealmModel realm = realmManager.getRealm("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
UserModel john = session.users().getUserByUsername("john", realm);
UserModel mary = session.users().getUserByUsername("mary", realm);
realmManager.getSession().users().revokeConsentForClient(realm, john.getId(), fooClient.getId());
ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm);
realmManager.getSession().users().revokeConsentForClient(realm, mary.getId(), hardcodedClient.getId());
commit();
realm = realmManager.getRealm("original");
john = session.users().getUserByUsername("john", realm);
Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId()));
mary = session.users().getUserByUsername("mary", realm);
Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, mary.getId(), hardcodedClient.getId()));
}
@Test
public void deleteUserTest() {
// Validate user deleted without any referential constraint errors
RealmModel realm = realmManager.getRealm("original");
UserModel john = session.users().getUserByUsername("john", realm);
session.users().removeUser(realm, john);
UserModel mary = session.users().getUserByUsername("mary", realm);
session.users().removeUser(realm, mary);
}
@Test
public void deleteClientScopeTest() {
RealmModel realm = realmManager.getRealm("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
ClientScopeModel fooScope = KeycloakModelUtils.getClientScopeByName(realm, "foo");
realm.removeClientScope(fooScope.getId());
commit();
realm = realmManager.getRealm("original");
fooClient = realm.getClientByClientId("foo-client");
UserModel john = session.users().getUserByUsername("john", realm);
UserConsentModel johnConsent = realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId());
Assert.assertEquals(johnConsent.getGrantedClientScopes().size(), 0);
}
@Test
public void deleteClientTest() {
RealmModel realm = realmManager.getRealm("original");
ClientModel barClient = realm.getClientByClientId("bar-client");
realm.removeClient(barClient.getId());
commit();
realm = realmManager.getRealm("original");
ClientModel fooClient = realm.getClientByClientId("foo-client");
Assert.assertNull(realm.getClientByClientId("bar-client"));
UserModel john = session.users().getUserByUsername("john", realm);
UserConsentModel johnFooConsent = realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId());
Assert.assertEquals(johnFooConsent.getGrantedClientScopes().size(), 1);
Assert.assertTrue(isClientScopeGranted(realm, "foo", johnFooConsent));
Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john.getId(), barClient.getId()));
}
@Test
public void deleteClientStorageTest() {
RealmModel realm = realmManager.getRealm("original");
realm.removeComponent(clientStorageComponent);
commit();
realm = realmManager.getRealm("original");
ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm);
Assert.assertNull(hardcodedClient);
UserModel mary = session.users().getUserByUsername("mary", realm);
List<UserConsentModel> maryConsents = realmManager.getSession().users().getConsents(realm, mary.getId());
Assert.assertEquals(1, maryConsents.size());
}
private boolean isClientScopeGranted(RealmModel realm, String scopeName, UserConsentModel consentModel) {
ClientScopeModel clientScope = KeycloakModelUtils.getClientScopeByName(realm, scopeName);
return consentModel.isClientScopeGranted(clientScope);
}
}

View file

@ -1,442 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.model;
import com.google.common.collect.ImmutableMap;
import org.junit.Assert;
import org.junit.Test;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserModel.RequiredAction;
import org.keycloak.services.managers.ClientManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertNotNull;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class UserModelTest extends AbstractModelTest {
@Test
public void persistUser() {
RealmModel realm = realmManager.createRealm("original");
KeycloakSession session = realmManager.getSession();
UserModel user = session.users().addUser(realm, "user");
user.setFirstName("first-name");
user.setLastName("last-name");
user.setEmail("email");
assertNotNull(user.getCreatedTimestamp());
// test that timestamp is current with 10s tollerance
Assert.assertTrue((System.currentTimeMillis() - user.getCreatedTimestamp()) < 10000);
user.addRequiredAction(RequiredAction.CONFIGURE_TOTP);
user.addRequiredAction(RequiredAction.UPDATE_PASSWORD);
RealmModel searchRealm = realmManager.getRealm(realm.getId());
UserModel persisted = session.users().getUserByUsername("user", searchRealm);
assertEquals(user, persisted);
searchRealm = realmManager.getRealm(realm.getId());
UserModel persisted2 = session.users().getUserById(user.getId(), searchRealm);
assertEquals(user, persisted2);
Map<String, String> attributes = new HashMap<String, String>();
attributes.put(UserModel.LAST_NAME, "last-name");
List<UserModel> search = session.users().searchForUser(attributes, realm);
Assert.assertEquals(search.size(), 1);
Assert.assertEquals(search.get(0).getUsername(), "user");
attributes.clear();
attributes.put(UserModel.EMAIL, "email");
search = session.users().searchForUser(attributes, realm);
Assert.assertEquals(search.size(), 1);
Assert.assertEquals(search.get(0).getUsername(), "user");
attributes.clear();
attributes.put(UserModel.LAST_NAME, "last-name");
attributes.put(UserModel.EMAIL, "email");
search = session.users().searchForUser(attributes, realm);
Assert.assertEquals(search.size(), 1);
Assert.assertEquals(search.get(0).getUsername(), "user");
}
@Test
public void webOriginSetTest() {
RealmModel realm = realmManager.createRealm("original");
ClientModel client = realm.addClient("user");
Assert.assertTrue(client.getWebOrigins().isEmpty());
client.addWebOrigin("origin-1");
Assert.assertEquals(1, client.getWebOrigins().size());
client.addWebOrigin("origin-2");
Assert.assertEquals(2, client.getWebOrigins().size());
client.removeWebOrigin("origin-2");
Assert.assertEquals(1, client.getWebOrigins().size());
client.removeWebOrigin("origin-1");
Assert.assertTrue(client.getWebOrigins().isEmpty());
client = realm.addClient("oauthclient2");
Assert.assertTrue(client.getWebOrigins().isEmpty());
client.addWebOrigin("origin-1");
Assert.assertEquals(1, client.getWebOrigins().size());
client.addWebOrigin("origin-2");
Assert.assertEquals(2, client.getWebOrigins().size());
client.removeWebOrigin("origin-2");
Assert.assertEquals(1, client.getWebOrigins().size());
client.removeWebOrigin("origin-1");
Assert.assertTrue(client.getWebOrigins().isEmpty());
}
@Test
public void testUserRequiredActions() throws Exception {
RealmModel realm = realmManager.createRealm("original");
UserModel user = session.users().addUser(realm, "user");
Assert.assertTrue(user.getRequiredActions().isEmpty());
user.addRequiredAction(RequiredAction.CONFIGURE_TOTP);
String id = realm.getId();
commit();
realm = realmManager.getRealm(id);
user = session.users().getUserByUsername("user", realm);
Assert.assertEquals(1, user.getRequiredActions().size());
Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.CONFIGURE_TOTP.name()));
user.addRequiredAction(RequiredAction.CONFIGURE_TOTP);
user = session.users().getUserByUsername("user", realm);
Assert.assertEquals(1, user.getRequiredActions().size());
Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.CONFIGURE_TOTP.name()));
user.addRequiredAction(RequiredAction.VERIFY_EMAIL.name());
user = session.users().getUserByUsername("user", realm);
Assert.assertEquals(2, user.getRequiredActions().size());
Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.CONFIGURE_TOTP.name()));
Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.VERIFY_EMAIL.name()));
user.removeRequiredAction(RequiredAction.CONFIGURE_TOTP.name());
user = session.users().getUserByUsername("user", realm);
Assert.assertEquals(1, user.getRequiredActions().size());
Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.VERIFY_EMAIL.name()));
user.removeRequiredAction(RequiredAction.VERIFY_EMAIL.name());
user = session.users().getUserByUsername("user", realm);
Assert.assertTrue(user.getRequiredActions().isEmpty());
}
@Test
public void testUserMultipleAttributes() throws Exception {
RealmModel realm = realmManager.createRealm("original");
UserModel user = session.users().addUser(realm, "user");
UserModel userNoAttrs = session.users().addUser(realm, "user-noattrs");
user.setSingleAttribute("key1", "value1");
List<String> attrVals = new ArrayList<>(Arrays.asList( "val21", "val22" ));
user.setAttribute("key2", attrVals);
commit();
// Test read attributes
realm = realmManager.getRealmByName("original");
user = session.users().getUserByUsername("user", realm);
attrVals = user.getAttribute("key1");
Assert.assertEquals(1, attrVals.size());
Assert.assertEquals("value1", attrVals.get(0));
Assert.assertEquals("value1", user.getFirstAttribute("key1"));
attrVals = user.getAttribute("key2");
Assert.assertEquals(2, attrVals.size());
Assert.assertTrue(attrVals.contains("val21"));
Assert.assertTrue(attrVals.contains("val22"));
attrVals = user.getAttribute("key3");
Assert.assertTrue(attrVals.isEmpty());
Assert.assertNull(user.getFirstAttribute("key3"));
Map<String, List<String>> allAttrVals = user.getAttributes();
Assert.assertEquals(2, allAttrVals.size());
Assert.assertEquals(allAttrVals.get("key1"), user.getAttribute("key1"));
Assert.assertEquals(allAttrVals.get("key2"), user.getAttribute("key2"));
// Test remove and rewrite attribute
user.removeAttribute("key1");
user.setSingleAttribute("key2", "val23");
commit();
realm = realmManager.getRealmByName("original");
user = session.users().getUserByUsername("user", realm);
Assert.assertNull(user.getFirstAttribute("key1"));
attrVals = user.getAttribute("key2");
Assert.assertEquals(1, attrVals.size());
Assert.assertEquals("val23", attrVals.get(0));
}
// KEYCLOAK-3494
@Test
public void testUpdateUserAttribute() throws Exception {
RealmModel realm = realmManager.createRealm("original");
UserModel user = session.users().addUser(realm, "user");
user.setSingleAttribute("key1", "value1");
commit();
realm = realmManager.getRealmByName("original");
user = session.users().getUserByUsername("user", realm);
// Update attribute
List<String> attrVals = new ArrayList<>(Arrays.asList( "val2" ));
user.setAttribute("key1", attrVals);
Map<String, List<String>> allAttrVals = user.getAttributes();
// Ensure same transaction is able to see updated value
Assert.assertEquals(1, allAttrVals.size());
Assert.assertEquals(allAttrVals.get("key1"), Arrays.asList("val2"));
commit();
}
// KEYCLOAK-3608
@Test
public void testUpdateUserSingleAttribute() {
Map<String, List<String>> expected = ImmutableMap.of(
"key1", Arrays.asList("value3"),
"key2", Arrays.asList("value2"));
RealmModel realm = realmManager.createRealm("original");
UserModel user = session.users().addUser(realm, "user");
user.setSingleAttribute("key1", "value1");
user.setSingleAttribute("key2", "value2");
// Overwrite the first attribute
user.setSingleAttribute("key1", "value3");
Assert.assertEquals(expected, user.getAttributes());
commit();
realm = session.realms().getRealmByName("original");
Assert.assertEquals(expected, session.users().getUserByUsername("user", realm).getAttributes());
}
@Test
public void testSearchByString() {
RealmModel realm = realmManager.createRealm("original");
UserModel user1 = session.users().addUser(realm, "user1");
commit();
realm = session.realms().getRealmByName("original");
List<UserModel> users = session.users().searchForUser("user", realm, 0, 7);
Assert.assertTrue(users.contains(user1));
}
@Test
public void testSearchByUserAttribute() throws Exception {
RealmModel realm = realmManager.createRealm("original");
UserModel user1 = session.users().addUser(realm, "user1");
UserModel user2 = session.users().addUser(realm, "user2");
UserModel user3 = session.users().addUser(realm, "user3");
RealmModel otherRealm = realmManager.createRealm("other");
UserModel otherRealmUser = session.users().addUser(otherRealm, "user1");
user1.setSingleAttribute("key1", "value1");
user1.setSingleAttribute("key2", "value21");
user2.setSingleAttribute("key1", "value1");
user2.setSingleAttribute("key2", "value22");
user3.setSingleAttribute("key2", "value21");
otherRealmUser.setSingleAttribute("key2", "value21");
commit();
realm = session.realms().getRealmByName("original");
List<UserModel> users = session.users().searchForUserByUserAttribute("key1", "value1", realm);
Assert.assertEquals(2, users.size());
Assert.assertTrue(users.contains(user1));
Assert.assertTrue(users.contains(user2));
users = session.users().searchForUserByUserAttribute("key2", "value21", realm);
Assert.assertEquals(2, users.size());
Assert.assertTrue(users.contains(user1));
Assert.assertTrue(users.contains(user3));
users = session.users().searchForUserByUserAttribute("key2", "value22", realm);
Assert.assertEquals(1, users.size());
Assert.assertTrue(users.contains(user2));
users = session.users().searchForUserByUserAttribute("key3", "value3", realm);
Assert.assertEquals(0, users.size());
}
@Test
public void testServiceAccountLink() throws Exception {
RealmModel realm = realmManager.createRealm("original");
ClientModel client = realm.addClient("foo");
UserModel user1 = session.users().addUser(realm, "user1");
user1.setFirstName("John");
user1.setLastName("Doe");
UserModel user2 = session.users().addUser(realm, "user2");
user2.setFirstName("John");
user2.setLastName("Doe");
// Search
Assert.assertNull(session.users().getServiceAccount(client));
List<UserModel> users = session.users().searchForUser("John Doe", realm);
Assert.assertEquals(2, users.size());
Assert.assertTrue(users.contains(user1));
Assert.assertTrue(users.contains(user2));
// Link service account
user1.setServiceAccountClientLink(client.getId());
commit();
// Search and assert service account user not found
realm = realmManager.getRealmByName("original");
client = realm.getClientByClientId("foo");
UserModel searched = session.users().getServiceAccount(client);
Assert.assertEquals(searched, user1);
users = session.users().searchForUser("John Doe", realm);
Assert.assertEquals(1, users.size());
Assert.assertFalse(users.contains(user1));
Assert.assertTrue(users.contains(user2));
users = session.users().getUsers(realm, false);
Assert.assertEquals(1, users.size());
Assert.assertFalse(users.contains(user1));
Assert.assertTrue(users.contains(user2));
users = session.users().getUsers(realm, true);
Assert.assertEquals(2, users.size());
Assert.assertTrue(users.contains(user1));
Assert.assertTrue(users.contains(user2));
Assert.assertEquals(2, session.users().getUsersCount(realm, true));
Assert.assertEquals(1, session.users().getUsersCount(realm, false));
// Remove client
new ClientManager(realmManager).removeClient(realm, client);
commit();
// Assert service account removed as well
realm = realmManager.getRealmByName("original");
Assert.assertNull(session.users().getUserByUsername("user1", realm));
}
@Test
public void testGrantToAll() {
RealmModel realm1 = realmManager.createRealm("realm1");
RoleModel role1 = realm1.addRole("role1");
UserModel user1 = realmManager.getSession().users().addUser(realm1, "user1");
UserModel user2 = realmManager.getSession().users().addUser(realm1, "user2");
RealmModel realm2 = realmManager.createRealm("realm2");
UserModel realm2User1 = realmManager.getSession().users().addUser(realm2, "user1");
commit();
realm1 = realmManager.getRealmByName("realm1");
role1 = realm1.getRole("role1");
realmManager.getSession().users().grantToAllUsers(realm1, role1);
commit();
realm1 = realmManager.getRealmByName("realm1");
role1 = realm1.getRole("role1");
user1 = realmManager.getSession().users().getUserByUsername("user1", realm1);
user2 = realmManager.getSession().users().getUserByUsername("user2", realm1);
Assert.assertTrue(user1.hasRole(role1));
Assert.assertTrue(user2.hasRole(role1));
realm2 = realmManager.getRealmByName("realm2");
realm2User1 = realmManager.getSession().users().getUserByUsername("user1", realm2);
Assert.assertFalse(realm2User1.hasRole(role1));
}
@Test
public void testUserNotBefore() throws Exception {
RealmModel realm = realmManager.createRealm("original");
UserModel user1 = session.users().addUser(realm, "user1");
session.users().setNotBeforeForUser(realm, user1, 10);
commit();
realm = realmManager.getRealmByName("original");
user1 = session.users().getUserByUsername("user1", realm);
int notBefore = session.users().getNotBeforeOfUser(realm, user1);
Assert.assertEquals(10, notBefore);
// Try to update
session.users().setNotBeforeForUser(realm, user1, 20);
commit();
realm = realmManager.getRealmByName("original");
user1 = session.users().getUserByUsername("user1", realm);
notBefore = session.users().getNotBeforeOfUser(realm, user1);
Assert.assertEquals(20, notBefore);
}
public static void assertEquals(UserModel expected, UserModel actual) {
Assert.assertEquals(expected.getUsername(), actual.getUsername());
Assert.assertEquals(expected.getCreatedTimestamp(), actual.getCreatedTimestamp());
Assert.assertEquals(expected.getFirstName(), actual.getFirstName());
Assert.assertEquals(expected.getLastName(), actual.getLastName());
String[] expectedRequiredActions = expected.getRequiredActions().toArray(new String[expected.getRequiredActions().size()]);
Arrays.sort(expectedRequiredActions);
String[] actualRequiredActions = actual.getRequiredActions().toArray(new String[actual.getRequiredActions().size()]);
Arrays.sort(actualRequiredActions);
Assert.assertArrayEquals(expectedRequiredActions, actualRequiredActions);
}
}

View file

@ -1,469 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.model;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.keycloak.cluster.ClusterProvider;
import org.keycloak.common.util.Time;
import org.keycloak.models.AuthenticatedClientSessionModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.session.UserSessionPersisterProvider;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.services.managers.ClientManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.models.UserManager;
import org.keycloak.testsuite.rule.KeycloakRule;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class UserSessionPersisterProviderTest {
@ClassRule
public static KeycloakRule kc = new KeycloakRule();
private KeycloakSession session;
private RealmModel realm;
private UserSessionPersisterProvider persister;
@Before
public void before() {
session = kc.startSession();
realm = session.realms().getRealm("test");
session.users().addUser(realm, "user1").setEmail("user1@localhost");
session.users().addUser(realm, "user2").setEmail("user2@localhost");
persister = session.getProvider(UserSessionPersisterProvider.class);
}
@After
public void after() {
resetSession();
session.sessions().removeUserSessions(realm);
UserModel user1 = session.users().getUserByUsername("user1", realm);
UserModel user2 = session.users().getUserByUsername("user2", realm);
UserManager um = new UserManager(session);
if (user1 != null) {
um.removeUser(realm, user1);
}
if (user2 != null) {
um.removeUser(realm, user2);
}
kc.stopSession(session, true);
}
@Test
public void testPersistenceWithLoad() {
// Create some sessions in infinispan
int started = Time.currentTime();
UserSessionModel[] origSessions = createSessions();
resetSession();
// Persist 3 created userSessions and clientSessions as offline
ClientModel testApp = realm.getClientByClientId("test-app");
List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, testApp);
for (UserSessionModel userSession : userSessions) {
persistUserSession(userSession, true);
}
// Persist 1 online session
UserSessionModel userSession = session.sessions().getUserSession(realm, origSessions[0].getId());
persistUserSession(userSession, false);
resetSession();
// Assert online session
List<UserSessionModel> loadedSessions = loadPersistedSessionsPaginated(false, 1, 1, 1);
UserSessionProviderTest.assertSession(loadedSessions.get(0), session.users().getUserByUsername("user1", realm), "127.0.0.1", started, started, "test-app", "third-party");
// Assert offline sessions
loadedSessions = loadPersistedSessionsPaginated(true, 2, 2, 3);
UserSessionProviderTest.assertSessions(loadedSessions, origSessions);
assertSessionLoaded(loadedSessions, origSessions[0].getId(), session.users().getUserByUsername("user1", realm), "127.0.0.1", started, started, "test-app", "third-party");
assertSessionLoaded(loadedSessions, origSessions[1].getId(), session.users().getUserByUsername("user1", realm), "127.0.0.2", started, started, "test-app");
assertSessionLoaded(loadedSessions, origSessions[2].getId(), session.users().getUserByUsername("user2", realm), "127.0.0.3", started, started, "test-app");
}
@Test
public void testUpdateAndRemove() {
// Create some sessions in infinispan
int started = Time.currentTime();
UserSessionModel[] origSessions = createSessions();
resetSession();
// Persist 1 offline session
UserSessionModel userSession = session.sessions().getUserSession(realm, origSessions[1].getId());
persistUserSession(userSession, true);
resetSession();
// Load offline session
List<UserSessionModel> loadedSessions = loadPersistedSessionsPaginated(true, 10, 1, 1);
UserSessionModel persistedSession = loadedSessions.get(0);
UserSessionProviderTest.assertSession(persistedSession, session.users().getUserByUsername("user1", realm), "127.0.0.2", started, started, "test-app");
// create new clientSession
AuthenticatedClientSessionModel clientSession = createClientSession(realm.getClientByClientId("third-party"), session.sessions().getUserSession(realm, persistedSession.getId()),
"http://redirect", "state");
persister.createClientSession(clientSession, true);
resetSession();
// Remove clientSession
persister.removeClientSession(userSession.getId(), realm.getClientByClientId("third-party").getId(), true);
resetSession();
// Assert clientSession removed
loadedSessions = loadPersistedSessionsPaginated(true, 10, 1, 1);
persistedSession = loadedSessions.get(0);
UserSessionProviderTest.assertSession(persistedSession, session.users().getUserByUsername("user1", realm), "127.0.0.2", started, started , "test-app");
// Remove userSession
persister.removeUserSession(persistedSession.getId(), true);
resetSession();
// Assert nothing found
loadPersistedSessionsPaginated(true, 10, 0, 0);
}
@Test
public void testOnRealmRemoved() {
RealmModel fooRealm = session.realms().createRealm("foo", "foo");
fooRealm.addClient("foo-app");
session.users().addUser(fooRealm, "user3");
UserSessionModel userSession = session.sessions().createUserSession(fooRealm, session.users().getUserByUsername("user3", fooRealm), "user3", "127.0.0.1", "form", true, null, null);
createClientSession(fooRealm.getClientByClientId("foo-app"), userSession, "http://redirect", "state");
resetSession();
// Persist offline session
fooRealm = session.realms().getRealm("foo");
userSession = session.sessions().getUserSession(fooRealm, userSession.getId());
persistUserSession(userSession, true);
resetSession();
// Assert session was persisted
loadPersistedSessionsPaginated(true, 10, 1, 1);
// Remove realm
RealmManager realmMgr = new RealmManager(session);
realmMgr.removeRealm(realmMgr.getRealm("foo"));
resetSession();
// Assert nothing loaded
loadPersistedSessionsPaginated(true, 10, 0, 0);
}
@Test
public void testOnClientRemoved() {
int started = Time.currentTime();
RealmModel fooRealm = session.realms().createRealm("foo", "foo");
fooRealm.addClient("foo-app");
fooRealm.addClient("bar-app");
session.users().addUser(fooRealm, "user3");
UserSessionModel userSession = session.sessions().createUserSession(fooRealm, session.users().getUserByUsername("user3", fooRealm), "user3", "127.0.0.1", "form", true, null, null);
createClientSession(fooRealm.getClientByClientId("foo-app"), userSession, "http://redirect", "state");
createClientSession(fooRealm.getClientByClientId("bar-app"), userSession, "http://redirect", "state");
resetSession();
// Persist offline session
fooRealm = session.realms().getRealm("foo");
userSession = session.sessions().getUserSession(fooRealm, userSession.getId());
persistUserSession(userSession, true);
resetSession();
RealmManager realmMgr = new RealmManager(session);
ClientManager clientMgr = new ClientManager(realmMgr);
fooRealm = realmMgr.getRealm("foo");
// Assert session was persisted with both clientSessions
UserSessionModel persistedSession = loadPersistedSessionsPaginated(true, 10, 1, 1).get(0);
UserSessionProviderTest.assertSession(persistedSession, session.users().getUserByUsername("user3", fooRealm), "127.0.0.1", started, started, "foo-app", "bar-app");
// Remove foo-app client
ClientModel client = fooRealm.getClientByClientId("foo-app");
clientMgr.removeClient(fooRealm, client);
resetSession();
realmMgr = new RealmManager(session);
clientMgr = new ClientManager(realmMgr);
fooRealm = realmMgr.getRealm("foo");
// Assert just one bar-app clientSession persisted now
persistedSession = loadPersistedSessionsPaginated(true, 10, 1, 1).get(0);
UserSessionProviderTest.assertSession(persistedSession, session.users().getUserByUsername("user3", fooRealm), "127.0.0.1", started, started, "bar-app");
// Remove bar-app client
client = fooRealm.getClientByClientId("bar-app");
clientMgr.removeClient(fooRealm, client);
resetSession();
// Assert loading still works - last userSession is still there, but no clientSession on it
loadPersistedSessionsPaginated(true, 10, 1, 1);
// Cleanup
realmMgr = new RealmManager(session);
realmMgr.removeRealm(realmMgr.getRealm("foo"));
}
@Test
public void testOnUserRemoved() {
// Create some sessions in infinispan
int started = Time.currentTime();
UserSessionModel[] origSessions = createSessions();
resetSession();
// Persist 2 offline sessions of 2 users
UserSessionModel userSession1 = session.sessions().getUserSession(realm, origSessions[1].getId());
UserSessionModel userSession2 = session.sessions().getUserSession(realm, origSessions[2].getId());
persistUserSession(userSession1, true);
persistUserSession(userSession2, true);
resetSession();
// Load offline sessions
List<UserSessionModel> loadedSessions = loadPersistedSessionsPaginated(true, 10, 1, 2);
// Properly delete user and assert his offlineSession removed
UserModel user1 = session.users().getUserByUsername("user1", realm);
new UserManager(session).removeUser(realm, user1);
resetSession();
Assert.assertEquals(1, persister.getUserSessionsCount(true));
loadedSessions = loadPersistedSessionsPaginated(true, 10, 1, 1);
UserSessionModel persistedSession = loadedSessions.get(0);
UserSessionProviderTest.assertSession(persistedSession, session.users().getUserByUsername("user2", realm), "127.0.0.3", started, started, "test-app");
// KEYCLOAK-2431 Assert that userSessionPersister is resistent even to situation, when users are deleted "directly".
// No exception will happen. However session will be still there
UserModel user2 = session.users().getUserByUsername("user2", realm);
session.users().removeUser(realm, user2);
loadedSessions = loadPersistedSessionsPaginated(true, 10, 1, 1);
// Cleanup
UserSessionModel userSession = loadedSessions.get(0);
session.sessions().removeUserSession(realm, userSession);
persister.removeUserSession(userSession.getId(), userSession.isOffline());
}
// KEYCLOAK-1999
@Test
public void testNoSessions() {
UserSessionPersisterProvider persister = session.getProvider(UserSessionPersisterProvider.class);
List<UserSessionModel> sessions = persister.loadUserSessions(0, 1, true, 0, "abc");
Assert.assertEquals(0, sessions.size());
}
@Test
public void testMoreSessions() {
// Create 10 userSessions - each having 1 clientSession
List<UserSessionModel> userSessions = new ArrayList<>();
UserModel user = session.users().getUserByUsername("user1", realm);
for (int i=0 ; i<20 ; i++) {
// Having different offsets for each session (to ensure that lastSessionRefresh is also different)
Time.setOffset(i);
UserSessionModel userSession = session.sessions().createUserSession(realm, user, "user1", "127.0.0.1", "form", true, null, null);
createClientSession(realm.getClientByClientId("test-app"), userSession, "http://redirect", "state");
userSessions.add(userSession);
}
resetSession();
for (UserSessionModel userSession : userSessions) {
UserSessionModel userSession2 = session.sessions().getUserSession(realm, userSession.getId());
persistUserSession(userSession2, true);
}
resetSession();
List<UserSessionModel> loadedSessions = loadPersistedSessionsPaginated(true, 2, 10, 20);
user = session.users().getUserByUsername("user1", realm);
ClientModel testApp = realm.getClientByClientId("test-app");
for (UserSessionModel loadedSession : loadedSessions) {
assertEquals(user.getId(), loadedSession.getUser().getId());
assertEquals("127.0.0.1", loadedSession.getIpAddress());
assertEquals(user.getUsername(), loadedSession.getLoginUsername());
assertEquals(1, loadedSession.getAuthenticatedClientSessions().size());
assertTrue(loadedSession.getAuthenticatedClientSessions().containsKey(testApp.getId()));
}
}
@Test
public void testExpiredSessions() {
// Create some sessions in infinispan
int started = Time.currentTime();
UserSessionModel[] origSessions = createSessions();
resetSession();
// Persist 2 offline sessions of 2 users
UserSessionModel userSession1 = session.sessions().getUserSession(realm, origSessions[1].getId());
UserSessionModel userSession2 = session.sessions().getUserSession(realm, origSessions[2].getId());
persistUserSession(userSession1, true);
persistUserSession(userSession2, true);
resetSession();
// Update one of the sessions with lastSessionRefresh of 20 days ahead
int lastSessionRefresh = Time.currentTime() + 1728000;
persister.updateLastSessionRefreshes(realm, lastSessionRefresh, Collections.singleton(userSession1.getId()), true);
resetSession();
// Increase time offset - 40 days
Time.setOffset(3456000);
try {
// Run expiration thread
persister.removeExpired(realm);
// Test the updated session is still in persister. Not updated session is not there anymore
List<UserSessionModel> loadedSessions = loadPersistedSessionsPaginated(true, 10, 1, 1);
UserSessionModel persistedSession = loadedSessions.get(0);
UserSessionProviderTest.assertSession(persistedSession, session.users().getUserByUsername("user1", realm), "127.0.0.2", started, lastSessionRefresh, "test-app");
} finally {
// Cleanup
Time.setOffset(0);
}
}
private AuthenticatedClientSessionModel createClientSession(ClientModel client, UserSessionModel userSession, String redirect, String state) {
AuthenticatedClientSessionModel clientSession = session.sessions().createClientSession(realm, client, userSession);
clientSession.setRedirectUri(redirect);
if (state != null) clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, state);
return clientSession;
}
private UserSessionModel[] createSessions() {
UserSessionModel[] sessions = new UserSessionModel[3];
sessions[0] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "user1", "127.0.0.1", "form", true, null, null);
createClientSession(realm.getClientByClientId("test-app"), sessions[0], "http://redirect", "state");
createClientSession(realm.getClientByClientId("third-party"), sessions[0], "http://redirect", "state");
sessions[1] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "user1", "127.0.0.2", "form", true, null, null);
createClientSession(realm.getClientByClientId("test-app"), sessions[1], "http://redirect", "state");
sessions[2] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user2", realm), "user2", "127.0.0.3", "form", true, null, null);
createClientSession(realm.getClientByClientId("test-app"), sessions[2], "http://redirect", "state");
return sessions;
}
private void persistUserSession(UserSessionModel userSession, boolean offline) {
persister.createUserSession(userSession, offline);
for (AuthenticatedClientSessionModel clientSession : userSession.getAuthenticatedClientSessions().values()) {
persister.createClientSession(clientSession, offline);
}
}
private void resetSession() {
kc.stopSession(session, true);
session = kc.startSession();
realm = session.realms().getRealm("test");
persister = session.getProvider(UserSessionPersisterProvider.class);
}
public static void assertSessionLoaded(List<UserSessionModel> sessions, String id, UserModel user, String ipAddress, int started, int lastRefresh, String... clients) {
for (UserSessionModel session : sessions) {
if (session.getId().equals(id)) {
UserSessionProviderTest.assertSession(session, user, ipAddress, started, lastRefresh, clients);
return;
}
}
Assert.fail("Session with ID " + id + " not found in the list");
}
private List<UserSessionModel> loadPersistedSessionsPaginated(boolean offline, int sessionsPerPage, int expectedPageCount, int expectedSessionsCount) {
int count = persister.getUserSessionsCount(offline);
int pageCount = 0;
boolean next = true;
List<UserSessionModel> result = new ArrayList<>();
int lastCreatedOn = 0;
String lastSessionId = "abc";
while (next) {
List<UserSessionModel> sess = persister.loadUserSessions(0, sessionsPerPage, offline, lastCreatedOn, lastSessionId);
if (sess.size() < sessionsPerPage) {
next = false;
// We had at least some session
if (sess.size() > 0) {
pageCount++;
}
} else {
pageCount++;
UserSessionModel lastSession = sess.get(sess.size() - 1);
lastCreatedOn = lastSession.getStarted();
lastSessionId = lastSession.getId();
}
result.addAll(sess);
}
Assert.assertEquals(pageCount, expectedPageCount);
Assert.assertEquals(result.size(), expectedSessionsCount);
return result;
}
}

View file

@ -1,467 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.model;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.keycloak.common.util.Time;
import org.keycloak.models.AuthenticatedClientSessionModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.session.UserSessionPersisterProvider;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.services.managers.ClientManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.models.UserManager;
import org.keycloak.services.managers.UserSessionManager;
import org.keycloak.testsuite.rule.KeycloakRule;
import org.keycloak.testsuite.rule.LoggingRule;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class UserSessionProviderOfflineTest {
@ClassRule
public static KeycloakRule kc = new KeycloakRule();
@Rule
public LoggingRule loggingRule = new LoggingRule(this);
private KeycloakSession session;
private RealmModel realm;
private UserSessionManager sessionManager;
private UserSessionPersisterProvider persister;
@Before
public void before() {
session = kc.startSession();
realm = session.realms().getRealm("test");
session.users().addUser(realm, "user1").setEmail("user1@localhost");
session.users().addUser(realm, "user2").setEmail("user2@localhost");
sessionManager = new UserSessionManager(session);
persister = session.getProvider(UserSessionPersisterProvider.class);
}
@After
public void after() {
resetSession();
session.sessions().removeUserSessions(realm);
UserModel user1 = session.users().getUserByUsername("user1", realm);
UserModel user2 = session.users().getUserByUsername("user2", realm);
UserManager um = new UserManager(session);
um.removeUser(realm, user1);
um.removeUser(realm, user2);
kc.stopSession(session, true);
}
@Test
public void testOfflineSessionsCrud() {
// Create some online sessions in infinispan
int started = Time.currentTime();
UserSessionModel[] origSessions = createSessions();
resetSession();
// Key is userSession ID, values are client UUIDS
Map<String, Set<String>> offlineSessions = new HashMap<>();
// Persist 3 created userSessions and clientSessions as offline
ClientModel testApp = realm.getClientByClientId("test-app");
List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, testApp);
for (UserSessionModel userSession : userSessions) {
offlineSessions.put(userSession.getId(), createOfflineSessionIncludeClientSessions(userSession));
}
resetSession();
// Assert all previously saved offline sessions found
for (Map.Entry<String, Set<String>> entry : offlineSessions.entrySet()) {
UserSessionModel offlineSession = sessionManager.findOfflineUserSession(realm, entry.getKey());
Assert.assertNotNull(offlineSession);
Assert.assertEquals(offlineSession.getAuthenticatedClientSessions().keySet(), entry.getValue());
}
// Find clients with offline token
UserModel user1 = session.users().getUserByUsername("user1", realm);
Set<ClientModel> clients = sessionManager.findClientsWithOfflineToken(realm, user1);
Assert.assertEquals(clients.size(), 2);
for (ClientModel client : clients) {
Assert.assertTrue(client.getClientId().equals("test-app") || client.getClientId().equals("third-party"));
}
UserModel user2 = session.users().getUserByUsername("user2", realm);
clients = sessionManager.findClientsWithOfflineToken(realm, user2);
Assert.assertEquals(clients.size(), 1);
Assert.assertTrue(clients.iterator().next().getClientId().equals("test-app"));
// Test count
testApp = realm.getClientByClientId("test-app");
ClientModel thirdparty = realm.getClientByClientId("third-party");
Assert.assertEquals(3, session.sessions().getOfflineSessionsCount(realm, testApp));
Assert.assertEquals(1, session.sessions().getOfflineSessionsCount(realm, thirdparty));
// Revoke "test-app" for user1
sessionManager.revokeOfflineToken(user1, testApp);
resetSession();
// Assert userSession revoked
testApp = realm.getClientByClientId("test-app");
thirdparty = realm.getClientByClientId("third-party");
// Still 2 sessions. The count of sessions by client may not be accurate after revoke due the
// performance optimizations (the "127.0.0.1" session still has another client "thirdparty" in it)
Assert.assertEquals(2, session.sessions().getOfflineSessionsCount(realm, testApp));
Assert.assertEquals(1, session.sessions().getOfflineSessionsCount(realm, thirdparty));
List<UserSessionModel> thirdpartySessions = session.sessions().getOfflineUserSessions(realm, thirdparty, 0, 10);
Assert.assertEquals(1, thirdpartySessions.size());
Assert.assertEquals("127.0.0.1", thirdpartySessions.get(0).getIpAddress());
Assert.assertEquals("user1", thirdpartySessions.get(0).getUser().getUsername());
user1 = session.users().getUserByUsername("user1", realm);
user2 = session.users().getUserByUsername("user2", realm);
clients = sessionManager.findClientsWithOfflineToken(realm, user1);
Assert.assertEquals(1, clients.size());
Assert.assertEquals("third-party", clients.iterator().next().getClientId());
clients = sessionManager.findClientsWithOfflineToken(realm, user2);
Assert.assertEquals(1, clients.size());
Assert.assertEquals("test-app", clients.iterator().next().getClientId());
// Revoke the second session for user1 too.
sessionManager.revokeOfflineToken(user1, thirdparty);
resetSession();
testApp = realm.getClientByClientId("test-app");
thirdparty = realm.getClientByClientId("third-party");
// Accurate count now. All sessions of user1 cleared
Assert.assertEquals(1, session.sessions().getOfflineSessionsCount(realm, testApp));
Assert.assertEquals(0, session.sessions().getOfflineSessionsCount(realm, thirdparty));
List<UserSessionModel> testAppSessions = session.sessions().getOfflineUserSessions(realm, testApp, 0, 10);
Assert.assertEquals(1, testAppSessions.size());
Assert.assertEquals("127.0.0.3", testAppSessions.get(0).getIpAddress());
Assert.assertEquals("user2", testAppSessions.get(0).getUser().getUsername());
clients = sessionManager.findClientsWithOfflineToken(realm, user1);
Assert.assertEquals(0, clients.size());
}
@Test
public void testOnRealmRemoved() {
RealmModel fooRealm = session.realms().createRealm("foo", "foo");
fooRealm.addClient("foo-app");
session.users().addUser(fooRealm, "user3");
UserSessionModel userSession = session.sessions().createUserSession(fooRealm, session.users().getUserByUsername("user3", fooRealm), "user3", "127.0.0.1", "form", true, null, null);
AuthenticatedClientSessionModel clientSession = createClientSession(fooRealm.getClientByClientId("foo-app"), userSession, "http://redirect", "state");
resetSession();
// Persist offline session
fooRealm = session.realms().getRealm("foo");
userSession = session.sessions().getUserSession(fooRealm, userSession.getId());
createOfflineSessionIncludeClientSessions(userSession);
resetSession();
UserSessionModel offlineUserSession = sessionManager.findOfflineUserSession(fooRealm, userSession.getId());
Assert.assertEquals(offlineUserSession.getAuthenticatedClientSessions().size(), 1);
AuthenticatedClientSessionModel offlineClientSession = offlineUserSession.getAuthenticatedClientSessions().values().iterator().next();
Assert.assertEquals("foo-app", offlineClientSession.getClient().getClientId());
Assert.assertEquals("user3", offlineClientSession.getUserSession().getUser().getUsername());
// Remove realm
RealmManager realmMgr = new RealmManager(session);
realmMgr.removeRealm(realmMgr.getRealm("foo"));
resetSession();
fooRealm = session.realms().createRealm("foo", "foo");
fooRealm.addClient("foo-app");
session.users().addUser(fooRealm, "user3");
resetSession();
// Assert nothing loaded
fooRealm = session.realms().getRealm("foo");
Assert.assertNull(sessionManager.findOfflineUserSession(fooRealm, userSession.getId()));
Assert.assertEquals(0, session.sessions().getOfflineSessionsCount(fooRealm, fooRealm.getClientByClientId("foo-app")));
// Cleanup
realmMgr = new RealmManager(session);
realmMgr.removeRealm(realmMgr.getRealm("foo"));
}
@Test
public void testOnClientRemoved() {
int started = Time.currentTime();
RealmModel fooRealm = session.realms().createRealm("foo", "foo");
fooRealm.addClient("foo-app");
fooRealm.addClient("bar-app");
session.users().addUser(fooRealm, "user3");
UserSessionModel userSession = session.sessions().createUserSession(fooRealm, session.users().getUserByUsername("user3", fooRealm), "user3", "127.0.0.1", "form", true, null, null);
createClientSession(fooRealm.getClientByClientId("foo-app"), userSession, "http://redirect", "state");
createClientSession(fooRealm.getClientByClientId("bar-app"), userSession, "http://redirect", "state");
resetSession();
// Create offline session
fooRealm = session.realms().getRealm("foo");
userSession = session.sessions().getUserSession(fooRealm, userSession.getId());
createOfflineSessionIncludeClientSessions(userSession);
resetSession();
RealmManager realmMgr = new RealmManager(session);
ClientManager clientMgr = new ClientManager(realmMgr);
fooRealm = realmMgr.getRealm("foo");
// Assert session was persisted with both clientSessions
UserSessionModel offlineSession = session.sessions().getOfflineUserSession(fooRealm, userSession.getId());
UserSessionProviderTest.assertSession(offlineSession, session.users().getUserByUsername("user3", fooRealm), "127.0.0.1", started, started, "foo-app", "bar-app");
// Remove foo-app client
ClientModel client = fooRealm.getClientByClientId("foo-app");
clientMgr.removeClient(fooRealm, client);
resetSession();
realmMgr = new RealmManager(session);
clientMgr = new ClientManager(realmMgr);
fooRealm = realmMgr.getRealm("foo");
// Assert just one bar-app clientSession persisted now
offlineSession = session.sessions().getOfflineUserSession(fooRealm, userSession.getId());
Assert.assertEquals(1, offlineSession.getAuthenticatedClientSessions().size());
Assert.assertEquals("bar-app", offlineSession.getAuthenticatedClientSessions().values().iterator().next().getClient().getClientId());
// Remove bar-app client
client = fooRealm.getClientByClientId("bar-app");
clientMgr.removeClient(fooRealm, client);
resetSession();
// Assert nothing loaded - userSession was removed as well because it was last userSession
realmMgr = new RealmManager(session);
fooRealm = realmMgr.getRealm("foo");
offlineSession = session.sessions().getOfflineUserSession(fooRealm, userSession.getId());
Assert.assertEquals(0, offlineSession.getAuthenticatedClientSessions().size());
// Cleanup
realmMgr = new RealmManager(session);
realmMgr.removeRealm(realmMgr.getRealm("foo"));
}
@Test
public void testOnUserRemoved() {
int started = Time.currentTime();
RealmModel fooRealm = session.realms().createRealm("foo", "foo");
fooRealm.addClient("foo-app");
session.users().addUser(fooRealm, "user3");
UserSessionModel userSession = session.sessions().createUserSession(fooRealm, session.users().getUserByUsername("user3", fooRealm), "user3", "127.0.0.1", "form", true, null, null);
AuthenticatedClientSessionModel clientSession = createClientSession(fooRealm.getClientByClientId("foo-app"), userSession, "http://redirect", "state");
resetSession();
// Create offline session
fooRealm = session.realms().getRealm("foo");
userSession = session.sessions().getUserSession(fooRealm, userSession.getId());
createOfflineSessionIncludeClientSessions(userSession);
resetSession();
RealmManager realmMgr = new RealmManager(session);
fooRealm = realmMgr.getRealm("foo");
UserModel user3 = session.users().getUserByUsername("user3", fooRealm);
// Assert session was persisted with both clientSessions
UserSessionModel offlineSession = session.sessions().getOfflineUserSession(fooRealm, userSession.getId());
UserSessionProviderTest.assertSession(offlineSession, user3, "127.0.0.1", started, started, "foo-app");
// Remove user3
new UserManager(session).removeUser(fooRealm, user3);
resetSession();
// Assert userSession removed as well
Assert.assertNull(session.sessions().getOfflineUserSession(fooRealm, userSession.getId()));
// Cleanup
realmMgr = new RealmManager(session);
realmMgr.removeRealm(realmMgr.getRealm("foo"));
}
@Test
public void testExpired() {
// Create some online sessions in infinispan
int started = Time.currentTime();
UserSessionModel[] origSessions = createSessions();
resetSession();
// Key is userSessionId, value is set of client UUIDS
Map<String, Set<String>> offlineSessions = new HashMap<>();
// Persist 3 created userSessions and clientSessions as offline
ClientModel testApp = realm.getClientByClientId("test-app");
List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, testApp);
for (UserSessionModel userSession : userSessions) {
offlineSessions.put(userSession.getId(), createOfflineSessionIncludeClientSessions(userSession));
}
resetSession();
// Assert all previously saved offline sessions found
for (Map.Entry<String, Set<String>> entry : offlineSessions.entrySet()) {
UserSessionModel foundSession = sessionManager.findOfflineUserSession(realm, entry.getKey());
Assert.assertEquals(foundSession.getAuthenticatedClientSessions().keySet(), entry.getValue());
}
UserSessionModel session0 = session.sessions().getOfflineUserSession(realm, origSessions[0].getId());
Assert.assertNotNull(session0);
// sessions are in persister too
Assert.assertEquals(3, persister.getUserSessionsCount(true));
// Increase timeOffset - 5 minutes
Time.setOffset(300);
try {
// Update lastSessionRefresh of session0. This will update lastSessionRefresh of all the sessions to DB as they were not yet updated to DB
session0.setLastSessionRefresh(Time.currentTime());
resetSession();
// Increase timeOffset - 20 days
Time.setOffset(1728000);
session0 = session.sessions().getOfflineUserSession(realm, origSessions[0].getId());
session0.setLastSessionRefresh(Time.currentTime());
resetSession();
// Increase timeOffset - 40 days
Time.setOffset(3456000);
// Expire and ensure that all sessions despite session0 were removed
session.sessions().removeExpired(realm);
persister.removeExpired(realm);
resetSession();
// assert session0 is the only session found
Assert.assertNotNull(session.sessions().getOfflineUserSession(realm, origSessions[0].getId()));
Assert.assertNull(session.sessions().getOfflineUserSession(realm, origSessions[1].getId()));
Assert.assertNull(session.sessions().getOfflineUserSession(realm, origSessions[2].getId()));
Assert.assertEquals(1, persister.getUserSessionsCount(true));
// Expire everything and assert nothing found
Time.setOffset(6000000);
session.sessions().removeExpired(realm);
persister.removeExpired(realm);
resetSession();
for (String userSessionId : offlineSessions.keySet()) {
Assert.assertNull(sessionManager.findOfflineUserSession(realm, userSessionId));
}
Assert.assertEquals(0, persister.getUserSessionsCount(true));
} finally {
Time.setOffset(0);
}
}
private Set<String> createOfflineSessionIncludeClientSessions(UserSessionModel userSession) {
Set<String> offlineSessions = new HashSet<>();
for (AuthenticatedClientSessionModel clientSession : userSession.getAuthenticatedClientSessions().values()) {
sessionManager.createOrUpdateOfflineSession(clientSession, userSession);
offlineSessions.add(clientSession.getClient().getId());
}
return offlineSessions;
}
private void resetSession() {
kc.stopSession(session, true);
session = kc.startSession();
realm = session.realms().getRealm("test");
sessionManager = new UserSessionManager(session);
persister = session.getProvider(UserSessionPersisterProvider.class);
}
private AuthenticatedClientSessionModel createClientSession(ClientModel client, UserSessionModel userSession, String redirect, String state) {
AuthenticatedClientSessionModel clientSession = session.sessions().createClientSession(client.getRealm(), client, userSession);
clientSession.setRedirectUri(redirect);
if (state != null) clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, state);
return clientSession;
}
private UserSessionModel[] createSessions() {
UserSessionModel[] sessions = new UserSessionModel[3];
sessions[0] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "user1", "127.0.0.1", "form", true, null, null);
Set<String> roles = new HashSet<String>();
roles.add("one");
roles.add("two");
Set<String> protocolMappers = new HashSet<String>();
protocolMappers.add("mapper-one");
protocolMappers.add("mapper-two");
createClientSession(realm.getClientByClientId("test-app"), sessions[0], "http://redirect", "state");
createClientSession(realm.getClientByClientId("third-party"), sessions[0], "http://redirect", "state");
sessions[1] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "user1", "127.0.0.2", "form", true, null, null);
createClientSession(realm.getClientByClientId("test-app"), sessions[1], "http://redirect", "state");
sessions[2] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user2", realm), "user2", "127.0.0.3", "form", true, null, null);
createClientSession(realm.getClientByClientId("test-app"), sessions[2], "http://redirect", "state");
return sessions;
}
}