keycloak-aplcache
Changes
model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java 4(+2 -2)
model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/ClientSessionEntity.java 1(+1 -0)
model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanKeycloakTransaction.java 166(+166 -0)
model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java 178(+21 -157)
model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/UserSessionAdapter.java 7(+7 -0)
model/infinispan/src/main/java/org/keycloak/sessions/infinispan/InfinispanLoginSessionProvider.java 69(+69 -0)
model/infinispan/src/main/java/org/keycloak/sessions/infinispan/LoginSessionAdapter.java 270(+270 -0)
model/infinispan/src/main/java/org/keycloak/sessions/infinispan/LoginSessionEntity.java 142(+142 -0)
model/jpa/src/main/java/org/keycloak/models/jpa/session/JpaUserSessionPersisterProvider.java 6(+5 -1)
server-spi-private/src/main/java/org/keycloak/authentication/AuthenticationFlowContext.java 3(+2 -1)
server-spi-private/src/main/java/org/keycloak/broker/provider/BrokeredIdentityContext.java 11(+6 -5)
server-spi-private/src/main/java/org/keycloak/models/session/DisabledUserSessionPersisterProvider.java 3(+2 -1)
server-spi-private/src/main/java/org/keycloak/models/session/PersistentClientSessionAdapter.java 120(+8 -112)
server-spi-private/src/main/java/org/keycloak/models/session/PersistentUserSessionAdapter.java 7(+7 -0)
server-spi-private/src/main/java/org/keycloak/models/session/UserSessionPersisterProvider.java 4(+2 -2)
services/src/main/java/org/keycloak/authentication/authenticators/broker/AbstractIdpAuthenticator.java 16(+8 -8)
services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpConfirmLinkAuthenticator.java 10(+5 -5)
services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpCreateUserIfUniqueAuthenticator.java 8(+4 -4)
services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpEmailVerificationAuthenticator.java 11(+4 -7)
services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpReviewProfileAuthenticator.java 7(+3 -4)
services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpUsernamePasswordForm.java 6(+3 -3)
services/src/main/java/org/keycloak/authentication/authenticators/broker/util/SerializedBrokeredIdentityContext.java 19(+10 -9)
services/src/main/java/org/keycloak/authentication/authenticators/browser/AbstractUsernameFormAuthenticator.java 6(+3 -3)
services/src/main/java/org/keycloak/authentication/authenticators/browser/CookieAuthenticator.java 5(+3 -2)
services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticator.java 2(+1 -1)
services/src/main/java/org/keycloak/authentication/authenticators/browser/ScriptBasedAuthenticator.java 2(+1 -1)
services/src/main/java/org/keycloak/authentication/authenticators/browser/SpnegoAuthenticator.java 2(+1 -1)
services/src/main/java/org/keycloak/authentication/authenticators/browser/UsernamePasswordForm.java 4(+2 -2)
services/src/main/java/org/keycloak/authentication/authenticators/directgrant/ValidateUsername.java 2(+1 -1)
services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialChooseUser.java 6(+3 -3)
services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialEmail.java 8(+4 -4)
services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetPassword.java 6(+3 -3)
services/src/main/java/org/keycloak/broker/provider/HardcodedUserSessionAttributeMapper.java 4(+2 -2)
services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java 24(+10 -14)
services/src/main/java/org/keycloak/protocol/saml/mappers/SAMLAttributeStatementMapper.java 4(+2 -2)
services/src/main/java/org/keycloak/protocol/saml/mappers/UserAttributeStatementMapper.java 4(+2 -2)
services/src/main/java/org/keycloak/protocol/saml/mappers/UserPropertyAttributeStatementMapper.java 4(+2 -2)
services/src/main/java/org/keycloak/protocol/saml/mappers/UserSessionNoteStatementMapper.java 4(+2 -2)
services/src/main/java/org/keycloak/protocol/saml/profile/ecp/authenticator/HttpBasicAuthenticator.java 2(+1 -1)
testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionInitializerTest.java 247(+124 -123)
testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionPersisterProviderTest.java 787(+394 -393)
testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderOfflineTest.java 811(+406 -405)
testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java 1144(+573 -571)
Details
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java
index c67a576..8abf19b 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java
@@ -157,12 +157,12 @@ public class ClientSessionAdapter implements ClientSessionModel {
}
@Override
- public String getAuthMethod() {
+ public String getProtocol() {
return entity.getAuthMethod();
}
@Override
- public void setAuthMethod(String authMethod) {
+ public void setProtocol(String authMethod) {
entity.setAuthMethod(authMethod);
update();
}
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/ClientSessionEntity.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/ClientSessionEntity.java
index 0cbdc79..6bce9e9 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/ClientSessionEntity.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/ClientSessionEntity.java
@@ -18,6 +18,7 @@
package org.keycloak.models.sessions.infinispan.entities;
import org.keycloak.models.ClientSessionModel;
+import org.keycloak.sessions.LoginSessionModel;
import java.util.HashMap;
import java.util.HashSet;
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanKeycloakTransaction.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanKeycloakTransaction.java
new file mode 100644
index 0000000..c6b30f4
--- /dev/null
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanKeycloakTransaction.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2017 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.models.sessions.infinispan;
+
+import org.keycloak.models.KeycloakTransaction;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.infinispan.Cache;
+import org.jboss.logging.Logger;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class InfinispanKeycloakTransaction implements KeycloakTransaction {
+
+ private final static Logger log = Logger.getLogger(InfinispanKeycloakTransaction.class);
+
+ public enum CacheOperation {
+ ADD, REMOVE, REPLACE
+ }
+
+ private boolean active;
+ private boolean rollback;
+ private final Map<Object, CacheTask> tasks = new HashMap<>();
+
+ @Override
+ public void begin() {
+ active = true;
+ }
+
+ @Override
+ public void commit() {
+ if (rollback) {
+ throw new RuntimeException("Rollback only!");
+ }
+
+ tasks.values().forEach(CacheTask::execute);
+ }
+
+ @Override
+ public void rollback() {
+ tasks.clear();
+ }
+
+ @Override
+ public void setRollbackOnly() {
+ rollback = true;
+ }
+
+ @Override
+ public boolean getRollbackOnly() {
+ return rollback;
+ }
+
+ @Override
+ public boolean isActive() {
+ return active;
+ }
+
+ public <K, V> void put(Cache<K, V> cache, K key, V value) {
+ log.tracev("Adding cache operation: {0} on {1}", CacheOperation.ADD, key);
+
+ Object taskKey = getTaskKey(cache, key);
+ if (tasks.containsKey(taskKey)) {
+ throw new IllegalStateException("Can't add session: task in progress for session");
+ } else {
+ tasks.put(taskKey, new CacheTask(cache, CacheOperation.ADD, key, value));
+ }
+ }
+
+ public <K, V> void replace(Cache<K, V> cache, K key, V value) {
+ log.tracev("Adding cache operation: {0} on {1}", CacheOperation.REPLACE, key);
+
+ Object taskKey = getTaskKey(cache, key);
+ CacheTask current = tasks.get(taskKey);
+ if (current != null) {
+ switch (current.operation) {
+ case ADD:
+ case REPLACE:
+ current.value = value;
+ return;
+ case REMOVE:
+ return;
+ }
+ } else {
+ tasks.put(taskKey, new CacheTask(cache, CacheOperation.REPLACE, key, value));
+ }
+ }
+
+ public <K, V> void remove(Cache<K, V> cache, K key) {
+ log.tracev("Adding cache operation: {0} on {1}", CacheOperation.REMOVE, key);
+
+ Object taskKey = getTaskKey(cache, key);
+ tasks.put(taskKey, new CacheTask(cache, CacheOperation.REMOVE, key, null));
+ }
+
+ // This is for possibility to lookup for session by id, which was created in this transaction
+ public <K, V> V get(Cache<K, V> cache, K key) {
+ Object taskKey = getTaskKey(cache, key);
+ CacheTask<K, V> current = tasks.get(taskKey);
+ if (current != null) {
+ switch (current.operation) {
+ case ADD:
+ case REPLACE:
+ return current.value;
+ }
+ }
+
+ return null;
+ }
+
+ private static <K, V> Object getTaskKey(Cache<K, V> cache, K key) {
+ if (key instanceof String) {
+ return new StringBuilder(cache.getName())
+ .append("::")
+ .append(key).toString();
+ } else {
+ return key;
+ }
+ }
+
+ public static class CacheTask<K, V> {
+ private final Cache<K, V> cache;
+ private final CacheOperation operation;
+ private final K key;
+ private V value;
+
+ public CacheTask(Cache<K, V> cache, CacheOperation operation, K key, V value) {
+ this.cache = cache;
+ this.operation = operation;
+ this.key = key;
+ this.value = value;
+ }
+
+ public void execute() {
+ log.tracev("Executing cache operation: {0} on {1}", operation, key);
+
+ switch (operation) {
+ case ADD:
+ cache.put(key, value);
+ break;
+ case REMOVE:
+ cache.remove(key);
+ break;
+ case REPLACE:
+ cache.replace(key, value);
+ break;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java
index a7c8c31..7fa9f81 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java
@@ -23,6 +23,7 @@ import org.infinispan.context.Flag;
import org.jboss.logging.Logger;
import org.keycloak.common.util.Time;
import org.keycloak.models.ClientInitialAccessModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
@@ -89,6 +90,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
return offline ? offlineSessionCache : sessionCache;
}
+ /*
@Override
public ClientSessionModel createClientSession(RealmModel realm, ClientModel client) {
String id = KeycloakModelUtils.generateId();
@@ -104,6 +106,12 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
ClientSessionAdapter wrap = wrap(realm, entity, false);
return wrap;
+ }*/
+
+ // TODO:mposolda
+ @Override
+ public ClientLoginSessionModel createClientSession(RealmModel realm, ClientModel client, UserSessionModel userSession) {
+ return null;
}
@Override
@@ -608,6 +616,8 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
}
}
+ // TODO:mposolda
+ /*
@Override
public ClientSessionModel createOfflineClientSession(ClientSessionModel clientSession) {
ClientSessionAdapter offlineClientSession = importClientSession(clientSession, true);
@@ -616,6 +626,11 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
offlineClientSession.setTimestamp(Time.currentTime());
return offlineClientSession;
+ }*/
+
+ @Override
+ public ClientLoginSessionModel createOfflineClientSession(ClientLoginSessionModel clientSession) {
+ return null;
}
@Override
@@ -624,27 +639,17 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
}
@Override
- public List<ClientSessionModel> getOfflineClientSessions(RealmModel realm, UserModel user) {
+ public List<UserSessionModel> getOfflineUserSessions(RealmModel realm, UserModel user) {
Iterator<Map.Entry<String, SessionEntity>> itr = offlineSessionCache.entrySet().stream().filter(UserSessionPredicate.create(realm.getId()).user(user.getId())).iterator();
- List<ClientSessionModel> clientSessions = new LinkedList<>();
+ List<UserSessionModel> userSessions = new LinkedList<>();
while(itr.hasNext()) {
UserSessionEntity entity = (UserSessionEntity) itr.next().getValue();
- Set<String> currClientSessions = entity.getClientSessions();
-
- if (currClientSessions == null) {
- continue;
- }
-
- for (String clientSessionId : currClientSessions) {
- ClientSessionEntity cls = (ClientSessionEntity) offlineSessionCache.get(clientSessionId);
- if (cls != null) {
- clientSessions.add(wrap(realm, cls, true));
- }
- }
+ UserSessionModel userSession = wrap(realm, entity, true);
+ userSessions.add(userSession);
}
- return clientSessions;
+ return userSessions;
}
@Override
@@ -695,7 +700,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
entity.setAction(clientSession.getAction());
entity.setAuthenticatorStatus(clientSession.getExecutionStatus());
- entity.setAuthMethod(clientSession.getAuthMethod());
+ entity.setAuthMethod(clientSession.getProtocol());
if (clientSession.getAuthenticatedUser() != null) {
entity.setAuthUserId(clientSession.getAuthenticatedUser().getId());
}
@@ -757,145 +762,4 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
return list;
}
-
- class InfinispanKeycloakTransaction implements KeycloakTransaction {
-
- private boolean active;
- private boolean rollback;
- private Map<Object, CacheTask> tasks = new HashMap<>();
-
- @Override
- public void begin() {
- active = true;
- }
-
- @Override
- public void commit() {
- if (rollback) {
- throw new RuntimeException("Rollback only!");
- }
-
- for (CacheTask task : tasks.values()) {
- task.execute();
- }
- }
-
- @Override
- public void rollback() {
- tasks.clear();
- }
-
- @Override
- public void setRollbackOnly() {
- rollback = true;
- }
-
- @Override
- public boolean getRollbackOnly() {
- return rollback;
- }
-
- @Override
- public boolean isActive() {
- return active;
- }
-
- public void put(Cache cache, Object key, Object value) {
- log.tracev("Adding cache operation: {0} on {1}", CacheOperation.ADD, key);
-
- Object taskKey = getTaskKey(cache, key);
- if (tasks.containsKey(taskKey)) {
- throw new IllegalStateException("Can't add session: task in progress for session");
- } else {
- tasks.put(taskKey, new CacheTask(cache, CacheOperation.ADD, key, value));
- }
- }
-
- public void replace(Cache cache, Object key, Object value) {
- log.tracev("Adding cache operation: {0} on {1}", CacheOperation.REPLACE, key);
-
- Object taskKey = getTaskKey(cache, key);
- CacheTask current = tasks.get(taskKey);
- if (current != null) {
- switch (current.operation) {
- case ADD:
- case REPLACE:
- current.value = value;
- return;
- case REMOVE:
- return;
- }
- } else {
- tasks.put(taskKey, new CacheTask(cache, CacheOperation.REPLACE, key, value));
- }
- }
-
- public void remove(Cache cache, Object key) {
- log.tracev("Adding cache operation: {0} on {1}", CacheOperation.REMOVE, key);
-
- Object taskKey = getTaskKey(cache, key);
- tasks.put(taskKey, new CacheTask(cache, CacheOperation.REMOVE, key, null));
- }
-
- // This is for possibility to lookup for session by id, which was created in this transaction
- public Object get(Cache cache, Object key) {
- Object taskKey = getTaskKey(cache, key);
- CacheTask current = tasks.get(taskKey);
- if (current != null) {
- switch (current.operation) {
- case ADD:
- case REPLACE:
- return current.value; }
- }
-
- return null;
- }
-
- private Object getTaskKey(Cache cache, Object key) {
- if (key instanceof String) {
- return new StringBuilder(cache.getName())
- .append("::")
- .append(key.toString()).toString();
- } else {
- // loginFailure cache
- return key;
- }
- }
-
- public class CacheTask {
- private Cache cache;
- private CacheOperation operation;
- private Object key;
- private Object value;
-
- public CacheTask(Cache cache, CacheOperation operation, Object key, Object value) {
- this.cache = cache;
- this.operation = operation;
- this.key = key;
- this.value = value;
- }
-
- public void execute() {
- log.tracev("Executing cache operation: {0} on {1}", operation, key);
-
- switch (operation) {
- case ADD:
- cache.put(key, value);
- break;
- case REMOVE:
- cache.remove(key);
- break;
- case REPLACE:
- cache.replace(key, value);
- break;
- }
- }
- }
-
- }
-
- public enum CacheOperation {
- ADD, REMOVE, REPLACE
- }
-
}
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/UserSessionAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/UserSessionAdapter.java
index bf1e6fd..6c81313 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/UserSessionAdapter.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/UserSessionAdapter.java
@@ -18,6 +18,7 @@
package org.keycloak.models.sessions.infinispan;
import org.infinispan.Cache;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
@@ -60,6 +61,12 @@ public class UserSessionAdapter implements UserSessionModel {
this.offline = offline;
}
+ // TODO;mposolda
+ @Override
+ public Map<String, ClientLoginSessionModel> getClientLoginSessions() {
+ return null;
+ }
+
public String getId() {
return entity.getId();
}
diff --git a/model/infinispan/src/main/java/org/keycloak/sessions/infinispan/InfinispanLoginSessionProvider.java b/model/infinispan/src/main/java/org/keycloak/sessions/infinispan/InfinispanLoginSessionProvider.java
new file mode 100644
index 0000000..8389424
--- /dev/null
+++ b/model/infinispan/src/main/java/org/keycloak/sessions/infinispan/InfinispanLoginSessionProvider.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.sessions.infinispan;
+
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.sessions.LoginSessionModel;
+import org.keycloak.sessions.LoginSessionProvider;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class InfinispanLoginSessionProvider implements LoginSessionProvider {
+
+ @Override
+ public LoginSessionModel createLoginSession(RealmModel realm, ClientModel client, boolean browser) {
+ return null;
+ }
+
+ @Override
+ public LoginSessionModel getCurrentLoginSession(RealmModel realm) {
+ return null;
+ }
+
+ @Override
+ public LoginSessionModel getLoginSession(RealmModel realm, String loginSessionId) {
+ return null;
+ }
+
+ @Override
+ public void removeLoginSession(RealmModel realm, LoginSessionModel loginSession) {
+
+ }
+
+ @Override
+ public void removeExpired(RealmModel realm) {
+
+ }
+
+ @Override
+ public void onRealmRemoved(RealmModel realm) {
+
+ }
+
+ @Override
+ public void onClientRemoved(RealmModel realm, ClientModel client) {
+
+ }
+
+ @Override
+ public void close() {
+
+ }
+}
diff --git a/model/infinispan/src/main/java/org/keycloak/sessions/infinispan/LoginSessionAdapter.java b/model/infinispan/src/main/java/org/keycloak/sessions/infinispan/LoginSessionAdapter.java
new file mode 100644
index 0000000..e8dda52
--- /dev/null
+++ b/model/infinispan/src/main/java/org/keycloak/sessions/infinispan/LoginSessionAdapter.java
@@ -0,0 +1,270 @@
+/*
+ * 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.sessions.infinispan;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.infinispan.Cache;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
+import org.keycloak.sessions.LoginSessionModel;
+
+/**
+ * NOTE: Calling setter doesn't automatically enlist for update
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class LoginSessionAdapter implements LoginSessionModel {
+
+ private KeycloakSession session;
+ private InfinispanLoginSessionProvider provider;
+ private Cache<String, SessionEntity> cache;
+ private RealmModel realm;
+ private LoginSessionEntity entity;
+
+ public LoginSessionAdapter(KeycloakSession session, InfinispanLoginSessionProvider provider, Cache<String, SessionEntity> cache, RealmModel realm,
+ LoginSessionEntity entity) {
+ this.session = session;
+ this.provider = provider;
+ this.cache = cache;
+ this.realm = realm;
+ this.entity = entity;
+ }
+
+ @Override
+ public String getId() {
+ return entity.getId();
+ }
+
+ @Override
+ public RealmModel getRealm() {
+ return realm;
+ }
+
+ @Override
+ public ClientModel getClient() {
+ return realm.getClientById(entity.getClientUuid());
+ }
+
+// @Override
+// public UserSessionAdapter getUserSession() {
+// return entity.getUserSession() != null ? provider.getUserSession(realm, entity.getUserSession(), offline) : null;
+// }
+//
+// @Override
+// public void setUserSession(UserSessionModel userSession) {
+// if (userSession == null) {
+// if (entity.getUserSession() != null) {
+// provider.dettachSession(getUserSession(), this);
+// }
+// entity.setUserSession(null);
+// } else {
+// UserSessionAdapter userSessionAdapter = (UserSessionAdapter) userSession;
+// if (entity.getUserSession() != null) {
+// if (entity.getUserSession().equals(userSession.getId())) {
+// return;
+// } else {
+// provider.dettachSession(userSessionAdapter, this);
+// }
+// } else {
+// provider.attachSession(userSessionAdapter, this);
+// }
+//
+// entity.setUserSession(userSession.getId());
+// }
+// }
+
+ @Override
+ public String getRedirectUri() {
+ return entity.getRedirectUri();
+ }
+
+ @Override
+ public void setRedirectUri(String uri) {
+ entity.setRedirectUri(uri);
+ }
+
+ @Override
+ public int getTimestamp() {
+ return entity.getTimestamp();
+ }
+
+ @Override
+ public void setTimestamp(int timestamp) {
+ entity.setTimestamp(timestamp);
+ }
+
+ @Override
+ public String getAction() {
+ return entity.getAction();
+ }
+
+ @Override
+ public void setAction(String action) {
+ entity.setAction(action);
+ }
+
+ @Override
+ public Set<String> getRoles() {
+ if (entity.getRoles() == null || entity.getRoles().isEmpty()) return Collections.emptySet();
+ return new HashSet<>(entity.getRoles());
+ }
+
+ @Override
+ public void setRoles(Set<String> roles) {
+ entity.setRoles(roles);
+ }
+
+ @Override
+ public Set<String> getProtocolMappers() {
+ if (entity.getProtocolMappers() == null || entity.getProtocolMappers().isEmpty()) return Collections.emptySet();
+ return new HashSet<>(entity.getProtocolMappers());
+ }
+
+ @Override
+ public void setProtocolMappers(Set<String> protocolMappers) {
+ entity.setProtocolMappers(protocolMappers);
+ }
+
+ @Override
+ public String getProtocol() {
+ return entity.getProtocol();
+ }
+
+ @Override
+ public void setProtocol(String protocol) {
+ entity.setProtocol(protocol);
+ }
+
+ @Override
+ public String getNote(String name) {
+ return entity.getNotes() != null ? entity.getNotes().get(name) : null;
+ }
+
+ @Override
+ public void setNote(String name, String value) {
+ if (entity.getNotes() == null) {
+ entity.setNotes(new HashMap<String, String>());
+ }
+ entity.getNotes().put(name, value);
+ }
+
+ @Override
+ public void removeNote(String name) {
+ if (entity.getNotes() != null) {
+ entity.getNotes().remove(name);
+ }
+ }
+
+ @Override
+ public Map<String, String> getNotes() {
+ if (entity.getNotes() == null || entity.getNotes().isEmpty()) return Collections.emptyMap();
+ Map<String, String> copy = new HashMap<>();
+ copy.putAll(entity.getNotes());
+ return copy;
+ }
+
+ @Override
+ public void setUserSessionNote(String name, String value) {
+ if (entity.getUserSessionNotes() == null) {
+ entity.setUserSessionNotes(new HashMap<String, String>());
+ }
+ entity.getUserSessionNotes().put(name, value);
+
+ }
+
+ @Override
+ public Map<String, String> getUserSessionNotes() {
+ if (entity.getUserSessionNotes() == null) {
+ return Collections.EMPTY_MAP;
+ }
+ HashMap<String, String> copy = new HashMap<>();
+ copy.putAll(entity.getUserSessionNotes());
+ return copy;
+ }
+
+ @Override
+ public void clearUserSessionNotes() {
+ entity.setUserSessionNotes(new HashMap<String, String>());
+
+ }
+
+ @Override
+ public Set<String> getRequiredActions() {
+ Set<String> copy = new HashSet<>();
+ copy.addAll(entity.getRequiredActions());
+ return copy;
+ }
+
+ @Override
+ public void addRequiredAction(String action) {
+ entity.getRequiredActions().add(action);
+
+ }
+
+ @Override
+ public void removeRequiredAction(String action) {
+ entity.getRequiredActions().remove(action);
+
+ }
+
+ @Override
+ public void addRequiredAction(UserModel.RequiredAction action) {
+ addRequiredAction(action.name());
+
+ }
+
+ @Override
+ public void removeRequiredAction(UserModel.RequiredAction action) {
+ removeRequiredAction(action.name());
+ }
+
+ @Override
+ public Map<String, LoginSessionModel.ExecutionStatus> getExecutionStatus() {
+ return entity.getExecutionStatus();
+ }
+
+ @Override
+ public void setExecutionStatus(String authenticator, LoginSessionModel.ExecutionStatus status) {
+ entity.getExecutionStatus().put(authenticator, status);
+
+ }
+
+ @Override
+ public void clearExecutionStatus() {
+ entity.getExecutionStatus().clear();
+ }
+
+ @Override
+ public UserModel getAuthenticatedUser() {
+ return entity.getAuthUserId() == null ? null : session.users().getUserById(entity.getAuthUserId(), realm); }
+
+ @Override
+ public void setAuthenticatedUser(UserModel user) {
+ if (user == null) entity.setAuthUserId(null);
+ else entity.setAuthUserId(user.getId());
+
+ }
+}
diff --git a/model/infinispan/src/main/java/org/keycloak/sessions/infinispan/LoginSessionEntity.java b/model/infinispan/src/main/java/org/keycloak/sessions/infinispan/LoginSessionEntity.java
new file mode 100644
index 0000000..97ccad4
--- /dev/null
+++ b/model/infinispan/src/main/java/org/keycloak/sessions/infinispan/LoginSessionEntity.java
@@ -0,0 +1,142 @@
+/*
+ * 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.sessions.infinispan;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
+import org.keycloak.sessions.LoginSessionModel;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class LoginSessionEntity extends SessionEntity {
+
+ private String clientUuid;
+ private String authUserId;
+
+ private String redirectUri;
+ private int timestamp;
+ private String action;
+ private Set<String> roles;
+ private Set<String> protocolMappers;
+
+ private Map<String, LoginSessionModel.ExecutionStatus> executionStatus;
+ private String protocol;
+
+ private Map<String, String> notes;
+ private Set<String> requiredActions;
+ private Map<String, String> userSessionNotes;
+
+ public String getClientUuid() {
+ return clientUuid;
+ }
+
+ public void setClientUuid(String clientUuid) {
+ this.clientUuid = clientUuid;
+ }
+
+ public String getAuthUserId() {
+ return authUserId;
+ }
+
+ public void setAuthUserId(String authUserId) {
+ this.authUserId = authUserId;
+ }
+
+ public String getRedirectUri() {
+ return redirectUri;
+ }
+
+ public void setRedirectUri(String redirectUri) {
+ this.redirectUri = redirectUri;
+ }
+
+ public int getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(int timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public String getAction() {
+ return action;
+ }
+
+ public void setAction(String action) {
+ this.action = action;
+ }
+
+ public Set<String> getRoles() {
+ return roles;
+ }
+
+ public void setRoles(Set<String> roles) {
+ this.roles = roles;
+ }
+
+ public Set<String> getProtocolMappers() {
+ return protocolMappers;
+ }
+
+ public void setProtocolMappers(Set<String> protocolMappers) {
+ this.protocolMappers = protocolMappers;
+ }
+
+ public Map<String, LoginSessionModel.ExecutionStatus> getExecutionStatus() {
+ return executionStatus;
+ }
+
+ public void setExecutionStatus(Map<String, LoginSessionModel.ExecutionStatus> executionStatus) {
+ this.executionStatus = executionStatus;
+ }
+
+ public String getProtocol() {
+ return protocol;
+ }
+
+ public void setProtocol(String protocol) {
+ this.protocol = protocol;
+ }
+
+ public Map<String, String> getNotes() {
+ return notes;
+ }
+
+ public void setNotes(Map<String, String> notes) {
+ this.notes = notes;
+ }
+
+ public Set<String> getRequiredActions() {
+ return requiredActions;
+ }
+
+ public void setRequiredActions(Set<String> requiredActions) {
+ this.requiredActions = requiredActions;
+ }
+
+ public Map<String, String> getUserSessionNotes() {
+ return userSessionNotes;
+ }
+
+ public void setUserSessionNotes(Map<String, String> userSessionNotes) {
+ this.userSessionNotes = userSessionNotes;
+ }
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/session/JpaUserSessionPersisterProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/session/JpaUserSessionPersisterProvider.java
index b3aea63..e842948 100644
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/session/JpaUserSessionPersisterProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/session/JpaUserSessionPersisterProvider.java
@@ -17,6 +17,7 @@
package org.keycloak.models.jpa.session;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
@@ -68,7 +69,7 @@ public class JpaUserSessionPersisterProvider implements UserSessionPersisterProv
}
@Override
- public void createClientSession(ClientSessionModel clientSession, boolean offline) {
+ public void createClientSession(UserSessionModel userSession, ClientLoginSessionModel clientSession, boolean offline) {
PersistentClientSessionAdapter adapter = new PersistentClientSessionAdapter(clientSession);
PersistentClientSessionModel model = adapter.getUpdatedModel();
@@ -217,6 +218,8 @@ public class JpaUserSessionPersisterProvider implements UserSessionPersisterProv
userSessionIds.add(entity.getUserSessionId());
}
+ // TODO:mposolda
+ /*
if (!userSessionIds.isEmpty()) {
TypedQuery<PersistentClientSessionEntity> query2 = em.createNamedQuery("findClientSessionsByUserSessions", PersistentClientSessionEntity.class);
query2.setParameter("userSessionIds", userSessionIds);
@@ -242,6 +245,7 @@ public class JpaUserSessionPersisterProvider implements UserSessionPersisterProv
}
}
}
+ */
return result;
}
diff --git a/server-spi/src/main/java/org/keycloak/models/ClientLoginSessionModel.java b/server-spi/src/main/java/org/keycloak/models/ClientLoginSessionModel.java
new file mode 100644
index 0000000..80d7c8d
--- /dev/null
+++ b/server-spi/src/main/java/org/keycloak/models/ClientLoginSessionModel.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.models;
+
+
+import org.keycloak.sessions.CommonClientSessionModel;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public interface ClientLoginSessionModel extends CommonClientSessionModel {
+
+ void setUserSession(UserSessionModel userSession);
+ UserSessionModel getUserSession();
+}
diff --git a/server-spi/src/main/java/org/keycloak/models/ClientSessionModel.java b/server-spi/src/main/java/org/keycloak/models/ClientSessionModel.java
index 84fa64e..109709f 100755
--- a/server-spi/src/main/java/org/keycloak/models/ClientSessionModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/ClientSessionModel.java
@@ -20,14 +20,12 @@ package org.keycloak.models;
import java.util.Map;
import java.util.Set;
+import org.keycloak.sessions.CommonClientSessionModel;
+
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
-public interface ClientSessionModel {
-
- public String getId();
- public RealmModel getRealm();
- public ClientModel getClient();
+public interface ClientSessionModel extends CommonClientSessionModel {
public UserSessionModel getUserSession();
public void setUserSession(UserSessionModel userSession);
@@ -35,41 +33,12 @@ public interface ClientSessionModel {
public String getRedirectUri();
public void setRedirectUri(String uri);
- public int getTimestamp();
-
- public void setTimestamp(int timestamp);
-
- public String getAction();
-
- public void setAction(String action);
-
- public Set<String> getRoles();
- public void setRoles(Set<String> roles);
-
- public Set<String> getProtocolMappers();
- public void setProtocolMappers(Set<String> protocolMappers);
-
public Map<String, ExecutionStatus> getExecutionStatus();
public void setExecutionStatus(String authenticator, ExecutionStatus status);
public void clearExecutionStatus();
public UserModel getAuthenticatedUser();
public void setAuthenticatedUser(UserModel user);
-
-
- /**
- * Authentication request type, i.e. OAUTH, SAML 2.0, SAML 1.1, etc.
- *
- * @return
- */
- public String getAuthMethod();
- public void setAuthMethod(String method);
-
- public String getNote(String name);
- public void setNote(String name, String value);
- public void removeNote(String name);
- public Map<String, String> getNotes();
-
/**
* Required actions that are attached to this client session.
*
@@ -103,28 +72,5 @@ public interface ClientSessionModel {
public void clearUserSessionNotes();
- public static enum Action {
- OAUTH_GRANT,
- CODE_TO_TOKEN,
- VERIFY_EMAIL,
- UPDATE_PROFILE,
- CONFIGURE_TOTP,
- UPDATE_PASSWORD,
- RECOVER_PASSWORD, // deprecated
- AUTHENTICATE,
- SOCIAL_CALLBACK,
- LOGGED_OUT,
- RESET_CREDENTIALS,
- EXECUTE_ACTIONS,
- REQUIRED_ACTIONS
- }
-
- public enum ExecutionStatus {
- FAILED,
- SUCCESS,
- SETUP_REQUIRED,
- ATTEMPTED,
- SKIPPED,
- CHALLENGED
- }
+
}
diff --git a/server-spi/src/main/java/org/keycloak/models/KeycloakSession.java b/server-spi/src/main/java/org/keycloak/models/KeycloakSession.java
index 766078d..1494126 100755
--- a/server-spi/src/main/java/org/keycloak/models/KeycloakSession.java
+++ b/server-spi/src/main/java/org/keycloak/models/KeycloakSession.java
@@ -20,6 +20,7 @@ package org.keycloak.models;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.cache.UserCache;
import org.keycloak.provider.Provider;
+import org.keycloak.sessions.LoginSessionProvider;
import org.keycloak.storage.federated.UserFederatedStorageProvider;
import java.util.Set;
@@ -102,6 +103,9 @@ public interface KeycloakSession {
UserSessionProvider sessions();
+ LoginSessionProvider loginSessions();
+
+
void close();
diff --git a/server-spi/src/main/java/org/keycloak/models/UserSessionModel.java b/server-spi/src/main/java/org/keycloak/models/UserSessionModel.java
index d58c405..99f69f7 100755
--- a/server-spi/src/main/java/org/keycloak/models/UserSessionModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/UserSessionModel.java
@@ -53,6 +53,9 @@ public interface UserSessionModel {
void setLastSessionRefresh(int seconds);
+ Map<String, ClientLoginSessionModel> getClientLoginSessions();
+
+ // TODO: Remove
List<ClientSessionModel> getClientSessions();
public String getNote(String name);
@@ -64,7 +67,7 @@ public interface UserSessionModel {
void setState(State state);
public static enum State {
- LOGGING_IN,
+ LOGGING_IN, // TODO: Maybe state "LOGGING_IN" is useless now once userSession is attached after requiredActions
LOGGED_IN,
LOGGING_OUT,
LOGGED_OUT
diff --git a/server-spi/src/main/java/org/keycloak/models/UserSessionProvider.java b/server-spi/src/main/java/org/keycloak/models/UserSessionProvider.java
index 4102de1..fbd5761 100755
--- a/server-spi/src/main/java/org/keycloak/models/UserSessionProvider.java
+++ b/server-spi/src/main/java/org/keycloak/models/UserSessionProvider.java
@@ -27,7 +27,7 @@ import java.util.List;
*/
public interface UserSessionProvider extends Provider {
- ClientSessionModel createClientSession(RealmModel realm, ClientModel client);
+ ClientLoginSessionModel createClientSession(RealmModel realm, ClientModel client, UserSessionModel userSession);
ClientSessionModel getClientSession(RealmModel realm, String id);
ClientSessionModel getClientSession(String id);
@@ -40,6 +40,8 @@ public interface UserSessionProvider extends Provider {
UserSessionModel getUserSessionByBrokerSessionId(RealmModel realm, String brokerSessionId);
long getActiveUserSessions(RealmModel realm, ClientModel client);
+
+ // This will remove attached ClientLoginSessionModels too
void removeUserSession(RealmModel realm, UserSessionModel session);
void removeUserSessions(RealmModel realm, UserModel user);
@@ -62,9 +64,9 @@ public interface UserSessionProvider extends Provider {
// Removes the attached clientSessions as well
void removeOfflineUserSession(RealmModel realm, UserSessionModel userSession);
- ClientSessionModel createOfflineClientSession(ClientSessionModel clientSession);
+ ClientLoginSessionModel createOfflineClientSession(ClientLoginSessionModel clientSession);
ClientSessionModel getOfflineClientSession(RealmModel realm, String clientSessionId);
- List<ClientSessionModel> getOfflineClientSessions(RealmModel realm, UserModel user);
+ List<UserSessionModel> getOfflineUserSessions(RealmModel realm, UserModel user);
// Don't remove userSession even if it's last userSession
void removeOfflineClientSession(RealmModel realm, String clientSessionId);
diff --git a/server-spi/src/main/java/org/keycloak/sessions/CommonClientSessionModel.java b/server-spi/src/main/java/org/keycloak/sessions/CommonClientSessionModel.java
new file mode 100644
index 0000000..c2e5193
--- /dev/null
+++ b/server-spi/src/main/java/org/keycloak/sessions/CommonClientSessionModel.java
@@ -0,0 +1,86 @@
+/*
+ * 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.sessions;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.RealmModel;
+
+/**
+ * Predecesor of LoginSessionModel, ClientLoginSessionModel and ClientSessionModel (then action tickets). Maybe we will remove it later...
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public interface CommonClientSessionModel {
+
+ public String getRedirectUri();
+ public void setRedirectUri(String uri);
+
+ public String getId();
+ public RealmModel getRealm();
+ public ClientModel getClient();
+
+ public int getTimestamp();
+ public void setTimestamp(int timestamp);
+
+ public String getAction();
+ public void setAction(String action);
+
+ public String getProtocol();
+ public void setProtocol(String method);
+
+ // TODO: Not needed here...?
+ public Set<String> getRoles();
+ public void setRoles(Set<String> roles);
+
+ // TODO: Not needed here...?
+ public Set<String> getProtocolMappers();
+ public void setProtocolMappers(Set<String> protocolMappers);
+
+ public String getNote(String name);
+ public void setNote(String name, String value);
+ public void removeNote(String name);
+ public Map<String, String> getNotes();
+
+ public static enum Action {
+ OAUTH_GRANT,
+ CODE_TO_TOKEN,
+ VERIFY_EMAIL,
+ UPDATE_PROFILE,
+ CONFIGURE_TOTP,
+ UPDATE_PASSWORD,
+ RECOVER_PASSWORD, // deprecated
+ AUTHENTICATE,
+ SOCIAL_CALLBACK,
+ LOGGED_OUT,
+ RESET_CREDENTIALS,
+ EXECUTE_ACTIONS,
+ REQUIRED_ACTIONS
+ }
+
+ public enum ExecutionStatus {
+ FAILED,
+ SUCCESS,
+ SETUP_REQUIRED,
+ ATTEMPTED,
+ SKIPPED,
+ CHALLENGED
+ }
+}
diff --git a/server-spi/src/main/java/org/keycloak/sessions/LoginSessionModel.java b/server-spi/src/main/java/org/keycloak/sessions/LoginSessionModel.java
new file mode 100644
index 0000000..e3fd0e7
--- /dev/null
+++ b/server-spi/src/main/java/org/keycloak/sessions/LoginSessionModel.java
@@ -0,0 +1,76 @@
+/*
+ * 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.sessions;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.keycloak.models.UserModel;
+
+/**
+ * Using class for now to avoid many updates among implementations
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public interface LoginSessionModel extends CommonClientSessionModel {
+
+//
+// public UserSessionModel getUserSession();
+// public void setUserSession(UserSessionModel userSession);
+
+
+ public Map<String, ExecutionStatus> getExecutionStatus();
+ public void setExecutionStatus(String authenticator, ExecutionStatus status);
+ public void clearExecutionStatus();
+ public UserModel getAuthenticatedUser();
+ public void setAuthenticatedUser(UserModel user);
+
+ /**
+ * Required actions that are attached to this client session.
+ *
+ * @return
+ */
+ Set<String> getRequiredActions();
+
+ void addRequiredAction(String action);
+
+ void removeRequiredAction(String action);
+
+ void addRequiredAction(UserModel.RequiredAction action);
+
+ void removeRequiredAction(UserModel.RequiredAction action);
+
+
+ /**
+ * These are notes you want applied to the UserSessionModel when the client session is attached to it.
+ *
+ * @param name
+ * @param value
+ */
+ public void setUserSessionNote(String name, String value);
+
+ /**
+ * These are notes you want applied to the UserSessionModel when the client session is attached to it.
+ *
+ * @return
+ */
+ public Map<String, String> getUserSessionNotes();
+
+ public void clearUserSessionNotes();
+
+}
diff --git a/server-spi/src/main/java/org/keycloak/sessions/LoginSessionProvider.java b/server-spi/src/main/java/org/keycloak/sessions/LoginSessionProvider.java
new file mode 100644
index 0000000..2b5141a
--- /dev/null
+++ b/server-spi/src/main/java/org/keycloak/sessions/LoginSessionProvider.java
@@ -0,0 +1,43 @@
+/*
+ * 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.sessions;
+
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.provider.Provider;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public interface LoginSessionProvider extends Provider {
+
+ LoginSessionModel createLoginSession(RealmModel realm, ClientModel client, boolean browser);
+
+ LoginSessionModel getCurrentLoginSession(RealmModel realm);
+
+ LoginSessionModel getLoginSession(RealmModel realm, String loginSessionId);
+
+ void removeLoginSession(RealmModel realm, LoginSessionModel loginSession);
+
+
+ void removeExpired(RealmModel realm);
+ void onRealmRemoved(RealmModel realm);
+ void onClientRemoved(RealmModel realm, ClientModel client);
+
+
+}
diff --git a/server-spi-private/src/main/java/org/keycloak/authentication/AuthenticationFlowContext.java b/server-spi-private/src/main/java/org/keycloak/authentication/AuthenticationFlowContext.java
index 98632fb..80c7575 100755
--- a/server-spi-private/src/main/java/org/keycloak/authentication/AuthenticationFlowContext.java
+++ b/server-spi-private/src/main/java/org/keycloak/authentication/AuthenticationFlowContext.java
@@ -22,6 +22,7 @@ import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.utils.FormMessage;
+import org.keycloak.sessions.LoginSessionModel;
import java.net.URI;
@@ -62,7 +63,7 @@ public interface AuthenticationFlowContext extends AbstractAuthenticationFlowCon
*
* @return
*/
- ClientSessionModel getClientSession();
+ LoginSessionModel getLoginSession();
/**
* Create a Freemarker form builder that presets the user, action URI, and a generated access code
diff --git a/server-spi-private/src/main/java/org/keycloak/authentication/FormContext.java b/server-spi-private/src/main/java/org/keycloak/authentication/FormContext.java
index 7c7d143..b131c20 100755
--- a/server-spi-private/src/main/java/org/keycloak/authentication/FormContext.java
+++ b/server-spi-private/src/main/java/org/keycloak/authentication/FormContext.java
@@ -26,6 +26,7 @@ import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
+import org.keycloak.sessions.LoginSessionModel;
import javax.ws.rs.core.UriInfo;
@@ -79,11 +80,11 @@ public interface FormContext {
RealmModel getRealm();
/**
- * ClientSessionModel attached to this flow
+ * LoginSessionModel attached to this flow
*
* @return
*/
- ClientSessionModel getClientSession();
+ LoginSessionModel getLoginSession();
/**
* Information about the IP address from the connecting HTTP client.
diff --git a/server-spi-private/src/main/java/org/keycloak/authentication/RequiredActionContext.java b/server-spi-private/src/main/java/org/keycloak/authentication/RequiredActionContext.java
index 3ece79e..df0bc66 100755
--- a/server-spi-private/src/main/java/org/keycloak/authentication/RequiredActionContext.java
+++ b/server-spi-private/src/main/java/org/keycloak/authentication/RequiredActionContext.java
@@ -26,6 +26,7 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
+import org.keycloak.sessions.LoginSessionModel;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
@@ -90,8 +91,7 @@ public interface RequiredActionContext {
*/
UserModel getUser();
RealmModel getRealm();
- ClientSessionModel getClientSession();
- UserSessionModel getUserSession();
+ LoginSessionModel getLoginSession();
ClientConnection getConnection();
UriInfo getUriInfo();
KeycloakSession getSession();
diff --git a/server-spi-private/src/main/java/org/keycloak/broker/provider/BrokeredIdentityContext.java b/server-spi-private/src/main/java/org/keycloak/broker/provider/BrokeredIdentityContext.java
index f2c8a7a..bcce1b8 100755
--- a/server-spi-private/src/main/java/org/keycloak/broker/provider/BrokeredIdentityContext.java
+++ b/server-spi-private/src/main/java/org/keycloak/broker/provider/BrokeredIdentityContext.java
@@ -19,6 +19,7 @@ package org.keycloak.broker.provider;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.Constants;
import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.sessions.LoginSessionModel;
import java.util.ArrayList;
import java.util.HashMap;
@@ -46,7 +47,7 @@ public class BrokeredIdentityContext {
private IdentityProviderModel idpConfig;
private IdentityProvider idp;
private Map<String, Object> contextData = new HashMap<>();
- private ClientSessionModel clientSession;
+ private LoginSessionModel loginSession;
public BrokeredIdentityContext(String id) {
if (id == null) {
@@ -190,12 +191,12 @@ public class BrokeredIdentityContext {
this.lastName = lastName;
}
- public ClientSessionModel getClientSession() {
- return clientSession;
+ public LoginSessionModel getLoginSession() {
+ return loginSession;
}
- public void setClientSession(ClientSessionModel clientSession) {
- this.clientSession = clientSession;
+ public void setLoginSession(LoginSessionModel loginSession) {
+ this.loginSession = loginSession;
}
public void setName(String name) {
diff --git a/server-spi-private/src/main/java/org/keycloak/forms/login/LoginFormsProvider.java b/server-spi-private/src/main/java/org/keycloak/forms/login/LoginFormsProvider.java
index f16f0c2..a379e9d 100755
--- a/server-spi-private/src/main/java/org/keycloak/forms/login/LoginFormsProvider.java
+++ b/server-spi-private/src/main/java/org/keycloak/forms/login/LoginFormsProvider.java
@@ -17,12 +17,12 @@
package org.keycloak.forms.login;
-import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.FormMessage;
import org.keycloak.provider.Provider;
+import org.keycloak.sessions.LoginSessionModel;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
@@ -70,13 +70,13 @@ public interface LoginFormsProvider extends Provider {
public Response createErrorPage();
- public Response createOAuthGrant(ClientSessionModel clientSessionModel);
+ public Response createOAuthGrant();
public Response createCode();
public LoginFormsProvider setClientSessionCode(String accessCode);
- public LoginFormsProvider setClientSession(ClientSessionModel clientSession);
+ public LoginFormsProvider setLoginSession(LoginSessionModel loginSession);
public LoginFormsProvider setAccessRequest(List<RoleModel> realmRolesRequested, MultivaluedMap<String,RoleModel> resourceRolesRequested, List<ProtocolMapperModel> protocolMappers);
public LoginFormsProvider setAccessRequest(String message);
diff --git a/server-spi-private/src/main/java/org/keycloak/models/session/DisabledUserSessionPersisterProvider.java b/server-spi-private/src/main/java/org/keycloak/models/session/DisabledUserSessionPersisterProvider.java
index f5e58d3..c860ea3 100644
--- a/server-spi-private/src/main/java/org/keycloak/models/session/DisabledUserSessionPersisterProvider.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/session/DisabledUserSessionPersisterProvider.java
@@ -18,6 +18,7 @@
package org.keycloak.models.session;
import org.keycloak.Config;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
@@ -70,7 +71,7 @@ public class DisabledUserSessionPersisterProvider implements UserSessionPersiste
}
@Override
- public void createClientSession(ClientSessionModel clientSession, boolean offline) {
+ public void createClientSession(UserSessionModel userSession, ClientLoginSessionModel clientSession, boolean offline) {
}
diff --git a/server-spi-private/src/main/java/org/keycloak/models/session/PersistentClientSessionAdapter.java b/server-spi-private/src/main/java/org/keycloak/models/session/PersistentClientSessionAdapter.java
index f842787..7194382 100644
--- a/server-spi-private/src/main/java/org/keycloak/models/session/PersistentClientSessionAdapter.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/session/PersistentClientSessionAdapter.java
@@ -18,6 +18,7 @@
package org.keycloak.models.session;
import com.fasterxml.jackson.annotation.JsonProperty;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.ModelException;
@@ -36,7 +37,7 @@ import java.util.Set;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
-public class PersistentClientSessionAdapter implements ClientSessionModel {
+public class PersistentClientSessionAdapter implements ClientLoginSessionModel {
private final PersistentClientSessionModel model;
private final RealmModel realm;
@@ -45,22 +46,20 @@ public class PersistentClientSessionAdapter implements ClientSessionModel {
private PersistentClientSessionData data;
- public PersistentClientSessionAdapter(ClientSessionModel clientSession) {
+ public PersistentClientSessionAdapter(ClientLoginSessionModel clientSession) {
data = new PersistentClientSessionData();
data.setAction(clientSession.getAction());
- data.setAuthMethod(clientSession.getAuthMethod());
- data.setExecutionStatus(clientSession.getExecutionStatus());
+ data.setAuthMethod(clientSession.getProtocol());
data.setNotes(clientSession.getNotes());
data.setProtocolMappers(clientSession.getProtocolMappers());
data.setRedirectUri(clientSession.getRedirectUri());
data.setRoles(clientSession.getRoles());
- data.setUserSessionNotes(clientSession.getUserSessionNotes());
model = new PersistentClientSessionModel();
model.setClientId(clientSession.getClient().getId());
model.setClientSessionId(clientSession.getId());
- if (clientSession.getAuthenticatedUser() != null) {
- model.setUserId(clientSession.getAuthenticatedUser().getId());
+ if (clientSession.getUserSession() != null) {
+ model.setUserId(clientSession.getUserSession().getUser().getId());
}
model.setUserSessionId(clientSession.getUserSession().getId());
model.setTimestamp(clientSession.getTimestamp());
@@ -178,37 +177,12 @@ public class PersistentClientSessionAdapter implements ClientSessionModel {
}
@Override
- public Map<String, ExecutionStatus> getExecutionStatus() {
- return getData().getExecutionStatus();
- }
-
- @Override
- public void setExecutionStatus(String authenticator, ExecutionStatus status) {
- getData().getExecutionStatus().put(authenticator, status);
- }
-
- @Override
- public void clearExecutionStatus() {
- getData().getExecutionStatus().clear();
- }
-
- @Override
- public UserModel getAuthenticatedUser() {
- return userSession.getUser();
- }
-
- @Override
- public void setAuthenticatedUser(UserModel user) {
- throw new IllegalStateException("Not supported setAuthenticatedUser");
- }
-
- @Override
- public String getAuthMethod() {
+ public String getProtocol() {
return getData().getAuthMethod();
}
@Override
- public void setAuthMethod(String method) {
+ public void setProtocol(String method) {
getData().setAuthMethod(method);
}
@@ -242,52 +216,6 @@ public class PersistentClientSessionAdapter implements ClientSessionModel {
return entity.getNotes();
}
- @Override
- public Set<String> getRequiredActions() {
- return getData().getRequiredActions();
- }
-
- @Override
- public void addRequiredAction(String action) {
- getData().getRequiredActions().add(action);
- }
-
- @Override
- public void removeRequiredAction(String action) {
- getData().getRequiredActions().remove(action);
- }
-
- @Override
- public void addRequiredAction(UserModel.RequiredAction action) {
- addRequiredAction(action.name());
- }
-
- @Override
- public void removeRequiredAction(UserModel.RequiredAction action) {
- removeRequiredAction(action.name());
- }
-
- @Override
- public void setUserSessionNote(String name, String value) {
- PersistentClientSessionData entity = getData();
- if (entity.getUserSessionNotes() == null) {
- entity.setUserSessionNotes(new HashMap<String, String>());
- }
- entity.getUserSessionNotes().put(name, value);
- }
-
- @Override
- public Map<String, String> getUserSessionNotes() {
- PersistentClientSessionData entity = getData();
- if (entity.getUserSessionNotes() == null || entity.getUserSessionNotes().isEmpty()) return Collections.emptyMap();
- return entity.getUserSessionNotes();
- }
-
- @Override
- public void clearUserSessionNotes() {
- PersistentClientSessionData entity = getData();
- entity.setUserSessionNotes(new HashMap<String, String>());
- }
@Override
public boolean equals(Object o) {
@@ -320,18 +248,9 @@ public class PersistentClientSessionAdapter implements ClientSessionModel {
@JsonProperty("notes")
private Map<String, String> notes;
- @JsonProperty("userSessionNotes")
- private Map<String, String> userSessionNotes;
-
- @JsonProperty("executionStatus")
- private Map<String, ClientSessionModel.ExecutionStatus> executionStatus = new HashMap<>();
-
@JsonProperty("action")
private String action;
- @JsonProperty("requiredActions")
- private Set<String> requiredActions = new HashSet<>();
-
public String getAuthMethod() {
return authMethod;
}
@@ -372,22 +291,6 @@ public class PersistentClientSessionAdapter implements ClientSessionModel {
this.notes = notes;
}
- public Map<String, String> getUserSessionNotes() {
- return userSessionNotes;
- }
-
- public void setUserSessionNotes(Map<String, String> userSessionNotes) {
- this.userSessionNotes = userSessionNotes;
- }
-
- public Map<String, ClientSessionModel.ExecutionStatus> getExecutionStatus() {
- return executionStatus;
- }
-
- public void setExecutionStatus(Map<String, ClientSessionModel.ExecutionStatus> executionStatus) {
- this.executionStatus = executionStatus;
- }
-
public String getAction() {
return action;
}
@@ -396,12 +299,5 @@ public class PersistentClientSessionAdapter implements ClientSessionModel {
this.action = action;
}
- public Set<String> getRequiredActions() {
- return requiredActions;
- }
-
- public void setRequiredActions(Set<String> requiredActions) {
- this.requiredActions = requiredActions;
- }
}
}
diff --git a/server-spi-private/src/main/java/org/keycloak/models/session/PersistentUserSessionAdapter.java b/server-spi-private/src/main/java/org/keycloak/models/session/PersistentUserSessionAdapter.java
index 6047be2..882dd53 100644
--- a/server-spi-private/src/main/java/org/keycloak/models/session/PersistentUserSessionAdapter.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/session/PersistentUserSessionAdapter.java
@@ -18,6 +18,7 @@
package org.keycloak.models.session;
import com.fasterxml.jackson.annotation.JsonProperty;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.ModelException;
import org.keycloak.models.RealmModel;
@@ -159,6 +160,12 @@ public class PersistentUserSessionAdapter implements UserSessionModel {
return clientSessions;
}
+ // TODO:mposolda
+ @Override
+ public Map<String, ClientLoginSessionModel> getClientLoginSessions() {
+ return null;
+ }
+
@Override
public String getNote(String name) {
return getData().getNotes()==null ? null : getData().getNotes().get(name);
diff --git a/server-spi-private/src/main/java/org/keycloak/models/session/UserSessionPersisterProvider.java b/server-spi-private/src/main/java/org/keycloak/models/session/UserSessionPersisterProvider.java
index c0d033a..cbaf31e 100644
--- a/server-spi-private/src/main/java/org/keycloak/models/session/UserSessionPersisterProvider.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/session/UserSessionPersisterProvider.java
@@ -17,8 +17,8 @@
package org.keycloak.models.session;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
@@ -35,7 +35,7 @@ public interface UserSessionPersisterProvider extends Provider {
void createUserSession(UserSessionModel userSession, boolean offline);
// Assuming that corresponding userSession is already persisted
- void createClientSession(ClientSessionModel clientSession, boolean offline);
+ void createClientSession(UserSessionModel userSession, ClientLoginSessionModel clientSession, boolean offline);
void updateUserSession(UserSessionModel userSession, boolean offline);
diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index e901929..3ebe6d3 100755
--- a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -45,6 +45,7 @@ import org.keycloak.events.admin.AuthDetails;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.AuthenticationFlowModel;
import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.ClientTemplateModel;
@@ -485,7 +486,7 @@ public class ModelToRepresentation {
rep.setUsername(session.getUser().getUsername());
rep.setUserId(session.getUser().getId());
rep.setIpAddress(session.getIpAddress());
- for (ClientSessionModel clientSession : session.getClientSessions()) {
+ for (ClientLoginSessionModel clientSession : session.getClientLoginSessions().values()) {
ClientModel client = clientSession.getClient();
rep.getClients().put(client.getId(), client.getClientId());
}
diff --git a/server-spi-private/src/main/java/org/keycloak/protocol/LoginProtocol.java b/server-spi-private/src/main/java/org/keycloak/protocol/LoginProtocol.java
index 086a8ed..015ead0 100755
--- a/server-spi-private/src/main/java/org/keycloak/protocol/LoginProtocol.java
+++ b/server-spi-private/src/main/java/org/keycloak/protocol/LoginProtocol.java
@@ -18,12 +18,14 @@
package org.keycloak.protocol;
import org.keycloak.events.EventBuilder;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.provider.Provider;
import org.keycloak.services.managers.ClientSessionCode;
+import org.keycloak.sessions.LoginSessionModel;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
@@ -66,19 +68,19 @@ public interface LoginProtocol extends Provider {
LoginProtocol setEventBuilder(EventBuilder event);
- Response authenticated(UserSessionModel userSession, ClientSessionCode accessCode);
+ Response authenticated(UserSessionModel userSession, ClientSessionCode<ClientLoginSessionModel> accessCode);
- Response sendError(ClientSessionModel clientSession, Error error);
+ Response sendError(LoginSessionModel loginSession, Error error);
- void backchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession);
- Response frontchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession);
+ void backchannelLogout(UserSessionModel userSession, ClientLoginSessionModel clientSession);
+ Response frontchannelLogout(UserSessionModel userSession, ClientLoginSessionModel clientSession);
Response finishLogout(UserSessionModel userSession);
/**
* @param userSession
- * @param clientSession
+ * @param loginSession
* @return true if SSO cookie authentication can't be used. User will need to "actively" reauthenticate
*/
- boolean requireReauthentication(UserSessionModel userSession, ClientSessionModel clientSession);
+ boolean requireReauthentication(UserSessionModel userSession, LoginSessionModel loginSession);
}
diff --git a/server-spi-private/src/main/java/org/keycloak/services/managers/ClientSessionCode.java b/server-spi-private/src/main/java/org/keycloak/services/managers/ClientSessionCode.java
index 3d536dd..4096924 100755
--- a/server-spi-private/src/main/java/org/keycloak/services/managers/ClientSessionCode.java
+++ b/server-spi-private/src/main/java/org/keycloak/services/managers/ClientSessionCode.java
@@ -21,7 +21,6 @@ import org.jboss.logging.Logger;
import org.keycloak.common.util.Base64Url;
import org.keycloak.common.util.Time;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
@@ -29,6 +28,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.OAuth2Constants;
+import org.keycloak.sessions.CommonClientSessionModel;
import java.security.MessageDigest;
import java.util.HashSet;
@@ -38,7 +38,7 @@ import java.util.Set;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
-public class ClientSessionCode {
+public class ClientSessionCode<CLIENT_SESSION extends CommonClientSessionModel> {
private static final String ACTIVE_CODE = "active_code";
@@ -48,7 +48,7 @@ public class ClientSessionCode {
private KeycloakSession session;
private final RealmModel realm;
- private final ClientSessionModel clientSession;
+ private final CLIENT_SESSION commonLoginSession;
public enum ActionType {
CLIENT,
@@ -56,45 +56,45 @@ public class ClientSessionCode {
USER
}
- public ClientSessionCode(KeycloakSession session, RealmModel realm, ClientSessionModel clientSession) {
+ public ClientSessionCode(KeycloakSession session, RealmModel realm, CLIENT_SESSION commonLoginSession) {
this.session = session;
this.realm = realm;
- this.clientSession = clientSession;
+ this.commonLoginSession = commonLoginSession;
}
- public static class ParseResult {
- ClientSessionCode code;
- boolean clientSessionNotFound;
+ public static class ParseResult<CLIENT_SESSION extends CommonClientSessionModel> {
+ ClientSessionCode<CLIENT_SESSION> code;
+ boolean loginSessionNotFound;
boolean illegalHash;
- ClientSessionModel clientSession;
+ CLIENT_SESSION clientSession;
- public ClientSessionCode getCode() {
+ public ClientSessionCode<CLIENT_SESSION> getCode() {
return code;
}
- public boolean isClientSessionNotFound() {
- return clientSessionNotFound;
+ public boolean isLoginSessionNotFound() {
+ return loginSessionNotFound;
}
public boolean isIllegalHash() {
return illegalHash;
}
- public ClientSessionModel getClientSession() {
+ public CLIENT_SESSION getClientSession() {
return clientSession;
}
}
- public static ParseResult parseResult(String code, KeycloakSession session, RealmModel realm) {
- ParseResult result = new ParseResult();
+ public static <CLIENT_SESSION extends CommonClientSessionModel> ParseResult<CLIENT_SESSION> parseResult(String code, KeycloakSession session, RealmModel realm, Class<CLIENT_SESSION> sessionClass) {
+ ParseResult<CLIENT_SESSION> result = new ParseResult<>();
if (code == null) {
result.illegalHash = true;
return result;
}
try {
- result.clientSession = getClientSession(code, session, realm);
+ result.clientSession = getClientSession(code, session, realm, sessionClass);
if (result.clientSession == null) {
- result.clientSessionNotFound = true;
+ result.loginSessionNotFound = true;
return result;
}
@@ -103,7 +103,7 @@ public class ClientSessionCode {
return result;
}
- result.code = new ClientSessionCode(session, realm, result.clientSession);
+ result.code = new ClientSessionCode<CLIENT_SESSION>(session, realm, result.clientSession);
return result;
} catch (RuntimeException e) {
result.illegalHash = true;
@@ -111,9 +111,9 @@ public class ClientSessionCode {
}
}
- public static ClientSessionCode parse(String code, KeycloakSession session, RealmModel realm) {
+ public static <CLIENT_SESSION extends CommonClientSessionModel> ClientSessionCode<CLIENT_SESSION> parse(String code, KeycloakSession session, RealmModel realm, Class<CLIENT_SESSION> sessionClass) {
try {
- ClientSessionModel clientSession = getClientSession(code, session, realm);
+ CLIENT_SESSION clientSession = getClientSession(code, session, realm, sessionClass);
if (clientSession == null) {
return null;
}
@@ -122,24 +122,18 @@ public class ClientSessionCode {
return null;
}
- return new ClientSessionCode(session, realm, clientSession);
+ return new ClientSessionCode<>(session, realm, clientSession);
} catch (RuntimeException e) {
return null;
}
}
- public static ClientSessionModel getClientSession(String code, KeycloakSession session, RealmModel realm) {
- try {
- String[] parts = code.split("\\.");
- String id = parts[1];
- return session.sessions().getClientSession(realm, id);
- } catch (ArrayIndexOutOfBoundsException e) {
- return null;
- }
+ public static <CLIENT_SESSION extends CommonClientSessionModel> CLIENT_SESSION getClientSession(String code, KeycloakSession session, RealmModel realm, Class<CLIENT_SESSION> sessionClass) {
+ return CodeGenerateUtil.parseSession(code, session, realm, sessionClass);
}
- public ClientSessionModel getClientSession() {
- return clientSession;
+ public CLIENT_SESSION getClientSession() {
+ return commonLoginSession;
}
public boolean isValid(String requestedAction, ActionType actionType) {
@@ -148,7 +142,7 @@ public class ClientSessionCode {
}
public boolean isActionActive(ActionType actionType) {
- int timestamp = clientSession.getTimestamp();
+ int timestamp = commonLoginSession.getTimestamp();
int lifespan;
switch (actionType) {
@@ -169,7 +163,7 @@ public class ClientSessionCode {
}
public boolean isValidAction(String requestedAction) {
- String action = clientSession.getAction();
+ String action = commonLoginSession.getAction();
if (action == null) {
return false;
}
@@ -182,7 +176,7 @@ public class ClientSessionCode {
public Set<RoleModel> getRequestedRoles() {
Set<RoleModel> requestedRoles = new HashSet<>();
- for (String roleId : clientSession.getRoles()) {
+ for (String roleId : commonLoginSession.getRoles()) {
RoleModel role = realm.getRoleById(roleId);
if (role != null) {
requestedRoles.add(role);
@@ -192,9 +186,11 @@ public class ClientSessionCode {
}
public Set<ProtocolMapperModel> getRequestedProtocolMappers() {
+ return getRequestedProtocolMappers(commonLoginSession.getProtocolMappers(), commonLoginSession.getClient());
+ }
+
+ public static Set<ProtocolMapperModel> getRequestedProtocolMappers(Set<String> protocolMappers, ClientModel client) {
Set<ProtocolMapperModel> requestedProtocolMappers = new HashSet<>();
- Set<String> protocolMappers = clientSession.getProtocolMappers();
- ClientModel client = clientSession.getClient();
ClientTemplateModel template = client.getClientTemplate();
if (protocolMappers != null) {
for (String protocolMapperId : protocolMappers) {
@@ -211,33 +207,33 @@ public class ClientSessionCode {
}
public void setAction(String action) {
- clientSession.setAction(action);
- clientSession.setTimestamp(Time.currentTime());
+ commonLoginSession.setAction(action);
+ commonLoginSession.setTimestamp(Time.currentTime());
}
public String getCode() {
- String nextCode = (String) session.getAttribute(NEXT_CODE + "." + clientSession.getId());
+ String nextCode = (String) session.getAttribute(NEXT_CODE + "." + commonLoginSession.getId());
if (nextCode == null) {
- nextCode = generateCode(clientSession);
- session.setAttribute(NEXT_CODE + "." + clientSession.getId(), nextCode);
+ nextCode = generateCode(commonLoginSession);
+ session.setAttribute(NEXT_CODE + "." + commonLoginSession.getId(), nextCode);
} else {
logger.debug("Code already generated for session, using code from session attributes");
}
return nextCode;
}
- private static String generateCode(ClientSessionModel clientSession) {
+ private static String generateCode(CommonClientSessionModel loginSession) {
try {
String actionId = Base64Url.encode(KeycloakModelUtils.generateSecret());
StringBuilder sb = new StringBuilder();
sb.append(actionId);
sb.append('.');
- sb.append(clientSession.getId());
+ sb.append(loginSession.getId());
// https://tools.ietf.org/html/rfc7636#section-4
- String codeChallenge = clientSession.getNote(OAuth2Constants.CODE_CHALLENGE);
- String codeChallengeMethod = clientSession.getNote(OAuth2Constants.CODE_CHALLENGE_METHOD);
+ String codeChallenge = loginSession.getNote(OAuth2Constants.CODE_CHALLENGE);
+ String codeChallengeMethod = loginSession.getNote(OAuth2Constants.CODE_CHALLENGE_METHOD);
if (codeChallenge != null) {
logger.debugf("PKCE received codeChallenge = %s", codeChallenge);
if (codeChallengeMethod == null) {
@@ -248,9 +244,9 @@ public class ClientSessionCode {
}
}
- String code = sb.toString();
+ String code = CodeGenerateUtil.generateCode(loginSession, actionId);
- clientSession.setNote(ACTIVE_CODE, code);
+ loginSession.setNote(ACTIVE_CODE, code);
return code;
} catch (Exception e) {
@@ -258,15 +254,15 @@ public class ClientSessionCode {
}
}
- private static boolean verifyCode(String code, ClientSessionModel clientSession) {
+ private static boolean verifyCode(String code, CommonClientSessionModel loginSession) {
try {
- String activeCode = clientSession.getNote(ACTIVE_CODE);
+ String activeCode = loginSession.getNote(ACTIVE_CODE);
if (activeCode == null) {
logger.debug("Active code not found in client session");
return false;
}
- clientSession.removeNote(ACTIVE_CODE);
+ loginSession.removeNote(ACTIVE_CODE);
return MessageDigest.isEqual(code.getBytes(), activeCode.getBytes());
} catch (Exception e) {
diff --git a/server-spi-private/src/main/java/org/keycloak/services/managers/CodeGenerateUtil.java b/server-spi-private/src/main/java/org/keycloak/services/managers/CodeGenerateUtil.java
new file mode 100644
index 0000000..9c6a571
--- /dev/null
+++ b/server-spi-private/src/main/java/org/keycloak/services/managers/CodeGenerateUtil.java
@@ -0,0 +1,99 @@
+/*
+ * 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.services.managers;
+
+import org.keycloak.models.ClientLoginSessionModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.sessions.CommonClientSessionModel;
+import org.keycloak.sessions.LoginSessionModel;
+
+/**
+ * TODO: More object oriented and rather add parsing/generating logic into the session implementations itself
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+class CodeGenerateUtil {
+
+ static <CS extends CommonClientSessionModel> CS parseSession(String code, KeycloakSession session, RealmModel realm, Class<CS> expectedClazz) {
+ CommonClientSessionModel result = null;
+ if (expectedClazz.equals(ClientSessionModel.class)) {
+ try {
+ String[] parts = code.split("\\.");
+ String id = parts[2];
+ result = session.sessions().getClientSession(realm, id);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return null;
+ }
+ } else if (expectedClazz.equals(LoginSessionModel.class)) {
+ result = session.loginSessions().getCurrentLoginSession(realm);
+ } else if (expectedClazz.equals(ClientLoginSessionModel.class)) {
+ try {
+ String[] parts = code.split("\\.");
+ String userSessionId = parts[1];
+ String clientUUID = parts[2];
+
+ UserSessionModel userSession = session.sessions().getUserSession(realm, userSessionId);
+ if (userSession == null) {
+ return null;
+ }
+
+ result = userSession.getClientLoginSessions().get(clientUUID);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return null;
+ }
+ } else {
+ throw new IllegalArgumentException("Not known impl: " + expectedClazz.getName());
+ }
+
+ return expectedClazz.cast(result);
+ }
+
+ static String generateCode(CommonClientSessionModel clientSession, String actionId) {
+ if (clientSession instanceof ClientSessionModel) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("cls.");
+ sb.append(actionId);
+ sb.append('.');
+ sb.append(clientSession.getId());
+
+ return sb.toString();
+ } else if (clientSession instanceof LoginSessionModel) {
+ // Should be sufficient. LoginSession itself is in the cookie
+ return actionId;
+ } else if (clientSession instanceof ClientLoginSessionModel) {
+ String userSessionId = ((ClientLoginSessionModel) clientSession).getUserSession().getId();
+ String clientUUID = clientSession.getClient().getId();
+ StringBuilder sb = new StringBuilder();
+ sb.append("uss.");
+ sb.append(actionId);
+ sb.append('.');
+ sb.append(userSessionId);
+ sb.append('.');
+ sb.append(clientUUID);
+ return sb.toString();
+ } else {
+ throw new IllegalArgumentException("Not known impl: " + clientSession.getClass().getName());
+ }
+ }
+
+
+}
diff --git a/server-spi-private/src/main/java/org/keycloak/sessions/LoginSessionProviderFactory.java b/server-spi-private/src/main/java/org/keycloak/sessions/LoginSessionProviderFactory.java
new file mode 100644
index 0000000..0dfbf87
--- /dev/null
+++ b/server-spi-private/src/main/java/org/keycloak/sessions/LoginSessionProviderFactory.java
@@ -0,0 +1,26 @@
+/*
+ * 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.sessions;
+
+import org.keycloak.provider.ProviderFactory;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public interface LoginSessionProviderFactory extends ProviderFactory<LoginSessionProvider> {
+}
diff --git a/server-spi-private/src/main/java/org/keycloak/sessions/LoginSessionSpi.java b/server-spi-private/src/main/java/org/keycloak/sessions/LoginSessionSpi.java
new file mode 100644
index 0000000..cffa4c5
--- /dev/null
+++ b/server-spi-private/src/main/java/org/keycloak/sessions/LoginSessionSpi.java
@@ -0,0 +1,49 @@
+/*
+ * 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.sessions;
+
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.provider.Spi;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class LoginSessionSpi implements Spi {
+
+ @Override
+ public boolean isInternal() {
+ return true;
+ }
+
+ @Override
+ public String getName() {
+ return "loginSessions";
+ }
+
+ @Override
+ public Class<? extends Provider> getProviderClass() {
+ return LoginSessionProvider.class;
+ }
+
+ @Override
+ public Class<? extends ProviderFactory> getProviderFactoryClass() {
+ return LoginSessionProviderFactory.class;
+ }
+
+}
diff --git a/server-spi-private/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/server-spi-private/src/main/resources/META-INF/services/org.keycloak.provider.Spi
index 9397536..f858ea1 100755
--- a/server-spi-private/src/main/resources/META-INF/services/org.keycloak.provider.Spi
+++ b/server-spi-private/src/main/resources/META-INF/services/org.keycloak.provider.Spi
@@ -32,6 +32,7 @@ org.keycloak.timer.TimerSpi
org.keycloak.scripting.ScriptingSpi
org.keycloak.services.managers.BruteForceProtectorSpi
org.keycloak.services.resource.RealmResourceSPI
+org.keycloak.sessions.LoginSessionSpi
org.keycloak.protocol.ClientInstallationSpi
org.keycloak.protocol.LoginProtocolSpi
org.keycloak.protocol.ProtocolMapperSpi
diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
index a34e4ee..4a5053f 100755
--- a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
+++ b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
@@ -31,6 +31,7 @@ import org.keycloak.forms.login.LoginFormsProvider;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.AuthenticationFlowModel;
import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
@@ -50,6 +51,7 @@ import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.LoginActionsService;
import org.keycloak.services.util.CacheControlUtil;
+import org.keycloak.sessions.LoginSessionModel;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
@@ -67,7 +69,7 @@ public class AuthenticationProcessor {
protected static final Logger logger = Logger.getLogger(AuthenticationProcessor.class);
protected RealmModel realm;
protected UserSessionModel userSession;
- protected ClientSessionModel clientSession;
+ protected LoginSessionModel loginSession;
protected ClientConnection connection;
protected UriInfo uriInfo;
protected KeycloakSession session;
@@ -87,7 +89,6 @@ public class AuthenticationProcessor {
* This could be an success message forwarded from another authenticator
*/
protected FormMessage forwardedSuccessMessage;
- protected boolean userSessionCreated;
// Used for client authentication
protected ClientModel client;
@@ -128,8 +129,8 @@ public class AuthenticationProcessor {
return clientAuthAttributes;
}
- public ClientSessionModel getClientSession() {
- return clientSession;
+ public LoginSessionModel getLoginSession() {
+ return loginSession;
}
public ClientConnection getConnection() {
@@ -148,17 +149,13 @@ public class AuthenticationProcessor {
return userSession;
}
- public boolean isUserSessionCreated() {
- return userSessionCreated;
- }
-
public AuthenticationProcessor setRealm(RealmModel realm) {
this.realm = realm;
return this;
}
- public AuthenticationProcessor setClientSession(ClientSessionModel clientSession) {
- this.clientSession = clientSession;
+ public AuthenticationProcessor setLoginSession(LoginSessionModel loginSession) {
+ this.loginSession = loginSession;
return this;
}
@@ -213,8 +210,8 @@ public class AuthenticationProcessor {
}
public String generateCode() {
- ClientSessionCode accessCode = new ClientSessionCode(session, getRealm(), getClientSession());
- clientSession.setTimestamp(Time.currentTime());
+ ClientSessionCode accessCode = new ClientSessionCode(session, getRealm(), getLoginSession());
+ loginSession.setTimestamp(Time.currentTime());
return accessCode.getCode();
}
@@ -232,15 +229,15 @@ public class AuthenticationProcessor {
}
public void setAutheticatedUser(UserModel user) {
- UserModel previousUser = clientSession.getAuthenticatedUser();
+ UserModel previousUser = getLoginSession().getAuthenticatedUser();
if (previousUser != null && !user.getId().equals(previousUser.getId()))
throw new AuthenticationFlowException(AuthenticationFlowError.USER_CONFLICT);
validateUser(user);
- getClientSession().setAuthenticatedUser(user);
+ getLoginSession().setAuthenticatedUser(user);
}
public void clearAuthenticatedUser() {
- getClientSession().setAuthenticatedUser(null);
+ getLoginSession().setAuthenticatedUser(null);
}
public class Result implements AuthenticationFlowContext, ClientAuthenticationFlowContext {
@@ -363,7 +360,7 @@ public class AuthenticationProcessor {
@Override
public UserModel getUser() {
- return getClientSession().getAuthenticatedUser();
+ return getLoginSession().getAuthenticatedUser();
}
@Override
@@ -397,8 +394,8 @@ public class AuthenticationProcessor {
}
@Override
- public ClientSessionModel getClientSession() {
- return AuthenticationProcessor.this.getClientSession();
+ public LoginSessionModel getLoginSession() {
+ return AuthenticationProcessor.this.getLoginSession();
}
@Override
@@ -490,12 +487,12 @@ public class AuthenticationProcessor {
@Override
public void cancelLogin() {
getEvent().error(Errors.REJECTED_BY_USER);
- LoginProtocol protocol = getSession().getProvider(LoginProtocol.class, getClientSession().getAuthMethod());
+ LoginProtocol protocol = getSession().getProvider(LoginProtocol.class, getLoginSession().getProtocol());
protocol.setRealm(getRealm())
.setHttpHeaders(getHttpRequest().getHttpHeaders())
.setUriInfo(getUriInfo())
.setEventBuilder(event);
- Response response = protocol.sendError(getClientSession(), Error.CANCELLED_BY_USER);
+ Response response = protocol.sendError(getLoginSession(), Error.CANCELLED_BY_USER);
forceChallenge(response);
}
@@ -539,7 +536,7 @@ public class AuthenticationProcessor {
public void logFailure() {
if (realm.isBruteForceProtected()) {
- String username = clientSession.getNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME);
+ String username = loginSession.getNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME);
// todo need to handle non form failures
if (username == null) {
@@ -569,7 +566,7 @@ public class AuthenticationProcessor {
}
public boolean isSuccessful(AuthenticationExecutionModel model) {
- ClientSessionModel.ExecutionStatus status = clientSession.getExecutionStatus().get(model.getId());
+ ClientSessionModel.ExecutionStatus status = loginSession.getExecutionStatus().get(model.getId());
if (status == null) return false;
return status == ClientSessionModel.ExecutionStatus.SUCCESS;
}
@@ -602,10 +599,10 @@ public class AuthenticationProcessor {
} else if (e.getError() == AuthenticationFlowError.FORK_FLOW) {
ForkFlowException reset = (ForkFlowException)e;
- ClientSessionModel clone = clone(session, clientSession);
+ LoginSessionModel clone = clone(session, loginSession);
clone.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
AuthenticationProcessor processor = new AuthenticationProcessor();
- processor.setClientSession(clone)
+ processor.setLoginSession(clone)
.setFlowPath(LoginActionsService.AUTHENTICATE_PATH)
.setFlowId(realm.getBrowserFlow().getId())
.setForwardedErrorMessage(reset.getErrorMessage())
@@ -707,12 +704,12 @@ public class AuthenticationProcessor {
}
- public static Response redirectToRequiredActions(KeycloakSession session, RealmModel realm, ClientSessionModel clientSession, UriInfo uriInfo) {
+ public static Response redirectToRequiredActions(KeycloakSession session, RealmModel realm, LoginSessionModel loginSession, UriInfo uriInfo) {
// redirect to non-action url so browser refresh button works without reposting past data
- ClientSessionCode accessCode = new ClientSessionCode(session, realm, clientSession);
+ ClientSessionCode<LoginSessionModel> accessCode = new ClientSessionCode<>(session, realm, loginSession);
accessCode.setAction(ClientSessionModel.Action.REQUIRED_ACTIONS.name());
- clientSession.setTimestamp(Time.currentTime());
+ loginSession.setTimestamp(Time.currentTime());
URI redirect = LoginActionsService.loginActionsBaseUrl(uriInfo)
.path(LoginActionsService.REQUIRED_ACTION)
@@ -721,22 +718,23 @@ public class AuthenticationProcessor {
}
- public static void resetFlow(ClientSessionModel clientSession) {
+ public static void resetFlow(LoginSessionModel loginSession) {
logger.debug("RESET FLOW");
- clientSession.setTimestamp(Time.currentTime());
- clientSession.setAuthenticatedUser(null);
- clientSession.clearExecutionStatus();
- clientSession.clearUserSessionNotes();
- clientSession.removeNote(CURRENT_AUTHENTICATION_EXECUTION);
+ loginSession.setTimestamp(Time.currentTime());
+ loginSession.setAuthenticatedUser(null);
+ loginSession.clearExecutionStatus();
+ loginSession.clearUserSessionNotes();
+ loginSession.removeNote(CURRENT_AUTHENTICATION_EXECUTION);
}
- public static ClientSessionModel clone(KeycloakSession session, ClientSessionModel clientSession) {
- ClientSessionModel clone = session.sessions().createClientSession(clientSession.getRealm(), clientSession.getClient());
- for (Map.Entry<String, String> entry : clientSession.getNotes().entrySet()) {
+ public static LoginSessionModel clone(KeycloakSession session, LoginSessionModel loginSession) {
+ // TODO: Doublecheck false...
+ LoginSessionModel clone = session.loginSessions().createLoginSession(loginSession.getRealm(), loginSession.getClient(), false);
+ for (Map.Entry<String, String> entry : loginSession.getNotes().entrySet()) {
clone.setNote(entry.getKey(), entry.getValue());
}
- clone.setRedirectUri(clientSession.getRedirectUri());
- clone.setAuthMethod(clientSession.getAuthMethod());
+ clone.setRedirectUri(loginSession.getRedirectUri());
+ clone.setProtocol(loginSession.getProtocol());
clone.setTimestamp(Time.currentTime());
clone.removeNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION);
return clone;
@@ -747,26 +745,26 @@ public class AuthenticationProcessor {
public Response authenticationAction(String execution) {
logger.debug("authenticationAction");
checkClientSession();
- String current = clientSession.getNote(CURRENT_AUTHENTICATION_EXECUTION);
+ String current = loginSession.getNote(CURRENT_AUTHENTICATION_EXECUTION);
if (!execution.equals(current)) {
logger.debug("Current execution does not equal executed execution. Might be a page refresh");
//logFailure();
//resetFlow(clientSession);
return authenticate();
}
- UserModel authUser = clientSession.getAuthenticatedUser();
+ UserModel authUser = loginSession.getAuthenticatedUser();
validateUser(authUser);
AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
if (model == null) {
logger.debug("Cannot find execution, reseting flow");
logFailure();
- resetFlow(clientSession);
+ resetFlow(loginSession);
return authenticate();
}
- event.client(clientSession.getClient().getClientId())
- .detail(Details.REDIRECT_URI, clientSession.getRedirectUri())
- .detail(Details.AUTH_METHOD, clientSession.getAuthMethod());
- String authType = clientSession.getNote(Details.AUTH_TYPE);
+ event.client(loginSession.getClient().getClientId())
+ .detail(Details.REDIRECT_URI, loginSession.getRedirectUri())
+ .detail(Details.AUTH_METHOD, loginSession.getProtocol());
+ String authType = loginSession.getNote(Details.AUTH_TYPE);
if (authType != null) {
event.detail(Details.AUTH_TYPE, authType);
}
@@ -774,14 +772,14 @@ public class AuthenticationProcessor {
AuthenticationFlow authenticationFlow = createFlowExecution(this.flowId, model);
Response challenge = authenticationFlow.processAction(execution);
if (challenge != null) return challenge;
- if (clientSession.getAuthenticatedUser() == null) {
+ if (loginSession.getAuthenticatedUser() == null) {
throw new AuthenticationFlowException(AuthenticationFlowError.UNKNOWN_USER);
}
return authenticationComplete();
}
public void checkClientSession() {
- ClientSessionCode code = new ClientSessionCode(session, realm, clientSession);
+ ClientSessionCode code = new ClientSessionCode(session, realm, loginSession);
String action = ClientSessionModel.Action.AUTHENTICATE.name();
if (!code.isValidAction(action)) {
throw new AuthenticationFlowException(AuthenticationFlowError.INVALID_CLIENT_SESSION);
@@ -789,25 +787,25 @@ public class AuthenticationProcessor {
if (!code.isActionActive(ClientSessionCode.ActionType.LOGIN)) {
throw new AuthenticationFlowException(AuthenticationFlowError.EXPIRED_CODE);
}
- clientSession.setTimestamp(Time.currentTime());
+ loginSession.setTimestamp(Time.currentTime());
}
public Response authenticateOnly() throws AuthenticationFlowException {
logger.debug("AUTHENTICATE ONLY");
checkClientSession();
- event.client(clientSession.getClient().getClientId())
- .detail(Details.REDIRECT_URI, clientSession.getRedirectUri())
- .detail(Details.AUTH_METHOD, clientSession.getAuthMethod());
- String authType = clientSession.getNote(Details.AUTH_TYPE);
+ event.client(loginSession.getClient().getClientId())
+ .detail(Details.REDIRECT_URI, loginSession.getRedirectUri())
+ .detail(Details.AUTH_METHOD, loginSession.getProtocol());
+ String authType = loginSession.getNote(Details.AUTH_TYPE);
if (authType != null) {
event.detail(Details.AUTH_TYPE, authType);
}
- UserModel authUser = clientSession.getAuthenticatedUser();
+ UserModel authUser = loginSession.getAuthenticatedUser();
validateUser(authUser);
AuthenticationFlow authenticationFlow = createFlowExecution(this.flowId, null);
Response challenge = authenticationFlow.processFlow();
if (challenge != null) return challenge;
- if (clientSession.getAuthenticatedUser() == null) {
+ if (loginSession.getAuthenticatedUser() == null) {
throw new AuthenticationFlowException(AuthenticationFlowError.UNKNOWN_USER);
}
return challenge;
@@ -835,34 +833,44 @@ public class AuthenticationProcessor {
}
}
- public void attachSession() {
- String username = clientSession.getAuthenticatedUser().getUsername();
- String attemptedUsername = clientSession.getNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME);
+ // May create userSession too
+ public ClientLoginSessionModel attachSession() {
+ return attachSession(loginSession, userSession, session, realm, connection, event);
+ }
+
+ // May create new userSession too (if userSession argument is null)
+ public static ClientLoginSessionModel attachSession(LoginSessionModel loginSession, UserSessionModel userSession, KeycloakSession session, RealmModel realm, ClientConnection connection, EventBuilder event) {
+ String username = loginSession.getAuthenticatedUser().getUsername();
+ String attemptedUsername = loginSession.getNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME);
if (attemptedUsername != null) username = attemptedUsername;
- String rememberMe = clientSession.getNote(Details.REMEMBER_ME);
+ String rememberMe = loginSession.getNote(Details.REMEMBER_ME);
boolean remember = rememberMe != null && rememberMe.equalsIgnoreCase("true");
if (userSession == null) { // if no authenticator attached a usersession
- userSession = session.sessions().createUserSession(realm, clientSession.getAuthenticatedUser(), username, connection.getRemoteAddr(), clientSession.getAuthMethod(), remember, null, null);
+ userSession = session.sessions().createUserSession(realm, loginSession.getAuthenticatedUser(), username, connection.getRemoteAddr(), loginSession.getProtocol(), remember, null, null);
userSession.setState(UserSessionModel.State.LOGGING_IN);
- userSessionCreated = true;
}
if (remember) {
event.detail(Details.REMEMBER_ME, "true");
}
- TokenManager.attachClientSession(userSession, clientSession);
+
+ ClientLoginSessionModel clientSession = TokenManager.attachLoginSession(session, userSession, loginSession);
+
event.user(userSession.getUser())
.detail(Details.USERNAME, username)
.session(userSession);
+
+ return clientSession;
}
public void evaluateRequiredActionTriggers() {
- AuthenticationManager.evaluateRequiredActionTriggers(session, userSession, clientSession, connection, request, uriInfo, event, realm, clientSession.getAuthenticatedUser());
+ AuthenticationManager.evaluateRequiredActionTriggers(session, loginSession, connection, request, uriInfo, event, realm, loginSession.getAuthenticatedUser());
}
public Response finishAuthentication(LoginProtocol protocol) {
event.success();
- RealmModel realm = clientSession.getRealm();
- return AuthenticationManager.redirectAfterSuccessfulFlow(session, realm, userSession, clientSession, request, uriInfo, connection, event, protocol);
+ RealmModel realm = loginSession.getRealm();
+ ClientLoginSessionModel clientSession = attachSession();
+ return AuthenticationManager.redirectAfterSuccessfulFlow(session, realm, userSession,clientSession, request, uriInfo, connection, event, protocol);
}
@@ -877,19 +885,21 @@ public class AuthenticationProcessor {
}
protected Response authenticationComplete() {
- attachSession();
+ // attachSession(); // Session will be attached after requiredActions + consents are finished.
if (isActionRequired()) {
- return redirectToRequiredActions(session, realm, clientSession, uriInfo);
+ // TODO:mposolda Changed this to avoid additional redirect. Doublecheck consequences...
+ //return redirectToRequiredActions(session, realm, loginSession, uriInfo);
+ return AuthenticationManager.nextActionAfterAuthentication(session, loginSession, connection, request, uriInfo, event);
} else {
- event.detail(Details.CODE_ID, clientSession.getId()); // todo This should be set elsewhere. find out why tests fail. Don't know where this is supposed to be set
+ event.detail(Details.CODE_ID, loginSession.getId()); // todo This should be set elsewhere. find out why tests fail. Don't know where this is supposed to be set
// the user has successfully logged in and we can clear his/her previous login failure attempts.
logSuccess();
- return AuthenticationManager.finishedRequiredActions(session, userSession, clientSession, connection, request, uriInfo, event);
+ return AuthenticationManager.finishedRequiredActions(session, loginSession, connection, request, uriInfo, event);
}
}
public boolean isActionRequired() {
- return AuthenticationManager.isActionRequired(session, userSession, clientSession, connection, request, uriInfo, event);
+ return AuthenticationManager.isActionRequired(session, loginSession, connection, request, uriInfo, event);
}
public AuthenticationProcessor.Result createAuthenticatorContext(AuthenticationExecutionModel model, Authenticator authenticator, List<AuthenticationExecutionModel> executions) {
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/broker/AbstractIdpAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/broker/AbstractIdpAuthenticator.java
index 87108da..fd65f61 100644
--- a/services/src/main/java/org/keycloak/authentication/authenticators/broker/AbstractIdpAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/broker/AbstractIdpAuthenticator.java
@@ -25,11 +25,11 @@ import org.keycloak.authentication.authenticators.broker.util.ExistingUserInfo;
import org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.events.Errors;
-import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.services.messages.Messages;
+import org.keycloak.sessions.LoginSessionModel;
import javax.ws.rs.core.Response;
@@ -59,13 +59,13 @@ public abstract class AbstractIdpAuthenticator implements Authenticator {
@Override
public void authenticate(AuthenticationFlowContext context) {
- ClientSessionModel clientSession = context.getClientSession();
+ LoginSessionModel loginSession = context.getLoginSession();
- SerializedBrokeredIdentityContext serializedCtx = SerializedBrokeredIdentityContext.readFromClientSession(clientSession, BROKERED_CONTEXT_NOTE);
+ SerializedBrokeredIdentityContext serializedCtx = SerializedBrokeredIdentityContext.readFromLoginSession(loginSession, BROKERED_CONTEXT_NOTE);
if (serializedCtx == null) {
throw new AuthenticationFlowException("Not found serialized context in clientSession", AuthenticationFlowError.IDENTITY_PROVIDER_ERROR);
}
- BrokeredIdentityContext brokerContext = serializedCtx.deserialize(context.getSession(), clientSession);
+ BrokeredIdentityContext brokerContext = serializedCtx.deserialize(context.getSession(), loginSession);
if (!brokerContext.getIdpConfig().isEnabled()) {
sendFailureChallenge(context, Errors.IDENTITY_PROVIDER_ERROR, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR, AuthenticationFlowError.IDENTITY_PROVIDER_ERROR);
@@ -76,9 +76,9 @@ public abstract class AbstractIdpAuthenticator implements Authenticator {
@Override
public void action(AuthenticationFlowContext context) {
- ClientSessionModel clientSession = context.getClientSession();
+ LoginSessionModel clientSession = context.getLoginSession();
- SerializedBrokeredIdentityContext serializedCtx = SerializedBrokeredIdentityContext.readFromClientSession(clientSession, BROKERED_CONTEXT_NOTE);
+ SerializedBrokeredIdentityContext serializedCtx = SerializedBrokeredIdentityContext.readFromLoginSession(clientSession, BROKERED_CONTEXT_NOTE);
if (serializedCtx == null) {
throw new AuthenticationFlowException("Not found serialized context in clientSession", AuthenticationFlowError.IDENTITY_PROVIDER_ERROR);
}
@@ -112,8 +112,8 @@ public abstract class AbstractIdpAuthenticator implements Authenticator {
}
- public static UserModel getExistingUser(KeycloakSession session, RealmModel realm, ClientSessionModel clientSession) {
- String existingUserId = clientSession.getNote(EXISTING_USER_INFO);
+ public static UserModel getExistingUser(KeycloakSession session, RealmModel realm, LoginSessionModel loginSession) {
+ String existingUserId = loginSession.getNote(EXISTING_USER_INFO);
if (existingUserId == null) {
throw new AuthenticationFlowException("Unexpected state. There is no existing duplicated user identified in ClientSession",
AuthenticationFlowError.INTERNAL_ERROR);
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpConfirmLinkAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpConfirmLinkAuthenticator.java
index 8234700..0b84872 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpConfirmLinkAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpConfirmLinkAuthenticator.java
@@ -24,12 +24,12 @@ import org.keycloak.authentication.authenticators.broker.util.ExistingUserInfo;
import org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.forms.login.LoginFormsProvider;
-import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.services.ServicesLogger;
import org.keycloak.services.messages.Messages;
+import org.keycloak.sessions.LoginSessionModel;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
@@ -41,9 +41,9 @@ public class IdpConfirmLinkAuthenticator extends AbstractIdpAuthenticator {
@Override
protected void authenticateImpl(AuthenticationFlowContext context, SerializedBrokeredIdentityContext serializedCtx, BrokeredIdentityContext brokerContext) {
- ClientSessionModel clientSession = context.getClientSession();
+ LoginSessionModel loginSession = context.getLoginSession();
- String existingUserInfo = clientSession.getNote(EXISTING_USER_INFO);
+ String existingUserInfo = loginSession.getNote(EXISTING_USER_INFO);
if (existingUserInfo == null) {
ServicesLogger.LOGGER.noDuplicationDetected();
context.attempted();
@@ -65,8 +65,8 @@ public class IdpConfirmLinkAuthenticator extends AbstractIdpAuthenticator {
String action = formData.getFirst("submitAction");
if (action != null && action.equals("updateProfile")) {
- context.getClientSession().setNote(ENFORCE_UPDATE_PROFILE, "true");
- context.getClientSession().removeNote(EXISTING_USER_INFO);
+ context.getLoginSession().setNote(ENFORCE_UPDATE_PROFILE, "true");
+ context.getLoginSession().removeNote(EXISTING_USER_INFO);
context.resetFlow();
} else if (action != null && action.equals("linkAccount")) {
context.success();
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpCreateUserIfUniqueAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpCreateUserIfUniqueAuthenticator.java
index 317cb64..f905e0c 100644
--- a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpCreateUserIfUniqueAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpCreateUserIfUniqueAuthenticator.java
@@ -53,7 +53,7 @@ public class IdpCreateUserIfUniqueAuthenticator extends AbstractIdpAuthenticator
KeycloakSession session = context.getSession();
RealmModel realm = context.getRealm();
- if (context.getClientSession().getNote(EXISTING_USER_INFO) != null) {
+ if (context.getLoginSession().getNote(EXISTING_USER_INFO) != null) {
context.attempted();
return;
}
@@ -61,7 +61,7 @@ public class IdpCreateUserIfUniqueAuthenticator extends AbstractIdpAuthenticator
String username = getUsername(context, serializedCtx, brokerContext);
if (username == null) {
ServicesLogger.LOGGER.resetFlow(realm.isRegistrationEmailAsUsername() ? "Email" : "Username");
- context.getClientSession().setNote(ENFORCE_UPDATE_PROFILE, "true");
+ context.getLoginSession().setNote(ENFORCE_UPDATE_PROFILE, "true");
context.resetFlow();
return;
}
@@ -91,14 +91,14 @@ public class IdpCreateUserIfUniqueAuthenticator extends AbstractIdpAuthenticator
userRegisteredSuccess(context, federatedUser, serializedCtx, brokerContext);
context.setUser(federatedUser);
- context.getClientSession().setNote(BROKER_REGISTERED_NEW_USER, "true");
+ context.getLoginSession().setNote(BROKER_REGISTERED_NEW_USER, "true");
context.success();
} else {
logger.debugf("Duplication detected. There is already existing user with %s '%s' .",
duplication.getDuplicateAttributeName(), duplication.getDuplicateAttributeValue());
// Set duplicated user, so next authenticators can deal with it
- context.getClientSession().setNote(EXISTING_USER_INFO, duplication.serialize());
+ context.getLoginSession().setNote(EXISTING_USER_INFO, duplication.serialize());
Response challengeResponse = context.form()
.setError(Messages.FEDERATED_IDENTITY_EXISTS, duplication.getDuplicateAttributeName(), duplication.getDuplicateAttributeValue())
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpEmailVerificationAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpEmailVerificationAuthenticator.java
index 420eb20..27a30e8 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpEmailVerificationAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpEmailVerificationAuthenticator.java
@@ -53,7 +53,7 @@ public class IdpEmailVerificationAuthenticator extends AbstractIdpAuthenticator
@Override
protected void authenticateImpl(AuthenticationFlowContext context, SerializedBrokeredIdentityContext serializedCtx, BrokeredIdentityContext brokerContext) {
- KeycloakSession session = context.getSession();
+ /*KeycloakSession session = context.getSession();
RealmModel realm = context.getRealm();
ClientSessionModel clientSession = context.getClientSession();
@@ -63,9 +63,6 @@ public class IdpEmailVerificationAuthenticator extends AbstractIdpAuthenticator
return;
}
- // Create action cookie to detect if email verification happened in same browser
- LoginActionsService.createActionCookie(context.getRealm(), context.getUriInfo(), context.getConnection(), context.getClientSession().getId());
-
VerifyEmail.setupKey(clientSession);
UserModel existingUser = getExistingUser(session, realm, clientSession);
@@ -107,12 +104,12 @@ public class IdpEmailVerificationAuthenticator extends AbstractIdpAuthenticator
.setStatus(Response.Status.OK)
.setAttribute(LoginFormsProvider.IDENTITY_PROVIDER_BROKER_CONTEXT, brokerContext)
.createIdpLinkEmailPage();
- context.forceChallenge(challenge);
+ context.forceChallenge(challenge);*/
}
@Override
protected void actionImpl(AuthenticationFlowContext context, SerializedBrokeredIdentityContext serializedCtx, BrokeredIdentityContext brokerContext) {
- MultivaluedMap<String, String> queryParams = context.getSession().getContext().getUri().getQueryParameters();
+ /*MultivaluedMap<String, String> queryParams = context.getSession().getContext().getUri().getQueryParameters();
String key = queryParams.getFirst(Constants.KEY);
ClientSessionModel clientSession = context.getClientSession();
RealmModel realm = context.getRealm();
@@ -149,7 +146,7 @@ public class IdpEmailVerificationAuthenticator extends AbstractIdpAuthenticator
.setError(Messages.MISSING_PARAMETER, Constants.KEY)
.createErrorPage();
context.failureChallenge(AuthenticationFlowError.IDENTITY_PROVIDER_ERROR, challengeResponse);
- }
+ }*/
}
@Override
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpReviewProfileAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpReviewProfileAuthenticator.java
index c58e3e1..edd3c62 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpReviewProfileAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpReviewProfileAuthenticator.java
@@ -33,7 +33,6 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.FormMessage;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
-import org.keycloak.services.ServicesLogger;
import org.keycloak.services.resources.AttributeFormDataProcessor;
import org.keycloak.services.validation.Validation;
@@ -74,7 +73,7 @@ public class IdpReviewProfileAuthenticator extends AbstractIdpAuthenticator {
}
protected boolean requiresUpdateProfilePage(AuthenticationFlowContext context, SerializedBrokeredIdentityContext userCtx, BrokeredIdentityContext brokerContext) {
- String enforceUpdateProfile = context.getClientSession().getNote(ENFORCE_UPDATE_PROFILE);
+ String enforceUpdateProfile = context.getLoginSession().getNote(ENFORCE_UPDATE_PROFILE);
if (Boolean.parseBoolean(enforceUpdateProfile)) {
return true;
}
@@ -123,12 +122,12 @@ public class IdpReviewProfileAuthenticator extends AbstractIdpAuthenticator {
}
userCtx.setEmail(email);
- context.getClientSession().setNote(UPDATE_PROFILE_EMAIL_CHANGED, "true");
+ context.getLoginSession().setNote(UPDATE_PROFILE_EMAIL_CHANGED, "true");
}
AttributeFormDataProcessor.process(formData, realm, userCtx);
- userCtx.saveToClientSession(context.getClientSession(), BROKERED_CONTEXT_NOTE);
+ userCtx.saveToLoginSession(context.getLoginSession(), BROKERED_CONTEXT_NOTE);
logger.debugf("Profile updated successfully after first authentication with identity provider '%s' for broker user '%s'.", brokerContext.getIdpConfig().getAlias(), userCtx.getUsername());
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpUsernamePasswordForm.java b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpUsernamePasswordForm.java
index cd09c37..071a1ec 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpUsernamePasswordForm.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpUsernamePasswordForm.java
@@ -39,7 +39,7 @@ public class IdpUsernamePasswordForm extends UsernamePasswordForm {
@Override
protected Response challenge(AuthenticationFlowContext context, MultivaluedMap<String, String> formData) {
- UserModel existingUser = AbstractIdpAuthenticator.getExistingUser(context.getSession(), context.getRealm(), context.getClientSession());
+ UserModel existingUser = AbstractIdpAuthenticator.getExistingUser(context.getSession(), context.getRealm(), context.getLoginSession());
return setupForm(context, formData, existingUser)
.setStatus(Response.Status.OK)
@@ -48,7 +48,7 @@ public class IdpUsernamePasswordForm extends UsernamePasswordForm {
@Override
protected boolean validateForm(AuthenticationFlowContext context, MultivaluedMap<String, String> formData) {
- UserModel existingUser = AbstractIdpAuthenticator.getExistingUser(context.getSession(), context.getRealm(), context.getClientSession());
+ UserModel existingUser = AbstractIdpAuthenticator.getExistingUser(context.getSession(), context.getRealm(), context.getLoginSession());
context.setUser(existingUser);
// Restore formData for the case of error
@@ -58,7 +58,7 @@ public class IdpUsernamePasswordForm extends UsernamePasswordForm {
}
protected LoginFormsProvider setupForm(AuthenticationFlowContext context, MultivaluedMap<String, String> formData, UserModel existingUser) {
- SerializedBrokeredIdentityContext serializedCtx = SerializedBrokeredIdentityContext.readFromClientSession(context.getClientSession(), AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE);
+ SerializedBrokeredIdentityContext serializedCtx = SerializedBrokeredIdentityContext.readFromLoginSession(context.getLoginSession(), AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE);
if (serializedCtx == null) {
throw new AuthenticationFlowException("Not found serialized context in clientSession", AuthenticationFlowError.IDENTITY_PROVIDER_ERROR);
}
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/broker/util/SerializedBrokeredIdentityContext.java b/services/src/main/java/org/keycloak/authentication/authenticators/broker/util/SerializedBrokeredIdentityContext.java
index 1e40462..86bb979 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/broker/util/SerializedBrokeredIdentityContext.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/broker/util/SerializedBrokeredIdentityContext.java
@@ -31,6 +31,7 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelException;
import org.keycloak.models.RealmModel;
import org.keycloak.services.resources.IdentityBrokerService;
+import org.keycloak.sessions.LoginSessionModel;
import org.keycloak.util.JsonSerialization;
import java.io.IOException;
@@ -246,7 +247,7 @@ public class SerializedBrokeredIdentityContext implements UpdateProfileContext {
}
}
- public BrokeredIdentityContext deserialize(KeycloakSession session, ClientSessionModel clientSession) {
+ public BrokeredIdentityContext deserialize(KeycloakSession session, LoginSessionModel loginSession) {
BrokeredIdentityContext ctx = new BrokeredIdentityContext(getId());
ctx.setUsername(getBrokerUsername());
@@ -258,7 +259,7 @@ public class SerializedBrokeredIdentityContext implements UpdateProfileContext {
ctx.setBrokerUserId(getBrokerUserId());
ctx.setToken(getToken());
- RealmModel realm = clientSession.getRealm();
+ RealmModel realm = loginSession.getRealm();
IdentityProviderModel idpConfig = realm.getIdentityProviderByAlias(getIdentityProviderId());
if (idpConfig == null) {
throw new ModelException("Can't find identity provider with ID " + getIdentityProviderId() + " in realm " + realm.getName());
@@ -282,7 +283,7 @@ public class SerializedBrokeredIdentityContext implements UpdateProfileContext {
}
}
- ctx.setClientSession(clientSession);
+ ctx.setLoginSession(loginSession);
return ctx;
}
@@ -299,7 +300,7 @@ public class SerializedBrokeredIdentityContext implements UpdateProfileContext {
ctx.setToken(context.getToken());
ctx.setIdentityProviderId(context.getIdpConfig().getAlias());
- ctx.emailAsUsername = context.getClientSession().getRealm().isRegistrationEmailAsUsername();
+ ctx.emailAsUsername = context.getLoginSession().getRealm().isRegistrationEmailAsUsername();
IdentityProviderDataMarshaller serializer = context.getIdp().getMarshaller();
@@ -314,23 +315,23 @@ public class SerializedBrokeredIdentityContext implements UpdateProfileContext {
}
// Save this context as note to clientSession
- public void saveToClientSession(ClientSessionModel clientSession, String noteKey) {
+ public void saveToLoginSession(LoginSessionModel loginSession, String noteKey) {
try {
String asString = JsonSerialization.writeValueAsString(this);
- clientSession.setNote(noteKey, asString);
+ loginSession.setNote(noteKey, asString);
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
- public static SerializedBrokeredIdentityContext readFromClientSession(ClientSessionModel clientSession, String noteKey) {
- String asString = clientSession.getNote(noteKey);
+ public static SerializedBrokeredIdentityContext readFromLoginSession(LoginSessionModel loginSession, String noteKey) {
+ String asString = loginSession.getNote(noteKey);
if (asString == null) {
return null;
} else {
try {
SerializedBrokeredIdentityContext serializedCtx = JsonSerialization.readValue(asString, SerializedBrokeredIdentityContext.class);
- serializedCtx.emailAsUsername = clientSession.getRealm().isRegistrationEmailAsUsername();
+ serializedCtx.emailAsUsername = loginSession.getRealm().isRegistrationEmailAsUsername();
return serializedCtx;
} catch (IOException ioe) {
throw new RuntimeException(ioe);
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/browser/AbstractUsernameFormAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/browser/AbstractUsernameFormAuthenticator.java
index f837d3c..fc73e18 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/browser/AbstractUsernameFormAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/browser/AbstractUsernameFormAuthenticator.java
@@ -126,7 +126,7 @@ public abstract class AbstractUsernameFormAuthenticator extends AbstractFormAuth
username = username.trim();
context.getEvent().detail(Details.USERNAME, username);
- context.getClientSession().setNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME, username);
+ context.getLoginSession().setNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME, username);
UserModel user = null;
try {
@@ -159,10 +159,10 @@ public abstract class AbstractUsernameFormAuthenticator extends AbstractFormAuth
String rememberMe = inputData.getFirst("rememberMe");
boolean remember = rememberMe != null && rememberMe.equalsIgnoreCase("on");
if (remember) {
- context.getClientSession().setNote(Details.REMEMBER_ME, "true");
+ context.getLoginSession().setNote(Details.REMEMBER_ME, "true");
context.getEvent().detail(Details.REMEMBER_ME, "true");
} else {
- context.getClientSession().removeNote(Details.REMEMBER_ME);
+ context.getLoginSession().removeNote(Details.REMEMBER_ME);
}
context.setUser(user);
return true;
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/browser/CookieAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/browser/CookieAuthenticator.java
index b4552af..d1c22f5 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/browser/CookieAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/browser/CookieAuthenticator.java
@@ -25,6 +25,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.protocol.LoginProtocol;
import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.sessions.LoginSessionModel;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -44,8 +45,8 @@ public class CookieAuthenticator implements Authenticator {
if (authResult == null) {
context.attempted();
} else {
- ClientSessionModel clientSession = context.getClientSession();
- LoginProtocol protocol = context.getSession().getProvider(LoginProtocol.class, clientSession.getAuthMethod());
+ LoginSessionModel clientSession = context.getLoginSession();
+ LoginProtocol protocol = context.getSession().getProvider(LoginProtocol.class, clientSession.getProtocol());
// Cookie re-authentication is skipped if re-authentication is required
if (protocol.requireReauthentication(authResult.getSession(), clientSession)) {
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticator.java
index f8408a4..8cfd714 100644
--- a/services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticator.java
@@ -63,7 +63,7 @@ public class IdentityProviderAuthenticator implements Authenticator {
List<IdentityProviderModel> identityProviders = context.getRealm().getIdentityProviders();
for (IdentityProviderModel identityProvider : identityProviders) {
if (identityProvider.isEnabled() && providerId.equals(identityProvider.getAlias())) {
- String accessCode = new ClientSessionCode(context.getSession(), context.getRealm(), context.getClientSession()).getCode();
+ String accessCode = new ClientSessionCode<>(context.getSession(), context.getRealm(), context.getLoginSession()).getCode();
Response response = Response.seeOther(
Urls.identityProviderAuthnRequest(context.getUriInfo().getBaseUri(), providerId, context.getRealm().getName(), accessCode))
.build();
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/browser/ScriptBasedAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/browser/ScriptBasedAuthenticator.java
index 0b400f0..1a90b59 100644
--- a/services/src/main/java/org/keycloak/authentication/authenticators/browser/ScriptBasedAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/browser/ScriptBasedAuthenticator.java
@@ -160,7 +160,7 @@ public class ScriptBasedAuthenticator implements Authenticator {
bindings.put("user", context.getUser());
bindings.put("session", context.getSession());
bindings.put("httpRequest", context.getHttpRequest());
- bindings.put("clientSession", context.getClientSession());
+ bindings.put("clientSession", context.getLoginSession());
bindings.put("LOG", LOGGER);
});
}
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/browser/SpnegoAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/browser/SpnegoAuthenticator.java
index 8bfb995..c909921 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/browser/SpnegoAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/browser/SpnegoAuthenticator.java
@@ -98,7 +98,7 @@ public class SpnegoAuthenticator extends AbstractUsernameFormAuthenticator imple
context.setUser(output.getAuthenticatedUser());
if (output.getState() != null && !output.getState().isEmpty()) {
for (Map.Entry<String, String> entry : output.getState().entrySet()) {
- context.getClientSession().setUserSessionNote(entry.getKey(), entry.getValue());
+ context.getLoginSession().setUserSessionNote(entry.getKey(), entry.getValue());
}
}
context.success();
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/browser/UsernamePasswordForm.java b/services/src/main/java/org/keycloak/authentication/authenticators/browser/UsernamePasswordForm.java
index 4f8e2d1..cde0cb3 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/browser/UsernamePasswordForm.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/browser/UsernamePasswordForm.java
@@ -59,7 +59,7 @@ public class UsernamePasswordForm extends AbstractUsernameFormAuthenticator impl
@Override
public void authenticate(AuthenticationFlowContext context) {
MultivaluedMap<String, String> formData = new MultivaluedMapImpl<>();
- String loginHint = context.getClientSession().getNote(OIDCLoginProtocol.LOGIN_HINT_PARAM);
+ String loginHint = context.getLoginSession().getNote(OIDCLoginProtocol.LOGIN_HINT_PARAM);
String rememberMeUsername = AuthenticationManager.getRememberMeUsername(context.getRealm(), context.getHttpRequest().getHttpHeaders());
@@ -72,7 +72,7 @@ public class UsernamePasswordForm extends AbstractUsernameFormAuthenticator impl
}
}
Response challengeResponse = challenge(context, formData);
- context.getClientSession().setNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION, context.getExecution().getId());
+ context.getLoginSession().setNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION, context.getExecution().getId());
context.challenge(challengeResponse);
}
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/directgrant/ValidateUsername.java b/services/src/main/java/org/keycloak/authentication/authenticators/directgrant/ValidateUsername.java
index da7a67f..409618f 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/directgrant/ValidateUsername.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/directgrant/ValidateUsername.java
@@ -55,7 +55,7 @@ public class ValidateUsername extends AbstractDirectGrantAuthenticator {
return;
}
context.getEvent().detail(Details.USERNAME, username);
- context.getClientSession().setNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME, username);
+ context.getLoginSession().setNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME, username);
UserModel user = null;
try {
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialChooseUser.java b/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialChooseUser.java
index 46097a0..9604504 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialChooseUser.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialChooseUser.java
@@ -53,9 +53,9 @@ public class ResetCredentialChooseUser implements Authenticator, AuthenticatorFa
@Override
public void authenticate(AuthenticationFlowContext context) {
- String existingUserId = context.getClientSession().getNote(AbstractIdpAuthenticator.EXISTING_USER_INFO);
+ String existingUserId = context.getLoginSession().getNote(AbstractIdpAuthenticator.EXISTING_USER_INFO);
if (existingUserId != null) {
- UserModel existingUser = AbstractIdpAuthenticator.getExistingUser(context.getSession(), context.getRealm(), context.getClientSession());
+ UserModel existingUser = AbstractIdpAuthenticator.getExistingUser(context.getSession(), context.getRealm(), context.getLoginSession());
logger.debugf("Forget-password triggered when reauthenticating user after first broker login. Skipping reset-credential-choose-user screen and using user '%s' ", existingUser.getUsername());
context.setUser(existingUser);
@@ -89,7 +89,7 @@ public class ResetCredentialChooseUser implements Authenticator, AuthenticatorFa
user = context.getSession().users().getUserByEmail(username, realm);
}
- context.getClientSession().setNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME, username);
+ context.getLoginSession().setNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME, username);
// we don't want people guessing usernames, so if there is a problem, just continue, but don't set the user
// a null user will notify further executions, that this was a failure.
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialEmail.java b/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialEmail.java
index 0d41b06..e74fa20 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialEmail.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialEmail.java
@@ -61,7 +61,7 @@ public class ResetCredentialEmail implements Authenticator, AuthenticatorFactory
@Override
public void authenticate(AuthenticationFlowContext context) {
- LoginActionsService.createActionCookie(context.getRealm(), context.getUriInfo(), context.getConnection(), context.getClientSession().getId());
+ /*LoginActionsService.createActionCookie(context.getRealm(), context.getUriInfo(), context.getConnection(), context.getClientSession().getId());
UserModel user = context.getUser();
String username = context.getClientSession().getNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME);
@@ -109,12 +109,12 @@ public class ResetCredentialEmail implements Authenticator, AuthenticatorFactory
.setError(Messages.EMAIL_SENT_ERROR)
.createErrorPage();
context.failure(AuthenticationFlowError.INTERNAL_ERROR, challenge);
- }
+ }*/
}
@Override
public void action(AuthenticationFlowContext context) {
- String secret = context.getClientSession().getNote(RESET_CREDENTIAL_SECRET);
+ /*String secret = context.getClientSession().getNote(RESET_CREDENTIAL_SECRET);
String key = context.getUriInfo().getQueryParameters().getFirst(Constants.KEY);
// Can only guess once! We remove the note so another guess can't happen
@@ -129,7 +129,7 @@ public class ResetCredentialEmail implements Authenticator, AuthenticatorFactory
}
// We now know email is valid, so set it to valid.
context.getUser().setEmailVerified(true);
- context.success();
+ context.success();*/
}
@Override
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetOTP.java b/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetOTP.java
index 40c703b..7dcf829 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetOTP.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetOTP.java
@@ -33,7 +33,7 @@ public class ResetOTP extends AbstractSetRequiredActionAuthenticator {
if (context.getExecution().isRequired() ||
(context.getExecution().isOptional() &&
configuredFor(context))) {
- context.getClientSession().addRequiredAction(UserModel.RequiredAction.CONFIGURE_TOTP);
+ context.getLoginSession().addRequiredAction(UserModel.RequiredAction.CONFIGURE_TOTP);
}
context.success();
}
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetPassword.java b/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetPassword.java
index 64098fa..9c0fdab 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetPassword.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetPassword.java
@@ -34,14 +34,14 @@ public class ResetPassword extends AbstractSetRequiredActionAuthenticator {
@Override
public void authenticate(AuthenticationFlowContext context) {
String actionCookie = LoginActionsService.getActionCookie(context.getSession().getContext().getRequestHeaders(), context.getRealm(), context.getUriInfo(), context.getConnection());
- if (actionCookie == null || !actionCookie.equals(context.getClientSession().getId())) {
- context.getClientSession().setNote(AuthenticationManager.END_AFTER_REQUIRED_ACTIONS, "true");
+ if (actionCookie == null || !actionCookie.equals(context.getLoginSession().getId())) {
+ context.getLoginSession().setNote(AuthenticationManager.END_AFTER_REQUIRED_ACTIONS, "true");
}
if (context.getExecution().isRequired() ||
(context.getExecution().isOptional() &&
configuredFor(context))) {
- context.getClientSession().addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
+ context.getLoginSession().addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
}
context.success();
}
diff --git a/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java b/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java
index 40433cf..d87301f 100755
--- a/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java
+++ b/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java
@@ -51,7 +51,7 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
protected boolean isProcessed(AuthenticationExecutionModel model) {
if (model.isDisabled()) return true;
- ClientSessionModel.ExecutionStatus status = processor.getClientSession().getExecutionStatus().get(model.getId());
+ ClientSessionModel.ExecutionStatus status = processor.getLoginSession().getExecutionStatus().get(model.getId());
if (status == null) return false;
return status == ClientSessionModel.ExecutionStatus.SUCCESS || status == ClientSessionModel.ExecutionStatus.SKIPPED
|| status == ClientSessionModel.ExecutionStatus.ATTEMPTED
@@ -75,7 +75,7 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
AuthenticationFlow authenticationFlow = processor.createFlowExecution(model.getFlowId(), model);
Response flowChallenge = authenticationFlow.processAction(actionExecution);
if (flowChallenge == null) {
- processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SUCCESS);
+ processor.getLoginSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SUCCESS);
if (model.isAlternative()) alternativeSuccessful = true;
return processFlow();
} else {
@@ -92,7 +92,7 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
authenticator.action(result);
Response response = processResult(result);
if (response == null) {
- processor.getClientSession().removeNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION);
+ processor.getLoginSession().removeNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION);
if (result.status == FlowStatus.SUCCESS) {
// we do this so that flow can redirect to a non-action URL
processor.setActionSuccessful();
@@ -119,7 +119,7 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
}
if (model.isAlternative() && alternativeSuccessful) {
logger.debug("Skip alternative execution");
- processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
+ processor.getLoginSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
continue;
}
if (model.isAuthenticatorFlow()) {
@@ -127,7 +127,7 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
AuthenticationFlow authenticationFlow = processor.createFlowExecution(model.getFlowId(), model);
Response flowChallenge = authenticationFlow.processFlow();
if (flowChallenge == null) {
- processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SUCCESS);
+ processor.getLoginSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SUCCESS);
if (model.isAlternative()) alternativeSuccessful = true;
continue;
} else {
@@ -135,13 +135,13 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
alternativeChallenge = flowChallenge;
challengedAlternativeExecution = model;
} else if (model.isRequired()) {
- processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
+ processor.getLoginSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
return flowChallenge;
} else if (model.isOptional()) {
- processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
+ processor.getLoginSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
continue;
} else {
- processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
+ processor.getLoginSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
continue;
}
return flowChallenge;
@@ -154,11 +154,11 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
}
Authenticator authenticator = factory.create(processor.getSession());
logger.debugv("authenticator: {0}", factory.getId());
- UserModel authUser = processor.getClientSession().getAuthenticatedUser();
+ UserModel authUser = processor.getLoginSession().getAuthenticatedUser();
if (authenticator.requiresUser() && authUser == null) {
if (alternativeChallenge != null) {
- processor.getClientSession().setExecutionStatus(challengedAlternativeExecution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
+ processor.getLoginSession().setExecutionStatus(challengedAlternativeExecution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
return alternativeChallenge;
}
throw new AuthenticationFlowException("authenticator: " + factory.getId(), AuthenticationFlowError.UNKNOWN_USER);
@@ -170,14 +170,14 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
if (model.isRequired()) {
if (factory.isUserSetupAllowed()) {
logger.debugv("authenticator SETUP_REQUIRED: {0}", factory.getId());
- processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SETUP_REQUIRED);
- authenticator.setRequiredActions(processor.getSession(), processor.getRealm(), processor.getClientSession().getAuthenticatedUser());
+ processor.getLoginSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SETUP_REQUIRED);
+ authenticator.setRequiredActions(processor.getSession(), processor.getRealm(), processor.getLoginSession().getAuthenticatedUser());
continue;
} else {
throw new AuthenticationFlowException(AuthenticationFlowError.CREDENTIAL_SETUP_REQUIRED);
}
} else if (model.isOptional()) {
- processor.getClientSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
+ processor.getLoginSession().setExecutionStatus(model.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
continue;
}
}
@@ -202,56 +202,56 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
switch (status) {
case SUCCESS:
logger.debugv("authenticator SUCCESS: {0}", execution.getAuthenticator());
- processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.SUCCESS);
+ processor.getLoginSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.SUCCESS);
if (execution.isAlternative()) alternativeSuccessful = true;
return null;
case FAILED:
logger.debugv("authenticator FAILED: {0}", execution.getAuthenticator());
processor.logFailure();
- processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.FAILED);
+ processor.getLoginSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.FAILED);
if (result.getChallenge() != null) {
return sendChallenge(result, execution);
}
throw new AuthenticationFlowException(result.getError());
case FORK:
logger.debugv("reset browser login from authenticator: {0}", execution.getAuthenticator());
- processor.getClientSession().setNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION, execution.getId());
+ processor.getLoginSession().setNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION, execution.getId());
throw new ForkFlowException(result.getSuccessMessage(), result.getErrorMessage());
case FORCE_CHALLENGE:
- processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
+ processor.getLoginSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
return sendChallenge(result, execution);
case CHALLENGE:
logger.debugv("authenticator CHALLENGE: {0}", execution.getAuthenticator());
if (execution.isRequired()) {
- processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
+ processor.getLoginSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
return sendChallenge(result, execution);
}
- UserModel authenticatedUser = processor.getClientSession().getAuthenticatedUser();
+ UserModel authenticatedUser = processor.getLoginSession().getAuthenticatedUser();
if (execution.isOptional() && authenticatedUser != null && result.getAuthenticator().configuredFor(processor.getSession(), processor.getRealm(), authenticatedUser)) {
- processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
+ processor.getLoginSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
return sendChallenge(result, execution);
}
if (execution.isAlternative()) {
alternativeChallenge = result.getChallenge();
challengedAlternativeExecution = execution;
} else {
- processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
+ processor.getLoginSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.SKIPPED);
}
return null;
case FAILURE_CHALLENGE:
logger.debugv("authenticator FAILURE_CHALLENGE: {0}", execution.getAuthenticator());
processor.logFailure();
- processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
+ processor.getLoginSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.CHALLENGED);
return sendChallenge(result, execution);
case ATTEMPTED:
logger.debugv("authenticator ATTEMPTED: {0}", execution.getAuthenticator());
if (execution.getRequirement() == AuthenticationExecutionModel.Requirement.REQUIRED) {
throw new AuthenticationFlowException(AuthenticationFlowError.INVALID_CREDENTIALS);
}
- processor.getClientSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.ATTEMPTED);
+ processor.getLoginSession().setExecutionStatus(execution.getId(), ClientSessionModel.ExecutionStatus.ATTEMPTED);
return null;
case FLOW_RESET:
- AuthenticationProcessor.resetFlow(processor.getClientSession());
+ AuthenticationProcessor.resetFlow(processor.getLoginSession());
return processor.authenticate();
default:
logger.debugv("authenticator INTERNAL_ERROR: {0}", execution.getAuthenticator());
@@ -261,7 +261,7 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
}
public Response sendChallenge(AuthenticationProcessor.Result result, AuthenticationExecutionModel execution) {
- processor.getClientSession().setNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION, execution.getId());
+ processor.getLoginSession().setNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION, execution.getId());
return result.getChallenge();
}
diff --git a/services/src/main/java/org/keycloak/authentication/FormAuthenticationFlow.java b/services/src/main/java/org/keycloak/authentication/FormAuthenticationFlow.java
index 59c85fb..b1d29f1 100755
--- a/services/src/main/java/org/keycloak/authentication/FormAuthenticationFlow.java
+++ b/services/src/main/java/org/keycloak/authentication/FormAuthenticationFlow.java
@@ -30,6 +30,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.FormMessage;
import org.keycloak.services.resources.LoginActionsService;
+import org.keycloak.sessions.LoginSessionModel;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
@@ -93,7 +94,7 @@ public class FormAuthenticationFlow implements AuthenticationFlow {
@Override
public UserModel getUser() {
- return getClientSession().getAuthenticatedUser();
+ return getLoginSession().getAuthenticatedUser();
}
@Override
@@ -107,8 +108,8 @@ public class FormAuthenticationFlow implements AuthenticationFlow {
}
@Override
- public ClientSessionModel getClientSession() {
- return processor.getClientSession();
+ public LoginSessionModel getLoginSession() {
+ return processor.getLoginSession();
}
@Override
@@ -178,7 +179,7 @@ public class FormAuthenticationFlow implements AuthenticationFlow {
FormActionFactory factory = (FormActionFactory)processor.getSession().getKeycloakSessionFactory().getProviderFactory(FormAction.class, formActionExecution.getAuthenticator());
FormAction action = factory.create(processor.getSession());
- UserModel authUser = processor.getClientSession().getAuthenticatedUser();
+ UserModel authUser = processor.getLoginSession().getAuthenticatedUser();
if (action.requiresUser() && authUser == null) {
throw new AuthenticationFlowException("form action: " + formExecution.getAuthenticator() + " requires user", AuthenticationFlowError.UNKNOWN_USER);
}
@@ -235,14 +236,14 @@ public class FormAuthenticationFlow implements AuthenticationFlow {
}
// set status and required actions only if form is fully successful
for (Map.Entry<String, ClientSessionModel.ExecutionStatus> entry : executionStatus.entrySet()) {
- processor.getClientSession().setExecutionStatus(entry.getKey(), entry.getValue());
+ processor.getLoginSession().setExecutionStatus(entry.getKey(), entry.getValue());
}
for (FormAction action : requiredActions) {
- action.setRequiredActions(processor.getSession(), processor.getRealm(), processor.getClientSession().getAuthenticatedUser());
+ action.setRequiredActions(processor.getSession(), processor.getRealm(), processor.getLoginSession().getAuthenticatedUser());
}
- processor.getClientSession().setExecutionStatus(actionExecution, ClientSessionModel.ExecutionStatus.SUCCESS);
- processor.getClientSession().removeNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION);
+ processor.getLoginSession().setExecutionStatus(actionExecution, ClientSessionModel.ExecutionStatus.SUCCESS);
+ processor.getLoginSession().removeNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION);
processor.setActionSuccessful();
return null;
}
@@ -262,7 +263,7 @@ public class FormAuthenticationFlow implements AuthenticationFlow {
public Response renderForm(MultivaluedMap<String, String> formData, List<FormMessage> errors) {
String executionId = formExecution.getId();
- processor.getClientSession().setNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION, executionId);
+ processor.getLoginSession().setNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION, executionId);
String code = processor.generateCode();
URI actionUrl = getActionUrl(executionId, code);
LoginFormsProvider form = processor.getSession().getProvider(LoginFormsProvider.class)
diff --git a/services/src/main/java/org/keycloak/authentication/forms/RegistrationUserCreation.java b/services/src/main/java/org/keycloak/authentication/forms/RegistrationUserCreation.java
index 90dee70..ddb42be 100755
--- a/services/src/main/java/org/keycloak/authentication/forms/RegistrationUserCreation.java
+++ b/services/src/main/java/org/keycloak/authentication/forms/RegistrationUserCreation.java
@@ -134,16 +134,16 @@ public class RegistrationUserCreation implements FormAction, FormActionFactory {
user.setEnabled(true);
user.setEmail(email);
- context.getClientSession().setNote(OIDCLoginProtocol.LOGIN_HINT_PARAM, username);
+ context.getLoginSession().setNote(OIDCLoginProtocol.LOGIN_HINT_PARAM, username);
AttributeFormDataProcessor.process(formData, context.getRealm(), user);
context.setUser(user);
context.getEvent().user(user);
context.getEvent().success();
context.newEvent().event(EventType.LOGIN);
- context.getEvent().client(context.getClientSession().getClient().getClientId())
- .detail(Details.REDIRECT_URI, context.getClientSession().getRedirectUri())
- .detail(Details.AUTH_METHOD, context.getClientSession().getAuthMethod());
- String authType = context.getClientSession().getNote(Details.AUTH_TYPE);
+ context.getEvent().client(context.getLoginSession().getClient().getClientId())
+ .detail(Details.REDIRECT_URI, context.getLoginSession().getRedirectUri())
+ .detail(Details.AUTH_METHOD, context.getLoginSession().getProtocol());
+ String authType = context.getLoginSession().getNote(Details.AUTH_TYPE);
if (authType != null) {
context.getEvent().detail(Details.AUTH_TYPE, authType);
}
diff --git a/services/src/main/java/org/keycloak/authentication/RequiredActionContextResult.java b/services/src/main/java/org/keycloak/authentication/RequiredActionContextResult.java
index 8f830d1..fd60a9d 100755
--- a/services/src/main/java/org/keycloak/authentication/RequiredActionContextResult.java
+++ b/services/src/main/java/org/keycloak/authentication/RequiredActionContextResult.java
@@ -23,13 +23,12 @@ import org.keycloak.common.ClientConnection;
import org.keycloak.common.util.Time;
import org.keycloak.events.EventBuilder;
import org.keycloak.forms.login.LoginFormsProvider;
-import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.resources.LoginActionsService;
+import org.keycloak.sessions.LoginSessionModel;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
@@ -40,8 +39,7 @@ import java.net.URI;
* @version $Revision: 1 $
*/
public class RequiredActionContextResult implements RequiredActionContext {
- protected UserSessionModel userSession;
- protected ClientSessionModel clientSession;
+ protected LoginSessionModel loginSession;
protected RealmModel realm;
protected EventBuilder eventBuilder;
protected KeycloakSession session;
@@ -51,12 +49,11 @@ public class RequiredActionContextResult implements RequiredActionContext {
protected UserModel user;
protected RequiredActionFactory factory;
- public RequiredActionContextResult(UserSessionModel userSession, ClientSessionModel clientSession,
+ public RequiredActionContextResult(LoginSessionModel loginSession,
RealmModel realm, EventBuilder eventBuilder, KeycloakSession session,
HttpRequest httpRequest,
UserModel user, RequiredActionFactory factory) {
- this.userSession = userSession;
- this.clientSession = clientSession;
+ this.loginSession = loginSession;
this.realm = realm;
this.eventBuilder = eventBuilder;
this.session = session;
@@ -81,13 +78,8 @@ public class RequiredActionContextResult implements RequiredActionContext {
}
@Override
- public ClientSessionModel getClientSession() {
- return clientSession;
- }
-
- @Override
- public UserSessionModel getUserSession() {
- return userSession;
+ public LoginSessionModel getLoginSession() {
+ return loginSession;
}
@Override
@@ -148,8 +140,8 @@ public class RequiredActionContextResult implements RequiredActionContext {
@Override
public String generateCode() {
- ClientSessionCode accessCode = new ClientSessionCode(session, getRealm(), getClientSession());
- clientSession.setTimestamp(Time.currentTime());
+ ClientSessionCode<LoginSessionModel> accessCode = new ClientSessionCode<>(session, getRealm(), getLoginSession());
+ loginSession.setTimestamp(Time.currentTime());
return accessCode.getCode();
}
diff --git a/services/src/main/java/org/keycloak/authentication/requiredactions/UpdatePassword.java b/services/src/main/java/org/keycloak/authentication/requiredactions/UpdatePassword.java
index aa5bf25..9984e82 100755
--- a/services/src/main/java/org/keycloak/authentication/requiredactions/UpdatePassword.java
+++ b/services/src/main/java/org/keycloak/authentication/requiredactions/UpdatePassword.java
@@ -88,8 +88,8 @@ public class UpdatePassword implements RequiredActionProvider, RequiredActionFac
String passwordConfirm = formData.getFirst("password-confirm");
EventBuilder errorEvent = event.clone().event(EventType.UPDATE_PASSWORD_ERROR)
- .client(context.getClientSession().getClient())
- .user(context.getClientSession().getUserSession().getUser());
+ .client(context.getLoginSession().getClient())
+ .user(context.getLoginSession().getAuthenticatedUser());
if (Validation.isBlank(passwordNew)) {
Response challenge = context.form()
diff --git a/services/src/main/java/org/keycloak/authentication/requiredactions/VerifyEmail.java b/services/src/main/java/org/keycloak/authentication/requiredactions/VerifyEmail.java
index 2d683d3..e45ddcb 100755
--- a/services/src/main/java/org/keycloak/authentication/requiredactions/VerifyEmail.java
+++ b/services/src/main/java/org/keycloak/authentication/requiredactions/VerifyEmail.java
@@ -62,6 +62,8 @@ public class VerifyEmail implements RequiredActionProvider, RequiredActionFactor
return;
}
+ // TODO:mposolda
+ /*
context.getEvent().clone().event(EventType.SEND_VERIFY_EMAIL).detail(Details.EMAIL, context.getUser().getEmail()).success();
LoginActionsService.createActionCookie(context.getRealm(), context.getUriInfo(), context.getConnection(), context.getUserSession().getId());
@@ -73,6 +75,7 @@ public class VerifyEmail implements RequiredActionProvider, RequiredActionFactor
.setUser(context.getUser());
Response challenge = loginFormsProvider.createResponse(UserModel.RequiredAction.VERIFY_EMAIL);
context.challenge(challenge);
+ */
}
@Override
diff --git a/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java b/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java
index 2e82794..88d8594 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java
@@ -38,6 +38,7 @@ import javax.ws.rs.core.Response;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.authorization.AuthorizationProvider;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.representations.idm.authorization.PolicyEvaluationRequest;
import org.keycloak.authorization.admin.representation.PolicyEvaluationResponseBuilder;
@@ -55,7 +56,6 @@ import org.keycloak.authorization.store.ScopeStore;
import org.keycloak.authorization.store.StoreFactory;
import org.keycloak.authorization.util.Permissions;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
@@ -67,6 +67,7 @@ import org.keycloak.representations.idm.authorization.ResourceRepresentation;
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
import org.keycloak.services.Urls;
import org.keycloak.services.resources.admin.RealmAuth;
+import org.keycloak.sessions.LoginSessionModel;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
@@ -192,19 +193,13 @@ public class PolicyEvaluationService {
private static class CloseableKeycloakIdentity extends KeycloakIdentity {
private UserSessionModel userSession;
- private ClientSessionModel clientSession;
- public CloseableKeycloakIdentity(AccessToken accessToken, KeycloakSession keycloakSession, UserSessionModel userSession, ClientSessionModel clientSession) {
+ public CloseableKeycloakIdentity(AccessToken accessToken, KeycloakSession keycloakSession, UserSessionModel userSession) {
super(accessToken, keycloakSession);
this.userSession = userSession;
- this.clientSession = clientSession;
}
public void close() {
- if (clientSession != null) {
- keycloakSession.sessions().removeClientSession(realm, clientSession);
- }
-
if (userSession != null) {
keycloakSession.sessions().removeUserSession(realm, userSession);
}
@@ -220,7 +215,7 @@ public class PolicyEvaluationService {
String subject = representation.getUserId();
- ClientSessionModel clientSession = null;
+ ClientLoginSessionModel clientSession = null;
UserSessionModel userSession = null;
if (subject != null) {
UserModel userModel = keycloakSession.users().getUserById(subject, realm);
@@ -234,11 +229,11 @@ public class PolicyEvaluationService {
if (clientId != null) {
ClientModel clientModel = realm.getClientById(clientId);
- clientSession = keycloakSession.sessions().createClientSession(realm, clientModel);
- clientSession.setAuthMethod(OIDCLoginProtocol.LOGIN_PROTOCOL);
+ LoginSessionModel loginSession = keycloakSession.loginSessions().createLoginSession(realm, clientModel, false);
+ loginSession.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
userSession = keycloakSession.sessions().createUserSession(realm, userModel, userModel.getUsername(), "127.0.0.1", "passwd", false, null, null);
- new TokenManager().attachClientSession(userSession, clientSession);
+ new TokenManager().attachLoginSession(keycloakSession, userSession, loginSession);
Set<RoleModel> requestedRoles = new HashSet<>();
for (String roleId : clientSession.getRoles()) {
@@ -276,6 +271,6 @@ public class PolicyEvaluationService {
representation.getRoleIds().forEach(roleName -> realmAccess.addRole(roleName));
}
- return new CloseableKeycloakIdentity(accessToken, keycloakSession, userSession, clientSession);
+ return new CloseableKeycloakIdentity(accessToken, keycloakSession, userSession);
}
}
\ No newline at end of file
diff --git a/services/src/main/java/org/keycloak/broker/provider/HardcodedUserSessionAttributeMapper.java b/services/src/main/java/org/keycloak/broker/provider/HardcodedUserSessionAttributeMapper.java
index e46798c..8409206 100755
--- a/services/src/main/java/org/keycloak/broker/provider/HardcodedUserSessionAttributeMapper.java
+++ b/services/src/main/java/org/keycloak/broker/provider/HardcodedUserSessionAttributeMapper.java
@@ -87,14 +87,14 @@ public class HardcodedUserSessionAttributeMapper extends AbstractIdentityProvide
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(ATTRIBUTE);
String attributeValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
- context.getClientSession().setUserSessionNote(attribute, attributeValue);
+ context.getLoginSession().setUserSessionNote(attribute, attributeValue);
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(ATTRIBUTE);
String attributeValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
- context.getClientSession().setUserSessionNote(attribute, attributeValue);
+ context.getLoginSession().setUserSessionNote(attribute, attributeValue);
}
@Override
diff --git a/services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java b/services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java
index 9f60404..b1c0872 100755
--- a/services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java
+++ b/services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java
@@ -23,8 +23,6 @@ import org.keycloak.authentication.requiredactions.util.UpdateProfileContext;
import org.keycloak.authentication.requiredactions.util.UserUpdateProfileContext;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.common.util.ObjectUtil;
-import org.keycloak.email.EmailException;
-import org.keycloak.email.EmailTemplateProvider;
import org.keycloak.forms.login.LoginFormsPages;
import org.keycloak.forms.login.LoginFormsProvider;
import org.keycloak.forms.login.freemarker.model.ClientBean;
@@ -39,8 +37,6 @@ import org.keycloak.forms.login.freemarker.model.RequiredActionUrlFormatterMetho
import org.keycloak.forms.login.freemarker.model.TotpBean;
import org.keycloak.forms.login.freemarker.model.UrlBean;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.Constants;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
@@ -50,6 +46,7 @@ import org.keycloak.models.UserModel;
import org.keycloak.models.utils.FormMessage;
import org.keycloak.services.Urls;
import org.keycloak.services.messages.Messages;
+import org.keycloak.sessions.LoginSessionModel;
import org.keycloak.theme.BrowserSecurityHeaderSetup;
import org.keycloak.theme.FreeMarkerException;
import org.keycloak.theme.FreeMarkerUtil;
@@ -77,7 +74,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
-import java.util.concurrent.TimeUnit;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -106,7 +102,7 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
private UserModel user;
- private ClientSessionModel clientSession;
+ private LoginSessionModel loginSession;
private final Map<String, Object> attributes = new HashMap<String, Object>();
public FreeMarkerLoginFormsProvider(KeycloakSession session, FreeMarkerUtil freeMarker) {
@@ -145,10 +141,11 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
page = LoginFormsPages.LOGIN_UPDATE_PASSWORD;
break;
case VERIFY_EMAIL:
- try {
+ // TODO:mposolda It should be also clientSession (actionTicket) involved here. Not just loginSession
+ /*try {
UriBuilder builder = Urls.loginActionEmailVerificationBuilder(uriInfo.getBaseUri());
builder.queryParam(OAuth2Constants.CODE, accessCode);
- builder.queryParam(Constants.KEY, clientSession.getNote(Constants.VERIFY_EMAIL_KEY));
+ builder.queryParam(Constants.KEY, loginSession.getNote(Constants.VERIFY_EMAIL_KEY));
String link = builder.build(realm.getName()).toString();
long expiration = TimeUnit.SECONDS.toMinutes(realm.getAccessCodeLifespanUserAction());
@@ -157,7 +154,7 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
} catch (EmailException e) {
logger.error("Failed to send verification email", e);
return setError(Messages.EMAIL_SENT_ERROR).createErrorPage();
- }
+ }*/
actionMessage = Messages.VERIFY_EMAIL;
page = LoginFormsPages.LOGIN_VERIFY_EMAIL;
@@ -298,7 +295,7 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
attributes.put("register", new RegisterBean(formData));
break;
case OAUTH_GRANT:
- attributes.put("oauth", new OAuthGrantBean(accessCode, clientSession, client, realmRolesRequested, resourceRolesRequested, protocolMappersRequested, this.accessRequestMessage));
+ attributes.put("oauth", new OAuthGrantBean(accessCode, client, realmRolesRequested, resourceRolesRequested, protocolMappersRequested, this.accessRequestMessage));
attributes.put("advancedMsg", new AdvancedMessageFormatterMethod(locale, messagesBundle));
break;
case CODE:
@@ -485,8 +482,7 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
}
@Override
- public Response createOAuthGrant(ClientSessionModel clientSession) {
- this.clientSession = clientSession;
+ public Response createOAuthGrant() {
return createResponse(LoginFormsPages.OAUTH_GRANT);
}
@@ -593,8 +589,8 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
}
@Override
- public LoginFormsProvider setClientSession(ClientSessionModel clientSession) {
- this.clientSession = clientSession;
+ public LoginFormsProvider setLoginSession(LoginSessionModel loginSession) {
+ this.loginSession = loginSession;
return this;
}
diff --git a/services/src/main/java/org/keycloak/forms/login/freemarker/model/OAuthGrantBean.java b/services/src/main/java/org/keycloak/forms/login/freemarker/model/OAuthGrantBean.java
index 556db25..bf424cb 100755
--- a/services/src/main/java/org/keycloak/forms/login/freemarker/model/OAuthGrantBean.java
+++ b/services/src/main/java/org/keycloak/forms/login/freemarker/model/OAuthGrantBean.java
@@ -18,7 +18,6 @@ package org.keycloak.forms.login.freemarker.model;
import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RoleModel;
@@ -38,7 +37,7 @@ public class OAuthGrantBean {
private ClientModel client;
private List<String> claimsRequested;
- public OAuthGrantBean(String code, ClientSessionModel clientSession, ClientModel client, List<RoleModel> realmRolesRequested, MultivaluedMap<String, RoleModel> resourceRolesRequested,
+ public OAuthGrantBean(String code, ClientModel client, List<RoleModel> realmRolesRequested, MultivaluedMap<String, RoleModel> resourceRolesRequested,
List<ProtocolMapperModel> protocolMappersRequested, String accessRequestMessage) {
this.code = code;
this.client = client;
diff --git a/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java b/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java
index 0c1462c..f0387e8 100755
--- a/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java
+++ b/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java
@@ -30,6 +30,7 @@ import org.keycloak.protocol.LoginProtocol.Error;
import org.keycloak.services.ServicesLogger;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.resources.LoginActionsService;
+import org.keycloak.sessions.LoginSessionModel;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
@@ -63,9 +64,9 @@ public abstract class AuthorizationEndpointBase {
this.event = event;
}
- protected AuthenticationProcessor createProcessor(ClientSessionModel clientSession, String flowId, String flowPath) {
+ protected AuthenticationProcessor createProcessor(LoginSessionModel loginSession, String flowId, String flowPath) {
AuthenticationProcessor processor = new AuthenticationProcessor();
- processor.setClientSession(clientSession)
+ processor.setLoginSession(loginSession)
.setFlowPath(flowPath)
.setFlowId(flowId)
.setBrowserFlow(true)
@@ -81,42 +82,45 @@ public abstract class AuthorizationEndpointBase {
/**
* Common method to handle browser authentication request in protocols unified way.
*
- * @param clientSession for current request
+ * @param loginSession for current request
* @param protocol handler for protocol used to initiate login
* @param isPassive set to true if login should be passive (without login screen shown)
* @param redirectToAuthentication if true redirect to flow url. If initial call to protocol is a POST, you probably want to do this. This is so we can disable the back button on browser
* @return response to be returned to the browser
*/
- protected Response handleBrowserAuthenticationRequest(ClientSessionModel clientSession, LoginProtocol protocol, boolean isPassive, boolean redirectToAuthentication) {
+ protected Response handleBrowserAuthenticationRequest(LoginSessionModel loginSession, LoginProtocol protocol, boolean isPassive, boolean redirectToAuthentication) {
AuthenticationFlowModel flow = getAuthenticationFlow();
String flowId = flow.getId();
- AuthenticationProcessor processor = createProcessor(clientSession, flowId, LoginActionsService.AUTHENTICATE_PATH);
- event.detail(Details.CODE_ID, clientSession.getId());
+ AuthenticationProcessor processor = createProcessor(loginSession, flowId, LoginActionsService.AUTHENTICATE_PATH);
+ event.detail(Details.CODE_ID, loginSession.getId());
if (isPassive) {
// OIDC prompt == NONE or SAML 2 IsPassive flag
// This means that client is just checking if the user is already completely logged in.
// We cancel login if any authentication action or required action is required
try {
if (processor.authenticateOnly() == null) {
- processor.attachSession();
+ // processor.attachSession();
} else {
- Response response = protocol.sendError(clientSession, Error.PASSIVE_LOGIN_REQUIRED);
- session.sessions().removeClientSession(realm, clientSession);
+ Response response = protocol.sendError(loginSession, Error.PASSIVE_LOGIN_REQUIRED);
+ session.loginSessions().removeLoginSession(realm, loginSession);
return response;
}
if (processor.isActionRequired()) {
- Response response = protocol.sendError(clientSession, Error.PASSIVE_INTERACTION_REQUIRED);
- session.sessions().removeClientSession(realm, clientSession);
+ Response response = protocol.sendError(loginSession, Error.PASSIVE_INTERACTION_REQUIRED);
+ session.loginSessions().removeLoginSession(realm, loginSession);
return response;
-
}
+
+ // Attach session once no requiredActions or other things are required
+ processor.attachSession();
} catch (Exception e) {
return processor.handleBrowserException(e);
}
return processor.finishAuthentication(protocol);
} else {
try {
- RestartLoginCookie.setRestartCookie(session, realm, clientConnection, uriInfo, clientSession);
+ // TODO: Check if this is required...
+ RestartLoginCookie.setRestartCookie(session, realm, clientConnection, uriInfo, loginSession);
if (redirectToAuthentication) {
return processor.redirectToFlow();
}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
index 1588321..3a41f92 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
@@ -44,6 +44,7 @@ import org.keycloak.services.Urls;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.LoginActionsService;
import org.keycloak.services.util.CacheControlUtil;
+import org.keycloak.sessions.LoginSessionModel;
import org.keycloak.util.TokenUtil;
import javax.ws.rs.GET;
@@ -63,12 +64,12 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
public static final String CODE_AUTH_TYPE = "code";
/**
- * Prefix used to store additional HTTP GET params from original client request into {@link ClientSessionModel} note to be available later in Authenticators, RequiredActions etc. Prefix is used to
+ * Prefix used to store additional HTTP GET params from original client request into {@link LoginSessionModel} note to be available later in Authenticators, RequiredActions etc. Prefix is used to
* prevent collisions with internally used notes.
*
- * @see ClientSessionModel#getNote(String)
+ * @see LoginSessionModel#getNote(String)
*/
- public static final String CLIENT_SESSION_NOTE_ADDITIONAL_REQ_PARAMS_PREFIX = "client_request_param_";
+ public static final String LOGIN_SESSION_NOTE_ADDITIONAL_REQ_PARAMS_PREFIX = "client_request_param_";
// https://tools.ietf.org/html/rfc7636#section-4.2
private static final Pattern VALID_CODE_CHALLENGE_PATTERN = Pattern.compile("^[0-9a-zA-Z\\-\\.~_]+$");
@@ -78,7 +79,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
}
private ClientModel client;
- private ClientSessionModel clientSession;
+ private LoginSessionModel loginSession;
private Action action;
private OIDCResponseType parsedResponseType;
@@ -125,7 +126,8 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
return errorResponse;
}
- createClientSession();
+ createLoginSession();
+
// So back button doesn't work
CacheControlUtil.noBackButtonCacheControlHeader();
switch (action) {
@@ -356,44 +358,44 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
}
}
- private void createClientSession() {
- clientSession = session.sessions().createClientSession(realm, client);
- clientSession.setAuthMethod(OIDCLoginProtocol.LOGIN_PROTOCOL);
- clientSession.setRedirectUri(redirectUri);
- clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
- clientSession.setNote(OIDCLoginProtocol.RESPONSE_TYPE_PARAM, request.getResponseType());
- clientSession.setNote(OIDCLoginProtocol.REDIRECT_URI_PARAM, request.getRedirectUriParam());
- clientSession.setNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
-
- if (request.getState() != null) clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, request.getState());
- if (request.getNonce() != null) clientSession.setNote(OIDCLoginProtocol.NONCE_PARAM, request.getNonce());
- if (request.getMaxAge() != null) clientSession.setNote(OIDCLoginProtocol.MAX_AGE_PARAM, String.valueOf(request.getMaxAge()));
- if (request.getScope() != null) clientSession.setNote(OIDCLoginProtocol.SCOPE_PARAM, request.getScope());
- if (request.getLoginHint() != null) clientSession.setNote(OIDCLoginProtocol.LOGIN_HINT_PARAM, request.getLoginHint());
- if (request.getPrompt() != null) clientSession.setNote(OIDCLoginProtocol.PROMPT_PARAM, request.getPrompt());
- if (request.getIdpHint() != null) clientSession.setNote(AdapterConstants.KC_IDP_HINT, request.getIdpHint());
- if (request.getResponseMode() != null) clientSession.setNote(OIDCLoginProtocol.RESPONSE_MODE_PARAM, request.getResponseMode());
+ private void createLoginSession() {
+ loginSession = session.loginSessions().createLoginSession(realm, client, true);
+ loginSession.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
+ loginSession.setRedirectUri(redirectUri);
+ loginSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
+ loginSession.setNote(OIDCLoginProtocol.RESPONSE_TYPE_PARAM, request.getResponseType());
+ loginSession.setNote(OIDCLoginProtocol.REDIRECT_URI_PARAM, request.getRedirectUriParam());
+ loginSession.setNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
+
+ if (request.getState() != null) loginSession.setNote(OIDCLoginProtocol.STATE_PARAM, request.getState());
+ if (request.getNonce() != null) loginSession.setNote(OIDCLoginProtocol.NONCE_PARAM, request.getNonce());
+ if (request.getMaxAge() != null) loginSession.setNote(OIDCLoginProtocol.MAX_AGE_PARAM, String.valueOf(request.getMaxAge()));
+ if (request.getScope() != null) loginSession.setNote(OIDCLoginProtocol.SCOPE_PARAM, request.getScope());
+ if (request.getLoginHint() != null) loginSession.setNote(OIDCLoginProtocol.LOGIN_HINT_PARAM, request.getLoginHint());
+ if (request.getPrompt() != null) loginSession.setNote(OIDCLoginProtocol.PROMPT_PARAM, request.getPrompt());
+ if (request.getIdpHint() != null) loginSession.setNote(AdapterConstants.KC_IDP_HINT, request.getIdpHint());
+ if (request.getResponseMode() != null) loginSession.setNote(OIDCLoginProtocol.RESPONSE_MODE_PARAM, request.getResponseMode());
// https://tools.ietf.org/html/rfc7636#section-4
- if (request.getCodeChallenge() != null) clientSession.setNote(OIDCLoginProtocol.CODE_CHALLENGE_PARAM, request.getCodeChallenge());
+ if (request.getCodeChallenge() != null) loginSession.setNote(OIDCLoginProtocol.CODE_CHALLENGE_PARAM, request.getCodeChallenge());
if (request.getCodeChallengeMethod() != null) {
- clientSession.setNote(OIDCLoginProtocol.CODE_CHALLENGE_METHOD_PARAM, request.getCodeChallengeMethod());
+ loginSession.setNote(OIDCLoginProtocol.CODE_CHALLENGE_METHOD_PARAM, request.getCodeChallengeMethod());
} else {
- clientSession.setNote(OIDCLoginProtocol.CODE_CHALLENGE_METHOD_PARAM, OIDCLoginProtocol.PKCE_METHOD_PLAIN);
+ loginSession.setNote(OIDCLoginProtocol.CODE_CHALLENGE_METHOD_PARAM, OIDCLoginProtocol.PKCE_METHOD_PLAIN);
}
if (request.getAdditionalReqParams() != null) {
for (String paramName : request.getAdditionalReqParams().keySet()) {
- clientSession.setNote(CLIENT_SESSION_NOTE_ADDITIONAL_REQ_PARAMS_PREFIX + paramName, request.getAdditionalReqParams().get(paramName));
+ loginSession.setNote(LOGIN_SESSION_NOTE_ADDITIONAL_REQ_PARAMS_PREFIX + paramName, request.getAdditionalReqParams().get(paramName));
}
}
}
private Response buildAuthorizationCodeAuthorizationResponse() {
this.event.event(EventType.LOGIN);
- clientSession.setNote(Details.AUTH_TYPE, CODE_AUTH_TYPE);
+ loginSession.setNote(Details.AUTH_TYPE, CODE_AUTH_TYPE);
- return handleBrowserAuthenticationRequest(clientSession, new OIDCLoginProtocol(session, realm, uriInfo, headers, event), TokenUtil.hasPrompt(request.getPrompt(), OIDCLoginProtocol.PROMPT_VALUE_NONE), false);
+ return handleBrowserAuthenticationRequest(loginSession, new OIDCLoginProtocol(session, realm, uriInfo, headers, event), TokenUtil.hasPrompt(request.getPrompt(), OIDCLoginProtocol.PROMPT_VALUE_NONE), false);
}
private Response buildRegister() {
@@ -402,7 +404,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
AuthenticationFlowModel flow = realm.getRegistrationFlow();
String flowId = flow.getId();
- AuthenticationProcessor processor = createProcessor(clientSession, flowId, LoginActionsService.REGISTRATION_PATH);
+ AuthenticationProcessor processor = createProcessor(loginSession, flowId, LoginActionsService.REGISTRATION_PATH);
return processor.authenticate();
}
@@ -413,7 +415,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
AuthenticationFlowModel flow = realm.getResetCredentialsFlow();
String flowId = flow.getId();
- AuthenticationProcessor processor = createProcessor(clientSession, flowId, LoginActionsService.RESET_CREDENTIALS_PATH);
+ AuthenticationProcessor processor = createProcessor(loginSession, flowId, LoginActionsService.RESET_CREDENTIALS_PATH);
return processor.authenticate();
}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java
index 8fa4341..e308bc9 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java
@@ -32,13 +32,12 @@ import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.models.AuthenticationFlowModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
-import org.keycloak.models.UserSessionProvider;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.protocol.oidc.TokenManager;
import org.keycloak.protocol.oidc.utils.AuthorizeClientUtil;
@@ -52,6 +51,7 @@ import org.keycloak.services.managers.ClientManager;
import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.Cors;
+import org.keycloak.sessions.LoginSessionModel;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.POST;
@@ -62,7 +62,6 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
-import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -208,29 +207,37 @@ public class TokenEndpoint {
throw new ErrorResponseException(OAuthErrorException.INVALID_REQUEST, "Missing parameter: " + OAuth2Constants.CODE, Response.Status.BAD_REQUEST);
}
- ClientSessionCode.ParseResult parseResult = ClientSessionCode.parseResult(code, session, realm);
- if (parseResult.isClientSessionNotFound() || parseResult.isIllegalHash()) {
+ ClientSessionCode.ParseResult<ClientLoginSessionModel> parseResult = ClientSessionCode.parseResult(code, session, realm, ClientLoginSessionModel.class);
+ if (parseResult.isLoginSessionNotFound() || parseResult.isIllegalHash()) {
String[] parts = code.split("\\.");
if (parts.length == 2) {
event.detail(Details.CODE_ID, parts[1]);
}
event.error(Errors.INVALID_CODE);
- if (parseResult.getClientSession() != null) {
- session.sessions().removeClientSession(realm, parseResult.getClientSession());
+
+ // Attempt to use same code twice should invalidate existing clientSession
+ ClientLoginSessionModel clientSession = parseResult.getClientSession();
+ if (clientSession != null) {
+ UserSessionModel userSession = clientSession.getUserSession();
+ String clientUUID = clientSession.getClient().getId();
+ userSession.getClientLoginSessions().remove(clientUUID);
}
+
throw new ErrorResponseException(OAuthErrorException.INVALID_GRANT, "Code not valid", Response.Status.BAD_REQUEST);
}
- ClientSessionModel clientSession = parseResult.getClientSession();
+ ClientLoginSessionModel clientSession = parseResult.getClientSession();
event.detail(Details.CODE_ID, clientSession.getId());
- if (!parseResult.getCode().isValid(ClientSessionModel.Action.CODE_TO_TOKEN.name(), ClientSessionCode.ActionType.CLIENT)) {
+ if (!parseResult.getCode().isValid(ClientLoginSessionModel.Action.CODE_TO_TOKEN.name(), ClientSessionCode.ActionType.CLIENT)) {
event.error(Errors.INVALID_CODE);
throw new ErrorResponseException(OAuthErrorException.INVALID_GRANT, "Code is expired", Response.Status.BAD_REQUEST);
}
+ // TODO: This shouldn't be needed to write into the clientLoginSessionModel itself
parseResult.getCode().setAction(null);
+ // TODO: Maybe rather create userSession even at this stage? Not sure...
UserSessionModel userSession = clientSession.getUserSession();
if (userSession == null) {
@@ -355,7 +362,8 @@ public class TokenEndpoint {
if (!result.isOfflineToken()) {
UserSessionModel userSession = session.sessions().getUserSession(realm, res.getSessionState());
- updateClientSessions(userSession.getClientSessions());
+ ClientLoginSessionModel clientSession = userSession.getClientLoginSessions().get(client.getId());
+ updateClientSession(clientSession);
updateUserSessionFromClientAuth(userSession);
}
@@ -369,7 +377,7 @@ public class TokenEndpoint {
return Cors.add(request, Response.ok(res, MediaType.APPLICATION_JSON_TYPE)).auth().allowedOrigins(uriInfo, client).allowedMethods("POST").exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS).build();
}
- private void updateClientSession(ClientSessionModel clientSession) {
+ private void updateClientSession(ClientLoginSessionModel clientSession) {
if(clientSession == null) {
ServicesLogger.LOGGER.clientSessionNull();
@@ -388,26 +396,6 @@ public class TokenEndpoint {
}
}
- private void updateClientSessions(List<ClientSessionModel> clientSessions) {
- if(clientSessions == null) {
- ServicesLogger.LOGGER.clientSessionNull();
- return;
- }
- for (ClientSessionModel clientSession : clientSessions) {
- if(clientSession == null) {
- ServicesLogger.LOGGER.clientSessionNull();
- continue;
- }
- if(clientSession.getClient() == null) {
- ServicesLogger.LOGGER.clientModelNull();
- continue;
- }
- if(client.getId().equals(clientSession.getClient().getId())) {
- updateClientSession(clientSession);
- }
- }
- }
-
private void updateUserSessionFromClientAuth(UserSessionModel userSession) {
for (Map.Entry<String, String> attr : clientAuthAttributes.entrySet()) {
userSession.setNote(attr.getKey(), attr.getValue());
@@ -428,17 +416,16 @@ public class TokenEndpoint {
}
String scope = formParams.getFirst(OAuth2Constants.SCOPE);
- UserSessionProvider sessions = session.sessions();
- ClientSessionModel clientSession = sessions.createClientSession(realm, client);
- clientSession.setAuthMethod(OIDCLoginProtocol.LOGIN_PROTOCOL);
- clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
- clientSession.setNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
- clientSession.setNote(OIDCLoginProtocol.SCOPE_PARAM, scope);
+ LoginSessionModel loginSession = session.loginSessions().createLoginSession(realm, client, false);
+ loginSession.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
+ loginSession.setAction(ClientLoginSessionModel.Action.AUTHENTICATE.name());
+ loginSession.setNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
+ loginSession.setNote(OIDCLoginProtocol.SCOPE_PARAM, scope);
AuthenticationFlowModel flow = realm.getDirectGrantFlow();
String flowId = flow.getId();
AuthenticationProcessor processor = new AuthenticationProcessor();
- processor.setClientSession(clientSession)
+ processor.setLoginSession(loginSession)
.setFlowId(flowId)
.setConnection(clientConnection)
.setEventBuilder(event)
@@ -449,13 +436,13 @@ public class TokenEndpoint {
Response challenge = processor.authenticateOnly();
if (challenge != null) return challenge;
processor.evaluateRequiredActionTriggers();
- UserModel user = clientSession.getAuthenticatedUser();
+ UserModel user = loginSession.getAuthenticatedUser();
if (user.getRequiredActions() != null && user.getRequiredActions().size() > 0) {
event.error(Errors.RESOLVE_REQUIRED_ACTIONS);
throw new ErrorResponseException(OAuthErrorException.INVALID_GRANT, "Account is not fully set up", Response.Status.BAD_REQUEST);
}
- processor.attachSession();
+ ClientLoginSessionModel clientSession = processor.attachSession();
UserSessionModel userSession = processor.getUserSession();
updateUserSessionFromClientAuth(userSession);
@@ -505,17 +492,15 @@ public class TokenEndpoint {
String scope = formParams.getFirst(OAuth2Constants.SCOPE);
- UserSessionProvider sessions = session.sessions();
-
- ClientSessionModel clientSession = sessions.createClientSession(realm, client);
- clientSession.setAuthMethod(OIDCLoginProtocol.LOGIN_PROTOCOL);
- clientSession.setNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
- clientSession.setNote(OIDCLoginProtocol.SCOPE_PARAM, scope);
+ LoginSessionModel loginSession = session.loginSessions().createLoginSession(realm, client, false);
+ loginSession.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
+ loginSession.setNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
+ loginSession.setNote(OIDCLoginProtocol.SCOPE_PARAM, scope);
- UserSessionModel userSession = sessions.createUserSession(realm, clientUser, clientUsername, clientConnection.getRemoteAddr(), ServiceAccountConstants.CLIENT_AUTH, false, null, null);
+ UserSessionModel userSession = session.sessions().createUserSession(realm, clientUser, clientUsername, clientConnection.getRemoteAddr(), ServiceAccountConstants.CLIENT_AUTH, false, null, null);
event.session(userSession);
- TokenManager.attachClientSession(userSession, clientSession);
+ ClientLoginSessionModel clientSession = TokenManager.attachLoginSession(session, userSession, loginSession);
// Notes about client details
userSession.setNote(ServiceAccountConstants.CLIENT_ID, client.getClientId());
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
index 8984a4d..763da1e 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
@@ -29,6 +29,7 @@ import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.jose.jws.Algorithm;
import org.keycloak.jose.jws.JWSBuilder;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractOIDCProtocolMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractOIDCProtocolMapper.java
index efe9434..d439343 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractOIDCProtocolMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractOIDCProtocolMapper.java
@@ -18,7 +18,7 @@
package org.keycloak.protocol.oidc.mappers;
import org.keycloak.Config;
-import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.ProtocolMapperModel;
@@ -61,7 +61,7 @@ public abstract class AbstractOIDCProtocolMapper implements ProtocolMapper {
}
public AccessToken transformUserInfoToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
- UserSessionModel userSession, ClientSessionModel clientSession) {
+ UserSessionModel userSession, ClientLoginSessionModel clientSession) {
if (!OIDCAttributeMapperHelper.includeInUserInfo(mappingModel)) {
return token;
@@ -72,7 +72,7 @@ public abstract class AbstractOIDCProtocolMapper implements ProtocolMapper {
}
public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
- UserSessionModel userSession, ClientSessionModel clientSession) {
+ UserSessionModel userSession, ClientLoginSessionModel clientSession) {
if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)){
return token;
@@ -83,7 +83,7 @@ public abstract class AbstractOIDCProtocolMapper implements ProtocolMapper {
}
public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
- UserSessionModel userSession, ClientSessionModel clientSession) {
+ UserSessionModel userSession, ClientLoginSessionModel clientSession) {
if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)){
return token;
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractPairwiseSubMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractPairwiseSubMapper.java
index 4666034..4b8b1f3 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractPairwiseSubMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractPairwiseSubMapper.java
@@ -1,7 +1,7 @@
package org.keycloak.protocol.oidc.mappers;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperContainerModel;
import org.keycloak.models.ProtocolMapperModel;
@@ -64,19 +64,19 @@ public abstract class AbstractPairwiseSubMapper extends AbstractOIDCProtocolMapp
}
@Override
- public final IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+ public final IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientLoginSessionModel clientSession) {
setSubject(token, generateSub(mappingModel, getSectorIdentifier(clientSession.getClient(), mappingModel), userSession.getUser().getId()));
return token;
}
@Override
- public final AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+ public final AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientLoginSessionModel clientSession) {
setSubject(token, generateSub(mappingModel, getSectorIdentifier(clientSession.getClient(), mappingModel), userSession.getUser().getId()));
return token;
}
@Override
- public final AccessToken transformUserInfoToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+ public final AccessToken transformUserInfoToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientLoginSessionModel clientSession) {
setSubject(token, generateSub(mappingModel, getSectorIdentifier(clientSession.getClient(), mappingModel), userSession.getUser().getId()));
return token;
}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/FullNameMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/FullNameMapper.java
index 1e4ad9d..1e9b3e2 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/FullNameMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/FullNameMapper.java
@@ -17,14 +17,11 @@
package org.keycloak.protocol.oidc.mappers;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.representations.AccessToken;
import org.keycloak.representations.IDToken;
import java.util.ArrayList;
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/GroupMembershipMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/GroupMembershipMapper.java
index 41dbb47..b733f5c 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/GroupMembershipMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/GroupMembershipMapper.java
@@ -17,15 +17,12 @@
package org.keycloak.protocol.oidc.mappers;
-import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.GroupModel;
-import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.representations.AccessToken;
import org.keycloak.representations.IDToken;
import java.util.ArrayList;
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedClaim.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedClaim.java
index 4062824..8d48ccf 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedClaim.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedClaim.java
@@ -17,13 +17,10 @@
package org.keycloak.protocol.oidc.mappers;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.representations.AccessToken;
import org.keycloak.representations.IDToken;
import java.util.ArrayList;
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedRole.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedRole.java
index 03ecb91..7ebb435 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedRole.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedRole.java
@@ -17,7 +17,7 @@
package org.keycloak.protocol.oidc.mappers;
-import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserSessionModel;
@@ -82,7 +82,7 @@ public class HardcodedRole extends AbstractOIDCProtocolMapper implements OIDCAcc
@Override
public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
- UserSessionModel userSession, ClientSessionModel clientSession) {
+ UserSessionModel userSession, ClientLoginSessionModel clientSession) {
String role = mappingModel.getConfig().get(ROLE_CONFIG);
String[] scopedRole = KeycloakModelUtils.parseRole(role);
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAccessTokenMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAccessTokenMapper.java
index 71dce26..387ef5c 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAccessTokenMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAccessTokenMapper.java
@@ -17,7 +17,7 @@
package org.keycloak.protocol.oidc.mappers;
-import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserSessionModel;
@@ -30,5 +30,5 @@ import org.keycloak.representations.AccessToken;
public interface OIDCAccessTokenMapper {
AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
- UserSessionModel userSession, ClientSessionModel clientSession);
+ UserSessionModel userSession, ClientLoginSessionModel clientSession);
}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCIDTokenMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCIDTokenMapper.java
index dabc4a3..ca80ed5 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCIDTokenMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCIDTokenMapper.java
@@ -17,7 +17,7 @@
package org.keycloak.protocol.oidc.mappers;
-import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserSessionModel;
@@ -30,5 +30,5 @@ import org.keycloak.representations.IDToken;
public interface OIDCIDTokenMapper {
IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
- UserSessionModel userSession, ClientSessionModel clientSession);
+ UserSessionModel userSession, ClientLoginSessionModel clientSession);
}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java
index fcdc373..c910400 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java
@@ -17,7 +17,7 @@
package org.keycloak.protocol.oidc.mappers;
-import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserSessionModel;
@@ -25,7 +25,6 @@ import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.AccessToken;
-import org.keycloak.representations.IDToken;
import java.util.ArrayList;
import java.util.HashMap;
@@ -90,7 +89,7 @@ public class RoleNameMapper extends AbstractOIDCProtocolMapper implements OIDCAc
@Override
public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
- UserSessionModel userSession, ClientSessionModel clientSession) {
+ UserSessionModel userSession, ClientLoginSessionModel clientSession) {
String role = mappingModel.getConfig().get(ROLE_CONFIG);
String newName = mappingModel.getConfig().get(NEW_ROLE_NAME);
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserAttributeMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserAttributeMapper.java
index e6d0d20..9b2cf0f 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserAttributeMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserAttributeMapper.java
@@ -17,15 +17,12 @@
package org.keycloak.protocol.oidc.mappers;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.protocol.ProtocolMapperUtils;
import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.representations.AccessToken;
import org.keycloak.representations.IDToken;
import java.util.ArrayList;
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserInfoTokenMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserInfoTokenMapper.java
index 67ac1a2..af5084c 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserInfoTokenMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserInfoTokenMapper.java
@@ -17,7 +17,7 @@
package org.keycloak.protocol.oidc.mappers;
-import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserSessionModel;
@@ -29,5 +29,5 @@ import org.keycloak.representations.AccessToken;
public interface UserInfoTokenMapper {
AccessToken transformUserInfoToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
- UserSessionModel userSession, ClientSessionModel clientSession);
+ UserSessionModel userSession, ClientLoginSessionModel clientSession);
}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserPropertyMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserPropertyMapper.java
index 6fd6491..2fc84ff 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserPropertyMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserPropertyMapper.java
@@ -17,14 +17,11 @@
package org.keycloak.protocol.oidc.mappers;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.ProtocolMapperUtils;
import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.representations.AccessToken;
import org.keycloak.representations.IDToken;
import java.util.ArrayList;
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserSessionNoteMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserSessionNoteMapper.java
index fd6bfe1..aadee6c 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserSessionNoteMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserSessionNoteMapper.java
@@ -17,14 +17,11 @@
package org.keycloak.protocol.oidc.mappers;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.ProtocolMapperUtils;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.representations.AccessToken;
import org.keycloak.representations.IDToken;
import java.util.ArrayList;
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
index 4c0691a..5dd0433 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
@@ -23,8 +23,8 @@ import org.keycloak.common.util.Time;
import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
@@ -38,6 +38,8 @@ import org.keycloak.services.ServicesLogger;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.managers.ResourceAdminManager;
+import org.keycloak.sessions.CommonClientSessionModel;
+import org.keycloak.sessions.LoginSessionModel;
import org.keycloak.util.TokenUtil;
import javax.ws.rs.core.HttpHeaders;
@@ -128,7 +130,7 @@ public class OIDCLoginProtocol implements LoginProtocol {
}
- private void setupResponseTypeAndMode(ClientSessionModel clientSession) {
+ private void setupResponseTypeAndMode(CommonClientSessionModel clientSession) {
String responseType = clientSession.getNote(OIDCLoginProtocol.RESPONSE_TYPE_PARAM);
String responseMode = clientSession.getNote(OIDCLoginProtocol.RESPONSE_MODE_PARAM);
this.responseType = OIDCResponseType.parse(responseType);
@@ -169,8 +171,8 @@ public class OIDCLoginProtocol implements LoginProtocol {
@Override
- public Response authenticated(UserSessionModel userSession, ClientSessionCode accessCode) {
- ClientSessionModel clientSession = accessCode.getClientSession();
+ public Response authenticated(UserSessionModel userSession, ClientSessionCode<ClientLoginSessionModel> accessCode) {
+ ClientLoginSessionModel clientSession = accessCode.getClientSession();
setupResponseTypeAndMode(clientSession);
String redirect = clientSession.getRedirectUri();
@@ -182,7 +184,7 @@ public class OIDCLoginProtocol implements LoginProtocol {
// Standard or hybrid flow
if (responseType.hasResponseType(OIDCResponseType.CODE)) {
- accessCode.setAction(ClientSessionModel.Action.CODE_TO_TOKEN.name());
+ accessCode.setAction(CommonClientSessionModel.Action.CODE_TO_TOKEN.name());
redirectUri.addParam(OAuth2Constants.CODE, accessCode.getCode());
}
@@ -227,15 +229,15 @@ public class OIDCLoginProtocol implements LoginProtocol {
@Override
- public Response sendError(ClientSessionModel clientSession, Error error) {
- setupResponseTypeAndMode(clientSession);
+ public Response sendError(LoginSessionModel loginSession, Error error) {
+ setupResponseTypeAndMode(loginSession);
- String redirect = clientSession.getRedirectUri();
- String state = clientSession.getNote(OIDCLoginProtocol.STATE_PARAM);
+ String redirect = loginSession.getRedirectUri();
+ String state = loginSession.getNote(OIDCLoginProtocol.STATE_PARAM);
OIDCRedirectUriBuilder redirectUri = OIDCRedirectUriBuilder.fromUri(redirect, responseMode).addParam(OAuth2Constants.ERROR, translateError(error));
if (state != null)
redirectUri.addParam(OAuth2Constants.STATE, state);
- session.sessions().removeClientSession(realm, clientSession);
+ session.loginSessions().removeLoginSession(realm, loginSession);
RestartLoginCookie.expireRestartCookie(realm, session.getContext().getConnection(), uriInfo);
return redirectUri.build();
}
@@ -256,13 +258,13 @@ public class OIDCLoginProtocol implements LoginProtocol {
}
@Override
- public void backchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) {
+ public void backchannelLogout(UserSessionModel userSession, ClientLoginSessionModel clientSession) {
ClientModel client = clientSession.getClient();
new ResourceAdminManager(session).logoutClientSession(uriInfo.getRequestUri(), realm, client, clientSession);
}
@Override
- public Response frontchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) {
+ public Response frontchannelLogout(UserSessionModel userSession, ClientLoginSessionModel clientSession) {
// todo oidc redirect support
throw new RuntimeException("NOT IMPLEMENTED");
}
@@ -289,18 +291,18 @@ public class OIDCLoginProtocol implements LoginProtocol {
@Override
- public boolean requireReauthentication(UserSessionModel userSession, ClientSessionModel clientSession) {
- return isPromptLogin(clientSession) || isAuthTimeExpired(userSession, clientSession);
+ public boolean requireReauthentication(UserSessionModel userSession, LoginSessionModel loginSession) {
+ return isPromptLogin(loginSession) || isAuthTimeExpired(userSession, loginSession);
}
- protected boolean isPromptLogin(ClientSessionModel clientSession) {
- String prompt = clientSession.getNote(OIDCLoginProtocol.PROMPT_PARAM);
+ protected boolean isPromptLogin(LoginSessionModel loginSession) {
+ String prompt = loginSession.getNote(OIDCLoginProtocol.PROMPT_PARAM);
return TokenUtil.hasPrompt(prompt, OIDCLoginProtocol.PROMPT_VALUE_LOGIN);
}
- protected boolean isAuthTimeExpired(UserSessionModel userSession, ClientSessionModel clientSession) {
+ protected boolean isAuthTimeExpired(UserSessionModel userSession, LoginSessionModel loginSession) {
String authTime = userSession.getNote(AuthenticationManager.AUTH_TIME);
- String maxAge = clientSession.getNote(OIDCLoginProtocol.MAX_AGE_PARAM);
+ String maxAge = loginSession.getNote(OIDCLoginProtocol.MAX_AGE_PARAM);
if (maxAge == null) {
return false;
}
@@ -310,7 +312,7 @@ public class OIDCLoginProtocol implements LoginProtocol {
if (authTimeInt + maxAgeInt < Time.currentTime()) {
logger.debugf("Authentication time is expired, needs to reauthenticate. userSession=%s, clientId=%s, maxAge=%d, authTime=%d", userSession.getId(),
- clientSession.getClient().getId(), maxAgeInt, authTimeInt);
+ loginSession.getClient().getId(), maxAgeInt, authTimeInt);
return true;
}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
index 4cedd6b..49a47a1 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
@@ -31,6 +31,7 @@ import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.JWSInputException;
import org.keycloak.jose.jws.crypto.HashProvider;
import org.keycloak.jose.jws.crypto.RSAProvider;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.ClientTemplateModel;
@@ -38,7 +39,6 @@ import org.keycloak.models.GroupModel;
import org.keycloak.models.KeyManager;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.ModelException;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
@@ -60,6 +60,7 @@ import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.managers.UserSessionManager;
+import org.keycloak.sessions.LoginSessionModel;
import org.keycloak.util.TokenUtil;
import org.keycloak.common.util.Time;
@@ -107,10 +108,10 @@ public class TokenManager {
public static class TokenValidation {
public final UserModel user;
public final UserSessionModel userSession;
- public final ClientSessionModel clientSession;
+ public final ClientLoginSessionModel clientSession;
public final AccessToken newToken;
- public TokenValidation(UserModel user, UserSessionModel userSession, ClientSessionModel clientSession, AccessToken newToken) {
+ public TokenValidation(UserModel user, UserSessionModel userSession, ClientLoginSessionModel clientSession, AccessToken newToken) {
this.user = user;
this.userSession = userSession;
this.clientSession = clientSession;
@@ -129,29 +130,18 @@ public class TokenManager {
}
UserSessionModel userSession = null;
- ClientSessionModel clientSession = null;
if (TokenUtil.TOKEN_TYPE_OFFLINE.equals(oldToken.getType())) {
UserSessionManager sessionManager = new UserSessionManager(session);
- clientSession = sessionManager.findOfflineClientSession(realm, oldToken.getClientSession());
- if (clientSession != null) {
- userSession = clientSession.getUserSession();
-
- if (userSession == null) {
- throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Offline user session not found", "Offline user session not found");
- }
-
- String userSessionId = oldToken.getSessionState();
- if (!userSessionId.equals(userSession.getId())) {
- throw new ModelException("User session don't match. Offline client session " + clientSession.getId() + ", It's user session " + userSession.getId() +
- " Wanted user session: " + userSessionId);
- }
+ userSession = sessionManager.findOfflineUserSession(realm, oldToken.getSessionState());
+ if (userSession != null) {
// Revoke timeouted offline userSession
if (userSession.getLastSessionRefresh() < Time.currentTime() - realm.getOfflineSessionIdleTimeout()) {
sessionManager.revokeOfflineUserSession(userSession);
- throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Offline user session not active", "Offline user session session not active");
+ throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Offline session not active", "Offline session not active");
}
+
}
} else {
// Find userSession regularly for online tokens
@@ -160,20 +150,14 @@ public class TokenManager {
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, connection, headers, true);
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Session not active", "Session not active");
}
-
- for (ClientSessionModel clientSessionModel : userSession.getClientSessions()) {
- if (clientSessionModel.getId().equals(oldToken.getClientSession())) {
- clientSession = clientSessionModel;
- break;
- }
- }
}
- if (clientSession == null) {
- throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Client session not active", "Client session not active");
+ if (userSession == null) {
+ throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Offline user session not found", "Offline user session not found");
}
- ClientModel client = clientSession.getClient();
+ ClientModel client = session.getContext().getClient();
+ ClientLoginSessionModel clientSession = userSession.getClientLoginSessions().get(client.getId());
if (!client.getClientId().equals(oldToken.getIssuedFor())) {
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Unmatching clients", "Unmatching clients");
@@ -221,18 +205,30 @@ public class TokenManager {
}
}
+<<<<<<< f392e79ad781014387c9fe5724815b24eab7a35f
userSession = session.sessions().getOfflineUserSession(realm, token.getSessionState());
if (AuthenticationManager.isOfflineSessionValid(realm, userSession)) {
ClientSessionModel clientSession = session.sessions().getOfflineClientSession(realm, token.getClientSession());
if (clientSession != null) {
return true;
}
+=======
+ ClientModel client = realm.getClientByClientId(token.getIssuedFor());
+ if (client == null || !client.isEnabled()) {
+ return false;
+ }
+
+ ClientLoginSessionModel clientSession = userSession.getClientLoginSessions().get(client.getId());
+ if (clientSession == null) {
+ return false;
+>>>>>>> KEYCLOAK-4626 AuthenticationSessions: start
}
return false;
}
- public RefreshResult refreshAccessToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, ClientModel authorizedClient, String encodedRefreshToken, EventBuilder event, HttpHeaders headers) throws OAuthErrorException {
+ public RefreshResult refreshAccessToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, ClientModel authorizedClient,
+ String encodedRefreshToken, EventBuilder event, HttpHeaders headers) throws OAuthErrorException {
RefreshToken refreshToken = verifyRefreshToken(session, realm, encodedRefreshToken);
event.user(refreshToken.getSubject()).session(refreshToken.getSessionState())
@@ -349,7 +345,8 @@ public class TokenManager {
}
}
- public AccessToken createClientAccessToken(KeycloakSession session, Set<RoleModel> requestedRoles, RealmModel realm, ClientModel client, UserModel user, UserSessionModel userSession, ClientSessionModel clientSession) {
+ public AccessToken createClientAccessToken(KeycloakSession session, Set<RoleModel> requestedRoles, RealmModel realm, ClientModel client, UserModel user, UserSessionModel userSession,
+ ClientLoginSessionModel clientSession) {
AccessToken token = initToken(realm, client, user, userSession, clientSession, session.getContext().getUri());
for (RoleModel role : requestedRoles) {
addComposites(token, role);
@@ -358,17 +355,14 @@ public class TokenManager {
return token;
}
- public static void attachClientSession(UserSessionModel session, ClientSessionModel clientSession) {
- if (clientSession.getUserSession() != null) {
- return;
- }
+ public static ClientLoginSessionModel attachLoginSession(KeycloakSession session, UserSessionModel userSession, LoginSessionModel loginSession) {
+ UserModel user = userSession.getUser();
+ ClientModel client = loginSession.getClient();
+ ClientLoginSessionModel clientSession = session.sessions().createClientSession(userSession.getRealm(), client, userSession);
- UserModel user = session.getUser();
- clientSession.setUserSession(session);
Set<String> requestedRoles = new HashSet<String>();
// todo scope param protocol independent
- String scopeParam = clientSession.getNote(OAuth2Constants.SCOPE);
- ClientModel client = clientSession.getClient();
+ String scopeParam = loginSession.getNote(OAuth2Constants.SCOPE);
for (RoleModel r : TokenManager.getAccess(scopeParam, true, client, user)) {
requestedRoles.add(r.getId());
}
@@ -378,28 +372,41 @@ public class TokenManager {
ClientTemplateModel clientTemplate = client.getClientTemplate();
if (clientTemplate != null && client.useTemplateMappers()) {
for (ProtocolMapperModel protocolMapper : clientTemplate.getProtocolMappers()) {
- if (protocolMapper.getProtocol().equals(clientSession.getAuthMethod())) {
+ if (protocolMapper.getProtocol().equals(loginSession.getProtocol())) {
requestedProtocolMappers.add(protocolMapper.getId());
}
}
}
for (ProtocolMapperModel protocolMapper : client.getProtocolMappers()) {
- if (protocolMapper.getProtocol().equals(clientSession.getAuthMethod())) {
+ if (protocolMapper.getProtocol().equals(loginSession.getProtocol())) {
requestedProtocolMappers.add(protocolMapper.getId());
}
}
clientSession.setProtocolMappers(requestedProtocolMappers);
- Map<String, String> transferredNotes = clientSession.getUserSessionNotes();
+ Map<String, String> transferredNotes = loginSession.getNotes();
for (Map.Entry<String, String> entry : transferredNotes.entrySet()) {
- session.setNote(entry.getKey(), entry.getValue());
+ clientSession.setNote(entry.getKey(), entry.getValue());
+ }
+
+ Map<String, String> transferredUserSessionNotes = loginSession.getUserSessionNotes();
+ for (Map.Entry<String, String> entry : transferredUserSessionNotes.entrySet()) {
+ userSession.setNote(entry.getKey(), entry.getValue());
}
+ clientSession.setTimestamp(Time.currentTime());
+
+ userSession.getClientLoginSessions().put(client.getId(), clientSession);
+
+ // Remove login session now
+ session.loginSessions().removeLoginSession(userSession.getRealm(), loginSession);
+
+ return clientSession;
}
- public static void dettachClientSession(UserSessionProvider sessions, RealmModel realm, ClientSessionModel clientSession) {
+ public static void dettachClientSession(UserSessionProvider sessions, RealmModel realm, ClientLoginSessionModel clientSession) {
UserSessionModel userSession = clientSession.getUserSession();
if (userSession == null) {
return;
@@ -543,8 +550,8 @@ public class TokenManager {
}
public AccessToken transformAccessToken(KeycloakSession session, AccessToken token, RealmModel realm, ClientModel client, UserModel user,
- UserSessionModel userSession, ClientSessionModel clientSession) {
- Set<ProtocolMapperModel> mappings = new ClientSessionCode(session, realm, clientSession).getRequestedProtocolMappers();
+ UserSessionModel userSession, ClientLoginSessionModel clientSession) {
+ Set<ProtocolMapperModel> mappings = ClientSessionCode.getRequestedProtocolMappers(clientSession.getProtocolMappers(), client);
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
for (ProtocolMapperModel mapping : mappings) {
@@ -558,8 +565,8 @@ public class TokenManager {
}
public AccessToken transformUserInfoAccessToken(KeycloakSession session, AccessToken token, RealmModel realm, ClientModel client, UserModel user,
- UserSessionModel userSession, ClientSessionModel clientSession) {
- Set<ProtocolMapperModel> mappings = new ClientSessionCode(session, realm, clientSession).getRequestedProtocolMappers();
+ UserSessionModel userSession, ClientLoginSessionModel clientSession) {
+ Set<ProtocolMapperModel> mappings = ClientSessionCode.getRequestedProtocolMappers(clientSession.getProtocolMappers(), client);
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
for (ProtocolMapperModel mapping : mappings) {
@@ -573,8 +580,8 @@ public class TokenManager {
}
public void transformIDToken(KeycloakSession session, IDToken token, RealmModel realm, ClientModel client, UserModel user,
- UserSessionModel userSession, ClientSessionModel clientSession) {
- Set<ProtocolMapperModel> mappings = new ClientSessionCode(session, realm, clientSession).getRequestedProtocolMappers();
+ UserSessionModel userSession, ClientLoginSessionModel clientSession) {
+ Set<ProtocolMapperModel> mappings = ClientSessionCode.getRequestedProtocolMappers(clientSession.getProtocolMappers(), client);
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
for (ProtocolMapperModel mapping : mappings) {
@@ -585,9 +592,9 @@ public class TokenManager {
}
}
- protected AccessToken initToken(RealmModel realm, ClientModel client, UserModel user, UserSessionModel session, ClientSessionModel clientSession, UriInfo uriInfo) {
+ protected AccessToken initToken(RealmModel realm, ClientModel client, UserModel user, UserSessionModel session, ClientLoginSessionModel clientSession, UriInfo uriInfo) {
AccessToken token = new AccessToken();
- if (clientSession != null) token.clientSession(clientSession.getId());
+ token.clientSession(clientSession.getId());
token.id(KeycloakModelUtils.generateId());
token.type(TokenUtil.TOKEN_TYPE_BEARER);
token.subject(user.getId());
@@ -607,9 +614,9 @@ public class TokenManager {
token.setAuthTime(Integer.parseInt(authTime));
}
- if (session != null) {
- token.setSessionState(session.getId());
- }
+
+ token.setSessionState(session.getId());
+
int tokenLifespan = getTokenLifespan(realm, clientSession);
if (tokenLifespan > 0) {
token.expiration(Time.currentTime() + tokenLifespan);
@@ -621,7 +628,7 @@ public class TokenManager {
return token;
}
- private int getTokenLifespan(RealmModel realm, ClientSessionModel clientSession) {
+ private int getTokenLifespan(RealmModel realm, ClientLoginSessionModel clientSession) {
boolean implicitFlow = false;
String responseType = clientSession.getNote(OIDCLoginProtocol.RESPONSE_TYPE_PARAM);
if (responseType != null) {
@@ -663,7 +670,7 @@ public class TokenManager {
return new JWSBuilder().type(JWT).kid(activeRsaKey.getKid()).jsonContent(token).sign(jwsAlgorithm, activeRsaKey.getPrivateKey());
}
- public AccessTokenResponseBuilder responseBuilder(RealmModel realm, ClientModel client, EventBuilder event, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+ public AccessTokenResponseBuilder responseBuilder(RealmModel realm, ClientModel client, EventBuilder event, KeycloakSession session, UserSessionModel userSession, ClientLoginSessionModel clientSession) {
return new AccessTokenResponseBuilder(realm, client, event, session, userSession, clientSession);
}
@@ -673,7 +680,7 @@ public class TokenManager {
EventBuilder event;
KeycloakSession session;
UserSessionModel userSession;
- ClientSessionModel clientSession;
+ ClientLoginSessionModel clientSession;
AccessToken accessToken;
RefreshToken refreshToken;
@@ -682,7 +689,7 @@ public class TokenManager {
boolean generateAccessTokenHash = false;
String codeHash;
- public AccessTokenResponseBuilder(RealmModel realm, ClientModel client, EventBuilder event, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+ public AccessTokenResponseBuilder(RealmModel realm, ClientModel client, EventBuilder event, KeycloakSession session, UserSessionModel userSession, ClientLoginSessionModel clientSession) {
this.realm = realm;
this.client = client;
this.event = event;
diff --git a/services/src/main/java/org/keycloak/protocol/RestartLoginCookie.java b/services/src/main/java/org/keycloak/protocol/RestartLoginCookie.java
index 51bdd81..4fda889 100644
--- a/services/src/main/java/org/keycloak/protocol/RestartLoginCookie.java
+++ b/services/src/main/java/org/keycloak/protocol/RestartLoginCookie.java
@@ -31,6 +31,7 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.util.CookieHelper;
+import org.keycloak.sessions.LoginSessionModel;
import javax.crypto.SecretKey;
import javax.ws.rs.core.Cookie;
@@ -125,10 +126,10 @@ public class RestartLoginCookie {
public RestartLoginCookie() {
}
- public RestartLoginCookie(ClientSessionModel clientSession) {
+ public RestartLoginCookie(LoginSessionModel clientSession) {
this.action = clientSession.getAction();
this.clientId = clientSession.getClient().getClientId();
- this.authMethod = clientSession.getAuthMethod();
+ this.authMethod = clientSession.getProtocol();
this.redirectUri = clientSession.getRedirectUri();
this.clientSession = clientSession.getId();
for (Map.Entry<String, String> entry : clientSession.getNotes().entrySet()) {
@@ -136,8 +137,8 @@ public class RestartLoginCookie {
}
}
- public static void setRestartCookie(KeycloakSession session, RealmModel realm, ClientConnection connection, UriInfo uriInfo, ClientSessionModel clientSession) {
- RestartLoginCookie restart = new RestartLoginCookie(clientSession);
+ public static void setRestartCookie(KeycloakSession session, RealmModel realm, ClientConnection connection, UriInfo uriInfo, LoginSessionModel loginSession) {
+ RestartLoginCookie restart = new RestartLoginCookie(loginSession);
String encoded = restart.encode(session, realm);
String path = AuthenticationManager.getRealmCookiePath(realm, uriInfo);
boolean secureOnly = realm.getSslRequired().isRequired(connection);
@@ -150,6 +151,8 @@ public class RestartLoginCookie {
CookieHelper.addCookie(KC_RESTART, "", path, null, null, 0, secureOnly, true);
}
+ // TODO:mposolda
+ /*
public static ClientSessionModel restartSession(KeycloakSession session, RealmModel realm, String code) throws Exception {
Cookie cook = session.getContext().getRequestHeaders().getCookies().get(KC_RESTART);
if (cook == null) {
@@ -183,5 +186,5 @@ public class RestartLoginCookie {
}
return clientSession;
- }
+ }*/
}
diff --git a/services/src/main/java/org/keycloak/protocol/saml/mappers/GroupMembershipMapper.java b/services/src/main/java/org/keycloak/protocol/saml/mappers/GroupMembershipMapper.java
index 1a2db26..3ffdec4 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/mappers/GroupMembershipMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/mappers/GroupMembershipMapper.java
@@ -19,7 +19,7 @@ package org.keycloak.protocol.saml.mappers;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
-import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
@@ -117,7 +117,7 @@ public class GroupMembershipMapper extends AbstractSAMLProtocolMapper implements
@Override
- public void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+ public void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientLoginSessionModel clientSession) {
String single = mappingModel.getConfig().get(SINGLE_GROUP_ATTRIBUTE);
boolean singleAttribute = Boolean.parseBoolean(single);
diff --git a/services/src/main/java/org/keycloak/protocol/saml/mappers/HardcodedAttributeMapper.java b/services/src/main/java/org/keycloak/protocol/saml/mappers/HardcodedAttributeMapper.java
index b8a6231..7909209 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/mappers/HardcodedAttributeMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/mappers/HardcodedAttributeMapper.java
@@ -18,7 +18,7 @@
package org.keycloak.protocol.saml.mappers;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
-import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserSessionModel;
@@ -76,7 +76,7 @@ public class HardcodedAttributeMapper extends AbstractSAMLProtocolMapper impleme
}
@Override
- public void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+ public void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientLoginSessionModel clientSession) {
String attributeValue = mappingModel.getConfig().get(ATTRIBUTE_VALUE);
AttributeStatementHelper.addAttribute(attributeStatement, mappingModel, attributeValue);
diff --git a/services/src/main/java/org/keycloak/protocol/saml/mappers/RoleListMapper.java b/services/src/main/java/org/keycloak/protocol/saml/mappers/RoleListMapper.java
index 5650333..169f25a 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/mappers/RoleListMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/mappers/RoleListMapper.java
@@ -19,7 +19,7 @@ package org.keycloak.protocol.saml.mappers;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
-import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.ProtocolMapperModel;
@@ -111,14 +111,14 @@ public class RoleListMapper extends AbstractSAMLProtocolMapper implements SAMLRo
}
@Override
- public void mapRoles(AttributeStatementType roleAttributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+ public void mapRoles(AttributeStatementType roleAttributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientLoginSessionModel clientSession) {
String single = mappingModel.getConfig().get(SINGLE_ROLE_ATTRIBUTE);
boolean singleAttribute = Boolean.parseBoolean(single);
List<SamlProtocol.ProtocolMapperProcessor<SAMLRoleNameMapper>> roleNameMappers = new LinkedList<>();
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
AttributeType singleAttributeType = null;
- Set<ProtocolMapperModel> requestedProtocolMappers = new ClientSessionCode(session, clientSession.getRealm(), clientSession).getRequestedProtocolMappers();
+ Set<ProtocolMapperModel> requestedProtocolMappers = ClientSessionCode.getRequestedProtocolMappers(clientSession.getProtocolMappers(), clientSession.getClient());
for (ProtocolMapperModel mapping : requestedProtocolMappers) {
ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
diff --git a/services/src/main/java/org/keycloak/protocol/saml/mappers/SAMLAttributeStatementMapper.java b/services/src/main/java/org/keycloak/protocol/saml/mappers/SAMLAttributeStatementMapper.java
index 48edfaa..8e33f92 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/mappers/SAMLAttributeStatementMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/mappers/SAMLAttributeStatementMapper.java
@@ -18,7 +18,7 @@
package org.keycloak.protocol.saml.mappers;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
-import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserSessionModel;
@@ -30,5 +30,5 @@ import org.keycloak.models.UserSessionModel;
public interface SAMLAttributeStatementMapper {
void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session,
- UserSessionModel userSession, ClientSessionModel clientSession);
+ UserSessionModel userSession, ClientLoginSessionModel clientSession);
}
diff --git a/services/src/main/java/org/keycloak/protocol/saml/mappers/SAMLLoginResponseMapper.java b/services/src/main/java/org/keycloak/protocol/saml/mappers/SAMLLoginResponseMapper.java
index cf5c9c8..329f1ac 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/mappers/SAMLLoginResponseMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/mappers/SAMLLoginResponseMapper.java
@@ -18,7 +18,7 @@
package org.keycloak.protocol.saml.mappers;
import org.keycloak.dom.saml.v2.protocol.ResponseType;
-import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserSessionModel;
@@ -30,5 +30,5 @@ import org.keycloak.models.UserSessionModel;
public interface SAMLLoginResponseMapper {
ResponseType transformLoginResponse(ResponseType response, ProtocolMapperModel mappingModel, KeycloakSession session,
- UserSessionModel userSession, ClientSessionModel clientSession);
+ UserSessionModel userSession, ClientLoginSessionModel clientSession);
}
diff --git a/services/src/main/java/org/keycloak/protocol/saml/mappers/SAMLRoleListMapper.java b/services/src/main/java/org/keycloak/protocol/saml/mappers/SAMLRoleListMapper.java
index a822d8c..e74c79f 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/mappers/SAMLRoleListMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/mappers/SAMLRoleListMapper.java
@@ -18,7 +18,7 @@
package org.keycloak.protocol.saml.mappers;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
-import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserSessionModel;
@@ -30,5 +30,5 @@ import org.keycloak.models.UserSessionModel;
public interface SAMLRoleListMapper {
void mapRoles(AttributeStatementType roleAttributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session,
- UserSessionModel userSession, ClientSessionModel clientSession);
+ UserSessionModel userSession, ClientLoginSessionModel clientSession);
}
diff --git a/services/src/main/java/org/keycloak/protocol/saml/mappers/UserAttributeStatementMapper.java b/services/src/main/java/org/keycloak/protocol/saml/mappers/UserAttributeStatementMapper.java
index f29d972..661c9b6 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/mappers/UserAttributeStatementMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/mappers/UserAttributeStatementMapper.java
@@ -18,7 +18,7 @@
package org.keycloak.protocol.saml.mappers;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
-import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserModel;
@@ -77,7 +77,7 @@ public class UserAttributeStatementMapper extends AbstractSAMLProtocolMapper imp
}
@Override
- public void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+ public void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientLoginSessionModel clientSession) {
UserModel user = userSession.getUser();
String attributeName = mappingModel.getConfig().get(ProtocolMapperUtils.USER_ATTRIBUTE);
List<String> attributeValues = KeycloakModelUtils.resolveAttribute(user, attributeName);
diff --git a/services/src/main/java/org/keycloak/protocol/saml/mappers/UserPropertyAttributeStatementMapper.java b/services/src/main/java/org/keycloak/protocol/saml/mappers/UserPropertyAttributeStatementMapper.java
index fd0de2a..adfc9aa 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/mappers/UserPropertyAttributeStatementMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/mappers/UserPropertyAttributeStatementMapper.java
@@ -18,7 +18,7 @@
package org.keycloak.protocol.saml.mappers;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
-import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserModel;
@@ -76,7 +76,7 @@ public class UserPropertyAttributeStatementMapper extends AbstractSAMLProtocolMa
}
@Override
- public void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+ public void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientLoginSessionModel clientSession) {
UserModel user = userSession.getUser();
String propertyName = mappingModel.getConfig().get(ProtocolMapperUtils.USER_ATTRIBUTE);
String propertyValue = ProtocolMapperUtils.getUserModelValue(user, propertyName);
diff --git a/services/src/main/java/org/keycloak/protocol/saml/mappers/UserSessionNoteStatementMapper.java b/services/src/main/java/org/keycloak/protocol/saml/mappers/UserSessionNoteStatementMapper.java
index d6fd4d0..d633e2c 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/mappers/UserSessionNoteStatementMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/mappers/UserSessionNoteStatementMapper.java
@@ -18,7 +18,7 @@
package org.keycloak.protocol.saml.mappers;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
-import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserSessionModel;
@@ -74,7 +74,7 @@ public class UserSessionNoteStatementMapper extends AbstractSAMLProtocolMapper i
}
@Override
- public void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+ public void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientLoginSessionModel clientSession) {
String note = mappingModel.getConfig().get("note");
String value = userSession.getNote(note);
if (value == null) return;
diff --git a/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/authenticator/HttpBasicAuthenticator.java b/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/authenticator/HttpBasicAuthenticator.java
index ddaec72..81496fc 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/authenticator/HttpBasicAuthenticator.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/authenticator/HttpBasicAuthenticator.java
@@ -104,7 +104,7 @@ public class HttpBasicAuthenticator implements AuthenticatorFactory {
boolean valid = context.getSession().userCredentialManager().isValid(realm, user, UserCredentialModel.password(password));
if (valid) {
- context.getClientSession().setAuthenticatedUser(user);
+ context.getLoginSession().setAuthenticatedUser(user);
context.success();
} else {
context.getEvent().user(user);
diff --git a/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java b/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java
index d2aaad6..f578f3d 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java
@@ -20,8 +20,8 @@ package org.keycloak.protocol.saml.profile.ecp;
import org.keycloak.dom.saml.v2.protocol.AuthnRequestType;
import org.keycloak.events.EventBuilder;
import org.keycloak.models.AuthenticationFlowModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.utils.DefaultAuthenticationFlows;
@@ -35,6 +35,7 @@ import org.keycloak.saml.common.constants.JBossSAMLConstants;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ConfigurationException;
import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.sessions.LoginSessionModel;
import org.w3c.dom.Document;
import javax.ws.rs.core.Response;
@@ -85,15 +86,15 @@ public class SamlEcpProfileService extends SamlService {
}
@Override
- protected Response newBrowserAuthentication(ClientSessionModel clientSession, boolean isPassive, boolean redirectToAuthentication, SamlProtocol samlProtocol) {
- return super.newBrowserAuthentication(clientSession, isPassive, redirectToAuthentication, createEcpSamlProtocol());
+ protected Response newBrowserAuthentication(LoginSessionModel loginSession, boolean isPassive, boolean redirectToAuthentication, SamlProtocol samlProtocol) {
+ return super.newBrowserAuthentication(loginSession, isPassive, redirectToAuthentication, createEcpSamlProtocol());
}
private SamlProtocol createEcpSamlProtocol() {
return new SamlProtocol() {
// method created to send a SOAP Binding response instead of a HTTP POST response
@Override
- protected Response buildAuthenticatedResponse(ClientSessionModel clientSession, String redirectUri, Document samlDocument, JaxrsSAML2BindingBuilder bindingBuilder) throws ConfigurationException, ProcessingException, IOException {
+ protected Response buildAuthenticatedResponse(ClientLoginSessionModel clientSession, String redirectUri, Document samlDocument, JaxrsSAML2BindingBuilder bindingBuilder) throws ConfigurationException, ProcessingException, IOException {
Document document = bindingBuilder.postBinding(samlDocument).getDocument();
try {
@@ -113,7 +114,7 @@ public class SamlEcpProfileService extends SamlService {
}
}
- private void createRequestAuthenticatedHeader(ClientSessionModel clientSession, Soap.SoapMessageBuilder messageBuilder) {
+ private void createRequestAuthenticatedHeader(ClientLoginSessionModel clientSession, Soap.SoapMessageBuilder messageBuilder) {
ClientModel client = clientSession.getClient();
if ("true".equals(client.getAttribute(SamlConfigAttributes.SAML_CLIENT_SIGNATURE_ATTRIBUTE))) {
@@ -133,7 +134,7 @@ public class SamlEcpProfileService extends SamlService {
}
@Override
- protected Response buildErrorResponse(ClientSessionModel clientSession, JaxrsSAML2BindingBuilder binding, Document document) throws ConfigurationException, ProcessingException, IOException {
+ protected Response buildErrorResponse(LoginSessionModel clientSession, JaxrsSAML2BindingBuilder binding, Document document) throws ConfigurationException, ProcessingException, IOException {
return Soap.createMessage().addToBody(document).build();
}
diff --git a/services/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java b/services/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
index 20d86c0..04da54a 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
@@ -30,8 +30,8 @@ import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.protocol.ResponseType;
import org.keycloak.events.EventBuilder;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeyManager;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
@@ -40,7 +40,6 @@ import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.LoginProtocol;
import org.keycloak.protocol.ProtocolMapper;
-import org.keycloak.protocol.RestartLoginCookie;
import org.keycloak.protocol.saml.mappers.SAMLAttributeStatementMapper;
import org.keycloak.protocol.saml.mappers.SAMLLoginResponseMapper;
import org.keycloak.protocol.saml.mappers.SAMLRoleListMapper;
@@ -61,6 +60,8 @@ import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.managers.ResourceAdminManager;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.RealmsResource;
+import org.keycloak.sessions.CommonClientSessionModel;
+import org.keycloak.sessions.LoginSessionModel;
import org.w3c.dom.Document;
import javax.ws.rs.core.HttpHeaders;
@@ -156,9 +157,9 @@ public class SamlProtocol implements LoginProtocol {
}
@Override
- public Response sendError(ClientSessionModel clientSession, Error error) {
+ public Response sendError(LoginSessionModel loginSession, Error error) {
try {
- ClientModel client = clientSession.getClient();
+ ClientModel client = loginSession.getClient();
if ("true".equals(client.getAttribute(SAML_IDP_INITIATED_LOGIN))) {
if (error == Error.CANCELLED_BY_USER) {
@@ -173,9 +174,9 @@ public class SamlProtocol implements LoginProtocol {
return ErrorPage.error(session, translateErrorToIdpInitiatedErrorMessage(error));
}
} else {
- SAML2ErrorResponseBuilder builder = new SAML2ErrorResponseBuilder().destination(clientSession.getRedirectUri()).issuer(getResponseIssuer(realm)).status(translateErrorToSAMLStatus(error).get());
+ SAML2ErrorResponseBuilder builder = new SAML2ErrorResponseBuilder().destination(loginSession.getRedirectUri()).issuer(getResponseIssuer(realm)).status(translateErrorToSAMLStatus(error).get());
try {
- JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder().relayState(clientSession.getNote(GeneralConstants.RELAY_STATE));
+ JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder().relayState(loginSession.getNote(GeneralConstants.RELAY_STATE));
SamlClient samlClient = new SamlClient(client);
KeyManager keyManager = session.keys();
if (samlClient.requiresRealmSignature()) {
@@ -198,22 +199,23 @@ public class SamlProtocol implements LoginProtocol {
binding.encrypt(publicKey);
}
Document document = builder.buildDocument();
- return buildErrorResponse(clientSession, binding, document);
+ return buildErrorResponse(loginSession, binding, document);
} catch (Exception e) {
return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
}
}
} finally {
- RestartLoginCookie.expireRestartCookie(realm, session.getContext().getConnection(), uriInfo);
- session.sessions().removeClientSession(realm, clientSession);
+ // TODO:mposolda
+ //RestartLoginCookie.expireRestartCookie(realm, session.getContext().getConnection(), uriInfo);
+ session.loginSessions().removeLoginSession(realm, loginSession);
}
}
- protected Response buildErrorResponse(ClientSessionModel clientSession, JaxrsSAML2BindingBuilder binding, Document document) throws ConfigurationException, ProcessingException, IOException {
- if (isPostBinding(clientSession)) {
- return binding.postBinding(document).response(clientSession.getRedirectUri());
+ protected Response buildErrorResponse(LoginSessionModel loginSession, JaxrsSAML2BindingBuilder binding, Document document) throws ConfigurationException, ProcessingException, IOException {
+ if (isPostBinding(loginSession)) {
+ return binding.postBinding(document).response(loginSession.getRedirectUri());
} else {
- return binding.redirectBinding(document).response(clientSession.getRedirectUri());
+ return binding.redirectBinding(document).response(loginSession.getRedirectUri());
}
}
@@ -248,10 +250,10 @@ public class SamlProtocol implements LoginProtocol {
return RealmsResource.realmBaseUrl(uriInfo).build(realm.getName()).toString();
}
- protected boolean isPostBinding(ClientSessionModel clientSession) {
- ClientModel client = clientSession.getClient();
+ protected boolean isPostBinding(CommonClientSessionModel loginSession) {
+ ClientModel client = loginSession.getClient();
SamlClient samlClient = new SamlClient(client);
- return SamlProtocol.SAML_POST_BINDING.equals(clientSession.getNote(SamlProtocol.SAML_BINDING)) || samlClient.forcePostBinding();
+ return SamlProtocol.SAML_POST_BINDING.equals(loginSession.getNote(SamlProtocol.SAML_BINDING)) || samlClient.forcePostBinding();
}
public static boolean isLogoutPostBindingForInitiator(UserSessionModel session) {
@@ -259,7 +261,7 @@ public class SamlProtocol implements LoginProtocol {
return SamlProtocol.SAML_POST_BINDING.equals(note);
}
- protected boolean isLogoutPostBindingForClient(ClientSessionModel clientSession) {
+ protected boolean isLogoutPostBindingForClient(ClientLoginSessionModel clientSession) {
ClientModel client = clientSession.getClient();
SamlClient samlClient = new SamlClient(client);
String logoutPostUrl = client.getAttribute(SAML_SINGLE_LOGOUT_SERVICE_URL_POST_ATTRIBUTE);
@@ -284,7 +286,7 @@ public class SamlProtocol implements LoginProtocol {
return (logoutRedirectUrl == null || logoutRedirectUrl.trim().isEmpty());
}
- protected String getNameIdFormat(SamlClient samlClient, ClientSessionModel clientSession) {
+ protected String getNameIdFormat(SamlClient samlClient, CommonClientSessionModel clientSession) {
String nameIdFormat = clientSession.getNote(GeneralConstants.NAMEID_FORMAT);
boolean forceFormat = samlClient.forceNameIDFormat();
@@ -297,7 +299,7 @@ public class SamlProtocol implements LoginProtocol {
return nameIdFormat;
}
- protected String getNameId(String nameIdFormat, ClientSessionModel clientSession, UserSessionModel userSession) {
+ protected String getNameId(String nameIdFormat, CommonClientSessionModel clientSession, UserSessionModel userSession) {
if (nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get())) {
return userSession.getUser().getEmail();
} else if (nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_TRANSIENT.get())) {
@@ -327,7 +329,7 @@ public class SamlProtocol implements LoginProtocol {
*
* @return the user's persistent NameId
*/
- protected String getPersistentNameId(final ClientSessionModel clientSession, final UserSessionModel userSession) {
+ protected String getPersistentNameId(final CommonClientSessionModel clientSession, final UserSessionModel userSession) {
// attempt to retrieve the UserID for the client-specific attribute
final UserModel user = userSession.getUser();
final String clientNameId = String.format("%s.%s", SAML_PERSISTENT_NAME_ID_FOR,
@@ -351,8 +353,8 @@ public class SamlProtocol implements LoginProtocol {
}
@Override
- public Response authenticated(UserSessionModel userSession, ClientSessionCode accessCode) {
- ClientSessionModel clientSession = accessCode.getClientSession();
+ public Response authenticated(UserSessionModel userSession, ClientSessionCode<ClientLoginSessionModel> accessCode) {
+ ClientLoginSessionModel clientSession = accessCode.getClientSession();
ClientModel client = clientSession.getClient();
SamlClient samlClient = new SamlClient(client);
String requestID = clientSession.getNote(SAML_REQUEST_ID);
@@ -460,7 +462,7 @@ public class SamlProtocol implements LoginProtocol {
}
}
- protected Response buildAuthenticatedResponse(ClientSessionModel clientSession, String redirectUri, Document samlDocument, JaxrsSAML2BindingBuilder bindingBuilder) throws ConfigurationException, ProcessingException, IOException {
+ protected Response buildAuthenticatedResponse(ClientLoginSessionModel clientSession, String redirectUri, Document samlDocument, JaxrsSAML2BindingBuilder bindingBuilder) throws ConfigurationException, ProcessingException, IOException {
if (isPostBinding(clientSession)) {
return bindingBuilder.postBinding(samlDocument).response(redirectUri);
} else {
@@ -479,7 +481,7 @@ public class SamlProtocol implements LoginProtocol {
}
public AttributeStatementType populateAttributeStatements(List<ProtocolMapperProcessor<SAMLAttributeStatementMapper>> attributeStatementMappers, KeycloakSession session, UserSessionModel userSession,
- ClientSessionModel clientSession) {
+ ClientLoginSessionModel clientSession) {
AttributeStatementType attributeStatement = new AttributeStatementType();
for (ProtocolMapperProcessor<SAMLAttributeStatementMapper> processor : attributeStatementMappers) {
processor.mapper.transformAttributeStatement(attributeStatement, processor.model, session, userSession, clientSession);
@@ -488,14 +490,14 @@ public class SamlProtocol implements LoginProtocol {
return attributeStatement;
}
- public ResponseType transformLoginResponse(List<ProtocolMapperProcessor<SAMLLoginResponseMapper>> mappers, ResponseType response, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+ public ResponseType transformLoginResponse(List<ProtocolMapperProcessor<SAMLLoginResponseMapper>> mappers, ResponseType response, KeycloakSession session, UserSessionModel userSession, ClientLoginSessionModel clientSession) {
for (ProtocolMapperProcessor<SAMLLoginResponseMapper> processor : mappers) {
response = processor.mapper.transformLoginResponse(response, processor.model, session, userSession, clientSession);
}
return response;
}
- public void populateRoles(ProtocolMapperProcessor<SAMLRoleListMapper> roleListMapper, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession,
+ public void populateRoles(ProtocolMapperProcessor<SAMLRoleListMapper> roleListMapper, KeycloakSession session, UserSessionModel userSession, ClientLoginSessionModel clientSession,
final AttributeStatementType existingAttributeStatement) {
if (roleListMapper == null)
return;
@@ -509,8 +511,8 @@ public class SamlProtocol implements LoginProtocol {
} else {
logoutServiceUrl = client.getAttribute(SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE);
}
- if (logoutServiceUrl == null && client instanceof ClientModel)
- logoutServiceUrl = ((ClientModel) client).getManagementUrl();
+ if (logoutServiceUrl == null)
+ logoutServiceUrl = client.getManagementUrl();
if (logoutServiceUrl == null || logoutServiceUrl.trim().equals(""))
return null;
return ResourceAdminManager.resolveUri(uriInfo.getRequestUri(), client.getRootUrl(), logoutServiceUrl);
@@ -518,11 +520,9 @@ public class SamlProtocol implements LoginProtocol {
}
@Override
- public Response frontchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) {
+ public Response frontchannelLogout(UserSessionModel userSession, ClientLoginSessionModel clientSession) {
ClientModel client = clientSession.getClient();
SamlClient samlClient = new SamlClient(client);
- if (!(client instanceof ClientModel))
- return null;
try {
boolean postBinding = isLogoutPostBindingForClient(clientSession);
String bindingUri = getLogoutServiceUrl(uriInfo, client, postBinding ? SAML_POST_BINDING : SAML_REDIRECT_BINDING);
@@ -615,7 +615,7 @@ public class SamlProtocol implements LoginProtocol {
}
@Override
- public void backchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) {
+ public void backchannelLogout(UserSessionModel userSession, ClientLoginSessionModel clientSession) {
ClientModel client = clientSession.getClient();
SamlClient samlClient = new SamlClient(client);
String logoutUrl = getLogoutServiceUrl(uriInfo, client, SAML_POST_BINDING);
@@ -674,7 +674,7 @@ public class SamlProtocol implements LoginProtocol {
}
- protected SAML2LogoutRequestBuilder createLogoutRequest(String logoutUrl, ClientSessionModel clientSession, ClientModel client) {
+ protected SAML2LogoutRequestBuilder createLogoutRequest(String logoutUrl, ClientLoginSessionModel clientSession, ClientModel client) {
// build userPrincipal with subject used at login
SAML2LogoutRequestBuilder logoutBuilder = new SAML2LogoutRequestBuilder().assertionExpiration(realm.getAccessCodeLifespan()).issuer(getResponseIssuer(realm)).sessionIndex(clientSession.getId())
.userPrincipal(clientSession.getNote(SAML_NAME_ID), clientSession.getNote(SAML_NAME_ID_FORMAT)).destination(logoutUrl);
@@ -682,7 +682,7 @@ public class SamlProtocol implements LoginProtocol {
}
@Override
- public boolean requireReauthentication(UserSessionModel userSession, ClientSessionModel clientSession) {
+ public boolean requireReauthentication(UserSessionModel userSession, LoginSessionModel clientSession) {
// Not yet supported
return false;
}
diff --git a/services/src/main/java/org/keycloak/protocol/saml/SamlService.java b/services/src/main/java/org/keycloak/protocol/saml/SamlService.java
index d67faa2..83445a6 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/SamlService.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/SamlService.java
@@ -86,6 +86,7 @@ import org.keycloak.rotation.HardcodedKeyLocator;
import org.keycloak.rotation.KeyLocator;
import org.keycloak.saml.SPMetadataDescriptor;
import org.keycloak.saml.processing.core.util.KeycloakKeySamlExtensionGenerator;
+import org.keycloak.sessions.LoginSessionModel;
/**
* Resource class for the oauth/openid connect token service
@@ -270,13 +271,13 @@ public class SamlService extends AuthorizationEndpointBase {
return ErrorPage.error(session, Messages.INVALID_REDIRECT_URI);
}
- ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
- clientSession.setAuthMethod(SamlProtocol.LOGIN_PROTOCOL);
- clientSession.setRedirectUri(redirect);
- clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
- clientSession.setNote(SamlProtocol.SAML_BINDING, bindingType);
- clientSession.setNote(GeneralConstants.RELAY_STATE, relayState);
- clientSession.setNote(SamlProtocol.SAML_REQUEST_ID, requestAbstractType.getID());
+ LoginSessionModel loginSession = session.loginSessions().createLoginSession(realm, client, true);
+ loginSession.setProtocol(SamlProtocol.LOGIN_PROTOCOL);
+ loginSession.setRedirectUri(redirect);
+ loginSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
+ loginSession.setNote(SamlProtocol.SAML_BINDING, bindingType);
+ loginSession.setNote(GeneralConstants.RELAY_STATE, relayState);
+ loginSession.setNote(SamlProtocol.SAML_REQUEST_ID, requestAbstractType.getID());
// Handle NameIDPolicy from SP
NameIDPolicyType nameIdPolicy = requestAbstractType.getNameIDPolicy();
@@ -285,7 +286,7 @@ public class SamlService extends AuthorizationEndpointBase {
String nameIdFormat = nameIdFormatUri.toString();
// TODO: Handle AllowCreate too, relevant for persistent NameID.
if (isSupportedNameIdFormat(nameIdFormat)) {
- clientSession.setNote(GeneralConstants.NAMEID_FORMAT, nameIdFormat);
+ loginSession.setNote(GeneralConstants.NAMEID_FORMAT, nameIdFormat);
} else {
event.detail(Details.REASON, "unsupported_nameid_format");
event.error(Errors.INVALID_SAML_AUTHN_REQUEST);
@@ -301,13 +302,13 @@ public class SamlService extends AuthorizationEndpointBase {
BaseIDAbstractType baseID = subject.getSubType().getBaseID();
if (baseID != null && baseID instanceof NameIDType) {
NameIDType nameID = (NameIDType) baseID;
- clientSession.setNote(OIDCLoginProtocol.LOGIN_HINT_PARAM, nameID.getValue());
+ loginSession.setNote(OIDCLoginProtocol.LOGIN_HINT_PARAM, nameID.getValue());
}
}
}
- return newBrowserAuthentication(clientSession, requestAbstractType.isIsPassive(), redirectToAuthentication);
+ return newBrowserAuthentication(loginSession, requestAbstractType.isIsPassive(), redirectToAuthentication);
}
protected String getBindingType(AuthnRequestType requestAbstractType) {
@@ -518,13 +519,13 @@ public class SamlService extends AuthorizationEndpointBase {
}
- protected Response newBrowserAuthentication(ClientSessionModel clientSession, boolean isPassive, boolean redirectToAuthentication) {
+ protected Response newBrowserAuthentication(LoginSessionModel loginSession, boolean isPassive, boolean redirectToAuthentication) {
SamlProtocol samlProtocol = new SamlProtocol().setEventBuilder(event).setHttpHeaders(headers).setRealm(realm).setSession(session).setUriInfo(uriInfo);
- return newBrowserAuthentication(clientSession, isPassive, redirectToAuthentication, samlProtocol);
+ return newBrowserAuthentication(loginSession, isPassive, redirectToAuthentication, samlProtocol);
}
- protected Response newBrowserAuthentication(ClientSessionModel clientSession, boolean isPassive, boolean redirectToAuthentication, SamlProtocol samlProtocol) {
- return handleBrowserAuthenticationRequest(clientSession, samlProtocol, isPassive, redirectToAuthentication);
+ protected Response newBrowserAuthentication(LoginSessionModel loginSession, boolean isPassive, boolean redirectToAuthentication, SamlProtocol samlProtocol) {
+ return handleBrowserAuthenticationRequest(loginSession, samlProtocol, isPassive, redirectToAuthentication);
}
/**
@@ -615,9 +616,9 @@ public class SamlService extends AuthorizationEndpointBase {
return ErrorPage.error(session, Messages.INVALID_REDIRECT_URI);
}
- ClientSessionModel clientSession = createClientSessionForIdpInitiatedSso(this.session, this.realm, client, relayState);
+ LoginSessionModel loginSession = createLoginSessionForIdpInitiatedSso(this.session, this.realm, client, relayState);
- return newBrowserAuthentication(clientSession, false, false);
+ return newBrowserAuthentication(loginSession, false, false);
}
/**
@@ -631,7 +632,7 @@ public class SamlService extends AuthorizationEndpointBase {
* @param relayState Optional relay state - free field as per SAML specification
* @return
*/
- public static ClientSessionModel createClientSessionForIdpInitiatedSso(KeycloakSession session, RealmModel realm, ClientModel client, String relayState) {
+ public static LoginSessionModel createLoginSessionForIdpInitiatedSso(KeycloakSession session, RealmModel realm, ClientModel client, String relayState) {
String bindingType = SamlProtocol.SAML_POST_BINDING;
if (client.getManagementUrl() == null && client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE) == null && client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE) != null) {
bindingType = SamlProtocol.SAML_REDIRECT_BINDING;
@@ -647,21 +648,21 @@ public class SamlService extends AuthorizationEndpointBase {
redirect = client.getManagementUrl();
}
- ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
- clientSession.setAuthMethod(SamlProtocol.LOGIN_PROTOCOL);
- clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
- clientSession.setNote(SamlProtocol.SAML_BINDING, SamlProtocol.SAML_POST_BINDING);
- clientSession.setNote(SamlProtocol.SAML_IDP_INITIATED_LOGIN, "true");
- clientSession.setRedirectUri(redirect);
+ LoginSessionModel loginSession = session.loginSessions().createLoginSession(realm, client, true);
+ loginSession.setProtocol(SamlProtocol.LOGIN_PROTOCOL);
+ loginSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
+ loginSession.setNote(SamlProtocol.SAML_BINDING, SamlProtocol.SAML_POST_BINDING);
+ loginSession.setNote(SamlProtocol.SAML_IDP_INITIATED_LOGIN, "true");
+ loginSession.setRedirectUri(redirect);
if (relayState == null) {
relayState = client.getAttribute(SamlProtocol.SAML_IDP_INITIATED_SSO_RELAY_STATE);
}
if (relayState != null && !relayState.trim().equals("")) {
- clientSession.setNote(GeneralConstants.RELAY_STATE, relayState);
+ loginSession.setNote(GeneralConstants.RELAY_STATE, relayState);
}
- return clientSession;
+ return loginSession;
}
@POST
diff --git a/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java
index 9d615a5..7d45f15 100644
--- a/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java
+++ b/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java
@@ -33,6 +33,7 @@ import org.keycloak.models.cache.CacheRealmProvider;
import org.keycloak.models.cache.UserCache;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
+import org.keycloak.sessions.LoginSessionProvider;
import org.keycloak.storage.UserStorageManager;
import org.keycloak.storage.federated.UserFederatedStorageProvider;
@@ -54,10 +55,10 @@ public class DefaultKeycloakSession implements KeycloakSession {
private final DefaultKeycloakTransactionManager transactionManager;
private final Map<String, Object> attributes = new HashMap<>();
private RealmProvider model;
- private UserProvider userModel;
private UserStorageManager userStorageManager;
private UserCredentialStoreManager userCredentialStorageManager;
private UserSessionProvider sessionProvider;
+ private LoginSessionProvider loginSessionProvider;
private UserFederatedStorageProvider userFederatedStorageProvider;
private KeycloakContext context;
private KeyManager keyManager;
@@ -237,6 +238,14 @@ public class DefaultKeycloakSession implements KeycloakSession {
}
@Override
+ public LoginSessionProvider loginSessions() {
+ if (loginSessionProvider == null) {
+ loginSessionProvider = getProvider(LoginSessionProvider.class);
+ }
+ return loginSessionProvider;
+ }
+
+ @Override
public KeyManager keys() {
if (keyManager == null) {
keyManager = new DefaultKeyManager(this);
diff --git a/services/src/main/java/org/keycloak/services/managers/Auth.java b/services/src/main/java/org/keycloak/services/managers/Auth.java
index 714a3a2..2ac7584 100755
--- a/services/src/main/java/org/keycloak/services/managers/Auth.java
+++ b/services/src/main/java/org/keycloak/services/managers/Auth.java
@@ -17,6 +17,7 @@
package org.keycloak.services.managers;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.RealmModel;
@@ -35,7 +36,7 @@ public class Auth {
private final UserModel user;
private final ClientModel client;
private final UserSessionModel session;
- private ClientSessionModel clientSession;
+ private ClientLoginSessionModel clientSession;
public Auth(RealmModel realm, AccessToken token, UserModel user, ClientModel client, UserSessionModel session, boolean cookie) {
this.cookie = cookie;
@@ -71,11 +72,11 @@ public class Auth {
return session;
}
- public ClientSessionModel getClientSession() {
+ public ClientLoginSessionModel getClientSession() {
return clientSession;
}
- public void setClientSession(ClientSessionModel clientSession) {
+ public void setClientSession(ClientLoginSessionModel clientSession) {
this.clientSession = clientSession;
}
diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
index cf7d73c..3cb8c68 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -20,6 +20,7 @@ import org.jboss.logging.Logger;
import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.TokenVerifier;
+import org.keycloak.authentication.AuthenticationProcessor;
import org.keycloak.authentication.RequiredActionContext;
import org.keycloak.authentication.RequiredActionContextResult;
import org.keycloak.authentication.RequiredActionFactory;
@@ -35,8 +36,8 @@ import org.keycloak.events.EventType;
import org.keycloak.forms.login.LoginFormsProvider;
import org.keycloak.jose.jws.AlgorithmType;
import org.keycloak.jose.jws.JWSBuilder;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeyManager;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
@@ -58,6 +59,7 @@ import org.keycloak.services.resources.IdentityBrokerService;
import org.keycloak.services.resources.RealmsResource;
import org.keycloak.services.util.CookieHelper;
import org.keycloak.services.util.P3PHelper;
+import org.keycloak.sessions.LoginSessionModel;
import javax.crypto.SecretKey;
import javax.ws.rs.core.Cookie;
@@ -68,6 +70,7 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
import java.security.PublicKey;
+import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@@ -159,7 +162,7 @@ public class AuthenticationManager {
logger.debugv("Logging out: {0} ({1})", user.getUsername(), userSession.getId());
expireUserSessionCookie(session, userSession, realm, uriInfo, headers, connection);
- for (ClientSessionModel clientSession : userSession.getClientSessions()) {
+ for (ClientLoginSessionModel clientSession : userSession.getClientLoginSessions().values()) {
backchannelLogoutClientSession(session, realm, clientSession, userSession, uriInfo, headers);
}
if (logoutBroker) {
@@ -169,6 +172,7 @@ public class AuthenticationManager {
try {
identityProvider.backchannelLogout(session, userSession, uriInfo, realm);
} catch (Exception e) {
+ logger.warn("Exception at broker backchannel logout for broker " + brokerId, e);
}
}
}
@@ -176,17 +180,17 @@ public class AuthenticationManager {
session.sessions().removeUserSession(realm, userSession);
}
- public static void backchannelLogoutClientSession(KeycloakSession session, RealmModel realm, ClientSessionModel clientSession, UserSessionModel userSession, UriInfo uriInfo, HttpHeaders headers) {
+ public static void backchannelLogoutClientSession(KeycloakSession session, RealmModel realm, ClientLoginSessionModel clientSession, UserSessionModel userSession, UriInfo uriInfo, HttpHeaders headers) {
ClientModel client = clientSession.getClient();
- if (client instanceof ClientModel && !client.isFrontchannelLogout() && !ClientSessionModel.Action.LOGGED_OUT.name().equals(clientSession.getAction())) {
- String authMethod = clientSession.getAuthMethod();
+ if (!client.isFrontchannelLogout() && !ClientLoginSessionModel.Action.LOGGED_OUT.name().equals(clientSession.getAction())) {
+ String authMethod = clientSession.getProtocol();
if (authMethod == null) return; // must be a keycloak service like account
LoginProtocol protocol = session.getProvider(LoginProtocol.class, authMethod);
protocol.setRealm(realm)
.setHttpHeaders(headers)
.setUriInfo(uriInfo);
protocol.backchannelLogout(userSession, clientSession);
- clientSession.setAction(ClientSessionModel.Action.LOGGED_OUT.name());
+ clientSession.setAction(ClientLoginSessionModel.Action.LOGGED_OUT.name());
}
}
@@ -197,8 +201,8 @@ public class AuthenticationManager {
List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
for (UserSessionModel userSession : userSessions) {
- List<ClientSessionModel> clientSessions = userSession.getClientSessions();
- for (ClientSessionModel clientSession : clientSessions) {
+ Collection<ClientLoginSessionModel> clientSessions = userSession.getClientLoginSessions().values();
+ for (ClientLoginSessionModel clientSession : clientSessions) {
if (clientSession.getClient().getId().equals(clientId)) {
AuthenticationManager.backchannelLogoutClientSession(session, realm, clientSession, userSession, uriInfo, headers);
TokenManager.dettachClientSession(session.sessions(), realm, clientSession);
@@ -215,16 +219,16 @@ public class AuthenticationManager {
if (userSession.getState() != UserSessionModel.State.LOGGING_OUT) {
userSession.setState(UserSessionModel.State.LOGGING_OUT);
}
- List<ClientSessionModel> redirectClients = new LinkedList<ClientSessionModel>();
- for (ClientSessionModel clientSession : userSession.getClientSessions()) {
+ List<ClientLoginSessionModel> redirectClients = new LinkedList<>();
+ for (ClientLoginSessionModel clientSession : userSession.getClientLoginSessions().values()) {
ClientModel client = clientSession.getClient();
- if (ClientSessionModel.Action.LOGGED_OUT.name().equals(clientSession.getAction())) continue;
+ if (ClientLoginSessionModel.Action.LOGGED_OUT.name().equals(clientSession.getAction())) continue;
if (client.isFrontchannelLogout()) {
- String authMethod = clientSession.getAuthMethod();
+ String authMethod = clientSession.getProtocol();
if (authMethod == null) continue; // must be a keycloak service like account
redirectClients.add(clientSession);
} else {
- String authMethod = clientSession.getAuthMethod();
+ String authMethod = clientSession.getProtocol();
if (authMethod == null) continue; // must be a keycloak service like account
LoginProtocol protocol = session.getProvider(LoginProtocol.class, authMethod);
protocol.setRealm(realm)
@@ -233,21 +237,21 @@ public class AuthenticationManager {
try {
logger.debugv("backchannel logout to: {0}", client.getClientId());
protocol.backchannelLogout(userSession, clientSession);
- clientSession.setAction(ClientSessionModel.Action.LOGGED_OUT.name());
+ clientSession.setAction(ClientLoginSessionModel.Action.LOGGED_OUT.name());
} catch (Exception e) {
ServicesLogger.LOGGER.failedToLogoutClient(e);
}
}
}
- for (ClientSessionModel nextRedirectClient : redirectClients) {
- String authMethod = nextRedirectClient.getAuthMethod();
+ for (ClientLoginSessionModel nextRedirectClient : redirectClients) {
+ String authMethod = nextRedirectClient.getProtocol();
LoginProtocol protocol = session.getProvider(LoginProtocol.class, authMethod);
protocol.setRealm(realm)
.setHttpHeaders(headers)
.setUriInfo(uriInfo);
// setting this to logged out cuz I"m not sure protocols can always verify that the client was logged out or not
- nextRedirectClient.setAction(ClientSessionModel.Action.LOGGED_OUT.name());
+ nextRedirectClient.setAction(ClientLoginSessionModel.Action.LOGGED_OUT.name());
try {
logger.debugv("frontchannel logout to: {0}", nextRedirectClient.getClient().getClientId());
Response response = protocol.frontchannelLogout(userSession, nextRedirectClient);
@@ -410,11 +414,11 @@ public class AuthenticationManager {
public static Response redirectAfterSuccessfulFlow(KeycloakSession session, RealmModel realm, UserSessionModel userSession,
- ClientSessionModel clientSession,
+ ClientLoginSessionModel clientSession,
HttpRequest request, UriInfo uriInfo, ClientConnection clientConnection,
- EventBuilder event) {
- LoginProtocol protocol = session.getProvider(LoginProtocol.class, clientSession.getAuthMethod());
- protocol.setRealm(realm)
+ EventBuilder event, String protocol) {
+ LoginProtocol protocolImpl = session.getProvider(LoginProtocol.class, protocol);
+ protocolImpl.setRealm(realm)
.setHttpHeaders(request.getHttpHeaders())
.setUriInfo(uriInfo)
.setEventBuilder(event);
@@ -423,7 +427,7 @@ public class AuthenticationManager {
}
public static Response redirectAfterSuccessfulFlow(KeycloakSession session, RealmModel realm, UserSessionModel userSession,
- ClientSessionModel clientSession,
+ ClientLoginSessionModel clientSession,
HttpRequest request, UriInfo uriInfo, ClientConnection clientConnection,
EventBuilder event, LoginProtocol protocol) {
Cookie sessionCookie = request.getHttpHeaders().getCookies().get(AuthenticationManager.KEYCLOAK_SESSION_COOKIE);
@@ -460,32 +464,33 @@ public class AuthenticationManager {
userSession.setNote(AUTH_TIME, String.valueOf(authTime));
}
- return protocol.authenticated(userSession, new ClientSessionCode(session, realm, clientSession));
+ return protocol.authenticated(userSession, new ClientSessionCode<>(session, realm, clientSession));
}
- public static boolean isSSOAuthentication(ClientSessionModel clientSession) {
+ public static boolean isSSOAuthentication(ClientLoginSessionModel clientSession) {
String ssoAuth = clientSession.getNote(SSO_AUTH);
return Boolean.parseBoolean(ssoAuth);
}
- public static Response nextActionAfterAuthentication(KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession,
+ public static Response nextActionAfterAuthentication(KeycloakSession session, LoginSessionModel loginSession,
ClientConnection clientConnection,
HttpRequest request, UriInfo uriInfo, EventBuilder event) {
- Response requiredAction = actionRequired(session, userSession, clientSession, clientConnection, request, uriInfo, event);
+ Response requiredAction = actionRequired(session, loginSession, clientConnection, request, uriInfo, event);
if (requiredAction != null) return requiredAction;
- return finishedRequiredActions(session, userSession, clientSession, clientConnection, request, uriInfo, event);
+ return finishedRequiredActions(session, loginSession, clientConnection, request, uriInfo, event);
}
- public static Response finishedRequiredActions(KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession, ClientConnection clientConnection, HttpRequest request, UriInfo uriInfo, EventBuilder event) {
- if (clientSession.getNote(END_AFTER_REQUIRED_ACTIONS) != null) {
+ public static Response finishedRequiredActions(KeycloakSession session, LoginSessionModel loginSession,
+ ClientConnection clientConnection, HttpRequest request, UriInfo uriInfo, EventBuilder event) {
+ if (loginSession.getNote(END_AFTER_REQUIRED_ACTIONS) != null) {
LoginFormsProvider infoPage = session.getProvider(LoginFormsProvider.class)
.setSuccess(Messages.ACCOUNT_UPDATED);
- if (clientSession.getNote(SET_REDIRECT_URI_AFTER_REQUIRED_ACTIONS) != null) {
- if (clientSession.getRedirectUri() != null) {
- infoPage.setAttribute("pageRedirectUri", clientSession.getRedirectUri());
+ if (loginSession.getNote(SET_REDIRECT_URI_AFTER_REQUIRED_ACTIONS) != null) {
+ if (loginSession.getRedirectUri() != null) {
+ infoPage.setAttribute("pageRedirectUri", loginSession.getRedirectUri());
}
} else {
@@ -493,31 +498,32 @@ public class AuthenticationManager {
}
Response response = infoPage
.createInfoPage();
- session.sessions().removeUserSession(session.getContext().getRealm(), userSession);
return response;
}
event.success();
- RealmModel realm = clientSession.getRealm();
- return redirectAfterSuccessfulFlow(session, realm , userSession, clientSession, request, uriInfo, clientConnection, event);
+ RealmModel realm = loginSession.getRealm();
+
+ ClientLoginSessionModel clientSession = AuthenticationProcessor.attachSession(loginSession, null, session, realm, clientConnection, event);
+ return redirectAfterSuccessfulFlow(session, realm , clientSession.getUserSession(), clientSession, request, uriInfo, clientConnection, event, loginSession.getProtocol());
}
- public static boolean isActionRequired(final KeycloakSession session, final UserSessionModel userSession, final ClientSessionModel clientSession,
+ public static boolean isActionRequired(final KeycloakSession session, final LoginSessionModel loginSession,
final ClientConnection clientConnection,
final HttpRequest request, final UriInfo uriInfo, final EventBuilder event) {
- final RealmModel realm = clientSession.getRealm();
- final UserModel user = userSession.getUser();
- final ClientModel client = clientSession.getClient();
+ final RealmModel realm = loginSession.getRealm();
+ final UserModel user = loginSession.getAuthenticatedUser();
+ final ClientModel client = loginSession.getClient();
- evaluateRequiredActionTriggers(session, userSession, clientSession, clientConnection, request, uriInfo, event, realm, user);
+ evaluateRequiredActionTriggers(session, loginSession, clientConnection, request, uriInfo, event, realm, user);
- if (!user.getRequiredActions().isEmpty() || !clientSession.getRequiredActions().isEmpty()) return true;
+ if (!user.getRequiredActions().isEmpty() || !loginSession.getRequiredActions().isEmpty()) return true;
if (client.isConsentRequired()) {
UserConsentModel grantedConsent = session.users().getConsentByClient(realm, user.getId(), client.getId());
- ClientSessionCode accessCode = new ClientSessionCode(session, realm, clientSession);
+ ClientSessionCode<LoginSessionModel> accessCode = new ClientSessionCode<>(session, realm, loginSession);
for (RoleModel r : accessCode.getRequestedRoles()) {
// Consent already granted by user
@@ -544,27 +550,27 @@ public class AuthenticationManager {
}
- public static Response actionRequired(final KeycloakSession session, final UserSessionModel userSession, final ClientSessionModel clientSession,
+ public static Response actionRequired(final KeycloakSession session, final LoginSessionModel loginSession,
final ClientConnection clientConnection,
final HttpRequest request, final UriInfo uriInfo, final EventBuilder event) {
- final RealmModel realm = clientSession.getRealm();
- final UserModel user = userSession.getUser();
- final ClientModel client = clientSession.getClient();
+ final RealmModel realm = loginSession.getRealm();
+ final UserModel user = loginSession.getAuthenticatedUser();
+ final ClientModel client = loginSession.getClient();
- evaluateRequiredActionTriggers(session, userSession, clientSession, clientConnection, request, uriInfo, event, realm, user);
+ evaluateRequiredActionTriggers(session, loginSession, clientConnection, request, uriInfo, event, realm, user);
logger.debugv("processAccessCode: go to oauth page?: {0}", client.isConsentRequired());
- event.detail(Details.CODE_ID, clientSession.getId());
+ event.detail(Details.CODE_ID, loginSession.getId());
Set<String> requiredActions = user.getRequiredActions();
- Response action = executionActions(session, userSession, clientSession, request, event, realm, user, requiredActions);
+ Response action = executionActions(session, loginSession, request, event, realm, user, requiredActions);
if (action != null) return action;
// executionActions() method should remove any duplicate actions that might be in the clientSession
- requiredActions = clientSession.getRequiredActions();
- action = executionActions(session, userSession, clientSession, request, event, realm, user, requiredActions);
+ requiredActions = loginSession.getRequiredActions();
+ action = executionActions(session, loginSession, request, event, realm, user, requiredActions);
if (action != null) return action;
if (client.isConsentRequired()) {
@@ -573,7 +579,7 @@ public class AuthenticationManager {
List<RoleModel> realmRoles = new LinkedList<>();
MultivaluedMap<String, RoleModel> resourceRoles = new MultivaluedMapImpl<>();
- ClientSessionCode accessCode = new ClientSessionCode(session, realm, clientSession);
+ ClientSessionCode<LoginSessionModel> accessCode = new ClientSessionCode<>(session, realm, loginSession);
for (RoleModel r : accessCode.getRequestedRoles()) {
// Consent already granted by user
@@ -599,13 +605,15 @@ public class AuthenticationManager {
// Skip grant screen if everything was already approved by this user
if (realmRoles.size() > 0 || resourceRoles.size() > 0 || protocolMappers.size() > 0) {
- accessCode.setAction(ClientSessionModel.Action.REQUIRED_ACTIONS.name());
- clientSession.setNote(CURRENT_REQUIRED_ACTION, ClientSessionModel.Action.OAUTH_GRANT.name());
+ accessCode.
+
+ setAction(ClientLoginSessionModel.Action.REQUIRED_ACTIONS.name());
+ loginSession.setNote(CURRENT_REQUIRED_ACTION, ClientLoginSessionModel.Action.OAUTH_GRANT.name());
return session.getProvider(LoginFormsProvider.class)
.setClientSessionCode(accessCode.getCode())
.setAccessRequest(realmRoles, resourceRoles, protocolMappers)
- .createOAuthGrant(clientSession);
+ .createOAuthGrant();
} else {
String consentDetail = (grantedConsent != null) ? Details.CONSENT_VALUE_PERSISTED_CONSENT : Details.CONSENT_VALUE_NO_CONSENT_REQUIRED;
event.detail(Details.CONSENT, consentDetail);
@@ -617,7 +625,7 @@ public class AuthenticationManager {
}
- protected static Response executionActions(KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession,
+ protected static Response executionActions(KeycloakSession session, LoginSessionModel loginSession,
HttpRequest request, EventBuilder event, RealmModel realm, UserModel user,
Set<String> requiredActions) {
for (String action : requiredActions) {
@@ -635,34 +643,34 @@ public class AuthenticationManager {
throw new RuntimeException("Unable to find factory for Required Action: " + model.getProviderId() + " did you forget to declare it in a META-INF/services file?");
}
RequiredActionProvider actionProvider = factory.create(session);
- RequiredActionContextResult context = new RequiredActionContextResult(userSession, clientSession, realm, event, session, request, user, factory);
+ RequiredActionContextResult context = new RequiredActionContextResult(loginSession, realm, event, session, request, user, factory);
actionProvider.requiredActionChallenge(context);
if (context.getStatus() == RequiredActionContext.Status.FAILURE) {
- LoginProtocol protocol = context.getSession().getProvider(LoginProtocol.class, context.getClientSession().getAuthMethod());
+ LoginProtocol protocol = context.getSession().getProvider(LoginProtocol.class, context.getLoginSession().getProtocol());
protocol.setRealm(context.getRealm())
.setHttpHeaders(context.getHttpRequest().getHttpHeaders())
.setUriInfo(context.getUriInfo())
.setEventBuilder(event);
- Response response = protocol.sendError(context.getClientSession(), Error.CONSENT_DENIED);
+ Response response = protocol.sendError(context.getLoginSession(), Error.CONSENT_DENIED);
event.error(Errors.REJECTED_BY_USER);
return response;
}
else if (context.getStatus() == RequiredActionContext.Status.CHALLENGE) {
- clientSession.setNote(CURRENT_REQUIRED_ACTION, model.getProviderId());
+ loginSession.setNote(CURRENT_REQUIRED_ACTION, model.getProviderId());
return context.getChallenge();
}
else if (context.getStatus() == RequiredActionContext.Status.SUCCESS) {
event.clone().event(EventType.CUSTOM_REQUIRED_ACTION).detail(Details.CUSTOM_REQUIRED_ACTION, factory.getId()).success();
// don't have to perform the same action twice, so remove it from both the user and session required actions
- clientSession.getUserSession().getUser().removeRequiredAction(factory.getId());
- clientSession.removeRequiredAction(factory.getId());
+ loginSession.getAuthenticatedUser().removeRequiredAction(factory.getId());
+ loginSession.removeRequiredAction(factory.getId());
}
}
return null;
}
- public static void evaluateRequiredActionTriggers(final KeycloakSession session, final UserSessionModel userSession, final ClientSessionModel clientSession, final ClientConnection clientConnection, final HttpRequest request, final UriInfo uriInfo, final EventBuilder event, final RealmModel realm, final UserModel user) {
+ public static void evaluateRequiredActionTriggers(final KeycloakSession session, final LoginSessionModel loginSession, final ClientConnection clientConnection, final HttpRequest request, final UriInfo uriInfo, final EventBuilder event, final RealmModel realm, final UserModel user) {
// see if any required actions need triggering, i.e. an expired password
for (RequiredActionProviderModel model : realm.getRequiredActionProviders()) {
@@ -672,7 +680,7 @@ public class AuthenticationManager {
throw new RuntimeException("Unable to find factory for Required Action: " + model.getProviderId() + " did you forget to declare it in a META-INF/services file?");
}
RequiredActionProvider provider = factory.create(session);
- RequiredActionContextResult result = new RequiredActionContextResult(userSession, clientSession, realm, event, session, request, user, factory) {
+ RequiredActionContextResult result = new RequiredActionContextResult(loginSession, realm, event, session, request, user, factory) {
@Override
public void challenge(Response response) {
throw new RuntimeException("Not allowed to call challenge() within evaluateTriggers()");
diff --git a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
index 12e0449..baf7ead 100755
--- a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
@@ -24,8 +24,8 @@ import org.keycloak.common.util.StringPropertyReplacer;
import org.keycloak.common.util.Time;
import org.keycloak.connections.httpclient.HttpClientProvider;
import org.keycloak.constants.AdapterConstants;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
@@ -113,7 +113,7 @@ public class ResourceAdminManager {
protected void logoutUserSessions(URI requestUri, RealmModel realm, List<UserSessionModel> userSessions) {
// Map from "app" to clientSessions for this app
- MultivaluedHashMap<ClientModel, ClientSessionModel> clientSessions = new MultivaluedHashMap<ClientModel, ClientSessionModel>();
+ MultivaluedHashMap<String, ClientLoginSessionModel> clientSessions = new MultivaluedHashMap<>();
for (UserSessionModel userSession : userSessions) {
putClientSessions(clientSessions, userSession);
}
@@ -121,37 +121,40 @@ public class ResourceAdminManager {
logger.debugv("logging out {0} resources ", clientSessions.size());
//logger.infov("logging out resources: {0}", clientSessions);
- for (Map.Entry<ClientModel, List<ClientSessionModel>> entry : clientSessions.entrySet()) {
- logoutClientSessions(requestUri, realm, entry.getKey(), entry.getValue());
+ for (Map.Entry<String, List<ClientLoginSessionModel>> entry : clientSessions.entrySet()) {
+ if (entry.getValue().size() == 0) {
+ continue;
+ }
+ logoutClientSessions(requestUri, realm, entry.getValue().get(0).getClient(), entry.getValue());
}
}
- private void putClientSessions(MultivaluedHashMap<ClientModel, ClientSessionModel> clientSessions, UserSessionModel userSession) {
- for (ClientSessionModel clientSession : userSession.getClientSessions()) {
- ClientModel client = clientSession.getClient();
- clientSessions.add(client, clientSession);
+ private void putClientSessions(MultivaluedHashMap<String, ClientLoginSessionModel> clientSessions, UserSessionModel userSession) {
+ for (Map.Entry<String, ClientLoginSessionModel> entry : userSession.getClientLoginSessions().entrySet()) {
+ clientSessions.add(entry.getKey(), entry.getValue());
}
}
public void logoutUserFromClient(URI requestUri, RealmModel realm, ClientModel resource, UserModel user) {
List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
- List<ClientSessionModel> ourAppClientSessions = null;
+ List<ClientLoginSessionModel> ourAppClientSessions = new LinkedList<>();
if (userSessions != null) {
- MultivaluedHashMap<ClientModel, ClientSessionModel> clientSessions = new MultivaluedHashMap<ClientModel, ClientSessionModel>();
for (UserSessionModel userSession : userSessions) {
- putClientSessions(clientSessions, userSession);
+ ClientLoginSessionModel clientSession = userSession.getClientLoginSessions().get(resource.getId());
+ if (clientSession != null) {
+ ourAppClientSessions.add(clientSession);
+ }
}
- ourAppClientSessions = clientSessions.get(resource);
}
logoutClientSessions(requestUri, realm, resource, ourAppClientSessions);
}
- public boolean logoutClientSession(URI requestUri, RealmModel realm, ClientModel resource, ClientSessionModel clientSession) {
+ public boolean logoutClientSession(URI requestUri, RealmModel realm, ClientModel resource, ClientLoginSessionModel clientSession) {
return logoutClientSessions(requestUri, realm, resource, Arrays.asList(clientSession));
}
- protected boolean logoutClientSessions(URI requestUri, RealmModel realm, ClientModel resource, List<ClientSessionModel> clientSessions) {
+ protected boolean logoutClientSessions(URI requestUri, RealmModel realm, ClientModel resource, List<ClientLoginSessionModel> clientSessions) {
String managementUrl = getManagementUrl(requestUri, resource);
if (managementUrl != null) {
@@ -160,7 +163,7 @@ public class ResourceAdminManager {
List<String> userSessions = new LinkedList<>();
if (clientSessions != null && clientSessions.size() > 0) {
adapterSessionIds = new MultivaluedHashMap<String, String>();
- for (ClientSessionModel clientSession : clientSessions) {
+ for (ClientLoginSessionModel clientSession : clientSessions) {
String adapterSessionId = clientSession.getNote(AdapterConstants.CLIENT_SESSION_STATE);
if (adapterSessionId != null) {
String host = clientSession.getNote(AdapterConstants.CLIENT_SESSION_HOST);
diff --git a/services/src/main/java/org/keycloak/services/managers/UserSessionManager.java b/services/src/main/java/org/keycloak/services/managers/UserSessionManager.java
index 4c8c2fe..a70c6f6 100644
--- a/services/src/main/java/org/keycloak/services/managers/UserSessionManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/UserSessionManager.java
@@ -18,11 +18,10 @@ package org.keycloak.services.managers;
import org.jboss.logging.Logger;
import org.keycloak.common.util.Time;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ModelException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
@@ -31,7 +30,6 @@ import org.keycloak.models.session.UserSessionPersisterProvider;
import org.keycloak.services.ServicesLogger;
import java.util.HashSet;
-import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@@ -52,7 +50,7 @@ public class UserSessionManager {
this.persister = session.getProvider(UserSessionPersisterProvider.class);
}
- public void createOrUpdateOfflineSession(ClientSessionModel clientSession, UserSessionModel userSession) {
+ public void createOrUpdateOfflineSession(ClientLoginSessionModel clientSession, UserSessionModel userSession) {
UserModel user = userSession.getUser();
// Create and persist offline userSession if we don't have one
@@ -65,50 +63,50 @@ public class UserSessionManager {
}
// Create and persist clientSession
- ClientSessionModel offlineClientSession = kcSession.sessions().getOfflineClientSession(clientSession.getRealm(), clientSession.getId());
+ ClientLoginSessionModel offlineClientSession = offlineUserSession.getClientLoginSessions().get(clientSession.getClient().getId());
if (offlineClientSession == null) {
createOfflineClientSession(user, clientSession, offlineUserSession);
}
}
- // userSessionId is provided from offline token. It's used just to verify if it match the ID from clientSession representation
- public ClientSessionModel findOfflineClientSession(RealmModel realm, String clientSessionId) {
- return kcSession.sessions().getOfflineClientSession(realm, clientSessionId);
+
+ public UserSessionModel findOfflineUserSession(RealmModel realm, String userSessionId) {
+ return kcSession.sessions().getOfflineUserSession(realm, userSessionId);
}
public Set<ClientModel> findClientsWithOfflineToken(RealmModel realm, UserModel user) {
- List<ClientSessionModel> clientSessions = kcSession.sessions().getOfflineClientSessions(realm, user);
+ List<UserSessionModel> userSessions = kcSession.sessions().getOfflineUserSessions(realm, user);
Set<ClientModel> clients = new HashSet<>();
- for (ClientSessionModel clientSession : clientSessions) {
- clients.add(clientSession.getClient());
+ for (UserSessionModel userSession : userSessions) {
+ Set<String> clientIds = userSession.getClientLoginSessions().keySet();
+ for (String clientUUID : clientIds) {
+ ClientModel client = realm.getClientById(clientUUID);
+ clients.add(client);
+ }
}
return clients;
}
- public List<UserSessionModel> findOfflineSessions(RealmModel realm, ClientModel client, UserModel user) {
- List<ClientSessionModel> clientSessions = kcSession.sessions().getOfflineClientSessions(realm, user);
- List<UserSessionModel> userSessions = new LinkedList<>();
- for (ClientSessionModel clientSession : clientSessions) {
- userSessions.add(clientSession.getUserSession());
- }
- return userSessions;
+ public List<UserSessionModel> findOfflineSessions(RealmModel realm, UserModel user) {
+ return kcSession.sessions().getOfflineUserSessions(realm, user);
}
public boolean revokeOfflineToken(UserModel user, ClientModel client) {
RealmModel realm = client.getRealm();
- List<ClientSessionModel> clientSessions = kcSession.sessions().getOfflineClientSessions(realm, user);
+ List<UserSessionModel> userSessions = kcSession.sessions().getOfflineUserSessions(realm, user);
boolean anyRemoved = false;
- for (ClientSessionModel clientSession : clientSessions) {
- if (clientSession.getClient().getId().equals(client.getId())) {
+ for (UserSessionModel userSession : userSessions) {
+ ClientLoginSessionModel clientSession = userSession.getClientLoginSessions().get(client.getId());
+ if (clientSession != null) {
if (logger.isTraceEnabled()) {
- logger.tracef("Removing existing offline token for user '%s' and client '%s' . ClientSessionID was '%s' .",
- user.getUsername(), client.getClientId(), clientSession.getId());
+ logger.tracef("Removing existing offline token for user '%s' and client '%s' .",
+ user.getUsername(), client.getClientId());
}
- kcSession.sessions().removeOfflineClientSession(realm, clientSession.getId());
+ userSession.getClientLoginSessions().remove(client.getClientId());
persister.removeClientSession(clientSession.getId(), true);
- checkOfflineUserSessionHasClientSessions(realm, user, clientSession.getUserSession(), clientSessions);
+ checkOfflineUserSessionHasClientSessions(realm, user, userSession);
anyRemoved = true;
}
}
@@ -124,7 +122,7 @@ public class UserSessionManager {
persister.removeUserSession(userSession.getId(), true);
}
- public boolean isOfflineTokenAllowed(ClientSessionModel clientSession) {
+ public boolean isOfflineTokenAllowed(ClientLoginSessionModel clientSession) {
RoleModel offlineAccessRole = clientSession.getRealm().getRole(Constants.OFFLINE_ACCESS_ROLE);
if (offlineAccessRole == null) {
ServicesLogger.LOGGER.roleNotInRealm(Constants.OFFLINE_ACCESS_ROLE);
@@ -144,30 +142,27 @@ public class UserSessionManager {
return offlineUserSession;
}
- private void createOfflineClientSession(UserModel user, ClientSessionModel clientSession, UserSessionModel userSession) {
+ private void createOfflineClientSession(UserModel user, ClientLoginSessionModel clientSession, UserSessionModel offlineUserSession) {
if (logger.isTraceEnabled()) {
logger.tracef("Creating new offline token client session. ClientSessionId: '%s', UserSessionID: '%s' , Username: '%s', Client: '%s'" ,
- clientSession.getId(), userSession.getId(), user.getUsername(), clientSession.getClient().getClientId());
+ clientSession.getId(), offlineUserSession.getId(), user.getUsername(), clientSession.getClient().getClientId());
}
- ClientSessionModel offlineClientSession = kcSession.sessions().createOfflineClientSession(clientSession);
- offlineClientSession.setUserSession(userSession);
- persister.createClientSession(clientSession, true);
+ ClientLoginSessionModel offlineClientSession = kcSession.sessions().createOfflineClientSession(clientSession);
+ offlineUserSession.getClientLoginSessions().put(clientSession.getClient().getId(), offlineClientSession);
+ persister.createClientSession(offlineUserSession, clientSession, true);
}
// Check if userSession has any offline clientSessions attached to it. Remove userSession if not
- private void checkOfflineUserSessionHasClientSessions(RealmModel realm, UserModel user, UserSessionModel userSession, List<ClientSessionModel> clientSessions) {
- String userSessionId = userSession.getId();
- for (ClientSessionModel clientSession : clientSessions) {
- if (clientSession.getUserSession().getId().equals(userSessionId)) {
- return;
- }
+ private void checkOfflineUserSessionHasClientSessions(RealmModel realm, UserModel user, UserSessionModel userSession) {
+ if (userSession.getClientLoginSessions().size() > 0) {
+ return;
}
if (logger.isTraceEnabled()) {
- logger.tracef("Removing offline userSession for user %s as it doesn't have any client sessions attached. UserSessionID: %s", user.getUsername(), userSessionId);
+ logger.tracef("Removing offline userSession for user %s as it doesn't have any client sessions attached. UserSessionID: %s", user.getUsername(), userSession.getId());
}
kcSession.sessions().removeOfflineUserSession(realm, userSession);
- persister.removeUserSession(userSessionId, true);
+ persister.removeUserSession(userSession.getId(), true);
}
}
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index e0e5f8b..f4737ad 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -30,6 +30,7 @@ import org.keycloak.forms.account.AccountPages;
import org.keycloak.forms.account.AccountProvider;
import org.keycloak.forms.login.LoginFormsProvider;
import org.keycloak.models.AccountRoles;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.FederatedIdentityModel;
@@ -164,16 +165,9 @@ public class AccountService extends AbstractSecuredLocalService {
if (authResult != null) {
UserSessionModel userSession = authResult.getSession();
if (userSession != null) {
- boolean associated = false;
- for (ClientSessionModel c : userSession.getClientSessions()) {
- if (c.getClient().equals(client)) {
- auth.setClientSession(c);
- associated = true;
- break;
- }
- }
+ boolean associated = userSession.getClientLoginSessions().get(client.getId()) != null;
if (!associated) {
- ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
+ ClientLoginSessionModel clientSession = session.sessions().createClientSession(userSession.getRealm(), client, userSession);
clientSession.setUserSession(userSession);
auth.setClientSession(clientSession);
}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
index 3259982..d745213 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
@@ -33,6 +33,7 @@ import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.events.admin.OperationType;
import org.keycloak.events.admin.ResourceType;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.Constants;
@@ -396,7 +397,7 @@ public class UsersResource {
@GET
@NoCache
@Produces(MediaType.APPLICATION_JSON)
- public List<UserSessionRepresentation> getSessions(final @PathParam("id") String id, final @PathParam("clientId") String clientId) {
+ public List<UserSessionRepresentation> getOfflineSessions(final @PathParam("id") String id, final @PathParam("clientId") String clientId) {
auth.requireView();
UserModel user = session.users().getUserById(id, realm);
@@ -407,19 +408,21 @@ public class UsersResource {
if (client == null) {
throw new NotFoundException("Client not found");
}
- List<UserSessionModel> sessions = new UserSessionManager(session).findOfflineSessions(realm, client, user);
+ List<UserSessionModel> sessions = new UserSessionManager(session).findOfflineSessions(realm, user);
List<UserSessionRepresentation> reps = new ArrayList<UserSessionRepresentation>();
for (UserSessionModel session : sessions) {
UserSessionRepresentation rep = ModelToRepresentation.toRepresentation(session);
// Update lastSessionRefresh with the timestamp from clientSession
- for (ClientSessionModel clientSession : session.getClientSessions()) {
- if (clientId.equals(clientSession.getClient().getId())) {
- rep.setLastAccess(Time.toMillis(clientSession.getTimestamp()));
- break;
- }
+ ClientLoginSessionModel clientSession = session.getClientLoginSessions().get(clientId);
+
+ // Skip if userSession is not for this client
+ if (clientSession == null) {
+ continue;
}
+ rep.setLastAccess(clientSession.getTimestamp());
+
reps.add(rep);
}
return reps;
@@ -864,6 +867,8 @@ public class UsersResource {
List<String> actions) {
auth.requireManage();
+ // TODO: This stuff must be refactored for actionTickets (clientSessions)
+ /*
UserModel user = session.users().getUserById(id, realm);
if (user == null) {
return ErrorResponse.error("User not found", Response.Status.NOT_FOUND);
@@ -884,6 +889,7 @@ public class UsersResource {
ClientSessionCode accessCode = new ClientSessionCode(session, realm, clientSession);
accessCode.setAction(ClientSessionModel.Action.EXECUTE_ACTIONS.name());
+
try {
UriBuilder builder = Urls.executeActionsBuilder(uriInfo.getBaseUri());
builder.queryParam("key", accessCode.getCode());
@@ -901,7 +907,8 @@ public class UsersResource {
} catch (EmailException e) {
ServicesLogger.LOGGER.failedToSendActionsEmail(e);
return ErrorResponse.error("Failed to send execute actions email", Response.Status.INTERNAL_SERVER_ERROR);
- }
+ }*/
+ return null;
}
/**
@@ -925,6 +932,7 @@ public class UsersResource {
return executeActionsEmail(id, redirectUri, clientId, actions);
}
+ /*
private ClientSessionModel createClientSession(UserModel user, String redirectUri, String clientId) {
if (!user.isEnabled()) {
@@ -965,7 +973,7 @@ public class UsersResource {
clientSession.setUserSession(userSession);
return clientSession;
- }
+ }*/
@GET
@Path("{id}/groups")
diff --git a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
index f9efe19..9dd9f95 100755
--- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
+++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
@@ -45,6 +45,7 @@ import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.forms.login.LoginFormsProvider;
import org.keycloak.models.AuthenticationFlowModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.Constants;
@@ -78,6 +79,7 @@ import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.util.CacheControlUtil;
import org.keycloak.services.validation.Validation;
+import org.keycloak.sessions.LoginSessionModel;
import org.keycloak.util.JsonSerialization;
import javax.ws.rs.GET;
@@ -108,7 +110,6 @@ import java.util.UUID;
import static org.keycloak.models.AccountRoles.MANAGE_ACCOUNT;
import static org.keycloak.models.AccountRoles.MANAGE_ACCOUNT_LINKS;
-import static org.keycloak.models.ClientSessionModel.Action.AUTHENTICATE;
import static org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_CLIENT_ID;
/**
@@ -116,981 +117,958 @@ import static org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_CLIENT_ID;
*
* @author Pedro Igor
*/
-public class IdentityBrokerService implements IdentityProvider.AuthenticationCallback {
-
- private static final Logger logger = Logger.getLogger(IdentityBrokerService.class);
-
- private final RealmModel realmModel;
-
- @Context
- private UriInfo uriInfo;
-
- @Context
- private KeycloakSession session;
-
- @Context
- private ClientConnection clientConnection;
-
- @Context
- private HttpRequest request;
-
- @Context
- private HttpHeaders headers;
-
- private EventBuilder event;
-
-
- public IdentityBrokerService(RealmModel realmModel) {
- if (realmModel == null) {
- throw new IllegalArgumentException("Realm can not be null.");
- }
- this.realmModel = realmModel;
- }
-
- public void init() {
- this.event = new EventBuilder(realmModel, session, clientConnection).event(EventType.IDENTITY_PROVIDER_LOGIN);
- }
-
- private void checkRealm() {
- if (!realmModel.isEnabled()) {
- event.error(Errors.REALM_DISABLED);
- throw new ErrorPageException(session, Messages.REALM_NOT_ENABLED);
- }
- }
-
- private ClientModel checkClient(String clientId) {
- if (clientId == null) {
- event.error(Errors.INVALID_REQUEST);
- throw new ErrorPageException(session, Messages.MISSING_PARAMETER, OIDCLoginProtocol.CLIENT_ID_PARAM);
- }
-
- event.client(clientId);
-
- ClientModel client = realmModel.getClientByClientId(clientId);
- if (client == null) {
- event.error(Errors.CLIENT_NOT_FOUND);
- throw new ErrorPageException(session, Messages.INVALID_REQUEST);
- }
-
- if (!client.isEnabled()) {
- event.error(Errors.CLIENT_DISABLED);
- throw new ErrorPageException(session, Messages.INVALID_REQUEST);
- }
- return client;
-
- }
-
- /**
- * Closes off CORS preflight requests for account linking
- *
- * @param providerId
- * @return
- */
- @OPTIONS
- @Path("/{provider_id}/link")
- public Response clientIntiatedAccountLinkingPreflight(@PathParam("provider_id") String providerId) {
- return Response.status(403).build(); // don't allow preflight
- }
-
-
- @GET
- @NoCache
- @Path("/{provider_id}/link")
- public Response clientInitiatedAccountLinking(@PathParam("provider_id") String providerId,
- @QueryParam("redirect_uri") String redirectUri,
- @QueryParam("client_id") String clientId,
- @QueryParam("nonce") String nonce,
- @QueryParam("hash") String hash
- ) {
- this.event.event(EventType.CLIENT_INITIATED_ACCOUNT_LINKING);
- checkRealm();
- ClientModel client = checkClient(clientId);
- AuthenticationManager authenticationManager = new AuthenticationManager();
- redirectUri = RedirectUtils.verifyRedirectUri(uriInfo, redirectUri, realmModel, client);
- if (redirectUri == null) {
- event.error(Errors.INVALID_REDIRECT_URI);
- throw new ErrorPageException(session, Messages.INVALID_REQUEST);
- }
-
- if (nonce == null || hash == null) {
- event.error(Errors.INVALID_REDIRECT_URI);
- throw new ErrorPageException(session, Messages.INVALID_REQUEST);
-
- }
-
- // only allow origins from client. Not sure we need this as I don't believe cookies can be
- // sent if CORS preflight requests can't execute.
- String origin = headers.getRequestHeaders().getFirst("Origin");
- if (origin != null) {
- String redirectOrigin = UriUtils.getOrigin(redirectUri);
- if (!redirectOrigin.equals(origin)) {
- event.error(Errors.ILLEGAL_ORIGIN);
- throw new ErrorPageException(session, Messages.INVALID_REQUEST);
-
- }
- }
-
- AuthResult cookieResult = authenticationManager.authenticateIdentityCookie(session, realmModel, true);
- String errorParam = "link_error";
- if (cookieResult == null) {
- event.error(Errors.NOT_LOGGED_IN);
- UriBuilder builder = UriBuilder.fromUri(redirectUri)
- .queryParam(errorParam, Errors.NOT_LOGGED_IN)
- .queryParam("nonce", nonce);
-
- return Response.status(302).location(builder.build()).build();
- }
-
-
-
- ClientSessionModel clientSession = null;
- for (ClientSessionModel cs : cookieResult.getSession().getClientSessions()) {
- if (cs.getClient().getClientId().equals(clientId)) {
- byte[] decoded = Base64Url.decode(hash);
- MessageDigest md = null;
- try {
- md = MessageDigest.getInstance("SHA-256");
- } catch (NoSuchAlgorithmException e) {
- throw new ErrorPageException(session, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST);
- }
- String input = nonce + cookieResult.getSession().getId() + cs.getId() + providerId;
- byte[] check = md.digest(input.getBytes(StandardCharsets.UTF_8));
- if (MessageDigest.isEqual(decoded, check)) {
- clientSession = cs;
- break;
- }
- }
- }
- if (clientSession == null) {
- event.error(Errors.INVALID_TOKEN);
- throw new ErrorPageException(session, Messages.INVALID_REQUEST);
- }
-
-
-
- ClientModel accountService = this.realmModel.getClientByClientId(ACCOUNT_MANAGEMENT_CLIENT_ID);
- if (!accountService.getId().equals(client.getId())) {
- RoleModel manageAccountRole = accountService.getRole(MANAGE_ACCOUNT);
-
- if (!clientSession.getRoles().contains(manageAccountRole.getId())) {
- RoleModel linkRole = accountService.getRole(MANAGE_ACCOUNT_LINKS);
- if (!clientSession.getRoles().contains(linkRole.getId())) {
- event.error(Errors.NOT_ALLOWED);
- UriBuilder builder = UriBuilder.fromUri(redirectUri)
- .queryParam(errorParam, Errors.NOT_ALLOWED)
- .queryParam("nonce", nonce);
- return Response.status(302).location(builder.build()).build();
- }
- }
- }
-
-
- IdentityProviderModel identityProviderModel = realmModel.getIdentityProviderByAlias(providerId);
- if (identityProviderModel == null) {
- event.error(Errors.UNKNOWN_IDENTITY_PROVIDER);
- UriBuilder builder = UriBuilder.fromUri(redirectUri)
- .queryParam(errorParam, Errors.UNKNOWN_IDENTITY_PROVIDER)
- .queryParam("nonce", nonce);
- return Response.status(302).location(builder.build()).build();
-
- }
-
-
-
- ClientSessionCode clientSessionCode = new ClientSessionCode(session, realmModel, clientSession);
- clientSessionCode.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
- clientSessionCode.getCode();
- clientSession.setRedirectUri(redirectUri);
- clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, UUID.randomUUID().toString());
-
- event.success();
-
-
- try {
- IdentityProvider identityProvider = getIdentityProvider(session, realmModel, providerId);
- Response response = identityProvider.performLogin(createAuthenticationRequest(providerId, clientSessionCode));
-
- if (response != null) {
- if (isDebugEnabled()) {
- logger.debugf("Identity provider [%s] is going to send a request [%s].", identityProvider, response);
- }
- return response;
- }
- } catch (IdentityBrokerException e) {
- return redirectToErrorPage(Messages.COULD_NOT_SEND_AUTHENTICATION_REQUEST, e, providerId);
- } catch (Exception e) {
- return redirectToErrorPage(Messages.UNEXPECTED_ERROR_HANDLING_REQUEST, e, providerId);
- }
-
- return redirectToErrorPage(Messages.COULD_NOT_PROCEED_WITH_AUTHENTICATION_REQUEST);
-
- }
-
-
- @POST
- @Path("/{provider_id}/login")
- public Response performPostLogin(@PathParam("provider_id") String providerId, @QueryParam("code") String code) {
- return performLogin(providerId, code);
- }
-
- @GET
- @NoCache
- @Path("/{provider_id}/login")
- public Response performLogin(@PathParam("provider_id") String providerId, @QueryParam("code") String code) {
- this.event.detail(Details.IDENTITY_PROVIDER, providerId);
-
- if (isDebugEnabled()) {
- logger.debugf("Sending authentication request to identity provider [%s].", providerId);
- }
-
- try {
- ParsedCodeContext parsedCode = parseClientSessionCode(code);
- if (parsedCode.response != null) {
- return parsedCode.response;
- }
-
- ClientSessionCode clientSessionCode = parsedCode.clientSessionCode;
- IdentityProviderModel identityProviderModel = realmModel.getIdentityProviderByAlias(providerId);
- if (identityProviderModel == null) {
- throw new IdentityBrokerException("Identity Provider [" + providerId + "] not found.");
- }
- if (identityProviderModel.isLinkOnly()) {
- throw new IdentityBrokerException("Identity Provider [" + providerId + "] is not allowed to perform a login.");
-
- }
- IdentityProviderFactory providerFactory = getIdentityProviderFactory(session, identityProviderModel);
-
- IdentityProvider identityProvider = providerFactory.create(session, identityProviderModel);
-
- Response response = identityProvider.performLogin(createAuthenticationRequest(providerId, clientSessionCode));
-
- if (response != null) {
- if (isDebugEnabled()) {
- logger.debugf("Identity provider [%s] is going to send a request [%s].", identityProvider, response);
- }
- return response;
- }
- } catch (IdentityBrokerException e) {
- return redirectToErrorPage(Messages.COULD_NOT_SEND_AUTHENTICATION_REQUEST, e, providerId);
- } catch (Exception e) {
- return redirectToErrorPage(Messages.UNEXPECTED_ERROR_HANDLING_REQUEST, e, providerId);
- }
-
- return redirectToErrorPage(Messages.COULD_NOT_PROCEED_WITH_AUTHENTICATION_REQUEST);
- }
-
- @Path("{provider_id}/endpoint")
- public Object getEndpoint(@PathParam("provider_id") String providerId) {
- IdentityProvider identityProvider = getIdentityProvider(session, realmModel, providerId);
- Object callback = identityProvider.callback(realmModel, this, event);
- ResteasyProviderFactory.getInstance().injectProperties(callback);
- //resourceContext.initResource(brokerService);
- return callback;
-
-
- }
-
- @Path("{provider_id}/token")
- @OPTIONS
- public Response retrieveTokenPreflight() {
- return Cors.add(this.request, Response.ok()).auth().preflight().build();
- }
-
- @GET
- @NoCache
- @Path("{provider_id}/token")
- public Response retrieveToken(@PathParam("provider_id") String providerId) {
- return getToken(providerId, false);
- }
-
- private boolean canReadBrokerToken(AccessToken token) {
- Map<String, AccessToken.Access> resourceAccess = token.getResourceAccess();
- AccessToken.Access brokerRoles = resourceAccess == null ? null : resourceAccess.get(Constants.BROKER_SERVICE_CLIENT_ID);
- return brokerRoles != null && brokerRoles.isUserInRole(Constants.READ_TOKEN_ROLE);
- }
-
- private Response getToken(String providerId, boolean forceRetrieval) {
- this.event.event(EventType.IDENTITY_PROVIDER_RETRIEVE_TOKEN);
-
- try {
- AppAuthManager authManager = new AppAuthManager();
- AuthResult authResult = authManager.authenticateBearerToken(this.session, this.realmModel, this.uriInfo, this.clientConnection, this.request.getHttpHeaders());
-
- if (authResult != null) {
- AccessToken token = authResult.getToken();
- String[] audience = token.getAudience();
- ClientModel clientModel = this.realmModel.getClientByClientId(audience[0]);
-
- if (clientModel == null) {
- return badRequest("Invalid client.");
- }
-
- session.getContext().setClient(clientModel);
-
- ClientModel brokerClient = realmModel.getClientByClientId(Constants.BROKER_SERVICE_CLIENT_ID);
- if (brokerClient == null) {
- return corsResponse(forbidden("Realm has not migrated to support the broker token exchange service"), clientModel);
-
- }
- if (!canReadBrokerToken(token)) {
- return corsResponse(forbidden("Client [" + clientModel.getClientId() + "] not authorized to retrieve tokens from identity provider [" + providerId + "]."), clientModel);
-
- }
-
- IdentityProvider identityProvider = getIdentityProvider(session, realmModel, providerId);
- IdentityProviderModel identityProviderConfig = getIdentityProviderConfig(providerId);
-
- if (identityProviderConfig.isStoreToken()) {
- FederatedIdentityModel identity = this.session.users().getFederatedIdentity(authResult.getUser(), providerId, this.realmModel);
-
- if (identity == null) {
- return corsResponse(badRequest("User [" + authResult.getUser().getId() + "] is not associated with identity provider [" + providerId + "]."), clientModel);
- }
-
- this.event.success();
-
- return corsResponse(identityProvider.retrieveToken(session, identity), clientModel);
- }
-
- return corsResponse(badRequest("Identity Provider [" + providerId + "] does not support this operation."), clientModel);
- }
-
- return badRequest("Invalid token.");
- } catch (IdentityBrokerException e) {
- return redirectToErrorPage(Messages.COULD_NOT_OBTAIN_TOKEN, e, providerId);
- } catch (Exception e) {
- return redirectToErrorPage(Messages.UNEXPECTED_ERROR_RETRIEVING_TOKEN, e, providerId);
- }
- }
-
- public Response authenticated(BrokeredIdentityContext context) {
- IdentityProviderModel identityProviderConfig = context.getIdpConfig();
-
- final ParsedCodeContext parsedCode;
- if (context.getContextData().get(SAMLEndpoint.SAML_IDP_INITIATED_CLIENT_ID) != null) {
- parsedCode = samlIdpInitiatedSSO((String) context.getContextData().get(SAMLEndpoint.SAML_IDP_INITIATED_CLIENT_ID));
- } else {
- parsedCode = parseClientSessionCode(context.getCode());
- }
- if (parsedCode.response != null) {
- return parsedCode.response;
- }
- ClientSessionCode clientCode = parsedCode.clientSessionCode;
-
- String providerId = identityProviderConfig.getAlias();
- if (!identityProviderConfig.isStoreToken()) {
- if (isDebugEnabled()) {
- logger.debugf("Token will not be stored for identity provider [%s].", providerId);
- }
- context.setToken(null);
- }
-
- ClientSessionModel clientSession = clientCode.getClientSession();
- context.setClientSession(clientSession);
-
- session.getContext().setClient(clientSession.getClient());
-
- context.getIdp().preprocessFederatedIdentity(session, realmModel, context);
- Set<IdentityProviderMapperModel> mappers = realmModel.getIdentityProviderMappersByAlias(context.getIdpConfig().getAlias());
- if (mappers != null) {
- KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
- for (IdentityProviderMapperModel mapper : mappers) {
- IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
- target.preprocessFederatedIdentity(session, realmModel, mapper, context);
- }
- }
-
- FederatedIdentityModel federatedIdentityModel = new FederatedIdentityModel(providerId, context.getId(),
- context.getUsername(), context.getToken());
-
- this.event.event(EventType.IDENTITY_PROVIDER_LOGIN)
- .detail(Details.REDIRECT_URI, clientSession.getRedirectUri())
- .detail(Details.IDENTITY_PROVIDER_USERNAME, context.getUsername());
-
- UserModel federatedUser = this.session.users().getUserByFederatedIdentity(federatedIdentityModel, this.realmModel);
-
- // Check if federatedUser is already authenticated (this means linking social into existing federatedUser account)
- if (clientSession.getUserSession() != null) {
- return performAccountLinking(clientSession, context, federatedIdentityModel, federatedUser);
- }
-
- if (federatedUser == null) {
-
- logger.debugf("Federated user not found for provider '%s' and broker username '%s' . Redirecting to flow for firstBrokerLogin", providerId, context.getUsername());
-
- String username = context.getModelUsername();
- if (username == null) {
- if (this.realmModel.isRegistrationEmailAsUsername() && !Validation.isBlank(context.getEmail())) {
- username = context.getEmail();
- } else if (context.getUsername() == null) {
- username = context.getIdpConfig().getAlias() + "." + context.getId();
- } else {
- username = context.getUsername();
- }
- }
- username = username.trim();
- context.setModelUsername(username);
-
- clientSession.setTimestamp(Time.currentTime());
-
- SerializedBrokeredIdentityContext ctx = SerializedBrokeredIdentityContext.serialize(context);
- ctx.saveToClientSession(clientSession, AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE);
-
- URI redirect = LoginActionsService.firstBrokerLoginProcessor(uriInfo)
- .queryParam(OAuth2Constants.CODE, clientCode.getCode())
- .build(realmModel.getName());
- return Response.status(302).location(redirect).build();
-
- } else {
- Response response = validateUser(federatedUser, realmModel);
- if (response != null) {
- return response;
- }
-
- updateFederatedIdentity(context, federatedUser);
- clientSession.setAuthenticatedUser(federatedUser);
-
- return finishOrRedirectToPostBrokerLogin(clientSession, context, false, parsedCode.clientSessionCode);
- }
- }
-
- public Response validateUser(UserModel user, RealmModel realm) {
- if (!user.isEnabled()) {
- event.error(Errors.USER_DISABLED);
- return ErrorPage.error(session, Messages.ACCOUNT_DISABLED);
- }
- if (realm.isBruteForceProtected()) {
- if (session.getProvider(BruteForceProtector.class).isTemporarilyDisabled(session, realm, user)) {
- event.error(Errors.USER_TEMPORARILY_DISABLED);
- return ErrorPage.error(session, Messages.ACCOUNT_DISABLED);
- }
- }
- return null;
- }
-
- // Callback from LoginActionsService after first login with broker was done and Keycloak account is successfully linked/created
- @GET
- @NoCache
- @Path("/after-first-broker-login")
- public Response afterFirstBrokerLogin(@QueryParam("code") String code) {
- ParsedCodeContext parsedCode = parseClientSessionCode(code);
- if (parsedCode.response != null) {
- return parsedCode.response;
- }
- return afterFirstBrokerLogin(parsedCode.clientSessionCode);
- }
-
- private Response afterFirstBrokerLogin(ClientSessionCode clientSessionCode) {
- ClientSessionModel clientSession = clientSessionCode.getClientSession();
-
- try {
- this.event.detail(Details.CODE_ID, clientSession.getId())
- .removeDetail("auth_method");
-
- SerializedBrokeredIdentityContext serializedCtx = SerializedBrokeredIdentityContext.readFromClientSession(clientSession, AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE);
- if (serializedCtx == null) {
- throw new IdentityBrokerException("Not found serialized context in clientSession");
- }
- BrokeredIdentityContext context = serializedCtx.deserialize(session, clientSession);
- String providerId = context.getIdpConfig().getAlias();
-
- event.detail(Details.IDENTITY_PROVIDER, providerId);
- event.detail(Details.IDENTITY_PROVIDER_USERNAME, context.getUsername());
-
- // firstBrokerLogin workflow finished. Removing note now
- clientSession.removeNote(AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE);
-
- UserModel federatedUser = clientSession.getAuthenticatedUser();
- if (federatedUser == null) {
- throw new IdentityBrokerException("Couldn't found authenticated federatedUser in clientSession");
- }
-
- event.user(federatedUser);
- event.detail(Details.USERNAME, federatedUser.getUsername());
-
- if (context.getIdpConfig().isAddReadTokenRoleOnCreate()) {
- ClientModel brokerClient = realmModel.getClientByClientId(Constants.BROKER_SERVICE_CLIENT_ID);
- if (brokerClient == null) {
- throw new IdentityBrokerException("Client 'broker' not available. Maybe realm has not migrated to support the broker token exchange service");
- }
- RoleModel readTokenRole = brokerClient.getRole(Constants.READ_TOKEN_ROLE);
- federatedUser.grantRole(readTokenRole);
- }
-
- // Add federated identity link here
- FederatedIdentityModel federatedIdentityModel = new FederatedIdentityModel(context.getIdpConfig().getAlias(), context.getId(),
- context.getUsername(), context.getToken());
- session.users().addFederatedIdentity(realmModel, federatedUser, federatedIdentityModel);
-
-
- String isRegisteredNewUser = clientSession.getNote(AbstractIdpAuthenticator.BROKER_REGISTERED_NEW_USER);
- if (Boolean.parseBoolean(isRegisteredNewUser)) {
-
- logger.debugf("Registered new user '%s' after first login with identity provider '%s'. Identity provider username is '%s' . ", federatedUser.getUsername(), providerId, context.getUsername());
-
- context.getIdp().importNewUser(session, realmModel, federatedUser, context);
- Set<IdentityProviderMapperModel> mappers = realmModel.getIdentityProviderMappersByAlias(providerId);
- if (mappers != null) {
- KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
- for (IdentityProviderMapperModel mapper : mappers) {
- IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
- target.importNewUser(session, realmModel, federatedUser, mapper, context);
- }
- }
-
- if (context.getIdpConfig().isTrustEmail() && !Validation.isBlank(federatedUser.getEmail()) && !Boolean.parseBoolean(clientSession.getNote(AbstractIdpAuthenticator.UPDATE_PROFILE_EMAIL_CHANGED))) {
- logger.debugf("Email verified automatically after registration of user '%s' through Identity provider '%s' ", federatedUser.getUsername(), context.getIdpConfig().getAlias());
- federatedUser.setEmailVerified(true);
- }
-
- event.event(EventType.REGISTER)
- .detail(Details.REGISTER_METHOD, "broker")
- .detail(Details.EMAIL, federatedUser.getEmail())
- .success();
-
- } else {
- logger.debugf("Linked existing keycloak user '%s' with identity provider '%s' . Identity provider username is '%s' .", federatedUser.getUsername(), providerId, context.getUsername());
-
- event.event(EventType.FEDERATED_IDENTITY_LINK)
- .success();
-
- updateFederatedIdentity(context, federatedUser);
- }
-
- return finishOrRedirectToPostBrokerLogin(clientSession, context, true, clientSessionCode);
-
- } catch (Exception e) {
- return redirectToErrorPage(Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR, e);
- }
- }
-
-
- private Response finishOrRedirectToPostBrokerLogin(ClientSessionModel clientSession, BrokeredIdentityContext context, boolean wasFirstBrokerLogin, ClientSessionCode clientSessionCode) {
- String postBrokerLoginFlowId = context.getIdpConfig().getPostBrokerLoginFlowId();
- if (postBrokerLoginFlowId == null) {
-
- logger.debugf("Skip redirect to postBrokerLogin flow. PostBrokerLogin flow not set for identityProvider '%s'.", context.getIdpConfig().getAlias());
- return afterPostBrokerLoginFlowSuccess(clientSession, context, wasFirstBrokerLogin, clientSessionCode);
- } else {
-
- logger.debugf("Redirect to postBrokerLogin flow after authentication with identityProvider '%s'.", context.getIdpConfig().getAlias());
-
- clientSession.setTimestamp(Time.currentTime());
-
- SerializedBrokeredIdentityContext ctx = SerializedBrokeredIdentityContext.serialize(context);
- ctx.saveToClientSession(clientSession, PostBrokerLoginConstants.PBL_BROKERED_IDENTITY_CONTEXT);
-
- clientSession.setNote(PostBrokerLoginConstants.PBL_AFTER_FIRST_BROKER_LOGIN, String.valueOf(wasFirstBrokerLogin));
-
- URI redirect = LoginActionsService.postBrokerLoginProcessor(uriInfo)
- .queryParam(OAuth2Constants.CODE, clientSessionCode.getCode())
- .build(realmModel.getName());
- return Response.status(302).location(redirect).build();
- }
- }
-
-
- // Callback from LoginActionsService after postBrokerLogin flow is finished
- @GET
- @NoCache
- @Path("/after-post-broker-login")
- public Response afterPostBrokerLoginFlow(@QueryParam("code") String code) {
- ParsedCodeContext parsedCode = parseClientSessionCode(code);
- if (parsedCode.response != null) {
- return parsedCode.response;
- }
- ClientSessionModel clientSession = parsedCode.clientSessionCode.getClientSession();
-
- try {
- SerializedBrokeredIdentityContext serializedCtx = SerializedBrokeredIdentityContext.readFromClientSession(clientSession, PostBrokerLoginConstants.PBL_BROKERED_IDENTITY_CONTEXT);
- if (serializedCtx == null) {
- throw new IdentityBrokerException("Not found serialized context in clientSession. Note " + PostBrokerLoginConstants.PBL_BROKERED_IDENTITY_CONTEXT + " was null");
- }
- BrokeredIdentityContext context = serializedCtx.deserialize(session, clientSession);
-
- String wasFirstBrokerLoginNote = clientSession.getNote(PostBrokerLoginConstants.PBL_AFTER_FIRST_BROKER_LOGIN);
- boolean wasFirstBrokerLogin = Boolean.parseBoolean(wasFirstBrokerLoginNote);
-
- // Ensure the post-broker-login flow was successfully finished
- String authStateNoteKey = PostBrokerLoginConstants.PBL_AUTH_STATE_PREFIX + context.getIdpConfig().getAlias();
- String authState = clientSession.getNote(authStateNoteKey);
- if (!Boolean.parseBoolean(authState)) {
- throw new IdentityBrokerException("Invalid request. Not found the flag that post-broker-login flow was finished");
- }
-
- // remove notes
- clientSession.removeNote(PostBrokerLoginConstants.PBL_BROKERED_IDENTITY_CONTEXT);
- clientSession.removeNote(PostBrokerLoginConstants.PBL_AFTER_FIRST_BROKER_LOGIN);
-
- return afterPostBrokerLoginFlowSuccess(clientSession, context, wasFirstBrokerLogin, parsedCode.clientSessionCode);
- } catch (IdentityBrokerException e) {
- return redirectToErrorPage(Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR, e);
- }
- }
-
- private Response afterPostBrokerLoginFlowSuccess(ClientSessionModel clientSession, BrokeredIdentityContext context, boolean wasFirstBrokerLogin, ClientSessionCode clientSessionCode) {
- String providerId = context.getIdpConfig().getAlias();
- UserModel federatedUser = clientSession.getAuthenticatedUser();
-
- if (wasFirstBrokerLogin) {
-
- String isDifferentBrowser = clientSession.getNote(AbstractIdpAuthenticator.IS_DIFFERENT_BROWSER);
- if (Boolean.parseBoolean(isDifferentBrowser)) {
- session.sessions().removeClientSession(realmModel, clientSession);
- return session.getProvider(LoginFormsProvider.class)
- .setSuccess(Messages.IDENTITY_PROVIDER_LINK_SUCCESS, context.getIdpConfig().getAlias(), context.getUsername())
- .createInfoPage();
- } else {
- return finishBrokerAuthentication(context, federatedUser, clientSession, providerId);
- }
-
- } else {
-
- boolean firstBrokerLoginInProgress = (clientSession.getNote(AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE) != null);
- if (firstBrokerLoginInProgress) {
- logger.debugf("Reauthenticated with broker '%s' when linking user '%s' with other broker", context.getIdpConfig().getAlias(), federatedUser.getUsername());
-
- UserModel linkingUser = AbstractIdpAuthenticator.getExistingUser(session, realmModel, clientSession);
- if (!linkingUser.getId().equals(federatedUser.getId())) {
- return redirectToErrorPage(Messages.IDENTITY_PROVIDER_DIFFERENT_USER_MESSAGE, federatedUser.getUsername(), linkingUser.getUsername());
- }
-
- return afterFirstBrokerLogin(clientSessionCode);
- } else {
- return finishBrokerAuthentication(context, federatedUser, clientSession, providerId);
- }
- }
- }
-
-
- private Response finishBrokerAuthentication(BrokeredIdentityContext context, UserModel federatedUser, ClientSessionModel clientSession, String providerId) {
- UserSessionModel userSession = this.session.sessions()
- .createUserSession(this.realmModel, federatedUser, federatedUser.getUsername(), this.clientConnection.getRemoteAddr(), "broker", false, context.getBrokerSessionId(), context.getBrokerUserId());
-
- this.event.user(federatedUser);
- this.event.session(userSession);
-
- TokenManager.attachClientSession(userSession, clientSession);
- context.getIdp().attachUserSession(userSession, clientSession, context);
- userSession.setNote(Details.IDENTITY_PROVIDER, providerId);
- userSession.setNote(Details.IDENTITY_PROVIDER_USERNAME, context.getUsername());
-
- if (isDebugEnabled()) {
- logger.debugf("Performing local authentication for user [%s].", federatedUser);
- }
-
- return AuthenticationProcessor.redirectToRequiredActions(session, realmModel, clientSession, uriInfo);
- }
-
-
- @Override
- public Response cancelled(String code) {
- ParsedCodeContext parsedCode = parseClientSessionCode(code);
- if (parsedCode.response != null) {
- return parsedCode.response;
- }
- ClientSessionCode clientCode = parsedCode.clientSessionCode;
-
- Response accountManagementFailedLinking = checkAccountManagementFailedLinking(clientCode.getClientSession(), Messages.CONSENT_DENIED);
- if (accountManagementFailedLinking != null) {
- return accountManagementFailedLinking;
- }
-
- return browserAuthentication(clientCode.getClientSession(), null);
- }
-
- @Override
- public Response error(String code, String message) {
- ParsedCodeContext parsedCode = parseClientSessionCode(code);
- if (parsedCode.response != null) {
- return parsedCode.response;
- }
- ClientSessionCode clientCode = parsedCode.clientSessionCode;
-
- Response accountManagementFailedLinking = checkAccountManagementFailedLinking(clientCode.getClientSession(), message);
- if (accountManagementFailedLinking != null) {
- return accountManagementFailedLinking;
- }
-
- return browserAuthentication(clientCode.getClientSession(), message);
- }
-
- private Response performAccountLinking(ClientSessionModel clientSession, BrokeredIdentityContext context, FederatedIdentityModel newModel, UserModel federatedUser) {
- this.event.event(EventType.FEDERATED_IDENTITY_LINK);
-
-
-
- UserModel authenticatedUser = clientSession.getUserSession().getUser();
-
- if (federatedUser != null && !authenticatedUser.getId().equals(federatedUser.getId())) {
- return redirectToAccountErrorPage(clientSession, Messages.IDENTITY_PROVIDER_ALREADY_LINKED, context.getIdpConfig().getAlias());
- }
-
- if (!authenticatedUser.hasRole(this.realmModel.getClientByClientId(ACCOUNT_MANAGEMENT_CLIENT_ID).getRole(MANAGE_ACCOUNT))) {
- return redirectToErrorPage(Messages.INSUFFICIENT_PERMISSION);
- }
-
- if (!authenticatedUser.isEnabled()) {
- return redirectToAccountErrorPage(clientSession, Messages.ACCOUNT_DISABLED);
- }
-
-
-
- if (federatedUser != null) {
- if (context.getIdpConfig().isStoreToken()) {
- FederatedIdentityModel oldModel = this.session.users().getFederatedIdentity(federatedUser, context.getIdpConfig().getAlias(), this.realmModel);
- if (!ObjectUtil.isEqualOrBothNull(context.getToken(), oldModel.getToken())) {
- this.session.users().updateFederatedIdentity(this.realmModel, federatedUser, newModel);
- if (isDebugEnabled()) {
- logger.debugf("Identity [%s] update with response from identity provider [%s].", federatedUser, context.getIdpConfig().getAlias());
- }
- }
- }
- } else {
- this.session.users().addFederatedIdentity(this.realmModel, authenticatedUser, newModel);
- }
- context.getIdp().attachUserSession(clientSession.getUserSession(), clientSession, context);
-
-
- if (isDebugEnabled()) {
- logger.debugf("Linking account [%s] from identity provider [%s] to user [%s].", newModel, context.getIdpConfig().getAlias(), authenticatedUser);
- }
-
- this.event.user(authenticatedUser)
- .detail(Details.USERNAME, authenticatedUser.getUsername())
- .detail(Details.IDENTITY_PROVIDER, newModel.getIdentityProvider())
- .detail(Details.IDENTITY_PROVIDER_USERNAME, newModel.getUserName())
- .success();
-
- // we do this to make sure that the parent IDP is logged out when this user session is complete.
-
- clientSession.getUserSession().setNote(Details.IDENTITY_PROVIDER, context.getIdpConfig().getAlias());
- clientSession.getUserSession().setNote(Details.IDENTITY_PROVIDER_USERNAME, context.getUsername());
-
- return Response.status(302).location(UriBuilder.fromUri(clientSession.getRedirectUri()).build()).build();
- }
-
- private void updateFederatedIdentity(BrokeredIdentityContext context, UserModel federatedUser) {
- FederatedIdentityModel federatedIdentityModel = this.session.users().getFederatedIdentity(federatedUser, context.getIdpConfig().getAlias(), this.realmModel);
-
- // Skip DB write if tokens are null or equal
- updateToken(context, federatedUser, federatedIdentityModel);
- context.getIdp().updateBrokeredUser(session, realmModel, federatedUser, context);
- Set<IdentityProviderMapperModel> mappers = realmModel.getIdentityProviderMappersByAlias(context.getIdpConfig().getAlias());
- if (mappers != null) {
- KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
- for (IdentityProviderMapperModel mapper : mappers) {
- IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
- target.updateBrokeredUser(session, realmModel, federatedUser, mapper, context);
- }
- }
-
- }
-
- private void updateToken(BrokeredIdentityContext context, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel) {
- if (context.getIdpConfig().isStoreToken() && !ObjectUtil.isEqualOrBothNull(context.getToken(), federatedIdentityModel.getToken())) {
- federatedIdentityModel.setToken(context.getToken());
-
- this.session.users().updateFederatedIdentity(this.realmModel, federatedUser, federatedIdentityModel);
-
- if (isDebugEnabled()) {
- logger.debugf("Identity [%s] update with response from identity provider [%s].", federatedUser, context.getIdpConfig().getAlias());
- }
- }
- }
-
- private ParsedCodeContext parseClientSessionCode(String code) {
- ClientSessionCode clientCode = ClientSessionCode.parse(code, this.session, this.realmModel);
-
- if (clientCode != null) {
- ClientSessionModel clientSession = clientCode.getClientSession();
-
- if (clientSession.getUserSession() != null) {
- this.event.session(clientSession.getUserSession());
- }
-
- ClientModel client = clientSession.getClient();
-
- if (client != null) {
-
- logger.debugf("Got authorization code from client [%s].", client.getClientId());
- this.event.client(client);
- this.session.getContext().setClient(client);
-
- if (!clientCode.isValid(AUTHENTICATE.name(), ClientSessionCode.ActionType.LOGIN)) {
- logger.debugf("Authorization code is not valid. Client session ID: %s, Client session's action: %s", clientSession.getId(), clientSession.getAction());
-
- // Check if error happened during login or during linking from account management
- Response accountManagementFailedLinking = checkAccountManagementFailedLinking(clientCode.getClientSession(), Messages.STALE_CODE_ACCOUNT);
- Response staleCodeError = (accountManagementFailedLinking != null) ? accountManagementFailedLinking : redirectToErrorPage(Messages.STALE_CODE);
-
-
- return ParsedCodeContext.response(staleCodeError);
- }
-
- if (isDebugEnabled()) {
- logger.debugf("Authorization code is valid.");
- }
-
- return ParsedCodeContext.clientSessionCode(clientCode);
- }
- }
-
- logger.debugf("Authorization code is not valid. Code: %s", code);
- Response staleCodeError = redirectToErrorPage(Messages.STALE_CODE);
- return ParsedCodeContext.response(staleCodeError);
- }
-
- /**
- * If there is a client whose SAML IDP-initiated SSO URL name is set to the
- * given {@code clientUrlName}, creates a fresh client session for that
- * client and returns a {@link ParsedCodeContext} object with that session.
- * Otherwise returns "client not found" response.
- *
- * @param clientUrlName
- * @return see description
- */
- private ParsedCodeContext samlIdpInitiatedSSO(final String clientUrlName) {
- event.event(EventType.LOGIN);
- CacheControlUtil.noBackButtonCacheControlHeader();
- Optional<ClientModel> oClient = this.realmModel.getClients().stream()
- .filter(c -> Objects.equals(c.getAttribute(SamlProtocol.SAML_IDP_INITIATED_SSO_URL_NAME), clientUrlName))
- .findFirst();
-
- if (! oClient.isPresent()) {
- event.error(Errors.CLIENT_NOT_FOUND);
- return ParsedCodeContext.response(redirectToErrorPage(Messages.CLIENT_NOT_FOUND));
- }
-
- ClientSessionModel clientSession = SamlService.createClientSessionForIdpInitiatedSso(session, realmModel, oClient.get(), null);
-
- return ParsedCodeContext.clientSessionCode(new ClientSessionCode(session, this.realmModel, clientSession));
- }
-
- /**
- * Returns {@code true} if the client session is defined for the given code
- * in the current session and for the current realm.
- * Does <b>not</b> check the session validity. To obtain client session if
- * and only if it exists and is valid, use {@link ClientSessionCode#parse}.
- *
- * @param code
- * @return
- */
- protected boolean isClientSessionRegistered(String code) {
- if (code == null) {
- return false;
- }
-
- try {
- return ClientSessionCode.getClientSession(code, this.session, this.realmModel) != null;
- } catch (RuntimeException e) {
- return false;
- }
- }
-
- private Response checkAccountManagementFailedLinking(ClientSessionModel clientSession, String error, Object... parameters) {
- if (clientSession.getUserSession() != null && clientSession.getClient() != null && clientSession.getClient().getClientId().equals(ACCOUNT_MANAGEMENT_CLIENT_ID)) {
-
- this.event.event(EventType.FEDERATED_IDENTITY_LINK);
- UserModel user = clientSession.getUserSession().getUser();
- this.event.user(user);
- this.event.detail(Details.USERNAME, user.getUsername());
-
- return redirectToAccountErrorPage(clientSession, error, parameters);
- } else {
- return null;
- }
- }
-
- private AuthenticationRequest createAuthenticationRequest(String providerId, ClientSessionCode clientSessionCode) {
- ClientSessionModel clientSession = null;
- String relayState = null;
-
- if (clientSessionCode != null) {
- clientSession = clientSessionCode.getClientSession();
- relayState = clientSessionCode.getCode();
- }
-
- return new AuthenticationRequest(this.session, this.realmModel, clientSession, this.request, this.uriInfo, relayState, getRedirectUri(providerId));
- }
-
- private String getRedirectUri(String providerId) {
- return Urls.identityProviderAuthnResponse(this.uriInfo.getBaseUri(), providerId, this.realmModel.getName()).toString();
- }
-
- private Response redirectToErrorPage(String message, Object ... parameters) {
- return redirectToErrorPage(message, null, parameters);
- }
-
- private Response redirectToErrorPage(String message, Throwable throwable, Object ... parameters) {
- if (message == null) {
- message = Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR;
- }
-
- fireErrorEvent(message, throwable);
- return ErrorPage.error(this.session, message, parameters);
- }
-
- private Response redirectToAccountErrorPage(ClientSessionModel clientSession, String message, Object ... parameters) {
- fireErrorEvent(message);
-
- FormMessage errorMessage = new FormMessage(message, parameters);
- try {
- String serializedError = JsonSerialization.writeValueAsString(errorMessage);
- clientSession.setNote(AccountService.ACCOUNT_MGMT_FORWARDED_ERROR_NOTE, serializedError);
- } catch (IOException ioe) {
- throw new RuntimeException(ioe);
- }
-
- return Response.status(302).location(UriBuilder.fromUri(clientSession.getRedirectUri()).build()).build();
- }
-
- private Response redirectToLoginPage(Throwable t, ClientSessionCode clientCode) {
- String message = t.getMessage();
-
- if (message == null) {
- message = Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR;
- }
-
- fireErrorEvent(message);
- return browserAuthentication(clientCode.getClientSession(), message);
- }
-
- protected Response browserAuthentication(ClientSessionModel clientSession, String errorMessage) {
- this.event.event(EventType.LOGIN);
- AuthenticationFlowModel flow = realmModel.getBrowserFlow();
- String flowId = flow.getId();
- AuthenticationProcessor processor = new AuthenticationProcessor();
- processor.setClientSession(clientSession)
- .setFlowPath(LoginActionsService.AUTHENTICATE_PATH)
- .setFlowId(flowId)
- .setBrowserFlow(true)
- .setConnection(clientConnection)
- .setEventBuilder(event)
- .setRealm(realmModel)
- .setSession(session)
- .setUriInfo(uriInfo)
- .setRequest(request);
- if (errorMessage != null) processor.setForwardedErrorMessage(new FormMessage(null, errorMessage));
-
- try {
- CacheControlUtil.noBackButtonCacheControlHeader();
- return processor.authenticate();
- } catch (Exception e) {
- return processor.handleBrowserException(e);
- }
- }
-
-
- private Response badRequest(String message) {
- fireErrorEvent(message);
- return ErrorResponse.error(message, Status.BAD_REQUEST);
- }
-
- private Response forbidden(String message) {
- fireErrorEvent(message);
- return ErrorResponse.error(message, Status.FORBIDDEN);
- }
+public class IdentityBrokerService {
+//public class IdentityBrokerService implements IdentityProvider.AuthenticationCallback {
+//
+// private static final Logger logger = Logger.getLogger(IdentityBrokerService.class);
+//
+// private final RealmModel realmModel;
+//
+// @Context
+// private UriInfo uriInfo;
+//
+// @Context
+// private KeycloakSession session;
+//
+// @Context
+// private ClientConnection clientConnection;
+//
+// @Context
+// private HttpRequest request;
+//
+// @Context
+// private HttpHeaders headers;
+//
+// private EventBuilder event;
+//
+//
+// public IdentityBrokerService(RealmModel realmModel) {
+// if (realmModel == null) {
+// throw new IllegalArgumentException("Realm can not be null.");
+// }
+// this.realmModel = realmModel;
+// }
+//
+// public void init() {
+// this.event = new EventBuilder(realmModel, session, clientConnection).event(EventType.IDENTITY_PROVIDER_LOGIN);
+// }
+//
+// private void checkRealm() {
+// if (!realmModel.isEnabled()) {
+// event.error(Errors.REALM_DISABLED);
+// throw new ErrorPageException(session, Messages.REALM_NOT_ENABLED);
+// }
+// }
+//
+// private ClientModel checkClient(String clientId) {
+// if (clientId == null) {
+// event.error(Errors.INVALID_REQUEST);
+// throw new ErrorPageException(session, Messages.MISSING_PARAMETER, OIDCLoginProtocol.CLIENT_ID_PARAM);
+// }
+//
+// event.client(clientId);
+//
+// ClientModel client = realmModel.getClientByClientId(clientId);
+// if (client == null) {
+// event.error(Errors.CLIENT_NOT_FOUND);
+// throw new ErrorPageException(session, Messages.INVALID_REQUEST);
+// }
+//
+// if (!client.isEnabled()) {
+// event.error(Errors.CLIENT_DISABLED);
+// throw new ErrorPageException(session, Messages.INVALID_REQUEST);
+// }
+// return client;
+//
+// }
+//
+// /**
+// * Closes off CORS preflight requests for account linking
+// *
+// * @param providerId
+// * @return
+// */
+// @OPTIONS
+// @Path("/{provider_id}/link")
+// public Response clientIntiatedAccountLinkingPreflight(@PathParam("provider_id") String providerId) {
+// return Response.status(403).build(); // don't allow preflight
+// }
+//
+//
+// @GET
+// @NoCache
+// @Path("/{provider_id}/link")
+// public Response clientInitiatedAccountLinking(@PathParam("provider_id") String providerId,
+// @QueryParam("redirect_uri") String redirectUri,
+// @QueryParam("client_id") String clientId,
+// @QueryParam("nonce") String nonce,
+// @QueryParam("hash") String hash
+// ) {
+// this.event.event(EventType.CLIENT_INITIATED_ACCOUNT_LINKING);
+// checkRealm();
+// ClientModel client = checkClient(clientId);
+// AuthenticationManager authenticationManager = new AuthenticationManager();
+// redirectUri = RedirectUtils.verifyRedirectUri(uriInfo, redirectUri, realmModel, client);
+// if (redirectUri == null) {
+// event.error(Errors.INVALID_REDIRECT_URI);
+// throw new ErrorPageException(session, Messages.INVALID_REQUEST);
+// }
+//
+// if (nonce == null || hash == null) {
+// event.error(Errors.INVALID_REDIRECT_URI);
+// throw new ErrorPageException(session, Messages.INVALID_REQUEST);
+//
+// }
+//
+// // only allow origins from client. Not sure we need this as I don't believe cookies can be
+// // sent if CORS preflight requests can't execute.
+// String origin = headers.getRequestHeaders().getFirst("Origin");
+// if (origin != null) {
+// String redirectOrigin = UriUtils.getOrigin(redirectUri);
+// if (!redirectOrigin.equals(origin)) {
+// event.error(Errors.ILLEGAL_ORIGIN);
+// throw new ErrorPageException(session, Messages.INVALID_REQUEST);
+//
+// }
+// }
+//
+// AuthResult cookieResult = authenticationManager.authenticateIdentityCookie(session, realmModel, true);
+// String errorParam = "link_error";
+// if (cookieResult == null) {
+// event.error(Errors.NOT_LOGGED_IN);
+// UriBuilder builder = UriBuilder.fromUri(redirectUri)
+// .queryParam(errorParam, Errors.NOT_LOGGED_IN)
+// .queryParam("nonce", nonce);
+//
+// return Response.status(302).location(builder.build()).build();
+// }
+//
+//
+//
+// ClientLoginSessionModel clientSession = null;
+// for (ClientLoginSessionModel cs : cookieResult.getSession().getClientLoginSessions().values()) {
+// if (cs.getClient().getClientId().equals(clientId)) {
+// byte[] decoded = Base64Url.decode(hash);
+// MessageDigest md = null;
+// try {
+// md = MessageDigest.getInstance("SHA-256");
+// } catch (NoSuchAlgorithmException e) {
+// throw new ErrorPageException(session, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST);
+// }
+// String input = nonce + cookieResult.getSession().getId() + cs.getId() + providerId;
+// byte[] check = md.digest(input.getBytes(StandardCharsets.UTF_8));
+// if (MessageDigest.isEqual(decoded, check)) {
+// clientSession = cs;
+// break;
+// }
+// }
+// }
+// if (clientSession == null) {
+// event.error(Errors.INVALID_TOKEN);
+// throw new ErrorPageException(session, Messages.INVALID_REQUEST);
+// }
+//
+//
+//
+// ClientModel accountService = this.realmModel.getClientByClientId(ACCOUNT_MANAGEMENT_CLIENT_ID);
+// if (!accountService.getId().equals(client.getId())) {
+// RoleModel manageAccountRole = accountService.getRole(MANAGE_ACCOUNT);
+//
+// if (!clientSession.getRoles().contains(manageAccountRole.getId())) {
+// RoleModel linkRole = accountService.getRole(MANAGE_ACCOUNT_LINKS);
+// if (!clientSession.getRoles().contains(linkRole.getId())) {
+// event.error(Errors.NOT_ALLOWED);
+// UriBuilder builder = UriBuilder.fromUri(redirectUri)
+// .queryParam(errorParam, Errors.NOT_ALLOWED)
+// .queryParam("nonce", nonce);
+// return Response.status(302).location(builder.build()).build();
+// }
+// }
+// }
+//
+//
+// IdentityProviderModel identityProviderModel = realmModel.getIdentityProviderByAlias(providerId);
+// if (identityProviderModel == null) {
+// event.error(Errors.UNKNOWN_IDENTITY_PROVIDER);
+// UriBuilder builder = UriBuilder.fromUri(redirectUri)
+// .queryParam(errorParam, Errors.UNKNOWN_IDENTITY_PROVIDER)
+// .queryParam("nonce", nonce);
+// return Response.status(302).location(builder.build()).build();
+//
+// }
+//
+//
+// // TODO: Create LoginSessionModel and Login cookie and set the state inside. See my notes document
+// ClientSessionCode clientSessionCode = new ClientSessionCode(session, realmModel, clientSession);
+// clientSessionCode.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
+// clientSessionCode.getCode();
+// clientSession.setRedirectUri(redirectUri);
+// clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, UUID.randomUUID().toString());
+//
+// event.success();
+//
+//
+// try {
+// IdentityProvider identityProvider = getIdentityProvider(session, realmModel, providerId);
+// Response response = identityProvider.performLogin(createAuthenticationRequest(providerId, clientSessionCode));
+//
+// if (response != null) {
+// if (isDebugEnabled()) {
+// logger.debugf("Identity provider [%s] is going to send a request [%s].", identityProvider, response);
+// }
+// return response;
+// }
+// } catch (IdentityBrokerException e) {
+// return redirectToErrorPage(Messages.COULD_NOT_SEND_AUTHENTICATION_REQUEST, e, providerId);
+// } catch (Exception e) {
+// return redirectToErrorPage(Messages.UNEXPECTED_ERROR_HANDLING_REQUEST, e, providerId);
+// }
+//
+// return redirectToErrorPage(Messages.COULD_NOT_PROCEED_WITH_AUTHENTICATION_REQUEST);
+//
+// }
+//
+//
+// @POST
+// @Path("/{provider_id}/login")
+// public Response performPostLogin(@PathParam("provider_id") String providerId, @QueryParam("code") String code) {
+// return performLogin(providerId, code);
+// }
+//
+// @GET
+// @NoCache
+// @Path("/{provider_id}/login")
+// public Response performLogin(@PathParam("provider_id") String providerId, @QueryParam("code") String code) {
+// this.event.detail(Details.IDENTITY_PROVIDER, providerId);
+//
+// if (isDebugEnabled()) {
+// logger.debugf("Sending authentication request to identity provider [%s].", providerId);
+// }
+//
+// try {
+// ParsedCodeContext parsedCode = parseClientSessionCode(code);
+// if (parsedCode.response != null) {
+// return parsedCode.response;
+// }
+//
+// ClientSessionCode clientSessionCode = parsedCode.clientSessionCode;
+// IdentityProviderModel identityProviderModel = realmModel.getIdentityProviderByAlias(providerId);
+// if (identityProviderModel == null) {
+// throw new IdentityBrokerException("Identity Provider [" + providerId + "] not found.");
+// }
+// if (identityProviderModel.isLinkOnly()) {
+// throw new IdentityBrokerException("Identity Provider [" + providerId + "] is not allowed to perform a login.");
+//
+// }
+// IdentityProviderFactory providerFactory = getIdentityProviderFactory(session, identityProviderModel);
+//
+// IdentityProvider identityProvider = providerFactory.create(session, identityProviderModel);
+//
+// Response response = identityProvider.performLogin(createAuthenticationRequest(providerId, clientSessionCode));
+//
+// if (response != null) {
+// if (isDebugEnabled()) {
+// logger.debugf("Identity provider [%s] is going to send a request [%s].", identityProvider, response);
+// }
+// return response;
+// }
+// } catch (IdentityBrokerException e) {
+// return redirectToErrorPage(Messages.COULD_NOT_SEND_AUTHENTICATION_REQUEST, e, providerId);
+// } catch (Exception e) {
+// return redirectToErrorPage(Messages.UNEXPECTED_ERROR_HANDLING_REQUEST, e, providerId);
+// }
+//
+// return redirectToErrorPage(Messages.COULD_NOT_PROCEED_WITH_AUTHENTICATION_REQUEST);
+// }
+//
+// @Path("{provider_id}/endpoint")
+// public Object getEndpoint(@PathParam("provider_id") String providerId) {
+// IdentityProvider identityProvider = getIdentityProvider(session, realmModel, providerId);
+// Object callback = identityProvider.callback(realmModel, this, event);
+// ResteasyProviderFactory.getInstance().injectProperties(callback);
+// //resourceContext.initResource(brokerService);
+// return callback;
+//
+//
+// }
+//
+// @Path("{provider_id}/token")
+// @OPTIONS
+// public Response retrieveTokenPreflight() {
+// return Cors.add(this.request, Response.ok()).auth().preflight().build();
+// }
+//
+// @GET
+// @NoCache
+// @Path("{provider_id}/token")
+// public Response retrieveToken(@PathParam("provider_id") String providerId) {
+// return getToken(providerId, false);
+// }
+//
+// private boolean canReadBrokerToken(AccessToken token) {
+// Map<String, AccessToken.Access> resourceAccess = token.getResourceAccess();
+// AccessToken.Access brokerRoles = resourceAccess == null ? null : resourceAccess.get(Constants.BROKER_SERVICE_CLIENT_ID);
+// return brokerRoles != null && brokerRoles.isUserInRole(Constants.READ_TOKEN_ROLE);
+// }
+//
+// private Response getToken(String providerId, boolean forceRetrieval) {
+// this.event.event(EventType.IDENTITY_PROVIDER_RETRIEVE_TOKEN);
+//
+// try {
+// AppAuthManager authManager = new AppAuthManager();
+// AuthResult authResult = authManager.authenticateBearerToken(this.session, this.realmModel, this.uriInfo, this.clientConnection, this.request.getHttpHeaders());
+//
+// if (authResult != null) {
+// AccessToken token = authResult.getToken();
+// String[] audience = token.getAudience();
+// ClientModel clientModel = this.realmModel.getClientByClientId(audience[0]);
+//
+// if (clientModel == null) {
+// return badRequest("Invalid client.");
+// }
+//
+// session.getContext().setClient(clientModel);
+//
+// ClientModel brokerClient = realmModel.getClientByClientId(Constants.BROKER_SERVICE_CLIENT_ID);
+// if (brokerClient == null) {
+// return corsResponse(forbidden("Realm has not migrated to support the broker token exchange service"), clientModel);
+//
+// }
+// if (!canReadBrokerToken(token)) {
+// return corsResponse(forbidden("Client [" + clientModel.getClientId() + "] not authorized to retrieve tokens from identity provider [" + providerId + "]."), clientModel);
+//
+// }
+//
+// IdentityProvider identityProvider = getIdentityProvider(session, realmModel, providerId);
+// IdentityProviderModel identityProviderConfig = getIdentityProviderConfig(providerId);
+//
+// if (identityProviderConfig.isStoreToken()) {
+// FederatedIdentityModel identity = this.session.users().getFederatedIdentity(authResult.getUser(), providerId, this.realmModel);
+//
+// if (identity == null) {
+// return corsResponse(badRequest("User [" + authResult.getUser().getId() + "] is not associated with identity provider [" + providerId + "]."), clientModel);
+// }
+//
+// this.event.success();
+//
+// return corsResponse(identityProvider.retrieveToken(session, identity), clientModel);
+// }
+//
+// return corsResponse(badRequest("Identity Provider [" + providerId + "] does not support this operation."), clientModel);
+// }
+//
+// return badRequest("Invalid token.");
+// } catch (IdentityBrokerException e) {
+// return redirectToErrorPage(Messages.COULD_NOT_OBTAIN_TOKEN, e, providerId);
+// } catch (Exception e) {
+// return redirectToErrorPage(Messages.UNEXPECTED_ERROR_RETRIEVING_TOKEN, e, providerId);
+// }
+// }
+//
+// public Response authenticated(BrokeredIdentityContext context) {
+// IdentityProviderModel identityProviderConfig = context.getIdpConfig();
+//
+// final ParsedCodeContext parsedCode;
+// if (context.getContextData().get(SAMLEndpoint.SAML_IDP_INITIATED_CLIENT_ID) != null) {
+// parsedCode = samlIdpInitiatedSSO((String) context.getContextData().get(SAMLEndpoint.SAML_IDP_INITIATED_CLIENT_ID));
+// } else {
+// parsedCode = parseClientSessionCode(context.getCode());
+// }
+// if (parsedCode.response != null) {
+// return parsedCode.response;
+// }
+// ClientSessionCode<LoginSessionModel> clientCode = parsedCode.clientSessionCode;
+//
+// String providerId = identityProviderConfig.getAlias();
+// if (!identityProviderConfig.isStoreToken()) {
+// if (isDebugEnabled()) {
+// logger.debugf("Token will not be stored for identity provider [%s].", providerId);
+// }
+// context.setToken(null);
+// }
+//
+// LoginSessionModel loginSession = clientCode.getClientSession();
+// context.setLoginSession(loginSession);
+//
+// session.getContext().setClient(loginSession.getClient());
+//
+// context.getIdp().preprocessFederatedIdentity(session, realmModel, context);
+// Set<IdentityProviderMapperModel> mappers = realmModel.getIdentityProviderMappersByAlias(context.getIdpConfig().getAlias());
+// if (mappers != null) {
+// KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
+// for (IdentityProviderMapperModel mapper : mappers) {
+// IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
+// target.preprocessFederatedIdentity(session, realmModel, mapper, context);
+// }
+// }
+//
+// FederatedIdentityModel federatedIdentityModel = new FederatedIdentityModel(providerId, context.getId(),
+// context.getUsername(), context.getToken());
+//
+// this.event.event(EventType.IDENTITY_PROVIDER_LOGIN)
+// .detail(Details.REDIRECT_URI, loginSession.getRedirectUri())
+// .detail(Details.IDENTITY_PROVIDER_USERNAME, context.getUsername());
+//
+// UserModel federatedUser = this.session.users().getUserByFederatedIdentity(federatedIdentityModel, this.realmModel);
+//
+// // Check if federatedUser is already authenticated (this means linking social into existing federatedUser account)
+// if (loginSession.getUserSession() != null) {
+// return performAccountLinking(clientSession, context, federatedIdentityModel, federatedUser);
+// }
+//
+// if (federatedUser == null) {
+//
+// logger.debugf("Federated user not found for provider '%s' and broker username '%s' . Redirecting to flow for firstBrokerLogin", providerId, context.getUsername());
+//
+// String username = context.getModelUsername();
+// if (username == null) {
+// if (this.realmModel.isRegistrationEmailAsUsername() && !Validation.isBlank(context.getEmail())) {
+// username = context.getEmail();
+// } else if (context.getUsername() == null) {
+// username = context.getIdpConfig().getAlias() + "." + context.getId();
+// } else {
+// username = context.getUsername();
+// }
+// }
+// username = username.trim();
+// context.setModelUsername(username);
+//
+// clientSession.setTimestamp(Time.currentTime());
+//
+// SerializedBrokeredIdentityContext ctx = SerializedBrokeredIdentityContext.serialize(context);
+// ctx.saveToClientSession(clientSession, AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE);
+//
+// URI redirect = LoginActionsService.firstBrokerLoginProcessor(uriInfo)
+// .queryParam(OAuth2Constants.CODE, clientCode.getCode())
+// .build(realmModel.getName());
+// return Response.status(302).location(redirect).build();
+//
+// } else {
+// Response response = validateUser(federatedUser, realmModel);
+// if (response != null) {
+// return response;
+// }
+//
+// updateFederatedIdentity(context, federatedUser);
+// clientSession.setAuthenticatedUser(federatedUser);
+//
+// return finishOrRedirectToPostBrokerLogin(clientSession, context, false, parsedCode.clientSessionCode);
+// }
+// }
+//
+// public Response validateUser(UserModel user, RealmModel realm) {
+// if (!user.isEnabled()) {
+// event.error(Errors.USER_DISABLED);
+// return ErrorPage.error(session, Messages.ACCOUNT_DISABLED);
+// }
+// if (realm.isBruteForceProtected()) {
+// if (session.getProvider(BruteForceProtector.class).isTemporarilyDisabled(session, realm, user)) {
+// event.error(Errors.USER_TEMPORARILY_DISABLED);
+// return ErrorPage.error(session, Messages.ACCOUNT_DISABLED);
+// }
+// }
+// return null;
+// }
+//
+// // Callback from LoginActionsService after first login with broker was done and Keycloak account is successfully linked/created
+// @GET
+// @NoCache
+// @Path("/after-first-broker-login")
+// public Response afterFirstBrokerLogin(@QueryParam("code") String code) {
+// ParsedCodeContext parsedCode = parseClientSessionCode(code);
+// if (parsedCode.response != null) {
+// return parsedCode.response;
+// }
+// return afterFirstBrokerLogin(parsedCode.clientSessionCode);
+// }
+//
+// private Response afterFirstBrokerLogin(ClientSessionCode clientSessionCode) {
+// ClientSessionModel clientSession = clientSessionCode.getClientSession();
+//
+// try {
+// this.event.detail(Details.CODE_ID, clientSession.getId())
+// .removeDetail("auth_method");
+//
+// SerializedBrokeredIdentityContext serializedCtx = SerializedBrokeredIdentityContext.readFromClientSession(clientSession, AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE);
+// if (serializedCtx == null) {
+// throw new IdentityBrokerException("Not found serialized context in clientSession");
+// }
+// BrokeredIdentityContext context = serializedCtx.deserialize(session, clientSession);
+// String providerId = context.getIdpConfig().getAlias();
+//
+// event.detail(Details.IDENTITY_PROVIDER, providerId);
+// event.detail(Details.IDENTITY_PROVIDER_USERNAME, context.getUsername());
+//
+// // firstBrokerLogin workflow finished. Removing note now
+// clientSession.removeNote(AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE);
+//
+// UserModel federatedUser = clientSession.getAuthenticatedUser();
+// if (federatedUser == null) {
+// throw new IdentityBrokerException("Couldn't found authenticated federatedUser in clientSession");
+// }
+//
+// event.user(federatedUser);
+// event.detail(Details.USERNAME, federatedUser.getUsername());
+//
+// if (context.getIdpConfig().isAddReadTokenRoleOnCreate()) {
+// ClientModel brokerClient = realmModel.getClientByClientId(Constants.BROKER_SERVICE_CLIENT_ID);
+// if (brokerClient == null) {
+// throw new IdentityBrokerException("Client 'broker' not available. Maybe realm has not migrated to support the broker token exchange service");
+// }
+// RoleModel readTokenRole = brokerClient.getRole(Constants.READ_TOKEN_ROLE);
+// federatedUser.grantRole(readTokenRole);
+// }
+//
+// // Add federated identity link here
+// FederatedIdentityModel federatedIdentityModel = new FederatedIdentityModel(context.getIdpConfig().getAlias(), context.getId(),
+// context.getUsername(), context.getToken());
+// session.users().addFederatedIdentity(realmModel, federatedUser, federatedIdentityModel);
+//
+//
+// String isRegisteredNewUser = clientSession.getNote(AbstractIdpAuthenticator.BROKER_REGISTERED_NEW_USER);
+// if (Boolean.parseBoolean(isRegisteredNewUser)) {
+//
+// logger.debugf("Registered new user '%s' after first login with identity provider '%s'. Identity provider username is '%s' . ", federatedUser.getUsername(), providerId, context.getUsername());
+//
+// context.getIdp().importNewUser(session, realmModel, federatedUser, context);
+// Set<IdentityProviderMapperModel> mappers = realmModel.getIdentityProviderMappersByAlias(providerId);
+// if (mappers != null) {
+// KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
+// for (IdentityProviderMapperModel mapper : mappers) {
+// IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
+// target.importNewUser(session, realmModel, federatedUser, mapper, context);
+// }
+// }
+//
+// if (context.getIdpConfig().isTrustEmail() && !Validation.isBlank(federatedUser.getEmail()) && !Boolean.parseBoolean(clientSession.getNote(AbstractIdpAuthenticator.UPDATE_PROFILE_EMAIL_CHANGED))) {
+// logger.debugf("Email verified automatically after registration of user '%s' through Identity provider '%s' ", federatedUser.getUsername(), context.getIdpConfig().getAlias());
+// federatedUser.setEmailVerified(true);
+// }
+//
+// event.event(EventType.REGISTER)
+// .detail(Details.REGISTER_METHOD, "broker")
+// .detail(Details.EMAIL, federatedUser.getEmail())
+// .success();
+//
+// } else {
+// logger.debugf("Linked existing keycloak user '%s' with identity provider '%s' . Identity provider username is '%s' .", federatedUser.getUsername(), providerId, context.getUsername());
+//
+// event.event(EventType.FEDERATED_IDENTITY_LINK)
+// .success();
+//
+// updateFederatedIdentity(context, federatedUser);
+// }
+//
+// return finishOrRedirectToPostBrokerLogin(clientSession, context, true, clientSessionCode);
+//
+// } catch (Exception e) {
+// return redirectToErrorPage(Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR, e);
+// }
+// }
+//
+//
+// private Response finishOrRedirectToPostBrokerLogin(ClientSessionModel clientSession, BrokeredIdentityContext context, boolean wasFirstBrokerLogin, ClientSessionCode clientSessionCode) {
+// String postBrokerLoginFlowId = context.getIdpConfig().getPostBrokerLoginFlowId();
+// if (postBrokerLoginFlowId == null) {
+//
+// logger.debugf("Skip redirect to postBrokerLogin flow. PostBrokerLogin flow not set for identityProvider '%s'.", context.getIdpConfig().getAlias());
+// return afterPostBrokerLoginFlowSuccess(clientSession, context, wasFirstBrokerLogin, clientSessionCode);
+// } else {
+//
+// logger.debugf("Redirect to postBrokerLogin flow after authentication with identityProvider '%s'.", context.getIdpConfig().getAlias());
+//
+// clientSession.setTimestamp(Time.currentTime());
+//
+// SerializedBrokeredIdentityContext ctx = SerializedBrokeredIdentityContext.serialize(context);
+// ctx.saveToClientSession(clientSession, PostBrokerLoginConstants.PBL_BROKERED_IDENTITY_CONTEXT);
+//
+// clientSession.setNote(PostBrokerLoginConstants.PBL_AFTER_FIRST_BROKER_LOGIN, String.valueOf(wasFirstBrokerLogin));
+//
+// URI redirect = LoginActionsService.postBrokerLoginProcessor(uriInfo)
+// .queryParam(OAuth2Constants.CODE, clientSessionCode.getCode())
+// .build(realmModel.getName());
+// return Response.status(302).location(redirect).build();
+// }
+// }
+//
+//
+// // Callback from LoginActionsService after postBrokerLogin flow is finished
+// @GET
+// @NoCache
+// @Path("/after-post-broker-login")
+// public Response afterPostBrokerLoginFlow(@QueryParam("code") String code) {
+// ParsedCodeContext parsedCode = parseClientSessionCode(code);
+// if (parsedCode.response != null) {
+// return parsedCode.response;
+// }
+// LoginSessionModel loginSession = parsedCode.clientSessionCode.getClientSession();
+//
+// try {
+// SerializedBrokeredIdentityContext serializedCtx = SerializedBrokeredIdentityContext.readFromLoginSession(loginSession, PostBrokerLoginConstants.PBL_BROKERED_IDENTITY_CONTEXT);
+// if (serializedCtx == null) {
+// throw new IdentityBrokerException("Not found serialized context in clientSession. Note " + PostBrokerLoginConstants.PBL_BROKERED_IDENTITY_CONTEXT + " was null");
+// }
+// BrokeredIdentityContext context = serializedCtx.deserialize(session, loginSession);
+//
+// String wasFirstBrokerLoginNote = loginSession.getNote(PostBrokerLoginConstants.PBL_AFTER_FIRST_BROKER_LOGIN);
+// boolean wasFirstBrokerLogin = Boolean.parseBoolean(wasFirstBrokerLoginNote);
+//
+// // Ensure the post-broker-login flow was successfully finished
+// String authStateNoteKey = PostBrokerLoginConstants.PBL_AUTH_STATE_PREFIX + context.getIdpConfig().getAlias();
+// String authState = loginSession.getNote(authStateNoteKey);
+// if (!Boolean.parseBoolean(authState)) {
+// throw new IdentityBrokerException("Invalid request. Not found the flag that post-broker-login flow was finished");
+// }
+//
+// // remove notes
+// loginSession.removeNote(PostBrokerLoginConstants.PBL_BROKERED_IDENTITY_CONTEXT);
+// loginSession.removeNote(PostBrokerLoginConstants.PBL_AFTER_FIRST_BROKER_LOGIN);
+//
+// return afterPostBrokerLoginFlowSuccess(loginSession, context, wasFirstBrokerLogin, parsedCode.clientSessionCode);
+// } catch (IdentityBrokerException e) {
+// return redirectToErrorPage(Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR, e);
+// }
+// }
+//
+// private Response afterPostBrokerLoginFlowSuccess(ClientSessionModel clientSession, BrokeredIdentityContext context, boolean wasFirstBrokerLogin, ClientSessionCode clientSessionCode) {
+// String providerId = context.getIdpConfig().getAlias();
+// UserModel federatedUser = clientSession.getAuthenticatedUser();
+//
+// if (wasFirstBrokerLogin) {
+//
+// String isDifferentBrowser = clientSession.getNote(AbstractIdpAuthenticator.IS_DIFFERENT_BROWSER);
+// if (Boolean.parseBoolean(isDifferentBrowser)) {
+// session.sessions().removeClientSession(realmModel, clientSession);
+// return session.getProvider(LoginFormsProvider.class)
+// .setSuccess(Messages.IDENTITY_PROVIDER_LINK_SUCCESS, context.getIdpConfig().getAlias(), context.getUsername())
+// .createInfoPage();
+// } else {
+// return finishBrokerAuthentication(context, federatedUser, clientSession, providerId);
+// }
+//
+// } else {
+//
+// boolean firstBrokerLoginInProgress = (clientSession.getNote(AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE) != null);
+// if (firstBrokerLoginInProgress) {
+// logger.debugf("Reauthenticated with broker '%s' when linking user '%s' with other broker", context.getIdpConfig().getAlias(), federatedUser.getUsername());
+//
+// UserModel linkingUser = AbstractIdpAuthenticator.getExistingUser(session, realmModel, clientSession);
+// if (!linkingUser.getId().equals(federatedUser.getId())) {
+// return redirectToErrorPage(Messages.IDENTITY_PROVIDER_DIFFERENT_USER_MESSAGE, federatedUser.getUsername(), linkingUser.getUsername());
+// }
+//
+// return afterFirstBrokerLogin(clientSessionCode);
+// } else {
+// return finishBrokerAuthentication(context, federatedUser, clientSession, providerId);
+// }
+// }
+// }
+//
+//
+// private Response finishBrokerAuthentication(BrokeredIdentityContext context, UserModel federatedUser, ClientSessionModel clientSession, String providerId) {
+// UserSessionModel userSession = this.session.sessions()
+// .createUserSession(this.realmModel, federatedUser, federatedUser.getUsername(), this.clientConnection.getRemoteAddr(), "broker", false, context.getBrokerSessionId(), context.getBrokerUserId());
+//
+// this.event.user(federatedUser);
+// this.event.session(userSession);
+//
+// // TODO: This is supposed to be called after requiredActions are processed
+// TokenManager.attachClientSession(userSession, clientSession);
+// context.getIdp().attachUserSession(userSession, clientSession, context);
+// userSession.setNote(Details.IDENTITY_PROVIDER, providerId);
+// userSession.setNote(Details.IDENTITY_PROVIDER_USERNAME, context.getUsername());
+//
+// if (isDebugEnabled()) {
+// logger.debugf("Performing local authentication for user [%s].", federatedUser);
+// }
+//
+// return AuthenticationProcessor.redirectToRequiredActions(session, realmModel, clientSession, uriInfo);
+// }
+//
+//
+// @Override
+// public Response cancelled(String code) {
+// ParsedCodeContext parsedCode = parseClientSessionCode(code);
+// if (parsedCode.response != null) {
+// return parsedCode.response;
+// }
+// ClientSessionCode clientCode = parsedCode.clientSessionCode;
+//
+// Response accountManagementFailedLinking = checkAccountManagementFailedLinking(clientCode.getClientSession(), Messages.CONSENT_DENIED);
+// if (accountManagementFailedLinking != null) {
+// return accountManagementFailedLinking;
+// }
+//
+// return browserAuthentication(clientCode.getClientSession(), null);
+// }
+//
+// @Override
+// public Response error(String code, String message) {
+// ParsedCodeContext parsedCode = parseClientSessionCode(code);
+// if (parsedCode.response != null) {
+// return parsedCode.response;
+// }
+// ClientSessionCode clientCode = parsedCode.clientSessionCode;
+//
+// Response accountManagementFailedLinking = checkAccountManagementFailedLinking(clientCode.getClientSession(), message);
+// if (accountManagementFailedLinking != null) {
+// return accountManagementFailedLinking;
+// }
+//
+// return browserAuthentication(clientCode.getClientSession(), message);
+// }
+//
+// private Response performAccountLinking(ClientSessionModel clientSession, BrokeredIdentityContext context, FederatedIdentityModel newModel, UserModel federatedUser) {
+// this.event.event(EventType.FEDERATED_IDENTITY_LINK);
+//
+//
+//
+// UserModel authenticatedUser = clientSession.getUserSession().getUser();
+//
+// if (federatedUser != null && !authenticatedUser.getId().equals(federatedUser.getId())) {
+// return redirectToAccountErrorPage(clientSession, Messages.IDENTITY_PROVIDER_ALREADY_LINKED, context.getIdpConfig().getAlias());
+// }
+//
+// if (!authenticatedUser.hasRole(this.realmModel.getClientByClientId(ACCOUNT_MANAGEMENT_CLIENT_ID).getRole(MANAGE_ACCOUNT))) {
+// return redirectToErrorPage(Messages.INSUFFICIENT_PERMISSION);
+// }
+//
+// if (!authenticatedUser.isEnabled()) {
+// return redirectToAccountErrorPage(clientSession, Messages.ACCOUNT_DISABLED);
+// }
+//
+//
+//
+// if (federatedUser != null) {
+// if (context.getIdpConfig().isStoreToken()) {
+// FederatedIdentityModel oldModel = this.session.users().getFederatedIdentity(federatedUser, context.getIdpConfig().getAlias(), this.realmModel);
+// if (!ObjectUtil.isEqualOrBothNull(context.getToken(), oldModel.getToken())) {
+// this.session.users().updateFederatedIdentity(this.realmModel, federatedUser, newModel);
+// if (isDebugEnabled()) {
+// logger.debugf("Identity [%s] update with response from identity provider [%s].", federatedUser, context.getIdpConfig().getAlias());
+// }
+// }
+// }
+// } else {
+// this.session.users().addFederatedIdentity(this.realmModel, authenticatedUser, newModel);
+// }
+// context.getIdp().attachUserSession(clientSession.getUserSession(), clientSession, context);
+//
+//
+// if (isDebugEnabled()) {
+// logger.debugf("Linking account [%s] from identity provider [%s] to user [%s].", newModel, context.getIdpConfig().getAlias(), authenticatedUser);
+// }
+//
+// this.event.user(authenticatedUser)
+// .detail(Details.USERNAME, authenticatedUser.getUsername())
+// .detail(Details.IDENTITY_PROVIDER, newModel.getIdentityProvider())
+// .detail(Details.IDENTITY_PROVIDER_USERNAME, newModel.getUserName())
+// .success();
+//
+// // we do this to make sure that the parent IDP is logged out when this user session is complete.
+//
+// clientSession.getUserSession().setNote(Details.IDENTITY_PROVIDER, context.getIdpConfig().getAlias());
+// clientSession.getUserSession().setNote(Details.IDENTITY_PROVIDER_USERNAME, context.getUsername());
+//
+// return Response.status(302).location(UriBuilder.fromUri(clientSession.getRedirectUri()).build()).build();
+// }
+//
+// private void updateFederatedIdentity(BrokeredIdentityContext context, UserModel federatedUser) {
+// FederatedIdentityModel federatedIdentityModel = this.session.users().getFederatedIdentity(federatedUser, context.getIdpConfig().getAlias(), this.realmModel);
+//
+// // Skip DB write if tokens are null or equal
+// updateToken(context, federatedUser, federatedIdentityModel);
+// context.getIdp().updateBrokeredUser(session, realmModel, federatedUser, context);
+// Set<IdentityProviderMapperModel> mappers = realmModel.getIdentityProviderMappersByAlias(context.getIdpConfig().getAlias());
+// if (mappers != null) {
+// KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
+// for (IdentityProviderMapperModel mapper : mappers) {
+// IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
+// target.updateBrokeredUser(session, realmModel, federatedUser, mapper, context);
+// }
+// }
+//
+// }
+//
+// private void updateToken(BrokeredIdentityContext context, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel) {
+// if (context.getIdpConfig().isStoreToken() && !ObjectUtil.isEqualOrBothNull(context.getToken(), federatedIdentityModel.getToken())) {
+// federatedIdentityModel.setToken(context.getToken());
+//
+// this.session.users().updateFederatedIdentity(this.realmModel, federatedUser, federatedIdentityModel);
+//
+// if (isDebugEnabled()) {
+// logger.debugf("Identity [%s] update with response from identity provider [%s].", federatedUser, context.getIdpConfig().getAlias());
+// }
+// }
+// }
+//
+// private ParsedCodeContext parseClientSessionCode(String code) {
+// ClientSessionCode<LoginSessionModel> clientCode = ClientSessionCode.parse(code, this.session, this.realmModel, LoginSessionModel.class);
+//
+// if (clientCode != null) {
+// LoginSessionModel loginSession = clientCode.getClientSession();
+//
+// ClientModel client = loginSession.getClient();
+//
+// if (client != null) {
+//
+// logger.debugf("Got authorization code from client [%s].", client.getClientId());
+// this.event.client(client);
+// this.session.getContext().setClient(client);
+//
+// if (!clientCode.isValid(AUTHENTICATE.name(), ClientSessionCode.ActionType.LOGIN)) {
+// logger.debugf("Authorization code is not valid. Client session ID: %s, Client session's action: %s", loginSession.getId(), loginSession.getAction());
+//
+// // Check if error happened during login or during linking from account management
+// Response accountManagementFailedLinking = checkAccountManagementFailedLinking(clientCode.getClientSession(), Messages.STALE_CODE_ACCOUNT);
+// Response staleCodeError = (accountManagementFailedLinking != null) ? accountManagementFailedLinking : redirectToErrorPage(Messages.STALE_CODE);
+//
+//
+// return ParsedCodeContext.response(staleCodeError);
+// }
+//
+// if (isDebugEnabled()) {
+// logger.debugf("Authorization code is valid.");
+// }
+//
+// return ParsedCodeContext.clientSessionCode(clientCode);
+// }
+// }
+//
+// logger.debugf("Authorization code is not valid. Code: %s", code);
+// Response staleCodeError = redirectToErrorPage(Messages.STALE_CODE);
+// return ParsedCodeContext.response(staleCodeError);
+// }
+//
+// /**
+// * If there is a client whose SAML IDP-initiated SSO URL name is set to the
+// * given {@code clientUrlName}, creates a fresh client session for that
+// * client and returns a {@link ParsedCodeContext} object with that session.
+// * Otherwise returns "client not found" response.
+// *
+// * @param clientUrlName
+// * @return see description
+// */
+// private ParsedCodeContext samlIdpInitiatedSSO(final String clientUrlName) {
+// event.event(EventType.LOGIN);
+// CacheControlUtil.noBackButtonCacheControlHeader();
+// Optional<ClientModel> oClient = this.realmModel.getClients().stream()
+// .filter(c -> Objects.equals(c.getAttribute(SamlProtocol.SAML_IDP_INITIATED_SSO_URL_NAME), clientUrlName))
+// .findFirst();
+//
+// if (! oClient.isPresent()) {
+// event.error(Errors.CLIENT_NOT_FOUND);
+// return ParsedCodeContext.response(redirectToErrorPage(Messages.CLIENT_NOT_FOUND));
+// }
+//
+// ClientSessionModel clientSession = SamlService.createClientSessionForIdpInitiatedSso(session, realmModel, oClient.get(), null);
+//
+// return ParsedCodeContext.clientSessionCode(new ClientSessionCode(session, this.realmModel, clientSession));
+// }
+//
+// private Response checkAccountManagementFailedLinking(LoginSessionModel loginSession, String error, Object... parameters) {
+// if (clientSession.getUserSession() != null && clientSession.getClient() != null && clientSession.getClient().getClientId().equals(ACCOUNT_MANAGEMENT_CLIENT_ID)) {
+//
+// this.event.event(EventType.FEDERATED_IDENTITY_LINK);
+// UserModel user = clientSession.getUserSession().getUser();
+// this.event.user(user);
+// this.event.detail(Details.USERNAME, user.getUsername());
+//
+// return redirectToAccountErrorPage(clientSession, error, parameters);
+// } else {
+// return null;
+// }
+// }
+//
+// private AuthenticationRequest createAuthenticationRequest(String providerId, ClientSessionCode<LoginSessionModel> clientSessionCode) {
+// LoginSessionModel loginSession = null;
+// String relayState = null;
+//
+// if (clientSessionCode != null) {
+// loginSession = clientSessionCode.getClientSession();
+// relayState = clientSessionCode.getCode();
+// }
+//
+// return new AuthenticationRequest(this.session, this.realmModel, clientSession, this.request, this.uriInfo, relayState, getRedirectUri(providerId));
+// }
+//
+// private String getRedirectUri(String providerId) {
+// return Urls.identityProviderAuthnResponse(this.uriInfo.getBaseUri(), providerId, this.realmModel.getName()).toString();
+// }
+//
+// private Response redirectToErrorPage(String message, Object ... parameters) {
+// return redirectToErrorPage(message, null, parameters);
+// }
+//
+// private Response redirectToErrorPage(String message, Throwable throwable, Object ... parameters) {
+// if (message == null) {
+// message = Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR;
+// }
+//
+// fireErrorEvent(message, throwable);
+// return ErrorPage.error(this.session, message, parameters);
+// }
+//
+// private Response redirectToAccountErrorPage(ClientSessionModel clientSession, String message, Object ... parameters) {
+// fireErrorEvent(message);
+//
+// FormMessage errorMessage = new FormMessage(message, parameters);
+// try {
+// String serializedError = JsonSerialization.writeValueAsString(errorMessage);
+// clientSession.setNote(AccountService.ACCOUNT_MGMT_FORWARDED_ERROR_NOTE, serializedError);
+// } catch (IOException ioe) {
+// throw new RuntimeException(ioe);
+// }
+//
+// return Response.status(302).location(UriBuilder.fromUri(clientSession.getRedirectUri()).build()).build();
+// }
+//
+// private Response redirectToLoginPage(Throwable t, ClientSessionCode clientCode) {
+// String message = t.getMessage();
+//
+// if (message == null) {
+// message = Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR;
+// }
+//
+// fireErrorEvent(message);
+// return browserAuthentication(clientCode.getClientSession(), message);
+// }
+//
+// protected Response browserAuthentication(ClientSessionModel clientSession, String errorMessage) {
+// this.event.event(EventType.LOGIN);
+// AuthenticationFlowModel flow = realmModel.getBrowserFlow();
+// String flowId = flow.getId();
+// AuthenticationProcessor processor = new AuthenticationProcessor();
+// processor.setClientSession(clientSession)
+// .setFlowPath(LoginActionsService.AUTHENTICATE_PATH)
+// .setFlowId(flowId)
+// .setBrowserFlow(true)
+// .setConnection(clientConnection)
+// .setEventBuilder(event)
+// .setRealm(realmModel)
+// .setSession(session)
+// .setUriInfo(uriInfo)
+// .setRequest(request);
+// if (errorMessage != null) processor.setForwardedErrorMessage(new FormMessage(null, errorMessage));
+//
+// try {
+// CacheControlUtil.noBackButtonCacheControlHeader();
+// return processor.authenticate();
+// } catch (Exception e) {
+// return processor.handleBrowserException(e);
+// }
+// }
+//
+//
+// private Response badRequest(String message) {
+// fireErrorEvent(message);
+// return ErrorResponse.error(message, Status.BAD_REQUEST);
+// }
+//
+// private Response forbidden(String message) {
+// fireErrorEvent(message);
+// return ErrorResponse.error(message, Status.FORBIDDEN);
+// }
public static IdentityProvider getIdentityProvider(KeycloakSession session, RealmModel realm, String alias) {
IdentityProviderModel identityProviderModel = realm.getIdentityProviderByAlias(alias);
@@ -1121,7 +1099,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
return availableProviders.get(model.getProviderId());
}
-
+/*
private IdentityProviderModel getIdentityProviderConfig(String providerId) {
IdentityProviderModel model = this.realmModel.getIdentityProviderByAlias(providerId);
if (model == null) {
@@ -1177,10 +1155,10 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
private static class ParsedCodeContext {
- private ClientSessionCode clientSessionCode;
+ private ClientSessionCode<LoginSessionModel> clientSessionCode;
private Response response;
- public static ParsedCodeContext clientSessionCode(ClientSessionCode clientSessionCode) {
+ public static ParsedCodeContext clientSessionCode(ClientSessionCode<LoginSessionModel> clientSessionCode) {
ParsedCodeContext ctx = new ParsedCodeContext();
ctx.clientSessionCode = clientSessionCode;
return ctx;
@@ -1192,4 +1170,5 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
return ctx;
}
}
+ */
}
diff --git a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
index 14df1dc..3c9b40b 100755
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
@@ -38,6 +38,7 @@ import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.forms.login.LoginFormsProvider;
import org.keycloak.models.AuthenticationFlowModel;
+import org.keycloak.models.ClientLoginSessionModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.Constants;
@@ -64,6 +65,8 @@ import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.util.CacheControlUtil;
import org.keycloak.services.util.CookieHelper;
+import org.keycloak.sessions.CommonClientSessionModel;
+import org.keycloak.sessions.LoginSessionModel;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
@@ -165,7 +168,8 @@ public class LoginActionsService {
private class Checks {
- ClientSessionCode clientCode;
+ // TODO: Merge with Hynek's code. This may not be just loginSession
+ ClientSessionCode<LoginSessionModel> clientCode;
Response response;
ClientSessionCode.ParseResult result;
@@ -174,16 +178,18 @@ public class LoginActionsService {
return false;
}
if (!clientCode.isValidAction(requiredAction)) {
- ClientSessionModel clientSession = clientCode.getClientSession();
- if (ClientSessionModel.Action.REQUIRED_ACTIONS.name().equals(clientSession.getAction())) {
+ LoginSessionModel loginSession = clientCode.getClientSession();
+ if (ClientSessionModel.Action.REQUIRED_ACTIONS.name().equals(loginSession.getAction())) {
response = redirectToRequiredActions(code);
return false;
- } else if (clientSession.getUserSession() != null && clientSession.getUserSession().getState() == UserSessionModel.State.LOGGED_IN) {
+
+ } // TODO:mposolda
+ /*else if (clientSession.getUserSession() != null && clientSession.getUserSession().getState() == UserSessionModel.State.LOGGED_IN) {
response = session.getProvider(LoginFormsProvider.class)
.setSuccess(Messages.ALREADY_LOGGED_IN)
.createInfoPage();
return false;
- }
+ }*/
}
if (!isActionActive(actionType)) return false;
return true;
@@ -229,10 +235,14 @@ public class LoginActionsService {
response = ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
return false;
}
- result = ClientSessionCode.parseResult(code, session, realm);
+
+ // TODO:mposolda it may not be just loginSessionModel
+ result = ClientSessionCode.parseResult(code, session, realm, LoginSessionModel.class);
clientCode = result.getCode();
if (clientCode == null) {
- if (result.isClientSessionNotFound()) { // timeout
+ // TODO:mposolda
+ /*
+ if (result.isLoginSessionNotFound()) { // timeout
try {
ClientSessionModel clientSession = RestartLoginCookie.restartSession(session, realm, code);
if (clientSession != null) {
@@ -245,10 +255,10 @@ public class LoginActionsService {
}
}
event.error(Errors.INVALID_CODE);
- response = ErrorPage.error(session, Messages.INVALID_CODE);
+ response = ErrorPage.error(session, Messages.INVALID_CODE);*/
return false;
}
- ClientSessionModel clientSession = clientCode.getClientSession();
+ LoginSessionModel clientSession = clientCode.getClientSession();
if (clientSession == null) {
event.error(Errors.INVALID_CODE);
response = ErrorPage.error(session, Messages.INVALID_CODE);
@@ -259,13 +269,13 @@ public class LoginActionsService {
if (client == null) {
event.error(Errors.CLIENT_NOT_FOUND);
response = ErrorPage.error(session, Messages.UNKNOWN_LOGIN_REQUESTER);
- session.sessions().removeClientSession(realm, clientSession);
+ session.loginSessions().removeLoginSession(realm, clientSession);
return false;
}
if (!client.isEnabled()) {
event.error(Errors.CLIENT_NOT_FOUND);
response = ErrorPage.error(session, Messages.LOGIN_REQUESTER_NOT_ENABLED);
- session.sessions().removeClientSession(realm, clientSession);
+ session.loginSessions().removeLoginSession(realm, clientSession);
return false;
}
session.getContext().setClient(client);
@@ -273,6 +283,8 @@ public class LoginActionsService {
}
public boolean verifyRequiredAction(String code, String executedAction) {
+ // TODO:mposolda
+ /*
if (!verifyCode(code)) {
return false;
}
@@ -306,7 +318,7 @@ public class LoginActionsService {
clientSession.removeNote(AuthenticationManager.CURRENT_REQUIRED_ACTION);
response = redirectToRequiredActions(code);
return false;
- }
+ }*/
return true;
}
@@ -325,8 +337,8 @@ public class LoginActionsService {
@QueryParam("execution") String execution) {
event.event(EventType.LOGIN);
- ClientSessionModel clientSession = ClientSessionCode.getClientSession(code, session, realm);
- if (clientSession != null && code.equals(clientSession.getNote(LAST_PROCESSED_CODE))) {
+ LoginSessionModel loginSession = ClientSessionCode.getClientSession(code, session, realm, LoginSessionModel.class);
+ if (loginSession != null && code.equals(loginSession.getNote(LAST_PROCESSED_CODE))) {
// Allow refresh of previous page
} else {
Checks checks = new Checks();
@@ -334,21 +346,21 @@ public class LoginActionsService {
return checks.response;
}
- ClientSessionCode clientSessionCode = checks.clientCode;
- clientSession = clientSessionCode.getClientSession();
+ ClientSessionCode<LoginSessionModel> clientSessionCode = checks.clientCode;
+ loginSession = clientSessionCode.getClientSession();
}
event.detail(Details.CODE_ID, code);
- clientSession.setNote(LAST_PROCESSED_CODE, code);
- return processAuthentication(execution, clientSession, null);
+ loginSession.setNote(LAST_PROCESSED_CODE, code);
+ return processAuthentication(execution, loginSession, null);
}
- protected Response processAuthentication(String execution, ClientSessionModel clientSession, String errorMessage) {
- return processFlow(execution, clientSession, AUTHENTICATE_PATH, realm.getBrowserFlow(), errorMessage, new AuthenticationProcessor());
+ protected Response processAuthentication(String execution, LoginSessionModel loginSession, String errorMessage) {
+ return processFlow(execution, loginSession, AUTHENTICATE_PATH, realm.getBrowserFlow(), errorMessage, new AuthenticationProcessor());
}
- protected Response processFlow(String execution, ClientSessionModel clientSession, String flowPath, AuthenticationFlowModel flow, String errorMessage, AuthenticationProcessor processor) {
- processor.setClientSession(clientSession)
+ protected Response processFlow(String execution, LoginSessionModel loginSession, String flowPath, AuthenticationFlowModel flow, String errorMessage, AuthenticationProcessor processor) {
+ processor.setLoginSession(loginSession)
.setFlowPath(flowPath)
.setBrowserFlow(true)
.setFlowId(flow.getId())
@@ -383,8 +395,8 @@ public class LoginActionsService {
@QueryParam("execution") String execution) {
event.event(EventType.LOGIN);
- ClientSessionModel clientSession = ClientSessionCode.getClientSession(code, session, realm);
- if (clientSession != null && code.equals(clientSession.getNote(LAST_PROCESSED_CODE))) {
+ LoginSessionModel loginSession = ClientSessionCode.getClientSession(code, session, realm, LoginSessionModel.class);
+ if (loginSession != null && code.equals(loginSession.getNote(LAST_PROCESSED_CODE))) {
// Post already processed (refresh) - ignore form post and return next form
request.getFormParameters().clear();
return authenticate(code, null);
@@ -394,18 +406,20 @@ public class LoginActionsService {
if (!checks.verifyCode(code, ClientSessionModel.Action.AUTHENTICATE.name(), ClientSessionCode.ActionType.LOGIN)) {
return checks.response;
}
- final ClientSessionCode clientCode = checks.clientCode;
- clientSession = clientCode.getClientSession();
- clientSession.setNote(LAST_PROCESSED_CODE, code);
+ final ClientSessionCode<LoginSessionModel> clientCode = checks.clientCode;
+ loginSession = clientCode.getClientSession();
+ loginSession.setNote(LAST_PROCESSED_CODE, code);
- return processAuthentication(execution, clientSession, null);
+ return processAuthentication(execution, loginSession, null);
}
@Path(RESET_CREDENTIALS_PATH)
@POST
public Response resetCredentialsPOST(@QueryParam("code") String code,
@QueryParam("execution") String execution) {
- return resetCredentials(code, execution);
+ // TODO:mposolda
+ //return resetCredentials(code, execution);
+ return null;
}
/**
@@ -422,6 +436,8 @@ public class LoginActionsService {
@QueryParam("execution") String execution) {
// we allow applications to link to reset credentials without going through OAuth or SAML handshakes
//
+ // TODO:mposolda
+ /*
if (code == null) {
if (!realm.isResetPasswordAllowed()) {
event.event(EventType.RESET_PASSWORD);
@@ -444,8 +460,11 @@ public class LoginActionsService {
return processResetCredentials(null, clientSession, null);
}
return resetCredentials(code, execution);
+ */
+ return null;
}
+ /*
protected Response resetCredentials(String code, String execution) {
event.event(EventType.RESET_PASSWORD);
Checks checks = new Checks();
@@ -488,11 +507,11 @@ public class LoginActionsService {
};
return processFlow(execution, clientSession, RESET_CREDENTIALS_PATH, realm.getResetCredentialsFlow(), errorMessage, authProcessor);
- }
+ }*/
- protected Response processRegistration(String execution, ClientSessionModel clientSession, String errorMessage) {
- return processFlow(execution, clientSession, REGISTRATION_PATH, realm.getRegistrationFlow(), errorMessage, new AuthenticationProcessor());
+ protected Response processRegistration(String execution, LoginSessionModel loginSession, String errorMessage) {
+ return processFlow(execution, loginSession, REGISTRATION_PATH, realm.getRegistrationFlow(), errorMessage, new AuthenticationProcessor());
}
@@ -517,8 +536,8 @@ public class LoginActionsService {
return checks.response;
}
event.detail(Details.CODE_ID, code);
- ClientSessionCode clientSessionCode = checks.clientCode;
- ClientSessionModel clientSession = clientSessionCode.getClientSession();
+ ClientSessionCode<LoginSessionModel> clientSessionCode = checks.clientCode;
+ LoginSessionModel clientSession = clientSessionCode.getClientSession();
AuthenticationManager.expireIdentityCookie(realm, uriInfo, clientConnection);
@@ -547,13 +566,14 @@ public class LoginActionsService {
return checks.response;
}
- ClientSessionCode clientCode = checks.clientCode;
- ClientSessionModel clientSession = clientCode.getClientSession();
+ ClientSessionCode<LoginSessionModel> clientCode = checks.clientCode;
+ LoginSessionModel loginSession = clientCode.getClientSession();
- return processRegistration(execution, clientSession, null);
+ return processRegistration(execution, loginSession, null);
}
-
+ // TODO:mposolda broker login
+/*
@Path(FIRST_BROKER_LOGIN_PATH)
@GET
public Response firstBrokerLoginGet(@QueryParam("code") String code,
@@ -647,6 +667,7 @@ public class LoginActionsService {
return Response.status(302).location(redirect).build();
}
+*/
/**
* OAuth grant page. You should not invoked this directly!
@@ -664,23 +685,22 @@ public class LoginActionsService {
if (!checks.verifyRequiredAction(code, ClientSessionModel.Action.OAUTH_GRANT.name())) {
return checks.response;
}
- ClientSessionCode accessCode = checks.clientCode;
- ClientSessionModel clientSession = accessCode.getClientSession();
+ ClientSessionCode<LoginSessionModel> accessCode = checks.clientCode;
+ LoginSessionModel loginSession = accessCode.getClientSession();
- initEvent(clientSession);
+ initLoginEvent(loginSession);
- UserSessionModel userSession = clientSession.getUserSession();
- UserModel user = userSession.getUser();
- ClientModel client = clientSession.getClient();
+ UserModel user = loginSession.getAuthenticatedUser();
+ ClientModel client = loginSession.getClient();
if (formData.containsKey("cancel")) {
- LoginProtocol protocol = session.getProvider(LoginProtocol.class, clientSession.getAuthMethod());
+ LoginProtocol protocol = session.getProvider(LoginProtocol.class, loginSession.getProtocol());
protocol.setRealm(realm)
.setHttpHeaders(headers)
.setUriInfo(uriInfo)
.setEventBuilder(event);
- Response response = protocol.sendError(clientSession, Error.CONSENT_DENIED);
+ Response response = protocol.sendError(loginSession, Error.CONSENT_DENIED);
event.error(Errors.REJECTED_BY_USER);
return response;
}
@@ -703,12 +723,16 @@ public class LoginActionsService {
event.detail(Details.CONSENT, Details.CONSENT_VALUE_CONSENT_GRANTED);
event.success();
- return AuthenticationManager.redirectAfterSuccessfulFlow(session, realm, userSession, clientSession, request, uriInfo, clientConnection, event);
+ // TODO:mposolda So assume that requiredActions were already done in this stage. Doublecheck...
+ ClientLoginSessionModel clientSession = AuthenticationProcessor.attachSession(loginSession, null, session, realm, clientConnection, event);
+ return AuthenticationManager.redirectAfterSuccessfulFlow(session, realm, clientSession.getUserSession(), clientSession, request, uriInfo, clientConnection, event, loginSession.getProtocol());
}
@Path("email-verification")
@GET
public Response emailVerification(@QueryParam("code") String code, @QueryParam("key") String key) {
+ // TODO:mposolda
+ /*
event.event(EventType.VERIFY_EMAIL);
if (key != null) {
ClientSessionModel clientSession = null;
@@ -783,7 +807,8 @@ public class LoginActionsService {
.setClientSession(clientSession)
.setUser(userSession.getUser())
.createResponse(RequiredAction.VERIFY_EMAIL);
- }
+ }*/
+ return null;
}
/**
@@ -795,6 +820,8 @@ public class LoginActionsService {
@Path("execute-actions")
@GET
public Response executeActions(@QueryParam("key") String key) {
+ // TODO:mposolda
+ /*
event.event(EventType.EXECUTE_ACTIONS);
if (key != null) {
Checks checks = new Checks();
@@ -810,7 +837,8 @@ public class LoginActionsService {
} else {
event.error(Errors.INVALID_CODE);
return ErrorPage.error(session, Messages.INVALID_CODE);
- }
+ }*/
+ return null;
}
private String getActionCookie() {
@@ -823,6 +851,7 @@ public class LoginActionsService {
return cookie != null ? cookie.getValue() : null;
}
+ // TODO: Remove this method. We will be able to use login-session-cookie
public static void createActionCookie(RealmModel realm, UriInfo uriInfo, ClientConnection clientConnection, String sessionId) {
CookieHelper.addCookie(ACTION_COOKIE, sessionId, AuthenticationManager.getRealmCookiePath(realm, uriInfo), null, null, -1, realm.getSslRequired().isRequired(clientConnection), true);
}
@@ -855,6 +884,36 @@ public class LoginActionsService {
}
}
+ private void initLoginEvent(LoginSessionModel loginSession) {
+ String responseType = loginSession.getNote(OIDCLoginProtocol.RESPONSE_TYPE_PARAM);
+ if (responseType == null) {
+ responseType = "code";
+ }
+ String respMode = loginSession.getNote(OIDCLoginProtocol.RESPONSE_MODE_PARAM);
+ OIDCResponseMode responseMode = OIDCResponseMode.parse(respMode, OIDCResponseType.parse(responseType));
+
+ event.event(EventType.LOGIN).client(loginSession.getClient())
+ .detail(Details.CODE_ID, loginSession.getId())
+ .detail(Details.REDIRECT_URI, loginSession.getRedirectUri())
+ .detail(Details.AUTH_METHOD, loginSession.getProtocol())
+ .detail(Details.RESPONSE_TYPE, responseType)
+ .detail(Details.RESPONSE_MODE, responseMode.toString().toLowerCase());
+
+ UserModel authenticatedUser = loginSession.getAuthenticatedUser();
+ if (authenticatedUser != null) {
+ event.user(authenticatedUser)
+ .detail(Details.USERNAME, authenticatedUser.getUsername());
+ } else {
+ event.detail(Details.USERNAME, loginSession.getNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME));
+ }
+
+ // TODO:mposolda Fix if this is called at firstBroker or postBroker login
+ /*
+ .detail(Details.IDENTITY_PROVIDER, userSession.getNote(Details.IDENTITY_PROVIDER))
+ .detail(Details.IDENTITY_PROVIDER_USERNAME, userSession.getNote(Details.IDENTITY_PROVIDER_USERNAME));
+ */
+ }
+
@Path(REQUIRED_ACTION)
@POST
public Response requiredActionPOST(@QueryParam("code") final String code,
@@ -872,7 +931,9 @@ public class LoginActionsService {
return processRequireAction(code, action);
}
- public Response processRequireAction(final String code, String action) {
+ private Response processRequireAction(final String code, String action) {
+ // TODO:mposolda
+ /*
event.event(EventType.CUSTOM_REQUIRED_ACTION);
event.detail(Details.CUSTOM_REQUIRED_ACTION, action);
Checks checks = new Checks();
@@ -937,9 +998,11 @@ public class LoginActionsService {
}
throw new RuntimeException("Unreachable");
+ */
+ return null;
}
- public Response redirectToRequiredActions(String code) {
+ private Response redirectToRequiredActions(String code) {
URI redirect = LoginActionsService.loginActionsBaseUrl(uriInfo)
.path(LoginActionsService.REQUIRED_ACTION)
.queryParam(OAuth2Constants.CODE, code).build(realm.getName());
diff --git a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
index bb8de2d..ab99d5d 100755
--- a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
@@ -234,12 +234,16 @@ public class RealmsResource {
public IdentityBrokerService getBrokerService(final @PathParam("realm") String name) {
RealmModel realm = init(name);
+ // TODO:mposolda
+ /*
IdentityBrokerService brokerService = new IdentityBrokerService(realm);
ResteasyProviderFactory.getInstance().injectProperties(brokerService);
brokerService.init();
return brokerService;
+ */
+ return null;
}
@OPTIONS
diff --git a/services/src/main/java/org/keycloak/social/twitter/TwitterIdentityProvider.java b/services/src/main/java/org/keycloak/social/twitter/TwitterIdentityProvider.java
index c6b340f..f81abc9 100755
--- a/services/src/main/java/org/keycloak/social/twitter/TwitterIdentityProvider.java
+++ b/services/src/main/java/org/keycloak/social/twitter/TwitterIdentityProvider.java
@@ -26,7 +26,6 @@ import org.keycloak.broker.social.SocialIdentityProvider;
import org.keycloak.common.ClientConnection;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
-import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.KeycloakSession;
@@ -48,8 +47,6 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
-import static org.keycloak.models.ClientSessionModel.Action.AUTHENTICATE;
-
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@@ -118,6 +115,8 @@ public class TwitterIdentityProvider extends AbstractIdentityProvider<OAuth2Iden
}
try {
+ // TODO:mposolda
+ /*
Twitter twitter = new TwitterFactory().getInstance();
twitter.setOAuthConsumer(getConfig().getClientId(), getConfig().getClientSecret());
@@ -152,6 +151,8 @@ public class TwitterIdentityProvider extends AbstractIdentityProvider<OAuth2Iden
identity.setCode(state);
return callback.authenticated(identity);
+ */
+ return null;
} catch (Exception e) {
logger.error("Could get user profile from twitter.", e);
}
@@ -161,29 +162,6 @@ public class TwitterIdentityProvider extends AbstractIdentityProvider<OAuth2Iden
return ErrorPage.error(session, Messages.UNEXPECTED_ERROR_HANDLING_RESPONSE);
}
- private ClientSessionCode parseClientSessionCode(String code) {
- ClientSessionCode clientCode = ClientSessionCode.parse(code, this.session, this.realm);
-
- if (clientCode != null && clientCode.isValid(AUTHENTICATE.name(), ClientSessionCode.ActionType.LOGIN)) {
- ClientSessionModel clientSession = clientCode.getClientSession();
-
- if (clientSession != null) {
- ClientModel client = clientSession.getClient();
-
- if (client == null) {
- throw new IdentityBrokerException("Invalid client");
- }
-
- logger.debugf("Got authorization code from client [%s].", client.getClientId());
- }
-
- logger.debugf("Authorization code is valid.");
-
- return clientCode;
- }
-
- throw new IdentityBrokerException("Invalid code, please login again through your application.");
- }
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionInitializerTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionInitializerTest.java
index 2db24ad..bc71a09 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionInitializerTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionInitializerTest.java
@@ -47,128 +47,129 @@ import java.util.Set;
*/
public class UserSessionInitializerTest {
- @ClassRule
- public static KeycloakRule kc = new KeycloakRule();
-
- private KeycloakSession session;
- private RealmModel realm;
- private UserSessionManager sessionManager;
-
- @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);
- }
-
- @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 testUserSessionInitializer() {
- UserSessionModel[] origSessions = createSessions();
-
- resetSession();
-
- // Create and persist offline sessions
- int started = Time.currentTime();
- int serverStartTime = session.getProvider(ClusterProvider.class).getClusterStartupTime();
-
- for (UserSessionModel origSession : origSessions) {
- UserSessionModel userSession = session.sessions().getUserSession(realm, origSession.getId());
- for (ClientSessionModel clientSession : userSession.getClientSessions()) {
- sessionManager.createOrUpdateOfflineSession(clientSession, userSession);
- }
- }
-
- resetSession();
-
- // Delete cache (persisted sessions are still kept)
- session.sessions().onRealmRemoved(realm);
-
- // Clear ispn cache to ensure initializerState is removed as well
- InfinispanConnectionProvider infinispan = session.getProvider(InfinispanConnectionProvider.class);
- infinispan.getCache(InfinispanConnectionProvider.WORK_CACHE_NAME).clear();
-
- resetSession();
-
- ClientModel testApp = realm.getClientByClientId("test-app");
- ClientModel thirdparty = realm.getClientByClientId("third-party");
- Assert.assertEquals(0, session.sessions().getOfflineSessionsCount(realm, testApp));
- Assert.assertEquals(0, session.sessions().getOfflineSessionsCount(realm, thirdparty));
-
- // Load sessions from persister into infinispan/memory
- UserSessionProviderFactory userSessionFactory = (UserSessionProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(UserSessionProvider.class);
- userSessionFactory.loadPersistentSessions(session.getKeycloakSessionFactory(), 1, 2);
-
- resetSession();
-
- // Assert sessions are in
- testApp = realm.getClientByClientId("test-app");
- Assert.assertEquals(3, session.sessions().getOfflineSessionsCount(realm, testApp));
- Assert.assertEquals(1, session.sessions().getOfflineSessionsCount(realm, thirdparty));
-
- List<UserSessionModel> loadedSessions = session.sessions().getOfflineUserSessions(realm, testApp, 0, 10);
- UserSessionProviderTest.assertSessions(loadedSessions, origSessions);
-
- UserSessionPersisterProviderTest.assertSessionLoaded(loadedSessions, origSessions[0].getId(), session.users().getUserByUsername("user1", realm), "127.0.0.1", started, serverStartTime, "test-app", "third-party");
- UserSessionPersisterProviderTest.assertSessionLoaded(loadedSessions, origSessions[1].getId(), session.users().getUserByUsername("user1", realm), "127.0.0.2", started, serverStartTime, "test-app");
- UserSessionPersisterProviderTest.assertSessionLoaded(loadedSessions, origSessions[2].getId(), session.users().getUserByUsername("user2", realm), "127.0.0.3", started, serverStartTime, "test-app");
- }
-
- private ClientSessionModel createClientSession(ClientModel client, UserSessionModel userSession, String redirect, String state, Set<String> roles, Set<String> protocolMappers) {
- ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
- if (userSession != null) clientSession.setUserSession(userSession);
- clientSession.setRedirectUri(redirect);
- if (state != null) clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, state);
- if (roles != null) clientSession.setRoles(roles);
- if (protocolMappers != null) clientSession.setProtocolMappers(protocolMappers);
- 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", roles, protocolMappers);
- createClientSession(realm.getClientByClientId("third-party"), sessions[0], "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
-
- 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", new HashSet<String>(), new HashSet<String>());
-
- 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", new HashSet<String>(), new HashSet<String>());
-
- resetSession();
-
- return sessions;
- }
-
- private void resetSession() {
- kc.stopSession(session, true);
- session = kc.startSession();
- realm = session.realms().getRealm("test");
- sessionManager = new UserSessionManager(session);
- }
+ // TODO:mposolda
+// @ClassRule
+// public static KeycloakRule kc = new KeycloakRule();
+//
+// private KeycloakSession session;
+// private RealmModel realm;
+// private UserSessionManager sessionManager;
+//
+// @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);
+// }
+//
+// @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 testUserSessionInitializer() {
+// UserSessionModel[] origSessions = createSessions();
+//
+// resetSession();
+//
+// // Create and persist offline sessions
+// int started = Time.currentTime();
+// int serverStartTime = session.getProvider(ClusterProvider.class).getClusterStartupTime();
+//
+// for (UserSessionModel origSession : origSessions) {
+// UserSessionModel userSession = session.sessions().getUserSession(realm, origSession.getId());
+// for (ClientSessionModel clientSession : userSession.getClientSessions()) {
+// sessionManager.createOrUpdateOfflineSession(clientSession, userSession);
+// }
+// }
+//
+// resetSession();
+//
+// // Delete cache (persisted sessions are still kept)
+// session.sessions().onRealmRemoved(realm);
+//
+// // Clear ispn cache to ensure initializerState is removed as well
+// InfinispanConnectionProvider infinispan = session.getProvider(InfinispanConnectionProvider.class);
+// infinispan.getCache(InfinispanConnectionProvider.WORK_CACHE_NAME).clear();
+//
+// resetSession();
+//
+// ClientModel testApp = realm.getClientByClientId("test-app");
+// ClientModel thirdparty = realm.getClientByClientId("third-party");
+// Assert.assertEquals(0, session.sessions().getOfflineSessionsCount(realm, testApp));
+// Assert.assertEquals(0, session.sessions().getOfflineSessionsCount(realm, thirdparty));
+//
+// // Load sessions from persister into infinispan/memory
+// UserSessionProviderFactory userSessionFactory = (UserSessionProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(UserSessionProvider.class);
+// userSessionFactory.loadPersistentSessions(session.getKeycloakSessionFactory(), 1, 2);
+//
+// resetSession();
+//
+// // Assert sessions are in
+// testApp = realm.getClientByClientId("test-app");
+// Assert.assertEquals(3, session.sessions().getOfflineSessionsCount(realm, testApp));
+// Assert.assertEquals(1, session.sessions().getOfflineSessionsCount(realm, thirdparty));
+//
+// List<UserSessionModel> loadedSessions = session.sessions().getOfflineUserSessions(realm, testApp, 0, 10);
+// UserSessionProviderTest.assertSessions(loadedSessions, origSessions);
+//
+// UserSessionPersisterProviderTest.assertSessionLoaded(loadedSessions, origSessions[0].getId(), session.users().getUserByUsername("user1", realm), "127.0.0.1", started, serverStartTime, "test-app", "third-party");
+// UserSessionPersisterProviderTest.assertSessionLoaded(loadedSessions, origSessions[1].getId(), session.users().getUserByUsername("user1", realm), "127.0.0.2", started, serverStartTime, "test-app");
+// UserSessionPersisterProviderTest.assertSessionLoaded(loadedSessions, origSessions[2].getId(), session.users().getUserByUsername("user2", realm), "127.0.0.3", started, serverStartTime, "test-app");
+// }
+//
+// private ClientSessionModel createClientSession(ClientModel client, UserSessionModel userSession, String redirect, String state, Set<String> roles, Set<String> protocolMappers) {
+// ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
+// if (userSession != null) clientSession.setUserSession(userSession);
+// clientSession.setRedirectUri(redirect);
+// if (state != null) clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, state);
+// if (roles != null) clientSession.setRoles(roles);
+// if (protocolMappers != null) clientSession.setProtocolMappers(protocolMappers);
+// 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", roles, protocolMappers);
+// createClientSession(realm.getClientByClientId("third-party"), sessions[0], "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
+//
+// 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", new HashSet<String>(), new HashSet<String>());
+//
+// 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", new HashSet<String>(), new HashSet<String>());
+//
+// resetSession();
+//
+// return sessions;
+// }
+//
+// private void resetSession() {
+// kc.stopSession(session, true);
+// session = kc.startSession();
+// realm = session.realms().getRealm("test");
+// sessionManager = new UserSessionManager(session);
+// }
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionPersisterProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionPersisterProviderTest.java
index 60d92d9..9e46ec6 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionPersisterProviderTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionPersisterProviderTest.java
@@ -45,397 +45,398 @@ import java.util.Set;
* @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 testUpdateTimestamps() {
- // 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();
-
- // update timestamps
- int newTime = started + 50;
- persister.updateAllTimestamps(newTime);
-
- // Assert online session
- List<UserSessionModel> loadedSessions = loadPersistedSessionsPaginated(false, 1, 1, 1);
- Assert.assertEquals(2, assertTimestampsUpdated(loadedSessions, newTime));
-
- // Assert offline sessions
- loadedSessions = loadPersistedSessionsPaginated(true, 2, 2, 3);
- Assert.assertEquals(4, assertTimestampsUpdated(loadedSessions, newTime));
- }
-
- private int assertTimestampsUpdated(List<UserSessionModel> loadedSessions, int expectedTime) {
- int clientSessionsCount = 0;
- for (UserSessionModel loadedSession : loadedSessions) {
- Assert.assertEquals(expectedTime, loadedSession.getLastSessionRefresh());
- for (ClientSessionModel clientSession : loadedSession.getClientSessions()) {
- Assert.assertEquals(expectedTime, clientSession.getTimestamp());
- clientSessionsCount++;
- }
- }
- return clientSessionsCount;
- }
-
- @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");
-
- // Update userSession
- Time.setOffset(10);
- try {
- persistedSession.setLastSessionRefresh(Time.currentTime());
- persistedSession.setNote("foo", "bar");
- persistedSession.setState(UserSessionModel.State.LOGGING_IN);
- persister.updateUserSession(persistedSession, true);
-
- // create new clientSession
- ClientSessionModel clientSession = createClientSession(realm.getClientByClientId("third-party"), session.sessions().getUserSession(realm, persistedSession.getId()),
- "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
- persister.createClientSession(clientSession, true);
-
- resetSession();
-
- // Assert session updated
- loadedSessions = loadPersistedSessionsPaginated(true, 10, 1, 1);
- persistedSession = loadedSessions.get(0);
- UserSessionProviderTest.assertSession(persistedSession, session.users().getUserByUsername("user1", realm), "127.0.0.2", started, started+10, "test-app", "third-party");
- Assert.assertEquals("bar", persistedSession.getNote("foo"));
- Assert.assertEquals(UserSessionModel.State.LOGGING_IN, persistedSession.getState());
-
- // Remove clientSession
- persister.removeClientSession(clientSession.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 + 10, "test-app");
-
- // Remove userSession
- persister.removeUserSession(persistedSession.getId(), true);
-
- resetSession();
-
- // Assert nothing found
- loadPersistedSessionsPaginated(true, 10, 0, 0);
- } finally {
- Time.setOffset(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", new HashSet<String>(), new HashSet<String>());
-
- 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", new HashSet<String>(), new HashSet<String>());
- createClientSession(fooRealm.getClientByClientId("bar-app"), userSession, "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
-
- 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 nothing loaded - userSession was removed as well because it was last userSession
- loadPersistedSessionsPaginated(true, 10, 0, 0);
-
- // 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"
- UserModel user2 = session.users().getUserByUsername("user2", realm);
- session.users().removeUser(realm, user2);
-
- loadedSessions = loadPersistedSessionsPaginated(true, 10, 0, 0);
-
- }
-
- // KEYCLOAK-1999
- @Test
- public void testNoSessions() {
- UserSessionPersisterProvider persister = session.getProvider(UserSessionPersisterProvider.class);
- List<UserSessionModel> sessions = persister.loadUserSessions(0, 1, true);
- Assert.assertEquals(0, sessions.size());
- }
-
-
- private ClientSessionModel createClientSession(ClientModel client, UserSessionModel userSession, String redirect, String state, Set<String> roles, Set<String> protocolMappers) {
- ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
- if (userSession != null) clientSession.setUserSession(userSession);
- clientSession.setRedirectUri(redirect);
- if (state != null) clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, state);
- if (roles != null) clientSession.setRoles(roles);
- if (protocolMappers != null) clientSession.setProtocolMappers(protocolMappers);
- 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", roles, protocolMappers);
- createClientSession(realm.getClientByClientId("third-party"), sessions[0], "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
-
- 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", new HashSet<String>(), new HashSet<String>());
-
- 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", new HashSet<String>(), new HashSet<String>());
-
- return sessions;
- }
-
- private void persistUserSession(UserSessionModel userSession, boolean offline) {
- persister.createUserSession(userSession, offline);
- for (ClientSessionModel clientSession : userSession.getClientSessions()) {
- 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 start = 0;
- int pageCount = 0;
- boolean next = true;
- List<UserSessionModel> result = new ArrayList<>();
- while (next && start < count) {
- List<UserSessionModel> sess = persister.loadUserSessions(start, sessionsPerPage, offline);
- if (sess.size() == 0) {
- next = false;
- } else {
- pageCount++;
- start += sess.size();
- result.addAll(sess);
- }
- }
-
- Assert.assertEquals(pageCount, expectedPageCount);
- Assert.assertEquals(result.size(), expectedSessionsCount);
- return result;
- }
+// TODO:mposolda
+
+// @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 testUpdateTimestamps() {
+// // 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();
+//
+// // update timestamps
+// int newTime = started + 50;
+// persister.updateAllTimestamps(newTime);
+//
+// // Assert online session
+// List<UserSessionModel> loadedSessions = loadPersistedSessionsPaginated(false, 1, 1, 1);
+// Assert.assertEquals(2, assertTimestampsUpdated(loadedSessions, newTime));
+//
+// // Assert offline sessions
+// loadedSessions = loadPersistedSessionsPaginated(true, 2, 2, 3);
+// Assert.assertEquals(4, assertTimestampsUpdated(loadedSessions, newTime));
+// }
+//
+// private int assertTimestampsUpdated(List<UserSessionModel> loadedSessions, int expectedTime) {
+// int clientSessionsCount = 0;
+// for (UserSessionModel loadedSession : loadedSessions) {
+// Assert.assertEquals(expectedTime, loadedSession.getLastSessionRefresh());
+// for (ClientSessionModel clientSession : loadedSession.getClientSessions()) {
+// Assert.assertEquals(expectedTime, clientSession.getTimestamp());
+// clientSessionsCount++;
+// }
+// }
+// return clientSessionsCount;
+// }
+//
+// @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");
+//
+// // Update userSession
+// Time.setOffset(10);
+// try {
+// persistedSession.setLastSessionRefresh(Time.currentTime());
+// persistedSession.setNote("foo", "bar");
+// persistedSession.setState(UserSessionModel.State.LOGGING_IN);
+// persister.updateUserSession(persistedSession, true);
+//
+// // create new clientSession
+// ClientSessionModel clientSession = createClientSession(realm.getClientByClientId("third-party"), session.sessions().getUserSession(realm, persistedSession.getId()),
+// "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
+// persister.createClientSession(clientSession, true);
+//
+// resetSession();
+//
+// // Assert session updated
+// loadedSessions = loadPersistedSessionsPaginated(true, 10, 1, 1);
+// persistedSession = loadedSessions.get(0);
+// UserSessionProviderTest.assertSession(persistedSession, session.users().getUserByUsername("user1", realm), "127.0.0.2", started, started+10, "test-app", "third-party");
+// Assert.assertEquals("bar", persistedSession.getNote("foo"));
+// Assert.assertEquals(UserSessionModel.State.LOGGING_IN, persistedSession.getState());
+//
+// // Remove clientSession
+// persister.removeClientSession(clientSession.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 + 10, "test-app");
+//
+// // Remove userSession
+// persister.removeUserSession(persistedSession.getId(), true);
+//
+// resetSession();
+//
+// // Assert nothing found
+// loadPersistedSessionsPaginated(true, 10, 0, 0);
+// } finally {
+// Time.setOffset(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", new HashSet<String>(), new HashSet<String>());
+//
+// 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", new HashSet<String>(), new HashSet<String>());
+// createClientSession(fooRealm.getClientByClientId("bar-app"), userSession, "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
+//
+// 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 nothing loaded - userSession was removed as well because it was last userSession
+// loadPersistedSessionsPaginated(true, 10, 0, 0);
+//
+// // 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"
+// UserModel user2 = session.users().getUserByUsername("user2", realm);
+// session.users().removeUser(realm, user2);
+//
+// loadedSessions = loadPersistedSessionsPaginated(true, 10, 0, 0);
+//
+// }
+//
+// // KEYCLOAK-1999
+// @Test
+// public void testNoSessions() {
+// UserSessionPersisterProvider persister = session.getProvider(UserSessionPersisterProvider.class);
+// List<UserSessionModel> sessions = persister.loadUserSessions(0, 1, true);
+// Assert.assertEquals(0, sessions.size());
+// }
+//
+//
+// private ClientSessionModel createClientSession(ClientModel client, UserSessionModel userSession, String redirect, String state, Set<String> roles, Set<String> protocolMappers) {
+// ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
+// if (userSession != null) clientSession.setUserSession(userSession);
+// clientSession.setRedirectUri(redirect);
+// if (state != null) clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, state);
+// if (roles != null) clientSession.setRoles(roles);
+// if (protocolMappers != null) clientSession.setProtocolMappers(protocolMappers);
+// 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", roles, protocolMappers);
+// createClientSession(realm.getClientByClientId("third-party"), sessions[0], "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
+//
+// 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", new HashSet<String>(), new HashSet<String>());
+//
+// 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", new HashSet<String>(), new HashSet<String>());
+//
+// return sessions;
+// }
+//
+// private void persistUserSession(UserSessionModel userSession, boolean offline) {
+// persister.createUserSession(userSession, offline);
+// for (ClientSessionModel clientSession : userSession.getClientSessions()) {
+// 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 start = 0;
+// int pageCount = 0;
+// boolean next = true;
+// List<UserSessionModel> result = new ArrayList<>();
+// while (next && start < count) {
+// List<UserSessionModel> sess = persister.loadUserSessions(start, sessionsPerPage, offline);
+// if (sess.size() == 0) {
+// next = false;
+// } else {
+// pageCount++;
+// start += sess.size();
+// result.addAll(sess);
+// }
+// }
+//
+// Assert.assertEquals(pageCount, expectedPageCount);
+// Assert.assertEquals(result.size(), expectedSessionsCount);
+// return result;
+// }
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderOfflineTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderOfflineTest.java
index fb4b3af..c69f8f9 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderOfflineTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderOfflineTest.java
@@ -51,409 +51,410 @@ import java.util.Set;
*/
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();
-
- Map<String, 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.putAll(createOfflineSessionIncludeClientSessions(userSession));
- }
-
- resetSession();
-
- // Assert all previously saved offline sessions found
- for (Map.Entry<String, String> entry : offlineSessions.entrySet()) {
- Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey()) != null);
-
- UserSessionModel offlineSession = session.sessions().getUserSession(realm, entry.getValue());
- boolean found = false;
- for (ClientSessionModel clientSession : offlineSession.getClientSessions()) {
- if (clientSession.getId().equals(entry.getKey())) {
- found = true;
- }
- }
- Assert.assertTrue(found);
- }
-
- // 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");
- Assert.assertEquals(1, session.sessions().getOfflineSessionsCount(realm, testApp));
- Assert.assertEquals(1, session.sessions().getOfflineSessionsCount(realm, thirdparty));
-
- List<UserSessionModel> testAppSessions = session.sessions().getOfflineUserSessions(realm, testApp, 0, 10);
- List<UserSessionModel> thirdpartySessions = session.sessions().getOfflineUserSessions(realm, thirdparty, 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());
- 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());
- }
-
- @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);
- ClientSessionModel clientSession = createClientSession(fooRealm.getClientByClientId("foo-app"), userSession, "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
-
- resetSession();
-
- // Persist offline session
- fooRealm = session.realms().getRealm("foo");
- userSession = session.sessions().getUserSession(fooRealm, userSession.getId());
- clientSession = session.sessions().getClientSession(fooRealm, clientSession.getId());
- sessionManager.createOrUpdateOfflineSession(userSession.getClientSessions().get(0), userSession);
-
- resetSession();
-
- ClientSessionModel offlineClientSession = sessionManager.findOfflineClientSession(fooRealm, clientSession.getId());
- Assert.assertEquals("foo-app", offlineClientSession.getClient().getClientId());
- Assert.assertEquals("user3", offlineClientSession.getUserSession().getUser().getUsername());
- Assert.assertEquals(offlineClientSession.getId(), offlineClientSession.getUserSession().getClientSessions().get(0).getId());
-
- // 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.findOfflineClientSession(fooRealm, clientSession.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", new HashSet<String>(), new HashSet<String>());
- createClientSession(fooRealm.getClientByClientId("bar-app"), userSession, "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
-
- 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.getClientSessions().size());
- Assert.assertEquals("bar-app", offlineSession.getClientSessions().get(0).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
- offlineSession = session.sessions().getOfflineUserSession(fooRealm, userSession.getId());
- Assert.assertEquals(0, offlineSession.getClientSessions().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);
- ClientSessionModel clientSession = createClientSession(fooRealm.getClientByClientId("foo-app"), userSession, "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
-
- 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()));
- Assert.assertNull(session.sessions().getOfflineClientSession(fooRealm, clientSession.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();
-
- Map<String, 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.putAll(createOfflineSessionIncludeClientSessions(userSession));
- }
-
- resetSession();
-
- // Assert all previously saved offline sessions found
- for (Map.Entry<String, String> entry : offlineSessions.entrySet()) {
- Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey()) != null);
- }
-
- UserSessionModel session0 = session.sessions().getOfflineUserSession(realm, origSessions[0].getId());
- Assert.assertNotNull(session0);
- List<String> clientSessions = new LinkedList<>();
- for (ClientSessionModel clientSession : session0.getClientSessions()) {
- clientSessions.add(clientSession.getId());
- Assert.assertNotNull(session.sessions().getOfflineClientSession(realm, clientSession.getId()));
- }
-
- UserSessionModel session1 = session.sessions().getOfflineUserSession(realm, origSessions[1].getId());
- Assert.assertEquals(1, session1.getClientSessions().size());
- ClientSessionModel cls1 = session1.getClientSessions().get(0);
-
- // sessions are in persister too
- Assert.assertEquals(3, persister.getUserSessionsCount(true));
-
- // Set lastSessionRefresh to session[0] to 0
- session0.setLastSessionRefresh(0);
-
- // Set timestamp to cls1 to 0
- cls1.setTimestamp(0);
-
- resetSession();
-
- session.sessions().removeExpired(realm);
-
- resetSession();
-
- // assert session0 not found now
- Assert.assertNull(session.sessions().getOfflineUserSession(realm, origSessions[0].getId()));
- for (String clientSession : clientSessions) {
- Assert.assertNull(session.sessions().getOfflineClientSession(realm, origSessions[0].getId()));
- offlineSessions.remove(clientSession);
- }
-
- // Assert cls1 not found too
- for (Map.Entry<String, String> entry : offlineSessions.entrySet()) {
- String userSessionId = entry.getValue();
- if (userSessionId.equals(session1.getId())) {
- Assert.assertFalse(sessionManager.findOfflineClientSession(realm, entry.getKey()) != null);
- } else {
- Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey()) != null);
- }
- }
- Assert.assertEquals(1, persister.getUserSessionsCount(true));
-
- // Expire everything and assert nothing found
- Time.setOffset(3000000);
- try {
- session.sessions().removeExpired(realm);
-
- resetSession();
-
- for (Map.Entry<String, String> entry : offlineSessions.entrySet()) {
- Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey()) == null);
- }
- Assert.assertEquals(0, persister.getUserSessionsCount(true));
-
- } finally {
- Time.setOffset(0);
- }
- }
-
- private Map<String, String> createOfflineSessionIncludeClientSessions(UserSessionModel userSession) {
- Map<String, String> offlineSessions = new HashMap<>();
-
- for (ClientSessionModel clientSession : userSession.getClientSessions()) {
- sessionManager.createOrUpdateOfflineSession(clientSession, userSession);
- offlineSessions.put(clientSession.getId(), userSession.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 ClientSessionModel createClientSession(ClientModel client, UserSessionModel userSession, String redirect, String state, Set<String> roles, Set<String> protocolMappers) {
- ClientSessionModel clientSession = session.sessions().createClientSession(client.getRealm(), client);
- if (userSession != null) clientSession.setUserSession(userSession);
- clientSession.setRedirectUri(redirect);
- if (state != null) clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, state);
- if (roles != null) clientSession.setRoles(roles);
- if (protocolMappers != null) clientSession.setProtocolMappers(protocolMappers);
- 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", roles, protocolMappers);
- createClientSession(realm.getClientByClientId("third-party"), sessions[0], "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
-
- 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", new HashSet<String>(), new HashSet<String>());
-
- 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", new HashSet<String>(), new HashSet<String>());
-
- return sessions;
- }
+ // TODO:mposolda
+// @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();
+//
+// Map<String, 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.putAll(createOfflineSessionIncludeClientSessions(userSession));
+// }
+//
+// resetSession();
+//
+// // Assert all previously saved offline sessions found
+// for (Map.Entry<String, String> entry : offlineSessions.entrySet()) {
+// Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey()) != null);
+//
+// UserSessionModel offlineSession = session.sessions().getUserSession(realm, entry.getValue());
+// boolean found = false;
+// for (ClientSessionModel clientSession : offlineSession.getClientSessions()) {
+// if (clientSession.getId().equals(entry.getKey())) {
+// found = true;
+// }
+// }
+// Assert.assertTrue(found);
+// }
+//
+// // 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");
+// Assert.assertEquals(1, session.sessions().getOfflineSessionsCount(realm, testApp));
+// Assert.assertEquals(1, session.sessions().getOfflineSessionsCount(realm, thirdparty));
+//
+// List<UserSessionModel> testAppSessions = session.sessions().getOfflineUserSessions(realm, testApp, 0, 10);
+// List<UserSessionModel> thirdpartySessions = session.sessions().getOfflineUserSessions(realm, thirdparty, 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());
+// 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());
+// }
+//
+// @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);
+// ClientSessionModel clientSession = createClientSession(fooRealm.getClientByClientId("foo-app"), userSession, "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
+//
+// resetSession();
+//
+// // Persist offline session
+// fooRealm = session.realms().getRealm("foo");
+// userSession = session.sessions().getUserSession(fooRealm, userSession.getId());
+// clientSession = session.sessions().getClientSession(fooRealm, clientSession.getId());
+// sessionManager.createOrUpdateOfflineSession(userSession.getClientSessions().get(0), userSession);
+//
+// resetSession();
+//
+// ClientSessionModel offlineClientSession = sessionManager.findOfflineClientSession(fooRealm, clientSession.getId());
+// Assert.assertEquals("foo-app", offlineClientSession.getClient().getClientId());
+// Assert.assertEquals("user3", offlineClientSession.getUserSession().getUser().getUsername());
+// Assert.assertEquals(offlineClientSession.getId(), offlineClientSession.getUserSession().getClientSessions().get(0).getId());
+//
+// // 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.findOfflineClientSession(fooRealm, clientSession.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", new HashSet<String>(), new HashSet<String>());
+// createClientSession(fooRealm.getClientByClientId("bar-app"), userSession, "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
+//
+// 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.getClientSessions().size());
+// Assert.assertEquals("bar-app", offlineSession.getClientSessions().get(0).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
+// offlineSession = session.sessions().getOfflineUserSession(fooRealm, userSession.getId());
+// Assert.assertEquals(0, offlineSession.getClientSessions().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);
+// ClientSessionModel clientSession = createClientSession(fooRealm.getClientByClientId("foo-app"), userSession, "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
+//
+// 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()));
+// Assert.assertNull(session.sessions().getOfflineClientSession(fooRealm, clientSession.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();
+//
+// Map<String, 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.putAll(createOfflineSessionIncludeClientSessions(userSession));
+// }
+//
+// resetSession();
+//
+// // Assert all previously saved offline sessions found
+// for (Map.Entry<String, String> entry : offlineSessions.entrySet()) {
+// Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey()) != null);
+// }
+//
+// UserSessionModel session0 = session.sessions().getOfflineUserSession(realm, origSessions[0].getId());
+// Assert.assertNotNull(session0);
+// List<String> clientSessions = new LinkedList<>();
+// for (ClientSessionModel clientSession : session0.getClientSessions()) {
+// clientSessions.add(clientSession.getId());
+// Assert.assertNotNull(session.sessions().getOfflineClientSession(realm, clientSession.getId()));
+// }
+//
+// UserSessionModel session1 = session.sessions().getOfflineUserSession(realm, origSessions[1].getId());
+// Assert.assertEquals(1, session1.getClientSessions().size());
+// ClientSessionModel cls1 = session1.getClientSessions().get(0);
+//
+// // sessions are in persister too
+// Assert.assertEquals(3, persister.getUserSessionsCount(true));
+//
+// // Set lastSessionRefresh to session[0] to 0
+// session0.setLastSessionRefresh(0);
+//
+// // Set timestamp to cls1 to 0
+// cls1.setTimestamp(0);
+//
+// resetSession();
+//
+// session.sessions().removeExpired(realm);
+//
+// resetSession();
+//
+// // assert session0 not found now
+// Assert.assertNull(session.sessions().getOfflineUserSession(realm, origSessions[0].getId()));
+// for (String clientSession : clientSessions) {
+// Assert.assertNull(session.sessions().getOfflineClientSession(realm, origSessions[0].getId()));
+// offlineSessions.remove(clientSession);
+// }
+//
+// // Assert cls1 not found too
+// for (Map.Entry<String, String> entry : offlineSessions.entrySet()) {
+// String userSessionId = entry.getValue();
+// if (userSessionId.equals(session1.getId())) {
+// Assert.assertFalse(sessionManager.findOfflineClientSession(realm, entry.getKey()) != null);
+// } else {
+// Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey()) != null);
+// }
+// }
+// Assert.assertEquals(1, persister.getUserSessionsCount(true));
+//
+// // Expire everything and assert nothing found
+// Time.setOffset(3000000);
+// try {
+// session.sessions().removeExpired(realm);
+//
+// resetSession();
+//
+// for (Map.Entry<String, String> entry : offlineSessions.entrySet()) {
+// Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey()) == null);
+// }
+// Assert.assertEquals(0, persister.getUserSessionsCount(true));
+//
+// } finally {
+// Time.setOffset(0);
+// }
+// }
+//
+// private Map<String, String> createOfflineSessionIncludeClientSessions(UserSessionModel userSession) {
+// Map<String, String> offlineSessions = new HashMap<>();
+//
+// for (ClientSessionModel clientSession : userSession.getClientSessions()) {
+// sessionManager.createOrUpdateOfflineSession(clientSession, userSession);
+// offlineSessions.put(clientSession.getId(), userSession.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 ClientSessionModel createClientSession(ClientModel client, UserSessionModel userSession, String redirect, String state, Set<String> roles, Set<String> protocolMappers) {
+// ClientSessionModel clientSession = session.sessions().createClientSession(client.getRealm(), client);
+// if (userSession != null) clientSession.setUserSession(userSession);
+// clientSession.setRedirectUri(redirect);
+// if (state != null) clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, state);
+// if (roles != null) clientSession.setRoles(roles);
+// if (protocolMappers != null) clientSession.setProtocolMappers(protocolMappers);
+// 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", roles, protocolMappers);
+// createClientSession(realm.getClientByClientId("third-party"), sessions[0], "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
+//
+// 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", new HashSet<String>(), new HashSet<String>());
+//
+// 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", new HashSet<String>(), new HashSet<String>());
+//
+// return sessions;
+// }
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java
index 824200d..534bff3 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java
@@ -52,575 +52,577 @@ import static org.junit.Assert.assertTrue;
*/
public class UserSessionProviderTest {
- @ClassRule
- public static KeycloakRule kc = new KeycloakRule();
-
- private KeycloakSession session;
- private RealmModel realm;
-
- @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");
- }
-
- @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 testCreateSessions() {
- int started = Time.currentTime();
- UserSessionModel[] sessions = createSessions();
-
- assertSession(session.sessions().getUserSession(realm, sessions[0].getId()), session.users().getUserByUsername("user1", realm), "127.0.0.1", started, started, "test-app", "third-party");
- assertSession(session.sessions().getUserSession(realm, sessions[1].getId()), session.users().getUserByUsername("user1", realm), "127.0.0.2", started, started, "test-app");
- assertSession(session.sessions().getUserSession(realm, sessions[2].getId()), session.users().getUserByUsername("user2", realm), "127.0.0.3", started, started, "test-app");
- }
-
- @Test
- public void testUpdateSession() {
- UserSessionModel[] sessions = createSessions();
- session.sessions().getUserSession(realm, sessions[0].getId()).setLastSessionRefresh(1000);
-
- resetSession();
-
- assertEquals(1000, session.sessions().getUserSession(realm, sessions[0].getId()).getLastSessionRefresh());
- }
-
- @Test
- public void testCreateClientSession() {
- UserSessionModel[] sessions = createSessions();
-
- List<ClientSessionModel> clientSessions = session.sessions().getUserSession(realm, sessions[0].getId()).getClientSessions();
- assertEquals(2, clientSessions.size());
-
- String client1 = realm.getClientByClientId("test-app").getId();
-
- ClientSessionModel session1;
-
- if (clientSessions.get(0).getClient().getId().equals(client1)) {
- session1 = clientSessions.get(0);
- } else {
- session1 = clientSessions.get(1);
- }
-
- assertEquals(null, session1.getAction());
- assertEquals(realm.getClientByClientId("test-app").getClientId(), session1.getClient().getClientId());
- assertEquals(sessions[0].getId(), session1.getUserSession().getId());
- assertEquals("http://redirect", session1.getRedirectUri());
- assertEquals("state", session1.getNote(OIDCLoginProtocol.STATE_PARAM));
- assertEquals(2, session1.getRoles().size());
- assertTrue(session1.getRoles().contains("one"));
- assertTrue(session1.getRoles().contains("two"));
- assertEquals(2, session1.getProtocolMappers().size());
- assertTrue(session1.getProtocolMappers().contains("mapper-one"));
- assertTrue(session1.getProtocolMappers().contains("mapper-two"));
- }
-
- @Test
- public void testUpdateClientSession() {
- UserSessionModel[] sessions = createSessions();
-
- String id = sessions[0].getClientSessions().get(0).getId();
-
- ClientSessionModel clientSession = session.sessions().getClientSession(realm, id);
-
- int time = clientSession.getTimestamp();
- assertEquals(null, clientSession.getAction());
-
- clientSession.setAction(ClientSessionModel.Action.CODE_TO_TOKEN.name());
- clientSession.setTimestamp(time + 10);
-
- kc.stopSession(session, true);
- session = kc.startSession();
-
- ClientSessionModel updated = session.sessions().getClientSession(realm, id);
- assertEquals(ClientSessionModel.Action.CODE_TO_TOKEN.name(), updated.getAction());
- assertEquals(time + 10, updated.getTimestamp());
- }
-
- @Test
- public void testGetUserSessions() {
- UserSessionModel[] sessions = createSessions();
-
- assertSessions(session.sessions().getUserSessions(realm, session.users().getUserByUsername("user1", realm)), sessions[0], sessions[1]);
- assertSessions(session.sessions().getUserSessions(realm, session.users().getUserByUsername("user2", realm)), sessions[2]);
- }
-
- @Test
- public void testRemoveUserSessionsByUser() {
- UserSessionModel[] sessions = createSessions();
-
- List<String> clientSessionsRemoved = new LinkedList<String>();
- List<String> clientSessionsKept = new LinkedList<String>();
- for (UserSessionModel s : sessions) {
- s = session.sessions().getUserSession(realm, s.getId());
-
- for (ClientSessionModel c : s.getClientSessions()) {
- if (c.getUserSession().getUser().getUsername().equals("user1")) {
- clientSessionsRemoved.add(c.getId());
- } else {
- clientSessionsKept.add(c.getId());
- }
- }
- }
-
- session.sessions().removeUserSessions(realm, session.users().getUserByUsername("user1", realm));
- resetSession();
-
- assertTrue(session.sessions().getUserSessions(realm, session.users().getUserByUsername("user1", realm)).isEmpty());
- assertFalse(session.sessions().getUserSessions(realm, session.users().getUserByUsername("user2", realm)).isEmpty());
-
- for (String c : clientSessionsRemoved) {
- assertNull(session.sessions().getClientSession(realm, c));
- }
- for (String c : clientSessionsKept) {
- assertNotNull(session.sessions().getClientSession(realm, c));
- }
- }
-
- @Test
- public void testRemoveUserSession() {
- UserSessionModel userSession = createSessions()[0];
-
- List<String> clientSessionsRemoved = new LinkedList<String>();
- for (ClientSessionModel c : userSession.getClientSessions()) {
- clientSessionsRemoved.add(c.getId());
- }
-
- session.sessions().removeUserSession(realm, userSession);
- resetSession();
-
- assertNull(session.sessions().getUserSession(realm, userSession.getId()));
- for (String c : clientSessionsRemoved) {
- assertNull(session.sessions().getClientSession(realm, c));
- }
- }
-
- @Test
- public void testRemoveUserSessionsByRealm() {
- UserSessionModel[] sessions = createSessions();
-
- List<ClientSessionModel> clientSessions = new LinkedList<ClientSessionModel>();
- for (UserSessionModel s : sessions) {
- clientSessions.addAll(s.getClientSessions());
- }
-
- session.sessions().removeUserSessions(realm);
- resetSession();
-
- assertTrue(session.sessions().getUserSessions(realm, session.users().getUserByUsername("user1", realm)).isEmpty());
- assertTrue(session.sessions().getUserSessions(realm, session.users().getUserByUsername("user2", realm)).isEmpty());
-
- for (ClientSessionModel c : clientSessions) {
- assertNull(session.sessions().getClientSession(realm, c.getId()));
- }
- }
-
- @Test
- public void testOnClientRemoved() {
- UserSessionModel[] sessions = createSessions();
-
- List<String> clientSessionsRemoved = new LinkedList<String>();
- List<String> clientSessionsKept = new LinkedList<String>();
- for (UserSessionModel s : sessions) {
- s = session.sessions().getUserSession(realm, s.getId());
- for (ClientSessionModel c : s.getClientSessions()) {
- if (c.getClient().getClientId().equals("third-party")) {
- clientSessionsRemoved.add(c.getId());
- } else {
- clientSessionsKept.add(c.getId());
- }
- }
- }
-
- session.sessions().onClientRemoved(realm, realm.getClientByClientId("third-party"));
- resetSession();
-
- for (String c : clientSessionsRemoved) {
- assertNull(session.sessions().getClientSession(realm, c));
- }
- for (String c : clientSessionsKept) {
- assertNotNull(session.sessions().getClientSession(realm, c));
- }
-
- session.sessions().onClientRemoved(realm, realm.getClientByClientId("test-app"));
- resetSession();
-
- for (String c : clientSessionsRemoved) {
- assertNull(session.sessions().getClientSession(realm, c));
- }
- for (String c : clientSessionsKept) {
- assertNull(session.sessions().getClientSession(realm, c));
- }
- }
-
- @Test
- public void testRemoveUserSessionsByExpired() {
- session.sessions().getUserSessions(realm, session.users().getUserByUsername("user1", realm));
- ClientModel client = realm.getClientByClientId("test-app");
-
- try {
- Set<String> expired = new HashSet<String>();
- Set<String> expiredClientSessions = new HashSet<String>();
-
- Time.setOffset(-(realm.getSsoSessionMaxLifespan() + 1));
- expired.add(session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "user1", "127.0.0.1", "form", true, null, null).getId());
- expiredClientSessions.add(session.sessions().createClientSession(realm, client).getId());
-
- Time.setOffset(0);
- UserSessionModel s = session.sessions().createUserSession(realm, session.users().getUserByUsername("user2", realm), "user2", "127.0.0.1", "form", true, null, null);
- //s.setLastSessionRefresh(Time.currentTime() - (realm.getSsoSessionIdleTimeout() + 1));
- s.setLastSessionRefresh(0);
- expired.add(s.getId());
-
- ClientSessionModel clSession = session.sessions().createClientSession(realm, client);
- clSession.setUserSession(s);
- expiredClientSessions.add(clSession.getId());
-
- Set<String> valid = new HashSet<String>();
- Set<String> validClientSessions = new HashSet<String>();
-
- valid.add(session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "user1", "127.0.0.1", "form", true, null, null).getId());
- validClientSessions.add(session.sessions().createClientSession(realm, client).getId());
-
- resetSession();
-
- session.sessions().removeExpired(realm);
- resetSession();
-
- for (String e : expired) {
- assertNull(session.sessions().getUserSession(realm, e));
- }
- for (String e : expiredClientSessions) {
- assertNull(session.sessions().getClientSession(realm, e));
- }
-
- for (String v : valid) {
- assertNotNull(session.sessions().getUserSession(realm, v));
- }
- for (String e : validClientSessions) {
- assertNotNull(session.sessions().getClientSession(realm, e));
- }
- } finally {
- Time.setOffset(0);
- }
- }
-
- @Test
- public void testExpireDetachedClientSessions() {
- try {
- realm.setAccessCodeLifespan(10);
- realm.setAccessCodeLifespanUserAction(10);
- realm.setAccessCodeLifespanLogin(30);
-
- // Login lifespan is largest
- String clientSessionId = session.sessions().createClientSession(realm, realm.getClientByClientId("test-app")).getId();
- resetSession();
-
- Time.setOffset(25);
- session.sessions().removeExpired(realm);
- resetSession();
-
- assertNotNull(session.sessions().getClientSession(clientSessionId));
-
- Time.setOffset(35);
- session.sessions().removeExpired(realm);
- resetSession();
-
- assertNull(session.sessions().getClientSession(clientSessionId));
-
- // User action is largest
- realm.setAccessCodeLifespanUserAction(40);
-
- Time.setOffset(0);
- clientSessionId = session.sessions().createClientSession(realm, realm.getClientByClientId("test-app")).getId();
- resetSession();
-
- Time.setOffset(35);
- session.sessions().removeExpired(realm);
- resetSession();
-
- assertNotNull(session.sessions().getClientSession(clientSessionId));
-
- Time.setOffset(45);
- session.sessions().removeExpired(realm);
- resetSession();
-
- assertNull(session.sessions().getClientSession(clientSessionId));
-
- // Access code is largest
- realm.setAccessCodeLifespan(50);
-
- Time.setOffset(0);
- clientSessionId = session.sessions().createClientSession(realm, realm.getClientByClientId("test-app")).getId();
- resetSession();
-
- Time.setOffset(45);
- session.sessions().removeExpired(realm);
- resetSession();
-
- assertNotNull(session.sessions().getClientSession(clientSessionId));
-
- Time.setOffset(55);
- session.sessions().removeExpired(realm);
- resetSession();
-
- assertNull(session.sessions().getClientSession(clientSessionId));
- } finally {
- Time.setOffset(0);
-
- realm.setAccessCodeLifespan(60);
- realm.setAccessCodeLifespanUserAction(300);
- realm.setAccessCodeLifespanLogin(1800);
-
- }
- }
-
- // KEYCLOAK-2508
- @Test
- public void testRemovingExpiredSession() {
- UserSessionModel[] sessions = createSessions();
- try {
- Time.setOffset(3600000);
- UserSessionModel userSession = sessions[0];
- RealmModel realm = userSession.getRealm();
- session.sessions().removeExpired(realm);
-
- resetSession();
-
- // Assert no exception is thrown here
- session.sessions().removeUserSession(realm, userSession);
- } finally {
- Time.setOffset(0);
- }
- }
-
- @Test
- public void testGetByClient() {
- UserSessionModel[] sessions = createSessions();
-
- assertSessions(session.sessions().getUserSessions(realm, realm.getClientByClientId("test-app")), sessions[0], sessions[1], sessions[2]);
- assertSessions(session.sessions().getUserSessions(realm, realm.getClientByClientId("third-party")), sessions[0]);
- }
-
- @Test
- public void testGetByClientPaginated() {
- try {
- for (int i = 0; i < 25; i++) {
- Time.setOffset(i);
- UserSessionModel userSession = session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "user1", "127.0.0." + i, "form", false, null, null);
- ClientSessionModel clientSession = session.sessions().createClientSession(realm, realm.getClientByClientId("test-app"));
- clientSession.setUserSession(userSession);
- clientSession.setRedirectUri("http://redirect");
- clientSession.setRoles(new HashSet<String>());
- clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, "state");
- clientSession.setTimestamp(userSession.getStarted());
- }
- } finally {
- Time.setOffset(0);
- }
-
- resetSession();
-
- assertPaginatedSession(realm, realm.getClientByClientId("test-app"), 0, 1, 1);
- assertPaginatedSession(realm, realm.getClientByClientId("test-app"), 0, 10, 10);
- assertPaginatedSession(realm, realm.getClientByClientId("test-app"), 10, 10, 10);
- assertPaginatedSession(realm, realm.getClientByClientId("test-app"), 20, 10, 5);
- assertPaginatedSession(realm, realm.getClientByClientId("test-app"), 30, 10, 0);
- }
-
- @Test
- public void testCreateAndGetInSameTransaction() {
- UserSessionModel userSession = session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "user1", "127.0.0.2", "form", true, null, null);
- ClientSessionModel clientSession = createClientSession(realm.getClientByClientId("test-app"), userSession, "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
-
- Assert.assertNotNull(session.sessions().getUserSession(realm, userSession.getId()));
- Assert.assertNotNull(session.sessions().getClientSession(realm, clientSession.getId()));
-
- Assert.assertEquals(userSession.getId(), clientSession.getUserSession().getId());
- Assert.assertEquals(1, userSession.getClientSessions().size());
- Assert.assertEquals(clientSession.getId(), userSession.getClientSessions().get(0).getId());
- }
-
- private void assertPaginatedSession(RealmModel realm, ClientModel client, int start, int max, int expectedSize) {
- List<UserSessionModel> sessions = session.sessions().getUserSessions(realm, client, start, max);
- String[] actualIps = new String[sessions.size()];
- for (int i = 0; i < actualIps.length; i++) {
- actualIps[i] = sessions.get(i).getIpAddress();
- }
-
- String[] expectedIps = new String[expectedSize];
- for (int i = 0; i < expectedSize; i++) {
- expectedIps[i] = "127.0.0." + (i + start);
- }
-
- assertArrayEquals(expectedIps, actualIps);
- }
-
- @Test
- public void testGetCountByClient() {
- createSessions();
-
- assertEquals(3, session.sessions().getActiveUserSessions(realm, realm.getClientByClientId("test-app")));
- assertEquals(1, session.sessions().getActiveUserSessions(realm, realm.getClientByClientId("third-party")));
- }
-
- @Test
- public void loginFailures() {
- UserLoginFailureModel failure1 = session.sessions().addUserLoginFailure(realm, "user1");
- failure1.incrementFailures();
-
- UserLoginFailureModel failure2 = session.sessions().addUserLoginFailure(realm, "user2");
- failure2.incrementFailures();
- failure2.incrementFailures();
-
- resetSession();
-
- failure1 = session.sessions().getUserLoginFailure(realm, "user1");
- assertEquals(1, failure1.getNumFailures());
-
- failure2 = session.sessions().getUserLoginFailure(realm, "user2");
- assertEquals(2, failure2.getNumFailures());
-
- resetSession();
-
- failure1 = session.sessions().getUserLoginFailure(realm, "user1");
- failure1.clearFailures();
-
- resetSession();
-
- failure1 = session.sessions().getUserLoginFailure(realm, "user1");
- assertEquals(0, failure1.getNumFailures());
-
- session.sessions().removeUserLoginFailure(realm, "user1");
-
- resetSession();
-
- assertNull(session.sessions().getUserLoginFailure(realm, "user1"));
-
- session.sessions().removeAllUserLoginFailures(realm);
-
- resetSession();
-
- assertNull(session.sessions().getUserLoginFailure(realm, "user2"));
- }
-
- @Test
- public void testOnUserRemoved() {
- createSessions();
-
- session.sessions().addUserLoginFailure(realm, "user1");
- session.sessions().addUserLoginFailure(realm, "user1@localhost");
- session.sessions().addUserLoginFailure(realm, "user2");
-
- resetSession();
-
- UserModel user1 = session.users().getUserByUsername("user1", realm);
- new UserManager(session).removeUser(realm, user1);
-
- resetSession();
-
- assertTrue(session.sessions().getUserSessions(realm, user1).isEmpty());
- assertFalse(session.sessions().getUserSessions(realm, session.users().getUserByUsername("user2", realm)).isEmpty());
-
- assertNull(session.sessions().getUserLoginFailure(realm, "user1"));
- assertNull(session.sessions().getUserLoginFailure(realm, "user1@localhost"));
- assertNotNull(session.sessions().getUserLoginFailure(realm, "user2"));
- }
-
- private ClientSessionModel createClientSession(ClientModel client, UserSessionModel userSession, String redirect, String state, Set<String> roles, Set<String> protocolMappers) {
- ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
- if (userSession != null) clientSession.setUserSession(userSession);
- clientSession.setRedirectUri(redirect);
- if (state != null) clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, state);
- if (roles != null) clientSession.setRoles(roles);
- if (protocolMappers != null) clientSession.setProtocolMappers(protocolMappers);
- 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", roles, protocolMappers);
- createClientSession(realm.getClientByClientId("third-party"), sessions[0], "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
-
- 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", new HashSet<String>(), new HashSet<String>());
-
- 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", new HashSet<String>(), new HashSet<String>());
-
- resetSession();
-
- return sessions;
- }
-
- private void resetSession() {
- kc.stopSession(session, true);
- session = kc.startSession();
- realm = session.realms().getRealm("test");
- }
-
- public static void assertSessions(List<UserSessionModel> actualSessions, UserSessionModel... expectedSessions) {
- String[] expected = new String[expectedSessions.length];
- for (int i = 0; i < expected.length; i++) {
- expected[i] = expectedSessions[i].getId();
- }
-
- String[] actual = new String[actualSessions.size()];
- for (int i = 0; i < actual.length; i++) {
- actual[i] = actualSessions.get(i).getId();
- }
-
- Arrays.sort(expected);
- Arrays.sort(actual);
-
- assertArrayEquals(expected, actual);
- }
-
- 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());
- assertEquals(true, 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.getClientSessions().size()];
- for (int i = 0; i < actualClients.length; i++) {
- actualClients[i] = session.getClientSessions().get(i).getClient().getClientId();
- }
-
- Arrays.sort(clients);
- Arrays.sort(actualClients);
-
- assertArrayEquals(clients, actualClients);
- }
+ // TODO:mposolda
+//
+// @ClassRule
+// public static KeycloakRule kc = new KeycloakRule();
+//
+// private KeycloakSession session;
+// private RealmModel realm;
+//
+// @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");
+// }
+//
+// @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 testCreateSessions() {
+// int started = Time.currentTime();
+// UserSessionModel[] sessions = createSessions();
+//
+// assertSession(session.sessions().getUserSession(realm, sessions[0].getId()), session.users().getUserByUsername("user1", realm), "127.0.0.1", started, started, "test-app", "third-party");
+// assertSession(session.sessions().getUserSession(realm, sessions[1].getId()), session.users().getUserByUsername("user1", realm), "127.0.0.2", started, started, "test-app");
+// assertSession(session.sessions().getUserSession(realm, sessions[2].getId()), session.users().getUserByUsername("user2", realm), "127.0.0.3", started, started, "test-app");
+// }
+//
+// @Test
+// public void testUpdateSession() {
+// UserSessionModel[] sessions = createSessions();
+// session.sessions().getUserSession(realm, sessions[0].getId()).setLastSessionRefresh(1000);
+//
+// resetSession();
+//
+// assertEquals(1000, session.sessions().getUserSession(realm, sessions[0].getId()).getLastSessionRefresh());
+// }
+//
+// @Test
+// public void testCreateClientSession() {
+// UserSessionModel[] sessions = createSessions();
+//
+// List<ClientSessionModel> clientSessions = session.sessions().getUserSession(realm, sessions[0].getId()).getClientSessions();
+// assertEquals(2, clientSessions.size());
+//
+// String client1 = realm.getClientByClientId("test-app").getId();
+//
+// ClientSessionModel session1;
+//
+// if (clientSessions.get(0).getClient().getId().equals(client1)) {
+// session1 = clientSessions.get(0);
+// } else {
+// session1 = clientSessions.get(1);
+// }
+//
+// assertEquals(null, session1.getAction());
+// assertEquals(realm.getClientByClientId("test-app").getClientId(), session1.getClient().getClientId());
+// assertEquals(sessions[0].getId(), session1.getUserSession().getId());
+// assertEquals("http://redirect", session1.getRedirectUri());
+// assertEquals("state", session1.getNote(OIDCLoginProtocol.STATE_PARAM));
+// assertEquals(2, session1.getRoles().size());
+// assertTrue(session1.getRoles().contains("one"));
+// assertTrue(session1.getRoles().contains("two"));
+// assertEquals(2, session1.getProtocolMappers().size());
+// assertTrue(session1.getProtocolMappers().contains("mapper-one"));
+// assertTrue(session1.getProtocolMappers().contains("mapper-two"));
+// }
+//
+// @Test
+// public void testUpdateClientSession() {
+// UserSessionModel[] sessions = createSessions();
+//
+// String id = sessions[0].getClientSessions().get(0).getId();
+//
+// ClientSessionModel clientSession = session.sessions().getClientSession(realm, id);
+//
+// int time = clientSession.getTimestamp();
+// assertEquals(null, clientSession.getAction());
+//
+// clientSession.setAction(ClientSessionModel.Action.CODE_TO_TOKEN.name());
+// clientSession.setTimestamp(time + 10);
+//
+// kc.stopSession(session, true);
+// session = kc.startSession();
+//
+// ClientSessionModel updated = session.sessions().getClientSession(realm, id);
+// assertEquals(ClientSessionModel.Action.CODE_TO_TOKEN.name(), updated.getAction());
+// assertEquals(time + 10, updated.getTimestamp());
+// }
+//
+// @Test
+// public void testGetUserSessions() {
+// UserSessionModel[] sessions = createSessions();
+//
+// assertSessions(session.sessions().getUserSessions(realm, session.users().getUserByUsername("user1", realm)), sessions[0], sessions[1]);
+// assertSessions(session.sessions().getUserSessions(realm, session.users().getUserByUsername("user2", realm)), sessions[2]);
+// }
+//
+// @Test
+// public void testRemoveUserSessionsByUser() {
+// UserSessionModel[] sessions = createSessions();
+//
+// List<String> clientSessionsRemoved = new LinkedList<String>();
+// List<String> clientSessionsKept = new LinkedList<String>();
+// for (UserSessionModel s : sessions) {
+// s = session.sessions().getUserSession(realm, s.getId());
+//
+// for (ClientSessionModel c : s.getClientSessions()) {
+// if (c.getUserSession().getUser().getUsername().equals("user1")) {
+// clientSessionsRemoved.add(c.getId());
+// } else {
+// clientSessionsKept.add(c.getId());
+// }
+// }
+// }
+//
+// session.sessions().removeUserSessions(realm, session.users().getUserByUsername("user1", realm));
+// resetSession();
+//
+// assertTrue(session.sessions().getUserSessions(realm, session.users().getUserByUsername("user1", realm)).isEmpty());
+// assertFalse(session.sessions().getUserSessions(realm, session.users().getUserByUsername("user2", realm)).isEmpty());
+//
+// for (String c : clientSessionsRemoved) {
+// assertNull(session.sessions().getClientSession(realm, c));
+// }
+// for (String c : clientSessionsKept) {
+// assertNotNull(session.sessions().getClientSession(realm, c));
+// }
+// }
+//
+// @Test
+// public void testRemoveUserSession() {
+// UserSessionModel userSession = createSessions()[0];
+//
+// List<String> clientSessionsRemoved = new LinkedList<String>();
+// for (ClientSessionModel c : userSession.getClientSessions()) {
+// clientSessionsRemoved.add(c.getId());
+// }
+//
+// session.sessions().removeUserSession(realm, userSession);
+// resetSession();
+//
+// assertNull(session.sessions().getUserSession(realm, userSession.getId()));
+// for (String c : clientSessionsRemoved) {
+// assertNull(session.sessions().getClientSession(realm, c));
+// }
+// }
+//
+// @Test
+// public void testRemoveUserSessionsByRealm() {
+// UserSessionModel[] sessions = createSessions();
+//
+// List<ClientSessionModel> clientSessions = new LinkedList<ClientSessionModel>();
+// for (UserSessionModel s : sessions) {
+// clientSessions.addAll(s.getClientSessions());
+// }
+//
+// session.sessions().removeUserSessions(realm);
+// resetSession();
+//
+// assertTrue(session.sessions().getUserSessions(realm, session.users().getUserByUsername("user1", realm)).isEmpty());
+// assertTrue(session.sessions().getUserSessions(realm, session.users().getUserByUsername("user2", realm)).isEmpty());
+//
+// for (ClientSessionModel c : clientSessions) {
+// assertNull(session.sessions().getClientSession(realm, c.getId()));
+// }
+// }
+//
+// @Test
+// public void testOnClientRemoved() {
+// UserSessionModel[] sessions = createSessions();
+//
+// List<String> clientSessionsRemoved = new LinkedList<String>();
+// List<String> clientSessionsKept = new LinkedList<String>();
+// for (UserSessionModel s : sessions) {
+// s = session.sessions().getUserSession(realm, s.getId());
+// for (ClientSessionModel c : s.getClientSessions()) {
+// if (c.getClient().getClientId().equals("third-party")) {
+// clientSessionsRemoved.add(c.getId());
+// } else {
+// clientSessionsKept.add(c.getId());
+// }
+// }
+// }
+//
+// session.sessions().onClientRemoved(realm, realm.getClientByClientId("third-party"));
+// resetSession();
+//
+// for (String c : clientSessionsRemoved) {
+// assertNull(session.sessions().getClientSession(realm, c));
+// }
+// for (String c : clientSessionsKept) {
+// assertNotNull(session.sessions().getClientSession(realm, c));
+// }
+//
+// session.sessions().onClientRemoved(realm, realm.getClientByClientId("test-app"));
+// resetSession();
+//
+// for (String c : clientSessionsRemoved) {
+// assertNull(session.sessions().getClientSession(realm, c));
+// }
+// for (String c : clientSessionsKept) {
+// assertNull(session.sessions().getClientSession(realm, c));
+// }
+// }
+//
+// @Test
+// public void testRemoveUserSessionsByExpired() {
+// session.sessions().getUserSessions(realm, session.users().getUserByUsername("user1", realm));
+// ClientModel client = realm.getClientByClientId("test-app");
+//
+// try {
+// Set<String> expired = new HashSet<String>();
+// Set<String> expiredClientSessions = new HashSet<String>();
+//
+// Time.setOffset(-(realm.getSsoSessionMaxLifespan() + 1));
+// expired.add(session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "user1", "127.0.0.1", "form", true, null, null).getId());
+// expiredClientSessions.add(session.sessions().createClientSession(realm, client).getId());
+//
+// Time.setOffset(0);
+// UserSessionModel s = session.sessions().createUserSession(realm, session.users().getUserByUsername("user2", realm), "user2", "127.0.0.1", "form", true, null, null);
+// //s.setLastSessionRefresh(Time.currentTime() - (realm.getSsoSessionIdleTimeout() + 1));
+// s.setLastSessionRefresh(0);
+// expired.add(s.getId());
+//
+// ClientSessionModel clSession = session.sessions().createClientSession(realm, client);
+// clSession.setUserSession(s);
+// expiredClientSessions.add(clSession.getId());
+//
+// Set<String> valid = new HashSet<String>();
+// Set<String> validClientSessions = new HashSet<String>();
+//
+// valid.add(session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "user1", "127.0.0.1", "form", true, null, null).getId());
+// validClientSessions.add(session.sessions().createClientSession(realm, client).getId());
+//
+// resetSession();
+//
+// session.sessions().removeExpired(realm);
+// resetSession();
+//
+// for (String e : expired) {
+// assertNull(session.sessions().getUserSession(realm, e));
+// }
+// for (String e : expiredClientSessions) {
+// assertNull(session.sessions().getClientSession(realm, e));
+// }
+//
+// for (String v : valid) {
+// assertNotNull(session.sessions().getUserSession(realm, v));
+// }
+// for (String e : validClientSessions) {
+// assertNotNull(session.sessions().getClientSession(realm, e));
+// }
+// } finally {
+// Time.setOffset(0);
+// }
+// }
+//
+// @Test
+// public void testExpireDetachedClientSessions() {
+// try {
+// realm.setAccessCodeLifespan(10);
+// realm.setAccessCodeLifespanUserAction(10);
+// realm.setAccessCodeLifespanLogin(30);
+//
+// // Login lifespan is largest
+// String clientSessionId = session.sessions().createClientSession(realm, realm.getClientByClientId("test-app")).getId();
+// resetSession();
+//
+// Time.setOffset(25);
+// session.sessions().removeExpired(realm);
+// resetSession();
+//
+// assertNotNull(session.sessions().getClientSession(clientSessionId));
+//
+// Time.setOffset(35);
+// session.sessions().removeExpired(realm);
+// resetSession();
+//
+// assertNull(session.sessions().getClientSession(clientSessionId));
+//
+// // User action is largest
+// realm.setAccessCodeLifespanUserAction(40);
+//
+// Time.setOffset(0);
+// clientSessionId = session.sessions().createClientSession(realm, realm.getClientByClientId("test-app")).getId();
+// resetSession();
+//
+// Time.setOffset(35);
+// session.sessions().removeExpired(realm);
+// resetSession();
+//
+// assertNotNull(session.sessions().getClientSession(clientSessionId));
+//
+// Time.setOffset(45);
+// session.sessions().removeExpired(realm);
+// resetSession();
+//
+// assertNull(session.sessions().getClientSession(clientSessionId));
+//
+// // Access code is largest
+// realm.setAccessCodeLifespan(50);
+//
+// Time.setOffset(0);
+// clientSessionId = session.sessions().createClientSession(realm, realm.getClientByClientId("test-app")).getId();
+// resetSession();
+//
+// Time.setOffset(45);
+// session.sessions().removeExpired(realm);
+// resetSession();
+//
+// assertNotNull(session.sessions().getClientSession(clientSessionId));
+//
+// Time.setOffset(55);
+// session.sessions().removeExpired(realm);
+// resetSession();
+//
+// assertNull(session.sessions().getClientSession(clientSessionId));
+// } finally {
+// Time.setOffset(0);
+//
+// realm.setAccessCodeLifespan(60);
+// realm.setAccessCodeLifespanUserAction(300);
+// realm.setAccessCodeLifespanLogin(1800);
+//
+// }
+// }
+//
+// // KEYCLOAK-2508
+// @Test
+// public void testRemovingExpiredSession() {
+// UserSessionModel[] sessions = createSessions();
+// try {
+// Time.setOffset(3600000);
+// UserSessionModel userSession = sessions[0];
+// RealmModel realm = userSession.getRealm();
+// session.sessions().removeExpired(realm);
+//
+// resetSession();
+//
+// // Assert no exception is thrown here
+// session.sessions().removeUserSession(realm, userSession);
+// } finally {
+// Time.setOffset(0);
+// }
+// }
+//
+// @Test
+// public void testGetByClient() {
+// UserSessionModel[] sessions = createSessions();
+//
+// assertSessions(session.sessions().getUserSessions(realm, realm.getClientByClientId("test-app")), sessions[0], sessions[1], sessions[2]);
+// assertSessions(session.sessions().getUserSessions(realm, realm.getClientByClientId("third-party")), sessions[0]);
+// }
+//
+// @Test
+// public void testGetByClientPaginated() {
+// try {
+// for (int i = 0; i < 25; i++) {
+// Time.setOffset(i);
+// UserSessionModel userSession = session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "user1", "127.0.0." + i, "form", false, null, null);
+// ClientSessionModel clientSession = session.sessions().createClientSession(realm, realm.getClientByClientId("test-app"));
+// clientSession.setUserSession(userSession);
+// clientSession.setRedirectUri("http://redirect");
+// clientSession.setRoles(new HashSet<String>());
+// clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, "state");
+// clientSession.setTimestamp(userSession.getStarted());
+// }
+// } finally {
+// Time.setOffset(0);
+// }
+//
+// resetSession();
+//
+// assertPaginatedSession(realm, realm.getClientByClientId("test-app"), 0, 1, 1);
+// assertPaginatedSession(realm, realm.getClientByClientId("test-app"), 0, 10, 10);
+// assertPaginatedSession(realm, realm.getClientByClientId("test-app"), 10, 10, 10);
+// assertPaginatedSession(realm, realm.getClientByClientId("test-app"), 20, 10, 5);
+// assertPaginatedSession(realm, realm.getClientByClientId("test-app"), 30, 10, 0);
+// }
+//
+// @Test
+// public void testCreateAndGetInSameTransaction() {
+// UserSessionModel userSession = session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "user1", "127.0.0.2", "form", true, null, null);
+// ClientSessionModel clientSession = createClientSession(realm.getClientByClientId("test-app"), userSession, "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
+//
+// Assert.assertNotNull(session.sessions().getUserSession(realm, userSession.getId()));
+// Assert.assertNotNull(session.sessions().getClientSession(realm, clientSession.getId()));
+//
+// Assert.assertEquals(userSession.getId(), clientSession.getUserSession().getId());
+// Assert.assertEquals(1, userSession.getClientSessions().size());
+// Assert.assertEquals(clientSession.getId(), userSession.getClientSessions().get(0).getId());
+// }
+//
+// private void assertPaginatedSession(RealmModel realm, ClientModel client, int start, int max, int expectedSize) {
+// List<UserSessionModel> sessions = session.sessions().getUserSessions(realm, client, start, max);
+// String[] actualIps = new String[sessions.size()];
+// for (int i = 0; i < actualIps.length; i++) {
+// actualIps[i] = sessions.get(i).getIpAddress();
+// }
+//
+// String[] expectedIps = new String[expectedSize];
+// for (int i = 0; i < expectedSize; i++) {
+// expectedIps[i] = "127.0.0." + (i + start);
+// }
+//
+// assertArrayEquals(expectedIps, actualIps);
+// }
+//
+// @Test
+// public void testGetCountByClient() {
+// createSessions();
+//
+// assertEquals(3, session.sessions().getActiveUserSessions(realm, realm.getClientByClientId("test-app")));
+// assertEquals(1, session.sessions().getActiveUserSessions(realm, realm.getClientByClientId("third-party")));
+// }
+//
+// @Test
+// public void loginFailures() {
+// UserLoginFailureModel failure1 = session.sessions().addUserLoginFailure(realm, "user1");
+// failure1.incrementFailures();
+//
+// UserLoginFailureModel failure2 = session.sessions().addUserLoginFailure(realm, "user2");
+// failure2.incrementFailures();
+// failure2.incrementFailures();
+//
+// resetSession();
+//
+// failure1 = session.sessions().getUserLoginFailure(realm, "user1");
+// assertEquals(1, failure1.getNumFailures());
+//
+// failure2 = session.sessions().getUserLoginFailure(realm, "user2");
+// assertEquals(2, failure2.getNumFailures());
+//
+// resetSession();
+//
+// failure1 = session.sessions().getUserLoginFailure(realm, "user1");
+// failure1.clearFailures();
+//
+// resetSession();
+//
+// failure1 = session.sessions().getUserLoginFailure(realm, "user1");
+// assertEquals(0, failure1.getNumFailures());
+//
+// session.sessions().removeUserLoginFailure(realm, "user1");
+//
+// resetSession();
+//
+// assertNull(session.sessions().getUserLoginFailure(realm, "user1"));
+//
+// session.sessions().removeAllUserLoginFailures(realm);
+//
+// resetSession();
+//
+// assertNull(session.sessions().getUserLoginFailure(realm, "user2"));
+// }
+//
+// @Test
+// public void testOnUserRemoved() {
+// createSessions();
+//
+// session.sessions().addUserLoginFailure(realm, "user1");
+// session.sessions().addUserLoginFailure(realm, "user1@localhost");
+// session.sessions().addUserLoginFailure(realm, "user2");
+//
+// resetSession();
+//
+// UserModel user1 = session.users().getUserByUsername("user1", realm);
+// new UserManager(session).removeUser(realm, user1);
+//
+// resetSession();
+//
+// assertTrue(session.sessions().getUserSessions(realm, user1).isEmpty());
+// assertFalse(session.sessions().getUserSessions(realm, session.users().getUserByUsername("user2", realm)).isEmpty());
+//
+// assertNull(session.sessions().getUserLoginFailure(realm, "user1"));
+// assertNull(session.sessions().getUserLoginFailure(realm, "user1@localhost"));
+// assertNotNull(session.sessions().getUserLoginFailure(realm, "user2"));
+// }
+//
+// private ClientSessionModel createClientSession(ClientModel client, UserSessionModel userSession, String redirect, String state, Set<String> roles, Set<String> protocolMappers) {
+// ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
+// if (userSession != null) clientSession.setUserSession(userSession);
+// clientSession.setRedirectUri(redirect);
+// if (state != null) clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, state);
+// if (roles != null) clientSession.setRoles(roles);
+// if (protocolMappers != null) clientSession.setProtocolMappers(protocolMappers);
+// 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", roles, protocolMappers);
+// createClientSession(realm.getClientByClientId("third-party"), sessions[0], "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
+//
+// 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", new HashSet<String>(), new HashSet<String>());
+//
+// 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", new HashSet<String>(), new HashSet<String>());
+//
+// resetSession();
+//
+// return sessions;
+// }
+//
+// private void resetSession() {
+// kc.stopSession(session, true);
+// session = kc.startSession();
+// realm = session.realms().getRealm("test");
+// }
+//
+// public static void assertSessions(List<UserSessionModel> actualSessions, UserSessionModel... expectedSessions) {
+// String[] expected = new String[expectedSessions.length];
+// for (int i = 0; i < expected.length; i++) {
+// expected[i] = expectedSessions[i].getId();
+// }
+//
+// String[] actual = new String[actualSessions.size()];
+// for (int i = 0; i < actual.length; i++) {
+// actual[i] = actualSessions.get(i).getId();
+// }
+//
+// Arrays.sort(expected);
+// Arrays.sort(actual);
+//
+// assertArrayEquals(expected, actual);
+// }
+//
+// 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());
+// assertEquals(true, 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.getClientSessions().size()];
+// for (int i = 0; i < actualClients.length; i++) {
+// actualClients[i] = session.getClientSessions().get(i).getClient().getClientId();
+// }
+//
+// Arrays.sort(clients);
+// Arrays.sort(actualClients);
+//
+// assertArrayEquals(clients, actualClients);
+// }
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/KeycloakRule.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/KeycloakRule.java
index 050bcf3..9c61e05 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/KeycloakRule.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/KeycloakRule.java
@@ -90,24 +90,6 @@ public class KeycloakRule extends AbstractKeycloakRule {
stopSession(session, true);
}
- public ClientSessionCode verifyCode(String code) {
- KeycloakSession session = startSession();
- try {
- RealmModel realm = session.realms().getRealm("test");
- try {
- ClientSessionCode accessCode = ClientSessionCode.parse(code, session, realm);
- if (accessCode == null) {
- Assert.fail("Invalid code");
- }
- return accessCode;
- } catch (Throwable t) {
- throw new AssertionError("Failed to parse code", t);
- }
- } finally {
- stopSession(session, false);
- }
- }
-
public abstract static class KeycloakSetup {
protected KeycloakSession session;
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/util/cli/PersistSessionsCommand.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/util/cli/PersistSessionsCommand.java
index b2ede3e..39b4d48 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/util/cli/PersistSessionsCommand.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/util/cli/PersistSessionsCommand.java
@@ -65,8 +65,9 @@ public class PersistSessionsCommand extends AbstractCommand {
});
}
+ // TODO:mposolda
private void createSessionsBatch(final int countInThisBatch) {
- final List<String> userSessionIds = new LinkedList<>();
+ /*final List<String> userSessionIds = new LinkedList<>();
final List<String> clientSessionIds = new LinkedList<>();
KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
@@ -120,7 +121,7 @@ public class PersistSessionsCommand extends AbstractCommand {
log.infof("%d client sessions persisted. Continue", counter);
}
- });
+ });*/
}
@Override
diff --git a/testsuite/integration/src/test/resources/log4j.properties b/testsuite/integration/src/test/resources/log4j.properties
index cac26ae..decc0aa 100755
--- a/testsuite/integration/src/test/resources/log4j.properties
+++ b/testsuite/integration/src/test/resources/log4j.properties
@@ -80,4 +80,7 @@ log4j.logger.org.apache.directory.server.ldap.LdapProtocolHandler=error
#log4j.logger.org.apache.http.impl.conn=debug
# Enable to view details from identity provider authenticator
-# log4j.logger.org.keycloak.authentication.authenticators.browser.IdentityProviderAuthenticator=trace
\ No newline at end of file
+# log4j.logger.org.keycloak.authentication.authenticators.browser.IdentityProviderAuthenticator=trace
+
+# TODO: Remove
+log4j.logger.org.keycloak.models.sessions.infinispan.InfinispanUserSessionProvider=debug
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/forms/PassThroughRegistration.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/forms/PassThroughRegistration.java
index 27de40e..b600c14 100755
--- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/forms/PassThroughRegistration.java
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/forms/PassThroughRegistration.java
@@ -52,15 +52,15 @@ public class PassThroughRegistration implements Authenticator, AuthenticatorFact
user.setEnabled(true);
user.setEmail(email);
- context.getClientSession().setNote(OIDCLoginProtocol.LOGIN_HINT_PARAM, username);
+ context.getLoginSession().setNote(OIDCLoginProtocol.LOGIN_HINT_PARAM, username);
context.setUser(user);
context.getEvent().user(user);
context.getEvent().success();
context.newEvent().event(EventType.LOGIN);
- context.getEvent().client(context.getClientSession().getClient().getClientId())
- .detail(Details.REDIRECT_URI, context.getClientSession().getRedirectUri())
- .detail(Details.AUTH_METHOD, context.getClientSession().getAuthMethod());
- String authType = context.getClientSession().getNote(Details.AUTH_TYPE);
+ context.getEvent().client(context.getLoginSession().getClient().getClientId())
+ .detail(Details.REDIRECT_URI, context.getLoginSession().getRedirectUri())
+ .detail(Details.AUTH_METHOD, context.getLoginSession().getProtocol());
+ String authType = context.getLoginSession().getNote(Details.AUTH_TYPE);
if (authType != null) {
context.getEvent().detail(Details.AUTH_TYPE, authType);
}