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 c67a576250..8abf19b2bb 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/InfinispanKeycloakTransaction.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanKeycloakTransaction.java
new file mode 100644
index 0000000000..c6b30f41cf
--- /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 Stian Thorgersen
+ */
+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 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 void put(Cache 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 void replace(Cache 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 void remove(Cache 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 V get(Cache cache, K 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 static Object getTaskKey(Cache cache, K key) {
+ if (key instanceof String) {
+ return new StringBuilder(cache.getName())
+ .append("::")
+ .append(key).toString();
+ } else {
+ return key;
+ }
+ }
+
+ public static class CacheTask {
+ private final Cache cache;
+ private final CacheOperation operation;
+ private final K key;
+ private V value;
+
+ public CacheTask(Cache 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 a7c8c31ec4..7fa9f81337 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 getOfflineClientSessions(RealmModel realm, UserModel user) {
+ public List getOfflineUserSessions(RealmModel realm, UserModel user) {
Iterator> itr = offlineSessionCache.entrySet().stream().filter(UserSessionPredicate.create(realm.getId()).user(user.getId())).iterator();
- List clientSessions = new LinkedList<>();
+ List userSessions = new LinkedList<>();
while(itr.hasNext()) {
UserSessionEntity entity = (UserSessionEntity) itr.next().getValue();
- Set 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 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 bf1e6fd391..6c81313c74 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 getClientLoginSessions() {
+ return null;
+ }
+
public String getId() {
return entity.getId();
}
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 0cbdc79d9b..6bce9e9287 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/sessions/infinispan/InfinispanLoginSessionProvider.java b/model/infinispan/src/main/java/org/keycloak/sessions/infinispan/InfinispanLoginSessionProvider.java
new file mode 100644
index 0000000000..8389424c3c
--- /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 Marek Posolda
+ */
+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 0000000000..e8dda52e63
--- /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 Marek Posolda
+ */
+public class LoginSessionAdapter implements LoginSessionModel {
+
+ private KeycloakSession session;
+ private InfinispanLoginSessionProvider provider;
+ private Cache cache;
+ private RealmModel realm;
+ private LoginSessionEntity entity;
+
+ public LoginSessionAdapter(KeycloakSession session, InfinispanLoginSessionProvider provider, Cache 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 getRoles() {
+ if (entity.getRoles() == null || entity.getRoles().isEmpty()) return Collections.emptySet();
+ return new HashSet<>(entity.getRoles());
+ }
+
+ @Override
+ public void setRoles(Set roles) {
+ entity.setRoles(roles);
+ }
+
+ @Override
+ public Set getProtocolMappers() {
+ if (entity.getProtocolMappers() == null || entity.getProtocolMappers().isEmpty()) return Collections.emptySet();
+ return new HashSet<>(entity.getProtocolMappers());
+ }
+
+ @Override
+ public void setProtocolMappers(Set 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());
+ }
+ entity.getNotes().put(name, value);
+ }
+
+ @Override
+ public void removeNote(String name) {
+ if (entity.getNotes() != null) {
+ entity.getNotes().remove(name);
+ }
+ }
+
+ @Override
+ public Map getNotes() {
+ if (entity.getNotes() == null || entity.getNotes().isEmpty()) return Collections.emptyMap();
+ Map 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());
+ }
+ entity.getUserSessionNotes().put(name, value);
+
+ }
+
+ @Override
+ public Map getUserSessionNotes() {
+ if (entity.getUserSessionNotes() == null) {
+ return Collections.EMPTY_MAP;
+ }
+ HashMap copy = new HashMap<>();
+ copy.putAll(entity.getUserSessionNotes());
+ return copy;
+ }
+
+ @Override
+ public void clearUserSessionNotes() {
+ entity.setUserSessionNotes(new HashMap());
+
+ }
+
+ @Override
+ public Set getRequiredActions() {
+ Set 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 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 0000000000..97ccad4bfc
--- /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 Marek Posolda
+ */
+public class LoginSessionEntity extends SessionEntity {
+
+ private String clientUuid;
+ private String authUserId;
+
+ private String redirectUri;
+ private int timestamp;
+ private String action;
+ private Set roles;
+ private Set protocolMappers;
+
+ private Map executionStatus;
+ private String protocol;
+
+ private Map notes;
+ private Set requiredActions;
+ private Map 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 getRoles() {
+ return roles;
+ }
+
+ public void setRoles(Set roles) {
+ this.roles = roles;
+ }
+
+ public Set getProtocolMappers() {
+ return protocolMappers;
+ }
+
+ public void setProtocolMappers(Set protocolMappers) {
+ this.protocolMappers = protocolMappers;
+ }
+
+ public Map getExecutionStatus() {
+ return executionStatus;
+ }
+
+ public void setExecutionStatus(Map executionStatus) {
+ this.executionStatus = executionStatus;
+ }
+
+ public String getProtocol() {
+ return protocol;
+ }
+
+ public void setProtocol(String protocol) {
+ this.protocol = protocol;
+ }
+
+ public Map getNotes() {
+ return notes;
+ }
+
+ public void setNotes(Map notes) {
+ this.notes = notes;
+ }
+
+ public Set getRequiredActions() {
+ return requiredActions;
+ }
+
+ public void setRequiredActions(Set requiredActions) {
+ this.requiredActions = requiredActions;
+ }
+
+ public Map getUserSessionNotes() {
+ return userSessionNotes;
+ }
+
+ public void setUserSessionNotes(Map 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 b3aea63f55..e842948493 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 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-private/src/main/java/org/keycloak/authentication/AuthenticationFlowContext.java b/server-spi-private/src/main/java/org/keycloak/authentication/AuthenticationFlowContext.java
index 98632fbe3c..80c7575c0b 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 7c7d143f13..b131c2021b 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 3ece79e5f4..df0bc66c03 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 f2c8a7aad7..bcce1b880f 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 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 f16f0c2165..a379e9df13 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 realmRolesRequested, MultivaluedMap resourceRolesRequested, List 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 f5e58d33bf..c860ea3090 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 f842787a2c..7194382bb8 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 Marek Posolda
*/
-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 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 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());
- }
- entity.getUserSessionNotes().put(name, value);
- }
-
- @Override
- public Map 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());
- }
@Override
public boolean equals(Object o) {
@@ -320,18 +248,9 @@ public class PersistentClientSessionAdapter implements ClientSessionModel {
@JsonProperty("notes")
private Map notes;
- @JsonProperty("userSessionNotes")
- private Map userSessionNotes;
-
- @JsonProperty("executionStatus")
- private Map executionStatus = new HashMap<>();
-
@JsonProperty("action")
private String action;
- @JsonProperty("requiredActions")
- private Set requiredActions = new HashSet<>();
-
public String getAuthMethod() {
return authMethod;
}
@@ -372,22 +291,6 @@ public class PersistentClientSessionAdapter implements ClientSessionModel {
this.notes = notes;
}
- public Map getUserSessionNotes() {
- return userSessionNotes;
- }
-
- public void setUserSessionNotes(Map userSessionNotes) {
- this.userSessionNotes = userSessionNotes;
- }
-
- public Map getExecutionStatus() {
- return executionStatus;
- }
-
- public void setExecutionStatus(Map executionStatus) {
- this.executionStatus = executionStatus;
- }
-
public String getAction() {
return action;
}
@@ -396,12 +299,5 @@ public class PersistentClientSessionAdapter implements ClientSessionModel {
this.action = action;
}
- public Set getRequiredActions() {
- return requiredActions;
- }
-
- public void setRequiredActions(Set 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 6047be29ea..882dd539d0 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 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 c0d033acb0..cbaf31eb30 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 e90192963f..3ebe6d3396 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 086a8edc48..015ead0fa3 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 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 3d536ddf05..4096924bed 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 Bill Burke
* @version $Revision: 1 $
*/
-public class ClientSessionCode {
+public class ClientSessionCode {
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 {
+ ClientSessionCode code;
+ boolean loginSessionNotFound;
boolean illegalHash;
- ClientSessionModel clientSession;
+ CLIENT_SESSION clientSession;
- public ClientSessionCode getCode() {
+ public ClientSessionCode 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 ParseResult parseResult(String code, KeycloakSession session, RealmModel realm, Class sessionClass) {
+ ParseResult 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(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 ClientSessionCode parse(String code, KeycloakSession session, RealmModel realm, Class 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 getClientSession(String code, KeycloakSession session, RealmModel realm, Class 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 getRequestedRoles() {
Set 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 getRequestedProtocolMappers() {
+ return getRequestedProtocolMappers(commonLoginSession.getProtocolMappers(), commonLoginSession.getClient());
+ }
+
+ public static Set getRequestedProtocolMappers(Set protocolMappers, ClientModel client) {
Set requestedProtocolMappers = new HashSet<>();
- Set 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 0000000000..9c6a571be2
--- /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 Marek Posolda
+ */
+class CodeGenerateUtil {
+
+ static CS parseSession(String code, KeycloakSession session, RealmModel realm, Class 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 0000000000..0dfbf8740f
--- /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 Marek Posolda
+ */
+public interface LoginSessionProviderFactory extends ProviderFactory {
+}
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 0000000000..cffa4c5023
--- /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 Marek Posolda
+ */
+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 9397536ea6..f858ea1ef9 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/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 0000000000..80d7c8dcfd
--- /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 Marek Posolda
+ */
+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 84fa64e1c1..109709fa58 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 Stian Thorgersen
*/
-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 getRoles();
- public void setRoles(Set roles);
-
- public Set getProtocolMappers();
- public void setProtocolMappers(Set protocolMappers);
-
public Map 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 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 766078d769..1494126624 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 d58c40522c..99f69f7616 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 getClientLoginSessions();
+
+ // TODO: Remove
List 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 4102de1f32..fbd5761cfb 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 getOfflineClientSessions(RealmModel realm, UserModel user);
+ List 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 0000000000..c2e51935a3
--- /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 Marek Posolda
+ */
+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 getRoles();
+ public void setRoles(Set roles);
+
+ // TODO: Not needed here...?
+ public Set getProtocolMappers();
+ public void setProtocolMappers(Set protocolMappers);
+
+ public String getNote(String name);
+ public void setNote(String name, String value);
+ public void removeNote(String name);
+ public Map 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 0000000000..e3fd0e726c
--- /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 Marek Posolda
+ */
+public interface LoginSessionModel extends CommonClientSessionModel {
+
+//
+// public UserSessionModel getUserSession();
+// public void setUserSession(UserSessionModel userSession);
+
+
+ public Map 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 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 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 0000000000..2b5141a68b
--- /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 Marek Posolda
+ */
+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/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
index a34e4ee914..4a5053fddf 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 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 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 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 executions) {
diff --git a/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java b/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java
index 40433cfee7..d87301f81f 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 59c85fb74a..b1d29f18a6 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 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 formData, List 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/RequiredActionContextResult.java b/services/src/main/java/org/keycloak/authentication/RequiredActionContextResult.java
index 8f830d1e40..fd60a9d10e 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 accessCode = new ClientSessionCode<>(session, getRealm(), getLoginSession());
+ loginSession.setTimestamp(Time.currentTime());
return accessCode.getCode();
}
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 87108da0a3..fd65f61eb9 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 82347004c6..0b848723df 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 317cb64873..f905e0cc2a 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 420eb20924..27a30e8647 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 queryParams = context.getSession().getContext().getUri().getQueryParameters();
+ /*MultivaluedMap 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 c58e3e16c5..edd3c62200 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 cd09c37159..071a1ec410 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 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 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 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 1e404621c7..86bb9795a7 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 f837d3ca51..fc73e1875a 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 b4552af50f..d1c22f543d 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 Bill Burke
@@ -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 f8408a4ecc..8cfd714c65 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 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 0b400f07ac..1a90b59ff5 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 8bfb995316..c909921641 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 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 4f8e2d1948..cde0cb3ad4 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 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 da7a67f1f7..409618f318 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 46097a022f..9604504891 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 0d41b062c6..e74fa20882 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 40c703b988..7dcf8293f0 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 64098fa379..9c0fdab7cd 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/forms/RegistrationUserCreation.java b/services/src/main/java/org/keycloak/authentication/forms/RegistrationUserCreation.java
index 90dee70808..ddb42be050 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/requiredactions/UpdatePassword.java b/services/src/main/java/org/keycloak/authentication/requiredactions/UpdatePassword.java
index aa5bf25db5..9984e823ae 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 2d683d3afa..e45ddcb657 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 2e82794927..88d859420b 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 Pedro Igor
@@ -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 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 e46798cd0c..8409206b04 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 9f60404077..b1c087207f 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 Stian Thorgersen
@@ -106,7 +102,7 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
private UserModel user;
- private ClientSessionModel clientSession;
+ private LoginSessionModel loginSession;
private final Map attributes = new HashMap();
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 556db25a47..bf424cb80d 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 claimsRequested;
- public OAuthGrantBean(String code, ClientSessionModel clientSession, ClientModel client, List realmRolesRequested, MultivaluedMap resourceRolesRequested,
+ public OAuthGrantBean(String code, ClientModel client, List realmRolesRequested, MultivaluedMap resourceRolesRequested,
List 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 0c1462c787..f0387e8055 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/RestartLoginCookie.java b/services/src/main/java/org/keycloak/protocol/RestartLoginCookie.java
index 51bdd81034..4fda88959f 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 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/oidc/OIDCLoginProtocol.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
index 4c0691a974..5dd0433a9a 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 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 4cedd6bd98..49a47a1c2d 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 requestedRoles, RealmModel realm, ClientModel client, UserModel user, UserSessionModel userSession, ClientSessionModel clientSession) {
+ public AccessToken createClientAccessToken(KeycloakSession session, Set 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 requestedRoles = new HashSet();
// 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 transferredNotes = clientSession.getUserSessionNotes();
+ Map transferredNotes = loginSession.getNotes();
for (Map.Entry entry : transferredNotes.entrySet()) {
- session.setNote(entry.getKey(), entry.getValue());
+ clientSession.setNote(entry.getKey(), entry.getValue());
}
+ Map transferredUserSessionNotes = loginSession.getUserSessionNotes();
+ for (Map.Entry 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 mappings = new ClientSessionCode(session, realm, clientSession).getRequestedProtocolMappers();
+ UserSessionModel userSession, ClientLoginSessionModel clientSession) {
+ Set 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 mappings = new ClientSessionCode(session, realm, clientSession).getRequestedProtocolMappers();
+ UserSessionModel userSession, ClientLoginSessionModel clientSession) {
+ Set 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 mappings = new ClientSessionCode(session, realm, clientSession).getRequestedProtocolMappers();
+ UserSessionModel userSession, ClientLoginSessionModel clientSession) {
+ Set 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/oidc/endpoints/AuthorizationEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
index 1588321f31..3a41f92daa 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()));
+ 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) 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());
+ 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 8fa4341344..e308bc9f51 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 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 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 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();
+ 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);
- 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);
-
- 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 8984a4db56..763da1e38c 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 efe9434b84..d43934370c 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 4666034705..4b8b1f3a47 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 1e4ad9df09..1e9b3e251f 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 41dbb47db9..b733f5c1e1 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 40628245dd..8d48ccf47d 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 03ecb91eb6..7ebb435695 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 71dce26829..387ef5c79b 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 dabc4a35cd..ca80ed5113 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 fcdc373904..c91040054f 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 e6d0d209f5..9b2cf0f24a 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 67ac1a2797..af5084c5f6 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 6fd649199d..2fc84ff1e9 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 fd6bfe1c68..aadee6c9db 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/saml/SamlProtocol.java b/services/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
index 20d86c0404..04da54a76e 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 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> attributeStatementMappers, KeycloakSession session, UserSessionModel userSession,
- ClientSessionModel clientSession) {
+ ClientLoginSessionModel clientSession) {
AttributeStatementType attributeStatement = new AttributeStatementType();
for (ProtocolMapperProcessor 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> mappers, ResponseType response, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+ public ResponseType transformLoginResponse(List> mappers, ResponseType response, KeycloakSession session, UserSessionModel userSession, ClientLoginSessionModel clientSession) {
for (ProtocolMapperProcessor processor : mappers) {
response = processor.mapper.transformLoginResponse(response, processor.model, session, userSession, clientSession);
}
return response;
}
- public void populateRoles(ProtocolMapperProcessor roleListMapper, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession,
+ public void populateRoles(ProtocolMapperProcessor 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 d67faa2b27..83445a6352 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/protocol/saml/mappers/GroupMembershipMapper.java b/services/src/main/java/org/keycloak/protocol/saml/mappers/GroupMembershipMapper.java
index 1a2db26f59..3ffdec4353 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 b8a62313d9..79092096f3 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 5650333c11..169f25ac38 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> roleNameMappers = new LinkedList<>();
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
AttributeType singleAttributeType = null;
- Set requestedProtocolMappers = new ClientSessionCode(session, clientSession.getRealm(), clientSession).getRequestedProtocolMappers();
+ Set 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 48edfaa81b..8e33f92e55 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 cf5c9c8bd4..329f1ac60b 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 a822d8cff0..e74c79f12f 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 f29d972234..661c9b6e62 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 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 fd0de2a87c..adfc9aac81 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 d6fd4d05a6..d633e2c70f 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/SamlEcpProfileService.java b/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java
index d2aaad68e6..f578f3d872 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/profile/ecp/authenticator/HttpBasicAuthenticator.java b/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/authenticator/HttpBasicAuthenticator.java
index ddaec72b80..81496fcb09 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/services/DefaultKeycloakSession.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java
index 9d615a5c36..7d45f15a3a 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 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;
@@ -236,6 +237,14 @@ public class DefaultKeycloakSession implements KeycloakSession {
return sessionProvider;
}
+ @Override
+ public LoginSessionProvider loginSessions() {
+ if (loginSessionProvider == null) {
+ loginSessionProvider = getProvider(LoginSessionProvider.class);
+ }
+ return loginSessionProvider;
+ }
+
@Override
public KeyManager keys() {
if (keyManager == null) {
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 714a3a2c70..2ac758442d 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 cf7d73cbd1..3cb8c68655 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 userSessions = session.sessions().getUserSessions(realm, user);
for (UserSessionModel userSession : userSessions) {
- List clientSessions = userSession.getClientSessions();
- for (ClientSessionModel clientSession : clientSessions) {
+ Collection 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 redirectClients = new LinkedList();
- for (ClientSessionModel clientSession : userSession.getClientSessions()) {
+ List 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 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 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 realmRoles = new LinkedList<>();
MultivaluedMap resourceRoles = new MultivaluedMapImpl<>();
- ClientSessionCode accessCode = new ClientSessionCode(session, realm, clientSession);
+ ClientSessionCode 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 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 12e0449b32..baf7eaddfc 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 userSessions) {
// Map from "app" to clientSessions for this app
- MultivaluedHashMap clientSessions = new MultivaluedHashMap();
+ MultivaluedHashMap 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> entry : clientSessions.entrySet()) {
- logoutClientSessions(requestUri, realm, entry.getKey(), entry.getValue());
+ for (Map.Entry> entry : clientSessions.entrySet()) {
+ if (entry.getValue().size() == 0) {
+ continue;
+ }
+ logoutClientSessions(requestUri, realm, entry.getValue().get(0).getClient(), entry.getValue());
}
}
- private void putClientSessions(MultivaluedHashMap clientSessions, UserSessionModel userSession) {
- for (ClientSessionModel clientSession : userSession.getClientSessions()) {
- ClientModel client = clientSession.getClient();
- clientSessions.add(client, clientSession);
+ private void putClientSessions(MultivaluedHashMap clientSessions, UserSessionModel userSession) {
+ for (Map.Entry entry : userSession.getClientLoginSessions().entrySet()) {
+ clientSessions.add(entry.getKey(), entry.getValue());
}
}
public void logoutUserFromClient(URI requestUri, RealmModel realm, ClientModel resource, UserModel user) {
List userSessions = session.sessions().getUserSessions(realm, user);
- List ourAppClientSessions = null;
+ List ourAppClientSessions = new LinkedList<>();
if (userSessions != null) {
- MultivaluedHashMap clientSessions = new MultivaluedHashMap();
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 clientSessions) {
+ protected boolean logoutClientSessions(URI requestUri, RealmModel realm, ClientModel resource, List clientSessions) {
String managementUrl = getManagementUrl(requestUri, resource);
if (managementUrl != null) {
@@ -160,7 +163,7 @@ public class ResourceAdminManager {
List userSessions = new LinkedList<>();
if (clientSessions != null && clientSessions.size() > 0) {
adapterSessionIds = new MultivaluedHashMap();
- 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 4c8c2fe89e..a70c6f63f1 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 findClientsWithOfflineToken(RealmModel realm, UserModel user) {
- List clientSessions = kcSession.sessions().getOfflineClientSessions(realm, user);
+ List userSessions = kcSession.sessions().getOfflineUserSessions(realm, user);
Set clients = new HashSet<>();
- for (ClientSessionModel clientSession : clientSessions) {
- clients.add(clientSession.getClient());
+ for (UserSessionModel userSession : userSessions) {
+ Set clientIds = userSession.getClientLoginSessions().keySet();
+ for (String clientUUID : clientIds) {
+ ClientModel client = realm.getClientById(clientUUID);
+ clients.add(client);
+ }
}
return clients;
}
- public List findOfflineSessions(RealmModel realm, ClientModel client, UserModel user) {
- List clientSessions = kcSession.sessions().getOfflineClientSessions(realm, user);
- List userSessions = new LinkedList<>();
- for (ClientSessionModel clientSession : clientSessions) {
- userSessions.add(clientSession.getUserSession());
- }
- return userSessions;
+ public List findOfflineSessions(RealmModel realm, UserModel user) {
+ return kcSession.sessions().getOfflineUserSessions(realm, user);
}
public boolean revokeOfflineToken(UserModel user, ClientModel client) {
RealmModel realm = client.getRealm();
- List clientSessions = kcSession.sessions().getOfflineClientSessions(realm, user);
+ List 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 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 e0e5f8b55d..f4737ad0b6 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/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
index f9efe19ab6..9dd9f9561c 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 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 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 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 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 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 not 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 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);
+// }
+//
+// LoginSessionModel loginSession = clientCode.getClientSession();
+// context.setLoginSession(loginSession);
+//
+// session.getContext().setClient(loginSession.getClient());
+//
+// context.getIdp().preprocessFederatedIdentity(session, realmModel, context);
+// Set 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 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 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, 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 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 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 clientSessionCode;
private Response response;
- public static ParsedCodeContext clientSessionCode(ClientSessionCode clientSessionCode) {
+ public static ParsedCodeContext clientSessionCode(ClientSessionCode 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 14df1dc222..3c9b40b4af 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 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 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 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 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 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 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 bb8de2d918..ab99d5d65c 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/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
index 3259982457..d74521370f 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 getSessions(final @PathParam("id") String id, final @PathParam("clientId") String clientId) {
+ public List 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 sessions = new UserSessionManager(session).findOfflineSessions(realm, client, user);
+ List sessions = new UserSessionManager(session).findOfflineSessions(realm, user);
List reps = new ArrayList();
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 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/social/twitter/TwitterIdentityProvider.java b/services/src/main/java/org/keycloak/social/twitter/TwitterIdentityProvider.java
index c6b340fb1b..f81abc91ae 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 Stian Thorgersen
*/
@@ -118,6 +115,8 @@ public class TwitterIdentityProvider extends AbstractIdentityProvider 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 roles, Set 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 roles = new HashSet();
- roles.add("one");
- roles.add("two");
-
- Set