diff --git a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.Beta1.xml b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.Beta1.xml
old mode 100644
new mode 100755
index e8acd713d0..c203b4e83a
--- a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.Beta1.xml
+++ b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.Beta1.xml
@@ -32,6 +32,9 @@
+
+
+
diff --git a/connections/jpa/src/main/resources/META-INF/persistence.xml b/connections/jpa/src/main/resources/META-INF/persistence.xml
index ddf4396d10..bb403256a1 100755
--- a/connections/jpa/src/main/resources/META-INF/persistence.xml
+++ b/connections/jpa/src/main/resources/META-INF/persistence.xml
@@ -23,6 +23,7 @@
org.keycloak.models.sessions.jpa.entities.ClientSessionEntity
org.keycloak.models.sessions.jpa.entities.ClientSessionRoleEntity
org.keycloak.models.sessions.jpa.entities.ClientSessionNoteEntity
+ org.keycloak.models.sessions.jpa.entities.UserSessionNoteEntity
org.keycloak.models.sessions.jpa.entities.UserSessionEntity
org.keycloak.models.sessions.jpa.entities.UsernameLoginFailureEntity
diff --git a/model/api/src/main/java/org/keycloak/models/ClientModel.java b/model/api/src/main/java/org/keycloak/models/ClientModel.java
index cba47d95fe..ecbb48950f 100755
--- a/model/api/src/main/java/org/keycloak/models/ClientModel.java
+++ b/model/api/src/main/java/org/keycloak/models/ClientModel.java
@@ -69,6 +69,9 @@ public interface ClientModel {
String getAttribute(String name);
Map getAttributes();
+ boolean isFrontchannelLogout();
+ void setFrontchannelLogout(boolean flag);
+
boolean isPublicClient();
void setPublicClient(boolean flag);
diff --git a/model/api/src/main/java/org/keycloak/models/ClientSessionModel.java b/model/api/src/main/java/org/keycloak/models/ClientSessionModel.java
index bdbc5c48f6..059afc941b 100755
--- a/model/api/src/main/java/org/keycloak/models/ClientSessionModel.java
+++ b/model/api/src/main/java/org/keycloak/models/ClientSessionModel.java
@@ -49,7 +49,8 @@ public interface ClientSessionModel {
UPDATE_PASSWORD,
RECOVER_PASSWORD,
AUTHENTICATE,
- SOCIAL_CALLBACK
+ SOCIAL_CALLBACK,
+ LOGGED_OUT
}
}
diff --git a/model/api/src/main/java/org/keycloak/models/UserSessionModel.java b/model/api/src/main/java/org/keycloak/models/UserSessionModel.java
index 03a93d6f44..61767b54ec 100755
--- a/model/api/src/main/java/org/keycloak/models/UserSessionModel.java
+++ b/model/api/src/main/java/org/keycloak/models/UserSessionModel.java
@@ -27,4 +27,18 @@ public interface UserSessionModel {
List getClientSessions();
+ public String getNote(String name);
+ public void setNote(String name, String value);
+ public void removeNote(String name);
+
+ State getState();
+ void setState(State state);
+
+ public static enum State {
+ LOGGING_IN,
+ LOGGED_IN,
+ LOGGING_OUT,
+ LOGGED_OUT
+ }
+
}
diff --git a/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java b/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java
index 3ca5761481..5b37c340fb 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java
@@ -18,6 +18,7 @@ public class ClientEntity extends AbstractIdentifiableEntity {
private int notBefore;
private boolean publicClient;
private boolean fullScopeAllowed;
+ private boolean frontchannelLogout;
private String realmId;
private Map attributes = new HashMap();
@@ -130,4 +131,12 @@ public class ClientEntity extends AbstractIdentifiableEntity {
public void setAttributes(Map attributes) {
this.attributes = attributes;
}
+
+ public boolean isFrontchannelLogout() {
+ return frontchannelLogout;
+ }
+
+ public void setFrontchannelLogout(boolean frontchannelLogout) {
+ this.frontchannelLogout = frontchannelLogout;
+ }
}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java
index 854fa62a97..dff08a685a 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java
@@ -125,6 +125,16 @@ public abstract class ClientAdapter implements ClientModel {
updatedClient.setPublicClient(flag);
}
+ public boolean isFrontchannelLogout() {
+ if (updatedClient != null) return updatedClient.isPublicClient();
+ return cachedClient.isFrontchannelLogout();
+ }
+
+ public void setFrontchannelLogout(boolean flag) {
+ getDelegateForUpdate();
+ updatedClient.setFrontchannelLogout(flag);
+ }
+
@Override
public boolean isFullScopeAllowed() {
if (updatedClient != null) return updatedClient.isFullScopeAllowed();
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java
index 484619fbdc..b4b605eff0 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java
@@ -28,6 +28,7 @@ public class CachedClient {
protected boolean publicClient;
protected boolean fullScopeAllowed;
protected boolean directGrantsOnly;
+ protected boolean frontchannelLogout;
protected int notBefore;
protected Set scope = new HashSet();
protected Set webOrigins = new HashSet();
@@ -42,6 +43,7 @@ public class CachedClient {
attributes.putAll(model.getAttributes());
notBefore = model.getNotBefore();
directGrantsOnly = model.isDirectGrantsOnly();
+ frontchannelLogout = model.isFrontchannelLogout();
publicClient = model.isPublicClient();
allowedClaimsMask = model.getAllowedClaimsMask();
fullScopeAllowed = model.isFullScopeAllowed();
@@ -112,4 +114,12 @@ public class CachedClient {
public Map getAttributes() {
return attributes;
}
+
+ public boolean isFrontchannelLogout() {
+ return frontchannelLogout;
+ }
+
+ public void setFrontchannelLogout(boolean frontchannelLogout) {
+ this.frontchannelLogout = frontchannelLogout;
+ }
}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
index 51257da7c0..e71ba141d1 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
@@ -80,6 +80,16 @@ public abstract class ClientAdapter implements ClientModel {
entity.setPublicClient(flag);
}
+ @Override
+ public boolean isFrontchannelLogout() {
+ return entity.isFrontchannelLogout();
+ }
+
+ @Override
+ public void setFrontchannelLogout(boolean flag) {
+ entity.setFrontchannelLogout(flag);
+ }
+
@Override
public boolean isFullScopeAllowed() {
return entity.isFullScopeAllowed();
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java
index c5652a82f5..8b32096780 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java
@@ -43,6 +43,8 @@ public abstract class ClientEntity {
private boolean publicClient;
@Column(name="PROTOCOL")
private String protocol;
+ @Column(name="FRONTCHANNEL_LOGOUT")
+ private boolean frontchannelLogout;
@Column(name="FULL_SCOPE_ALLOWED")
private boolean fullScopeAllowed;
@@ -169,4 +171,12 @@ public abstract class ClientEntity {
public void setProtocol(String protocol) {
this.protocol = protocol;
}
+
+ public boolean isFrontchannelLogout() {
+ return frontchannelLogout;
+ }
+
+ public void setFrontchannelLogout(boolean frontchannelLogout) {
+ this.frontchannelLogout = frontchannelLogout;
+ }
}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java
index b549f36db6..ad56f84ff1 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java
@@ -159,6 +159,18 @@ public abstract class ClientAdapter extends A
updateMongoEntity();
}
+
+ @Override
+ public boolean isFrontchannelLogout() {
+ return getMongoEntityAsClient().isFrontchannelLogout();
+ }
+
+ @Override
+ public void setFrontchannelLogout(boolean flag) {
+ getMongoEntityAsClient().setFrontchannelLogout(flag);
+ updateMongoEntity();
+ }
+
@Override
public boolean isFullScopeAllowed() {
return getMongoEntityAsClient().isFullScopeAllowed();
diff --git a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/UserSessionAdapter.java b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/UserSessionAdapter.java
index 1c6ffb6ccc..dfd7914e58 100755
--- a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/UserSessionAdapter.java
+++ b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/UserSessionAdapter.java
@@ -11,6 +11,7 @@ import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
import org.keycloak.models.sessions.infinispan.entities.UserSessionEntity;
import java.util.Collections;
+import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
@@ -77,6 +78,39 @@ public class UserSessionAdapter implements UserSessionModel {
update();
}
+ @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);
+ update();
+ }
+
+ @Override
+ public void removeNote(String name) {
+ if (entity.getNotes() != null) {
+ entity.getNotes().remove(name);
+ update();
+ }
+ }
+
+ @Override
+ public State getState() {
+ return entity.getState();
+ }
+
+ @Override
+ public void setState(State state) {
+ entity.setState(state);
+ update();
+ }
+
@Override
public List getClientSessions() {
if (entity.getClientSessions() != null) {
diff --git a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/UserSessionEntity.java b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/UserSessionEntity.java
old mode 100644
new mode 100755
index 3300ae666f..99c23a934b
--- a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/UserSessionEntity.java
+++ b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/UserSessionEntity.java
@@ -1,5 +1,8 @@
package org.keycloak.models.sessions.infinispan.entities;
+import org.keycloak.models.UserSessionModel;
+
+import java.util.Map;
import java.util.Set;
/**
@@ -23,6 +26,10 @@ public class UserSessionEntity extends SessionEntity {
private Set clientSessions;
+ private UserSessionModel.State state;
+
+ private Map notes;
+
public String getUser() {
return user;
}
@@ -86,4 +93,20 @@ public class UserSessionEntity extends SessionEntity {
public void setClientSessions(Set clientSessions) {
this.clientSessions = clientSessions;
}
+
+ public Map getNotes() {
+ return notes;
+ }
+
+ public void setNotes(Map notes) {
+ this.notes = notes;
+ }
+
+ public UserSessionModel.State getState() {
+ return state;
+ }
+
+ public void setState(UserSessionModel.State state) {
+ this.state = state;
+ }
}
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaUserSessionProvider.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaUserSessionProvider.java
index 6708a2dbb7..094d6adf1a 100755
--- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaUserSessionProvider.java
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaUserSessionProvider.java
@@ -173,6 +173,10 @@ public class JpaUserSessionProvider implements UserSessionProvider {
.setParameter("realmId", realm.getId())
.setParameter("userId", user.getId())
.executeUpdate();
+ em.createNamedQuery("removeUserSessionNoteByUser")
+ .setParameter("realmId", realm.getId())
+ .setParameter("userId", user.getId())
+ .executeUpdate();
em.createNamedQuery("removeUserSessionByUser")
.setParameter("realmId", realm.getId())
.setParameter("userId", user.getId())
@@ -211,6 +215,11 @@ public class JpaUserSessionProvider implements UserSessionProvider {
.setParameter("maxTime", maxTime)
.setParameter("idleTime", idleTime)
.executeUpdate();
+ em.createNamedQuery("removeUserSessionNoteByExpired")
+ .setParameter("realmId", realm.getId())
+ .setParameter("maxTime", maxTime)
+ .setParameter("idleTime", idleTime)
+ .executeUpdate();
em.createNamedQuery("removeUserSessionByExpired")
.setParameter("realmId", realm.getId())
.setParameter("maxTime", maxTime)
@@ -223,6 +232,7 @@ public class JpaUserSessionProvider implements UserSessionProvider {
em.createNamedQuery("removeClientSessionNoteByRealm").setParameter("realmId", realm.getId()).executeUpdate();
em.createNamedQuery("removeClientSessionRoleByRealm").setParameter("realmId", realm.getId()).executeUpdate();
em.createNamedQuery("removeClientSessionByRealm").setParameter("realmId", realm.getId()).executeUpdate();
+ em.createNamedQuery("removeUserSessionNoteByRealm").setParameter("realmId", realm.getId()).executeUpdate();
em.createNamedQuery("removeUserSessionByRealm").setParameter("realmId", realm.getId()).executeUpdate();
}
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/UserSessionAdapter.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/UserSessionAdapter.java
index 2110453051..ca164270c5 100755
--- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/UserSessionAdapter.java
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/UserSessionAdapter.java
@@ -7,8 +7,10 @@ import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.sessions.jpa.entities.ClientSessionEntity;
import org.keycloak.models.sessions.jpa.entities.UserSessionEntity;
+import org.keycloak.models.sessions.jpa.entities.UserSessionNoteEntity;
import javax.persistence.EntityManager;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -78,6 +80,55 @@ public class UserSessionAdapter implements UserSessionModel {
entity.setLastSessionRefresh(seconds);
}
+ @Override
+ public void setNote(String name, String value) {
+ for (UserSessionNoteEntity attr : entity.getNotes()) {
+ if (attr.getName().equals(name)) {
+ attr.setValue(value);
+ return;
+ }
+ }
+ UserSessionNoteEntity attr = new UserSessionNoteEntity();
+ attr.setName(name);
+ attr.setValue(value);
+ attr.setUserSession(entity);
+ em.persist(attr);
+ entity.getNotes().add(attr);
+ }
+
+ @Override
+ public void removeNote(String name) {
+ Iterator it = entity.getNotes().iterator();
+ while (it.hasNext()) {
+ UserSessionNoteEntity attr = it.next();
+ if (attr.getName().equals(name)) {
+ it.remove();
+ em.remove(attr);
+ }
+ }
+ }
+
+ @Override
+ public String getNote(String name) {
+ for (UserSessionNoteEntity attr : entity.getNotes()) {
+ if (attr.getName().equals(name)) {
+ return attr.getValue();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public State getState() {
+ return entity.getState();
+ }
+
+ @Override
+ public void setState(State state) {
+ entity.setState(state);
+
+ }
+
@Override
public List getClientSessions() {
List clientSessions = new LinkedList();
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/UserSessionEntity.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/UserSessionEntity.java
index e807861e48..73f9b605ae 100755
--- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/UserSessionEntity.java
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/UserSessionEntity.java
@@ -1,5 +1,7 @@
package org.keycloak.models.sessions.jpa.entities;
+import org.keycloak.models.UserSessionModel;
+
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
@@ -54,9 +56,15 @@ public class UserSessionEntity {
@Column(name="LAST_SESSION_REFRESH")
protected int lastSessionRefresh;
+ @Column(name="USER_SESSION_STATE")
+ protected UserSessionModel.State state;
+
@OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="session")
protected Collection clientSessions = new ArrayList();
+ @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="userSession")
+ protected Collection notes = new ArrayList();
+
public String getId() {
return id;
}
@@ -133,4 +141,19 @@ public class UserSessionEntity {
return clientSessions;
}
+ public UserSessionModel.State getState() {
+ return state;
+ }
+
+ public void setState(UserSessionModel.State state) {
+ this.state = state;
+ }
+
+ public Collection getNotes() {
+ return notes;
+ }
+
+ public void setNotes(Collection notes) {
+ this.notes = notes;
+ }
}
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/UserSessionNoteEntity.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/UserSessionNoteEntity.java
new file mode 100755
index 0000000000..762ce6a317
--- /dev/null
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/UserSessionNoteEntity.java
@@ -0,0 +1,107 @@
+package org.keycloak.models.sessions.jpa.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+/**
+ * @author Bill Burke
+ * @version $Revision: 1 $
+ */
+@NamedQueries({
+ @NamedQuery(name = "removeUserSessionNoteByUser", query="delete from UserSessionNoteEntity r where r.userSession IN (select s from UserSessionEntity s where s.realmId = :realmId and s.userId = :userId)"),
+ @NamedQuery(name = "removeUserSessionNoteByRealm", query="delete from UserSessionNoteEntity r where r.userSession IN (select c from UserSessionEntity c where c.realmId = :realmId)"),
+ @NamedQuery(name = "removeUserSessionNoteByExpired", query = "delete from UserSessionNoteEntity r where r.userSession IN (select s from UserSessionEntity s where s.realmId = :realmId and (s.started < :maxTime or s.lastSessionRefresh < :idleTime))")
+})
+@Table(name="USER_SESSION_NOTE")
+@Entity
+@IdClass(UserSessionNoteEntity.Key.class)
+public class UserSessionNoteEntity {
+
+ @Id
+ @ManyToOne(fetch= FetchType.LAZY)
+ @JoinColumn(name = "USER_SESSION")
+ protected UserSessionEntity userSession;
+
+ @Id
+ @Column(name = "NAME")
+ protected String name;
+ @Column(name = "VALUE")
+ protected String value;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public UserSessionEntity getUserSession() {
+ return userSession;
+ }
+
+ public void setUserSession(UserSessionEntity userSession) {
+ this.userSession = userSession;
+ }
+
+ public static class Key implements Serializable {
+
+ protected UserSessionEntity userSession;
+
+ protected String name;
+
+ public Key() {
+ }
+
+ public Key(UserSessionEntity clientSession, String name) {
+ this.userSession = clientSession;
+ this.name = name;
+ }
+
+ public UserSessionEntity getUserSession() {
+ return userSession;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Key key = (Key) o;
+
+ if (name != null ? !name.equals(key.name) : key.name != null) return false;
+ if (userSession != null ? !userSession.getId().equals(key.userSession != null ? key.userSession.getId() : null) : key.userSession != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = userSession != null ? userSession.getId().hashCode() : 0;
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ return result;
+ }
+ }
+
+}
diff --git a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/UserSessionAdapter.java b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/UserSessionAdapter.java
index e2da268763..5b215a055f 100755
--- a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/UserSessionAdapter.java
+++ b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/UserSessionAdapter.java
@@ -81,6 +81,17 @@ public class UserSessionAdapter implements UserSessionModel {
entity.setLastSessionRefresh(lastSessionRefresh);
}
+ @Override
+ public State getState() {
+ return entity.getState();
+ }
+
+ @Override
+ public void setState(State state) {
+ entity.setState(state);
+
+ }
+
@Override
public List getClientSessions() {
List clientSessionModels = new LinkedList();
@@ -106,4 +117,22 @@ public class UserSessionAdapter implements UserSessionModel {
return getId().hashCode();
}
+ @Override
+ public String getNote(String name) {
+ return entity.getNotes().get(name);
+ }
+
+ @Override
+ public void setNote(String name, String value) {
+ entity.getNotes().put(name, value);
+
+ }
+
+ @Override
+ public void removeNote(String name) {
+ entity.getNotes().remove(name);
+
+ }
+
+
}
diff --git a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/entities/UserSessionEntity.java b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/entities/UserSessionEntity.java
old mode 100644
new mode 100755
index 30cb920145..16b74db626
--- a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/entities/UserSessionEntity.java
+++ b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/entities/UserSessionEntity.java
@@ -1,8 +1,12 @@
package org.keycloak.models.sessions.mem.entities;
+import org.keycloak.models.UserSessionModel;
+
import java.util.Collections;
+import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
/**
* @author Stian Thorgersen
@@ -18,6 +22,8 @@ public class UserSessionEntity {
private boolean rememberMe;
private int started;
private int lastSessionRefresh;
+ private UserSessionModel.State state;
+ private Map notes = new HashMap();
private List clientSessions = Collections.synchronizedList(new LinkedList());
public String getId() {
@@ -109,4 +115,15 @@ public class UserSessionEntity {
return clientSessions;
}
+ public Map getNotes() {
+ return notes;
+ }
+
+ public UserSessionModel.State getState() {
+ return state;
+ }
+
+ public void setState(UserSessionModel.State state) {
+ this.state = state;
+ }
}
diff --git a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/UserSessionAdapter.java b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/UserSessionAdapter.java
index 0f30e5aa72..c12f377861 100755
--- a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/UserSessionAdapter.java
+++ b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/UserSessionAdapter.java
@@ -82,6 +82,18 @@ public class UserSessionAdapter extends AbstractMongoAdapter getClientSessions() {
List sessions = new LinkedList();
@@ -97,6 +109,23 @@ public class UserSessionAdapter extends AbstractMongoAdapterStian Thorgersen
@@ -34,6 +37,10 @@ public class MongoUserSessionEntity extends AbstractIdentifiableEntity implement
private List clientSessions = new ArrayList();
+ private Map notes = new HashMap();
+
+ private UserSessionModel.State state;
+
public String getRealmId() {
return realmId;
}
@@ -114,4 +121,19 @@ public class MongoUserSessionEntity extends AbstractIdentifiableEntity implement
context.getMongoStore().removeEntities(MongoClientSessionEntity.class, query, context);
}
+ public Map getNotes() {
+ return notes;
+ }
+
+ public void setNotes(Map notes) {
+ this.notes = notes;
+ }
+
+ public UserSessionModel.State getState() {
+ return state;
+ }
+
+ public void setState(UserSessionModel.State state) {
+ this.state = state;
+ }
}
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java
index ed1b9552ae..294f210006 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java
@@ -140,11 +140,14 @@ public class SAML2BindingBuilder {
}
public String htmlResponse() throws ProcessingException, ConfigurationException, IOException {
- return buildHtml(encoded());
+ return buildHtml(encoded(), destination);
}
public Response response() throws ConfigurationException, ProcessingException, IOException {
- return buildResponse(document);
+ return buildResponse(document, destination);
+ }
+ public Response response(String actionUrl) throws ConfigurationException, ProcessingException, IOException {
+ return buildResponse(document, actionUrl);
}
}
@@ -162,11 +165,15 @@ public class SAML2BindingBuilder {
public Document getDocument() {
return document;
}
- public URI responseUri() throws ConfigurationException, ProcessingException, IOException {
- return generateRedirectUri("SAMLResponse", document);
+ public URI responseUri(String redirectUri) throws ConfigurationException, ProcessingException, IOException {
+ return generateRedirectUri("SAMLResponse", redirectUri, document);
}
public Response response() throws ProcessingException, ConfigurationException, IOException {
- URI uri = responseUri();
+ return response(destination);
+ }
+
+ public Response response(String redirectUri) throws ProcessingException, ConfigurationException, IOException {
+ URI uri = responseUri(redirectUri);
CacheControl cacheControl = new CacheControl();
cacheControl.setNoCache(true);
@@ -259,8 +266,8 @@ public class SAML2BindingBuilder {
}
- protected Response buildResponse(Document responseDoc) throws ProcessingException, ConfigurationException, IOException {
- String str = buildHtmlPostResponse(responseDoc);
+ protected Response buildResponse(Document responseDoc, String actionUrl) throws ProcessingException, ConfigurationException, IOException {
+ String str = buildHtmlPostResponse(responseDoc, actionUrl);
CacheControl cacheControl = new CacheControl();
cacheControl.setNoCache(true);
@@ -269,14 +276,14 @@ public class SAML2BindingBuilder {
.header("Cache-Control", "no-cache, no-store").build();
}
- protected String buildHtmlPostResponse(Document responseDoc) throws ProcessingException, ConfigurationException, IOException {
+ protected String buildHtmlPostResponse(Document responseDoc, String actionUrl) throws ProcessingException, ConfigurationException, IOException {
byte[] responseBytes = DocumentUtil.getDocumentAsString(responseDoc).getBytes("UTF-8");
String samlResponse = PostBindingUtil.base64Encode(new String(responseBytes));
- return buildHtml(samlResponse);
+ return buildHtml(samlResponse, actionUrl);
}
- protected String buildHtml(String samlResponse) {
+ protected String buildHtml(String samlResponse, String actionUrl) {
if (destination == null) {
throw SALM2LoginResponseBuilder.logger.nullValueError("Destination is null");
}
@@ -291,7 +298,7 @@ public class SAML2BindingBuilder {
builder.append("");
builder.append("");
- builder.append("