diff --git a/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java
index 3580e3924f6..5a3a8fd7ae2 100755
--- a/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java
@@ -1,6 +1,7 @@
package org.keycloak.representations.idm;
import java.util.List;
+import java.util.Map;
/**
* @author Bill Burke
@@ -21,6 +22,8 @@ public class ApplicationRepresentation {
protected Integer notBefore;
protected Boolean bearerOnly;
protected Boolean publicClient;
+ protected String protocol;
+ protected Map attributes;
protected Boolean fullScopeAllowed;
@@ -143,4 +146,20 @@ public class ApplicationRepresentation {
public void setFullScopeAllowed(Boolean fullScopeAllowed) {
this.fullScopeAllowed = fullScopeAllowed;
}
+
+ public String getProtocol() {
+ return protocol;
+ }
+
+ public void setProtocol(String protocol) {
+ this.protocol = protocol;
+ }
+
+ public Map getAttributes() {
+ return attributes;
+ }
+
+ public void setAttributes(Map attributes) {
+ this.attributes = attributes;
+ }
}
diff --git a/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java
index 4c2193d49db..e61cdfc5279 100755
--- a/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java
@@ -1,6 +1,7 @@
package org.keycloak.representations.idm;
import java.util.List;
+import java.util.Map;
/**
* @author Bill Burke
@@ -16,6 +17,8 @@ public class OAuthClientRepresentation {
protected ClaimRepresentation claims;
protected Integer notBefore;
protected Boolean publicClient;
+ protected String protocol;
+ protected Map attributes;
protected Boolean directGrantsOnly;
protected Boolean fullScopeAllowed;
@@ -108,4 +111,19 @@ public class OAuthClientRepresentation {
this.fullScopeAllowed = fullScopeAllowed;
}
+ public String getProtocol() {
+ return protocol;
+ }
+
+ public void setProtocol(String protocol) {
+ this.protocol = protocol;
+ }
+
+ public Map getAttributes() {
+ return attributes;
+ }
+
+ public void setAttributes(Map attributes) {
+ this.attributes = attributes;
+ }
}
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 9ca5a70fd74..61e1574bf8f 100755
--- a/model/api/src/main/java/org/keycloak/models/ClientModel.java
+++ b/model/api/src/main/java/org/keycloak/models/ClientModel.java
@@ -1,5 +1,6 @@
package org.keycloak.models;
+import java.util.Map;
import java.util.Set;
/**
@@ -53,6 +54,15 @@ public interface ClientModel {
boolean isFullScopeAllowed();
void setFullScopeAllowed(boolean value);
+ String getProtocol();
+ void setProtocol(String protocol);
+
+ void setAttribute(String name, String value);
+ void removeAttribute(String name);
+ String getAttribute(String name);
+ Map getAttributes();
+
+
boolean isPublicClient();
void setPublicClient(boolean flag);
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 0d23c35fb65..3ca5761481c 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
@@ -1,7 +1,9 @@
package org.keycloak.models.entities;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* @author Marek Posolda
@@ -11,12 +13,15 @@ public class ClientEntity extends AbstractIdentifiableEntity {
private String name;
private boolean enabled;
private String secret;
+ private String protocol;
private long allowedClaimsMask;
private int notBefore;
private boolean publicClient;
private boolean fullScopeAllowed;
private String realmId;
+ private Map attributes = new HashMap();
+
private List webOrigins = new ArrayList();
private List redirectUris = new ArrayList();
@@ -109,4 +114,20 @@ public class ClientEntity extends AbstractIdentifiableEntity {
public void setFullScopeAllowed(boolean fullScopeAllowed) {
this.fullScopeAllowed = fullScopeAllowed;
}
+
+ public String getProtocol() {
+ return protocol;
+ }
+
+ public void setProtocol(String protocol) {
+ this.protocol = protocol;
+ }
+
+ public Map getAttributes() {
+ return attributes;
+ }
+
+ public void setAttributes(Map attributes) {
+ this.attributes = attributes;
+ }
}
diff --git a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index 069768058e3..c610e2bc5a5 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -212,6 +212,8 @@ public class ModelToRepresentation {
rep.setEnabled(applicationModel.isEnabled());
rep.setAdminUrl(applicationModel.getManagementUrl());
rep.setPublicClient(applicationModel.isPublicClient());
+ rep.setProtocol(applicationModel.getProtocol());
+ rep.setAttributes(applicationModel.getAttributes());
rep.setFullScopeAllowed(applicationModel.isFullScopeAllowed());
rep.setBearerOnly(applicationModel.isBearerOnly());
rep.setSurrogateAuthRequired(applicationModel.isSurrogateAuthRequired());
@@ -241,6 +243,8 @@ public class ModelToRepresentation {
rep.setName(model.getClientId());
rep.setEnabled(model.isEnabled());
rep.setPublicClient(model.isPublicClient());
+ rep.setProtocol(model.getProtocol());
+ rep.setAttributes(model.getAttributes());
rep.setFullScopeAllowed(model.isFullScopeAllowed());
rep.setDirectGrantsOnly(model.isDirectGrantsOnly());
Set redirectUris = model.getRedirectUris();
diff --git a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index f3f3970da79..9d30bcef0dc 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -368,6 +368,7 @@ public class RepresentationToModel {
applicationModel.setBaseUrl(resourceRep.getBaseUrl());
if (resourceRep.isBearerOnly() != null) applicationModel.setBearerOnly(resourceRep.isBearerOnly());
if (resourceRep.isPublicClient() != null) applicationModel.setPublicClient(resourceRep.isPublicClient());
+ if (resourceRep.getProtocol() != null) applicationModel.setProtocol(resourceRep.getProtocol());
if (resourceRep.isFullScopeAllowed() != null) applicationModel.setFullScopeAllowed(resourceRep.isFullScopeAllowed());
else applicationModel.setFullScopeAllowed(true);
applicationModel.updateApplication();
@@ -381,6 +382,12 @@ public class RepresentationToModel {
KeycloakModelUtils.generateSecret(applicationModel);
}
+ if (resourceRep.getAttributes() != null) {
+ for (Map.Entry entry : resourceRep.getAttributes().entrySet()) {
+ applicationModel.setAttribute(entry.getKey(), entry.getValue());
+ }
+ }
+
if (resourceRep.getRedirectUris() != null) {
for (String redirectUri : resourceRep.getRedirectUris()) {
@@ -438,6 +445,14 @@ public class RepresentationToModel {
if (rep.isSurrogateAuthRequired() != null) resource.setSurrogateAuthRequired(rep.isSurrogateAuthRequired());
resource.updateApplication();
+ if (rep.getProtocol() != null) resource.setProtocol(rep.getProtocol());
+ if (rep.getAttributes() != null) {
+ for (Map.Entry entry : rep.getAttributes().entrySet()) {
+ resource.setAttribute(entry.getKey(), entry.getValue());
+ }
+ }
+
+
if (rep.getNotBefore() != null) {
resource.setNotBefore(rep.getNotBefore());
}
@@ -565,6 +580,12 @@ public class RepresentationToModel {
if (rep.getNotBefore() != null) {
model.setNotBefore(rep.getNotBefore());
}
+ if (rep.getProtocol() != null) model.setProtocol(rep.getProtocol());
+ if (rep.getAttributes() != null) {
+ for (Map.Entry entry : rep.getAttributes().entrySet()) {
+ model.setAttribute(entry.getKey(), entry.getValue());
+ }
+ }
}
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 1565e4358b1..854fa62a97e 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
@@ -6,7 +6,9 @@ import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.cache.entities.CachedClient;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
/**
@@ -208,4 +210,43 @@ public abstract class ClientAdapter implements ClientModel {
updatedClient.setNotBefore(notBefore);
}
+ @Override
+ public String getProtocol() {
+ if (updatedClient != null) return updatedClient.getProtocol();
+ return cachedClient.getProtocol();
+ }
+
+ @Override
+ public void setProtocol(String protocol) {
+ getDelegateForUpdate();
+ updatedClient.setProtocol(protocol);
+ }
+
+ @Override
+ public void setAttribute(String name, String value) {
+ getDelegateForUpdate();
+ updatedClient.setAttribute(name, value);
+
+ }
+
+ @Override
+ public void removeAttribute(String name) {
+ getDelegateForUpdate();
+ updatedClient.removeAttribute(name);
+
+ }
+
+ @Override
+ public String getAttribute(String name) {
+ if (updatedClient != null) return updatedClient.getAttribute(name);
+ return cachedClient.getAttributes().get(name);
+ }
+
+ @Override
+ public Map getAttributes() {
+ if (updatedClient != null) return updatedClient.getAttributes();
+ Map copy = new HashMap();
+ copy.putAll(cachedClient.getAttributes());
+ return copy;
+ }
}
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 5ee1e8d2891..484619fbdcc 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
@@ -6,7 +6,9 @@ import org.keycloak.models.RealmProvider;
import org.keycloak.models.RoleModel;
import org.keycloak.models.cache.RealmCache;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
/**
@@ -21,6 +23,8 @@ public class CachedClient {
protected Set redirectUris = new HashSet();
protected boolean enabled;
protected String secret;
+ protected String protocol;
+ protected Map attributes = new HashMap();
protected boolean publicClient;
protected boolean fullScopeAllowed;
protected boolean directGrantsOnly;
@@ -34,6 +38,8 @@ public class CachedClient {
name = model.getClientId();
this.realm = realm.getId();
enabled = model.isEnabled();
+ protocol = model.getProtocol();
+ attributes.putAll(model.getAttributes());
notBefore = model.getNotBefore();
directGrantsOnly = model.isDirectGrantsOnly();
publicClient = model.isPublicClient();
@@ -98,4 +104,12 @@ public class CachedClient {
public boolean isFullScopeAllowed() {
return fullScopeAllowed;
}
+
+ public String getProtocol() {
+ return protocol;
+ }
+
+ public Map getAttributes() {
+ return attributes;
+ }
}
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 16a370e4d25..51257da7c0d 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
@@ -10,8 +10,10 @@ import org.keycloak.models.jpa.entities.ScopeMappingEntity;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
/**
@@ -247,4 +249,38 @@ public abstract class ClientAdapter implements ClientModel {
public int hashCode() {
return entity.getId().hashCode();
}
+
+ @Override
+ public String getProtocol() {
+ return entity.getProtocol();
+ }
+
+ @Override
+ public void setProtocol(String protocol) {
+ entity.setProtocol(protocol);
+
+ }
+
+ @Override
+ public void setAttribute(String name, String value) {
+ entity.getAttributes().put(name, value);
+
+ }
+
+ @Override
+ public void removeAttribute(String name) {
+ entity.getAttributes().remove(name);
+ }
+
+ @Override
+ public String getAttribute(String name) {
+ return entity.getAttributes().get(name);
+ }
+
+ @Override
+ public Map getAttributes() {
+ Map copy = new HashMap();
+ copy.putAll(entity.getAttributes());
+ return copy;
+ }
}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AttributeMap.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AttributeMap.java
deleted file mode 100755
index 625b051bba7..00000000000
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AttributeMap.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.keycloak.models.jpa.entities;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author Bill Burke
- * @version $Revision: 1 $
- */
-public class AttributeMap {
- Map attributes = new HashMap();
-
- public void set(String key, String value) {
- attributes.put(key, value);
- }
-
- public void set(String key, Boolean value) {
- attributes.put(key, value.toString());
- }
-
- public void set(String key, Integer value) {
- attributes.put(key, value.toString());
- }
-
- public String get(String key) {
- return attributes.get(key);
- }
-
- public String get(String key, String defaultValue) {
- String value = attributes.get(key);
- return value == null ? defaultValue : value;
- }
-
- public String[] getArray(String key) {
- String value = get(key);
- if (value != null) {
- String[] a = value.split(",");
- for (int i = 0; i < a.length; i++) {
- a[i] = a[i].trim();
- }
- return a;
- } else {
- return null;
- }
- }
-
- public Integer getInt(String key) {
- return getInt(key, null);
- }
-
- public Integer getInt(String key, Integer defaultValue) {
- String v = get(key, null);
- return v != null ? Integer.parseInt(v) : defaultValue;
- }
-
- public Long getLong(String key) {
- return getLong(key, null);
- }
-
- public Long getLong(String key, Long defaultValue) {
- String v = get(key, null);
- return v != null ? Long.parseLong(v) : defaultValue;
- }
-
- public Boolean getBoolean(String key) {
- return getBoolean(key, null);
- }
-
- public Boolean getBoolean(String key, Boolean defaultValue) {
- String v = get(key, null);
- return v != null ? Boolean.parseBoolean(v) : defaultValue;
- }}
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 7bc66c39b4f..c5652a82f57 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
@@ -10,9 +10,12 @@ import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
+import javax.persistence.MapKeyColumn;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
/**
@@ -38,6 +41,8 @@ public abstract class ClientEntity {
private int notBefore;
@Column(name="PUBLIC_CLIENT")
private boolean publicClient;
+ @Column(name="PROTOCOL")
+ private String protocol;
@Column(name="FULL_SCOPE_ALLOWED")
private boolean fullScopeAllowed;
@@ -55,6 +60,12 @@ public abstract class ClientEntity {
@CollectionTable(name = "REDIRECT_URIS", joinColumns={ @JoinColumn(name="CLIENT_ID") })
protected Set redirectUris = new HashSet();
+ @ElementCollection
+ @MapKeyColumn(name="NAME")
+ @Column(name="VALUE", length = 2048)
+ @CollectionTable(name="CLIENT_ATTRIBUTES", joinColumns={ @JoinColumn(name="CLIENT_ID") })
+ protected Map attributes = new HashMap();
+
public RealmEntity getRealm() {
return realm;
}
@@ -142,4 +153,20 @@ public abstract class ClientEntity {
public void setFullScopeAllowed(boolean fullScopeAllowed) {
this.fullScopeAllowed = fullScopeAllowed;
}
+
+ public Map getAttributes() {
+ return attributes;
+ }
+
+ public void setAttributes(Map attributes) {
+ this.attributes = attributes;
+ }
+
+ public String getProtocol() {
+ return protocol;
+ }
+
+ public void setProtocol(String protocol) {
+ this.protocol = protocol;
+ }
}
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 dae9f4fcb78..b549f36db64 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
@@ -12,8 +12,10 @@ import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
import org.keycloak.models.mongo.utils.MongoModelUtils;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
/**
@@ -240,4 +242,42 @@ public abstract class ClientAdapter extends A
getMongoStore().pullItemFromList(this.getMongoEntity(), "scopeIds", role.getId(), invocationContext);
}
+ @Override
+ public String getProtocol() {
+ return getMongoEntityAsClient().getProtocol();
+ }
+
+ @Override
+ public void setProtocol(String protocol) {
+ getMongoEntityAsClient().setProtocol(protocol);
+ updateMongoEntity();
+
+ }
+
+ @Override
+ public void setAttribute(String name, String value) {
+ getMongoEntityAsClient().getAttributes().put(name, value);
+ updateMongoEntity();
+
+ }
+
+ @Override
+ public void removeAttribute(String name) {
+ getMongoEntityAsClient().getAttributes().remove(name);
+ updateMongoEntity();
+ }
+
+ @Override
+ public String getAttribute(String name) {
+ return getMongoEntityAsClient().getAttributes().get(name);
+ }
+
+ @Override
+ public Map getAttributes() {
+ Map copy = new HashMap();
+ copy.putAll(getMongoEntityAsClient().getAttributes());
+ return copy;
+ }
+
+
}
diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
index 240d5cb4980..e1402c9ad3c 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -18,6 +18,7 @@ import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionProvider;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.models.utils.RepresentationToModel;
+import org.keycloak.protocol.oidc.OpenIDConnect;
import org.keycloak.representations.idm.ApplicationRepresentation;
import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;