diff --git a/connections/jpa/src/main/resources/META-INF/persistence.xml b/connections/jpa/src/main/resources/META-INF/persistence.xml
index ec843ec9da6..a5069535d08 100755
--- a/connections/jpa/src/main/resources/META-INF/persistence.xml
+++ b/connections/jpa/src/main/resources/META-INF/persistence.xml
@@ -21,6 +21,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.UserSessionEntity
org.keycloak.models.sessions.jpa.entities.UsernameLoginFailureEntity
diff --git a/model/api/src/main/java/org/keycloak/models/ClientSessionModel.java b/model/api/src/main/java/org/keycloak/models/ClientSessionModel.java
old mode 100644
new mode 100755
index 66f21318f23..01b12c50fa0
--- a/model/api/src/main/java/org/keycloak/models/ClientSessionModel.java
+++ b/model/api/src/main/java/org/keycloak/models/ClientSessionModel.java
@@ -27,6 +27,10 @@ public interface ClientSessionModel {
public Set getRoles();
+ public String getNote(String name);
+ public void setNote(String name, String value);
+ public void removeNote(String name);
+
public static enum Action {
OAUTH_GRANT,
CODE_TO_TOKEN,
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java
old mode 100644
new mode 100755
index ebcef17cd5d..d397667ef90
--- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java
@@ -6,10 +6,12 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.sessions.jpa.entities.ClientSessionEntity;
+import org.keycloak.models.sessions.jpa.entities.ClientSessionNoteEntity;
import org.keycloak.models.sessions.jpa.entities.ClientSessionRoleEntity;
import javax.persistence.EntityManager;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.Set;
/**
@@ -29,6 +31,44 @@ public class ClientSessionAdapter implements ClientSessionModel {
this.entity = entity;
}
+ @Override
+ public void setNote(String name, String value) {
+ for (ClientSessionNoteEntity attr : entity.getNotes()) {
+ if (attr.getName().equals(name)) {
+ attr.setValue(value);
+ return;
+ }
+ }
+ ClientSessionNoteEntity attr = new ClientSessionNoteEntity();
+ attr.setName(name);
+ attr.setValue(value);
+ attr.setClientSession(entity);
+ em.persist(attr);
+ entity.getNotes().add(attr);
+ }
+
+ @Override
+ public void removeNote(String name) {
+ Iterator it = entity.getNotes().iterator();
+ while (it.hasNext()) {
+ ClientSessionNoteEntity attr = it.next();
+ if (attr.getName().equals(name)) {
+ it.remove();
+ em.remove(attr);
+ }
+ }
+ }
+
+ @Override
+ public String getNote(String name) {
+ for (ClientSessionNoteEntity attr : entity.getNotes()) {
+ if (attr.getName().equals(name)) {
+ return attr.getValue();
+ }
+ }
+ return null;
+ }
+
@Override
public String getId() {
return entity.getId();
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
old mode 100644
new mode 100755
index 92e416b3b56..5e04193c31a
--- 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
@@ -185,6 +185,10 @@ public class JpaUserSessionProvider implements UserSessionProvider {
@Override
public void removeUserSessions(RealmModel realm, UserModel user) {
+ em.createNamedQuery("removeClientSessionNoteByUser")
+ .setParameter("realmId", realm.getId())
+ .setParameter("userId", user.getId())
+ .executeUpdate();
em.createNamedQuery("removeClientSessionRoleByUser")
.setParameter("realmId", realm.getId())
.setParameter("userId", user.getId())
@@ -209,6 +213,11 @@ public class JpaUserSessionProvider implements UserSessionProvider {
.setParameter("maxTime", maxTime)
.setParameter("idleTime", idleTime)
.executeUpdate();
+ em.createNamedQuery("removeClientSessionNoteByExpired")
+ .setParameter("realmId", realm.getId())
+ .setParameter("maxTime", maxTime)
+ .setParameter("idleTime", idleTime)
+ .executeUpdate();
em.createNamedQuery("removeClientSessionByExpired")
.setParameter("realmId", realm.getId())
.setParameter("maxTime", maxTime)
@@ -223,6 +232,7 @@ public class JpaUserSessionProvider implements UserSessionProvider {
@Override
public void removeUserSessions(RealmModel realm) {
+ 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("removeUserSessionByRealm").setParameter("realmId", realm.getId()).executeUpdate();
@@ -236,6 +246,7 @@ public class JpaUserSessionProvider implements UserSessionProvider {
@Override
public void onClientRemoved(RealmModel realm, ClientModel client) {
+ em.createNamedQuery("removeClientSessionNoteByClient").setParameter("realmId", realm.getId()).setParameter("clientId", client.getId()).executeUpdate();
em.createNamedQuery("removeClientSessionRoleByClient").setParameter("realmId", realm.getId()).setParameter("clientId", client.getId()).executeUpdate();
em.createNamedQuery("removeClientSessionByClient").setParameter("realmId", realm.getId()).setParameter("clientId", client.getId()).executeUpdate();
}
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionEntity.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionEntity.java
index ffd62c3cee1..0563706fc9b 100755
--- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionEntity.java
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionEntity.java
@@ -56,6 +56,9 @@ public class ClientSessionEntity {
@OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="clientSession")
protected Collection roles = new ArrayList();
+ @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="clientSession")
+ protected Collection notes = new ArrayList();
+
public String getId() {
return id;
}
@@ -120,4 +123,11 @@ public class ClientSessionEntity {
this.roles = roles;
}
+ 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/ClientSessionNoteEntity.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionNoteEntity.java
new file mode 100755
index 00000000000..a08c9d2dd34
--- /dev/null
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionNoteEntity.java
@@ -0,0 +1,108 @@
+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 = "removeClientSessionNoteByUser", query="delete from ClientSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and s.userId = :userId))"),
+ @NamedQuery(name = "removeClientSessionNoteByClient", query="delete from ClientSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.clientId = :clientId and c.session IN (select s from UserSessionEntity s where s.realmId = :realmId))"),
+ @NamedQuery(name = "removeClientSessionNoteByRealm", query="delete from ClientSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId))"),
+ @NamedQuery(name = "removeClientSessionNoteByExpired", query = "delete from ClientSessionNoteEntity r where r.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and (s.started < :maxTime or s.lastSessionRefresh < :idleTime)))")
+})
+@Table(name="CLIENT_SESSION_NOTE")
+@Entity
+@IdClass(ClientSessionNoteEntity.Key.class)
+public class ClientSessionNoteEntity {
+
+ @Id
+ @ManyToOne(fetch= FetchType.LAZY)
+ @JoinColumn(name = "CLIENT_SESSION")
+ protected ClientSessionEntity clientSession;
+
+ @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 ClientSessionEntity getClientSession() {
+ return clientSession;
+ }
+
+ public void setClientSession(ClientSessionEntity clientSession) {
+ this.clientSession = clientSession;
+ }
+
+ public static class Key implements Serializable {
+
+ protected ClientSessionEntity clientSession;
+
+ protected String name;
+
+ public Key() {
+ }
+
+ public Key(ClientSessionEntity clientSession, String name) {
+ this.clientSession = clientSession;
+ this.name = name;
+ }
+
+ public ClientSessionEntity getClientSession() {
+ return clientSession;
+ }
+
+ 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 (clientSession != null ? !clientSession.getId().equals(key.clientSession != null ? key.clientSession.getId() : null) : key.clientSession != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = clientSession != null ? clientSession.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/ClientSessionAdapter.java b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java
old mode 100644
new mode 100755
index 81918b1e47a..649915da4db
--- a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java
+++ b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java
@@ -76,4 +76,22 @@ public class ClientSessionAdapter implements ClientSessionModel {
return entity.getRoles();
}
+ @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/ClientSessionEntity.java b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/entities/ClientSessionEntity.java
old mode 100644
new mode 100755
index f56829d25c2..50940027664
--- a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/entities/ClientSessionEntity.java
+++ b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/entities/ClientSessionEntity.java
@@ -2,6 +2,8 @@ package org.keycloak.models.sessions.mem.entities;
import org.keycloak.models.ClientSessionModel;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Set;
/**
@@ -20,6 +22,7 @@ public class ClientSessionEntity {
private int timestamp;
private ClientSessionModel.Action action;
private Set roles;
+ private Map notes = new HashMap();
public String getId() {
return id;
@@ -84,4 +87,8 @@ public class ClientSessionEntity {
public void setRoles(Set roles) {
this.roles = roles;
}
+
+ public Map getNotes() {
+ return notes;
+ }
}
diff --git a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java
old mode 100644
new mode 100755
index c21ae096bf2..420b7a0095c
--- a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java
+++ b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java
@@ -85,4 +85,20 @@ public class ClientSessionAdapter implements ClientSessionModel {
return entity.getRoles() != null ? new HashSet(entity.getRoles()) : null;
}
+ @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-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoClientSessionEntity.java b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoClientSessionEntity.java
index d454f27b313..6d16717d4b2 100755
--- a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoClientSessionEntity.java
+++ b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoClientSessionEntity.java
@@ -2,7 +2,9 @@ package org.keycloak.models.sessions.mongo.entities;
import org.keycloak.models.ClientSessionModel;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* @author Stian Thorgersen
@@ -18,6 +20,7 @@ public class MongoClientSessionEntity {
private int timestamp;
private ClientSessionModel.Action action;
private List roles;
+ private Map notes = new HashMap();
public String getId() {
return id;
@@ -75,4 +78,11 @@ public class MongoClientSessionEntity {
this.roles = roles;
}
+ public Map getNotes() {
+ return notes;
+ }
+
+ public void setNotes(Map notes) {
+ this.notes = notes;
+ }
}
diff --git a/services/pom.xml b/services/pom.xml
index e2390b72869..0e5e59708c0 100755
--- a/services/pom.xml
+++ b/services/pom.xml
@@ -14,6 +14,11 @@
+
+ org.picketlink
+ picketlink-federation
+ 2.7.0-SNAPSHOT
+
org.bouncycastle
bcprov-jdk16
diff --git a/services/src/main/java/org/keycloak/services/resources/BrowserLoginProtocol.java b/services/src/main/java/org/keycloak/services/resources/BrowserLoginProtocol.java
new file mode 100755
index 00000000000..bdea5a36d0e
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/BrowserLoginProtocol.java
@@ -0,0 +1,15 @@
+package org.keycloak.services.resources;
+
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * @author Bill Burke
+ * @version $Revision: 1 $
+ */
+public interface BrowserLoginProtocol
+{
+}