Merge pull request #1974 from patriot1burke/master

set frameork for template config
This commit is contained in:
Bill Burke 2016-01-05 10:03:48 -05:00
commit 63975886cb
24 changed files with 1187 additions and 189 deletions

View file

@ -18,6 +18,39 @@
<column name="FULL_SCOPE_ALLOWED" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="CONSENT_REQUIRED" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="STANDARD_FLOW_ENABLED" type="BOOLEAN" defaultValueBoolean="true">
<constraints nullable="false"/>
</column>
<column name="IMPLICIT_FLOW_ENABLED" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="DIRECT_ACCESS_GRANTS_ENABLED" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="SERVICE_ACCOUNTS_ENABLED" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="FRONTCHANNEL_LOGOUT" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="BEARER_ONLY" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="PUBLIC_CLIENT" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="CLIENT_TEMPLATE_ATTRIBUTES">
<column name="TEMPLATE_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="VALUE" type="VARCHAR(2048)"/>
<column name="NAME" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="TEMPLATE_SCOPE_MAPPING">
<column name="TEMPLATE_ID" type="VARCHAR(36)">
@ -69,6 +102,8 @@
<addPrimaryKey columnNames="TEMPLATE_ID, ROLE_ID" constraintName="PK_TEMPLATE_SCOPE" tableName="TEMPLATE_SCOPE_MAPPING"/>
<addForeignKeyConstraint baseColumnNames="TEMPLATE_ID" baseTableName="TEMPLATE_SCOPE_MAPPING" constraintName="FK_TEMPL_SCOPE_TEMPL" referencedColumnNames="ID" referencedTableName="CLIENT_TEMPLATE"/>
<addForeignKeyConstraint baseColumnNames="ROLE_ID" baseTableName="TEMPLATE_SCOPE_MAPPING" constraintName="FK_TEMPL_SCOPE_ROLE" referencedColumnNames="ID" referencedTableName="KEYCLOAK_ROLE"/>
<addPrimaryKey columnNames="TEMPLATE_ID, NAME" constraintName="PK_CL_TMPL_ATTR" tableName="CLIENT_TEMPLATE_ATTRIBUTES"/>
<addForeignKeyConstraint baseColumnNames="TEMPLATE_ID" baseTableName="CLIENT_TEMPLATE_ATTRIBUTES" constraintName="FK_CL_TEMPL_ATTR_TEMPL" referencedColumnNames="ID" referencedTableName="CLIENT_TEMPLATE"/>
</changeSet>

View file

@ -17,6 +17,16 @@ public class ClientTemplateRepresentation {
protected String description;
protected String protocol;
protected Boolean fullScopeAllowed;
protected Boolean bearerOnly;
protected Boolean consentRequired;
protected Boolean standardFlowEnabled;
protected Boolean implicitFlowEnabled;
protected Boolean directAccessGrantsEnabled;
protected Boolean serviceAccountsEnabled;
protected Boolean publicClient;
protected Boolean frontchannelLogout;
protected Map<String, String> attributes;
protected List<ProtocolMapperRepresentation> protocolMappers;
public String getId() {
@ -67,4 +77,76 @@ public class ClientTemplateRepresentation {
public void setFullScopeAllowed(Boolean fullScopeAllowed) {
this.fullScopeAllowed = fullScopeAllowed;
}
public Boolean isBearerOnly() {
return bearerOnly;
}
public void setBearerOnly(Boolean bearerOnly) {
this.bearerOnly = bearerOnly;
}
public Boolean isConsentRequired() {
return consentRequired;
}
public void setConsentRequired(Boolean consentRequired) {
this.consentRequired = consentRequired;
}
public Boolean isStandardFlowEnabled() {
return standardFlowEnabled;
}
public void setStandardFlowEnabled(Boolean standardFlowEnabled) {
this.standardFlowEnabled = standardFlowEnabled;
}
public Boolean isImplicitFlowEnabled() {
return implicitFlowEnabled;
}
public void setImplicitFlowEnabled(Boolean implicitFlowEnabled) {
this.implicitFlowEnabled = implicitFlowEnabled;
}
public Boolean isDirectAccessGrantsEnabled() {
return directAccessGrantsEnabled;
}
public void setDirectAccessGrantsEnabled(Boolean directAccessGrantsEnabled) {
this.directAccessGrantsEnabled = directAccessGrantsEnabled;
}
public Boolean isServiceAccountsEnabled() {
return serviceAccountsEnabled;
}
public void setServiceAccountsEnabled(Boolean serviceAccountsEnabled) {
this.serviceAccountsEnabled = serviceAccountsEnabled;
}
public Boolean isPublicClient() {
return publicClient;
}
public void setPublicClient(Boolean publicClient) {
this.publicClient = publicClient;
}
public Boolean isFrontchannelLogout() {
return frontchannelLogout;
}
public void setFrontchannelLogout(Boolean frontchannelLogout) {
this.frontchannelLogout = frontchannelLogout;
}
public Map<String, String> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, String> attributes) {
this.attributes = attributes;
}
}

View file

@ -0,0 +1,55 @@
package org.keycloak.models;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ClientConfigResolver {
protected ClientModel client;
protected ClientTemplateModel clientTemplate;
public ClientConfigResolver(ClientModel client) {
this.client = client;
this.clientTemplate = client.getClientTemplate();
}
public String resolveAttribute(String name) {
if (clientTemplate != null && client.useTemplateConfig()) {
return clientTemplate.getAttribute(name);
} else {
return client.getAttribute(name);
}
}
public boolean isFrontchannelLogout() {
if (clientTemplate != null && client.useTemplateConfig()) {
return clientTemplate.isFrontchannelLogout();
}
return client.isFrontchannelLogout();
}
boolean isConsentRequired() {
if (clientTemplate != null && client.useTemplateConfig()) {
return clientTemplate.isConsentRequired();
}
return client.isConsentRequired();
}
boolean isStandardFlowEnabled() {
if (clientTemplate != null && client.useTemplateConfig()) {
return clientTemplate.isStandardFlowEnabled();
}
return client.isStandardFlowEnabled();
}
boolean isServiceAccountsEnabled() {
if (clientTemplate != null && client.useTemplateConfig()) {
return clientTemplate.isServiceAccountsEnabled();
}
return client.isServiceAccountsEnabled();
}
}

View file

@ -23,5 +23,35 @@ public interface ClientTemplateModel extends ProtocolMapperContainerModel, Scope
String getProtocol();
void setProtocol(String protocol);
void setAttribute(String name, String value);
void removeAttribute(String name);
String getAttribute(String name);
Map<String, String> getAttributes();
boolean isFrontchannelLogout();
void setFrontchannelLogout(boolean flag);
boolean isBearerOnly();
void setBearerOnly(boolean only);
boolean isPublicClient();
void setPublicClient(boolean flag);
boolean isConsentRequired();
void setConsentRequired(boolean consentRequired);
boolean isStandardFlowEnabled();
void setStandardFlowEnabled(boolean standardFlowEnabled);
boolean isImplicitFlowEnabled();
void setImplicitFlowEnabled(boolean implicitFlowEnabled);
boolean isDirectAccessGrantsEnabled();
void setDirectAccessGrantsEnabled(boolean directAccessGrantsEnabled);
boolean isServiceAccountsEnabled();
void setServiceAccountsEnabled(boolean serviceAccountsEnabled);
}

View file

@ -15,8 +15,17 @@ public class ClientTemplateEntity extends AbstractIdentifiableEntity {
private String realmId;
private String protocol;
private boolean fullScopeAllowed;
private List<String> scopeIds = new ArrayList<String>();
private List<ProtocolMapperEntity> protocolMappers = new ArrayList<ProtocolMapperEntity>();
private boolean bearerOnly;
private boolean consentRequired;
private boolean standardFlowEnabled;
private boolean implicitFlowEnabled;
private boolean directAccessGrantsEnabled;
private boolean serviceAccountsEnabled;
private boolean publicClient;
private boolean frontchannelLogout;
private List<String> scopeIds = new ArrayList<>();
private List<ProtocolMapperEntity> protocolMappers = new ArrayList<>();
private Map<String, String> attributes = new HashMap<>();
public String getName() {
return name;
@ -73,5 +82,77 @@ public class ClientTemplateEntity extends AbstractIdentifiableEntity {
public void setScopeIds(List<String> scopeIds) {
this.scopeIds = scopeIds;
}
public boolean isBearerOnly() {
return bearerOnly;
}
public void setBearerOnly(boolean bearerOnly) {
this.bearerOnly = bearerOnly;
}
public boolean isConsentRequired() {
return consentRequired;
}
public void setConsentRequired(boolean consentRequired) {
this.consentRequired = consentRequired;
}
public boolean isStandardFlowEnabled() {
return standardFlowEnabled;
}
public void setStandardFlowEnabled(boolean standardFlowEnabled) {
this.standardFlowEnabled = standardFlowEnabled;
}
public boolean isImplicitFlowEnabled() {
return implicitFlowEnabled;
}
public void setImplicitFlowEnabled(boolean implicitFlowEnabled) {
this.implicitFlowEnabled = implicitFlowEnabled;
}
public boolean isDirectAccessGrantsEnabled() {
return directAccessGrantsEnabled;
}
public void setDirectAccessGrantsEnabled(boolean directAccessGrantsEnabled) {
this.directAccessGrantsEnabled = directAccessGrantsEnabled;
}
public boolean isServiceAccountsEnabled() {
return serviceAccountsEnabled;
}
public void setServiceAccountsEnabled(boolean serviceAccountsEnabled) {
this.serviceAccountsEnabled = serviceAccountsEnabled;
}
public boolean isPublicClient() {
return publicClient;
}
public void setPublicClient(boolean publicClient) {
this.publicClient = publicClient;
}
public Map<String, String> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, String> attributes) {
this.attributes = attributes;
}
public boolean isFrontchannelLogout() {
return frontchannelLogout;
}
public void setFrontchannelLogout(boolean frontchannelLogout) {
this.frontchannelLogout = frontchannelLogout;
}
}

View file

@ -903,7 +903,7 @@ public class RepresentationToModel {
}
}
if (resourceRep.isUseTemplateConfig() != null) client.setUseTemplateConfig(resourceRep.isUseTemplateConfig());
else client.setUseTemplateConfig(resourceRep.getClientTemplate() != null);
else client.setUseTemplateConfig(false); // default to false for now
if (resourceRep.isUseTemplateScope() != null) client.setUseTemplateScope(resourceRep.isUseTemplateScope());
else client.setUseTemplateScope(resourceRep.getClientTemplate() != null);
@ -1022,6 +1022,23 @@ public class RepresentationToModel {
client.addProtocolMapper(toModel(mapper));
}
}
if (resourceRep.isBearerOnly() != null) client.setBearerOnly(resourceRep.isBearerOnly());
if (resourceRep.isConsentRequired() != null) client.setConsentRequired(resourceRep.isConsentRequired());
if (resourceRep.isStandardFlowEnabled() != null) client.setStandardFlowEnabled(resourceRep.isStandardFlowEnabled());
if (resourceRep.isImplicitFlowEnabled() != null) client.setImplicitFlowEnabled(resourceRep.isImplicitFlowEnabled());
if (resourceRep.isDirectAccessGrantsEnabled() != null) client.setDirectAccessGrantsEnabled(resourceRep.isDirectAccessGrantsEnabled());
if (resourceRep.isServiceAccountsEnabled() != null) client.setServiceAccountsEnabled(resourceRep.isServiceAccountsEnabled());
if (resourceRep.isPublicClient() != null) client.setPublicClient(resourceRep.isPublicClient());
if (resourceRep.isFrontchannelLogout() != null) client.setFrontchannelLogout(resourceRep.isFrontchannelLogout());
if (resourceRep.getAttributes() != null) {
for (Map.Entry<String, String> entry : resourceRep.getAttributes().entrySet()) {
client.setAttribute(entry.getKey(), entry.getValue());
}
}
return client;
}
@ -1035,6 +1052,23 @@ public class RepresentationToModel {
if (rep.getProtocol() != null) resource.setProtocol(rep.getProtocol());
if (rep.isBearerOnly() != null) resource.setBearerOnly(rep.isBearerOnly());
if (rep.isConsentRequired() != null) resource.setConsentRequired(rep.isConsentRequired());
if (rep.isStandardFlowEnabled() != null) resource.setStandardFlowEnabled(rep.isStandardFlowEnabled());
if (rep.isImplicitFlowEnabled() != null) resource.setImplicitFlowEnabled(rep.isImplicitFlowEnabled());
if (rep.isDirectAccessGrantsEnabled() != null) resource.setDirectAccessGrantsEnabled(rep.isDirectAccessGrantsEnabled());
if (rep.isServiceAccountsEnabled() != null) resource.setServiceAccountsEnabled(rep.isServiceAccountsEnabled());
if (rep.isPublicClient() != null) resource.setPublicClient(rep.isPublicClient());
if (rep.isFullScopeAllowed() != null) resource.setFullScopeAllowed(rep.isFullScopeAllowed());
if (rep.isFrontchannelLogout() != null) resource.setFrontchannelLogout(rep.isFrontchannelLogout());
if (rep.getAttributes() != null) {
for (Map.Entry<String, String> entry : rep.getAttributes().entrySet()) {
resource.setAttribute(entry.getKey(), entry.getValue());
}
}
}
public static long getClaimsMask(ClaimRepresentation rep) {

View file

@ -194,6 +194,127 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
return false;
}
public boolean isPublicClient() {
if (updated != null) return updated.isPublicClient();
return cached.isPublicClient();
}
public void setPublicClient(boolean flag) {
getDelegateForUpdate();
updated.setPublicClient(flag);
}
public boolean isFrontchannelLogout() {
if (updated != null) return updated.isPublicClient();
return cached.isFrontchannelLogout();
}
public void setFrontchannelLogout(boolean flag) {
getDelegateForUpdate();
updated.setFrontchannelLogout(flag);
}
@Override
public void setAttribute(String name, String value) {
getDelegateForUpdate();
updated.setAttribute(name, value);
}
@Override
public void removeAttribute(String name) {
getDelegateForUpdate();
updated.removeAttribute(name);
}
@Override
public String getAttribute(String name) {
if (updated != null) return updated.getAttribute(name);
return cached.getAttributes().get(name);
}
@Override
public Map<String, String> getAttributes() {
if (updated != null) return updated.getAttributes();
Map<String, String> copy = new HashMap<String, String>();
copy.putAll(cached.getAttributes());
return copy;
}
@Override
public boolean isBearerOnly() {
if (updated != null) return updated.isBearerOnly();
return cached.isBearerOnly();
}
@Override
public void setBearerOnly(boolean only) {
getDelegateForUpdate();
updated.setBearerOnly(only);
}
@Override
public boolean isConsentRequired() {
if (updated != null) return updated.isConsentRequired();
return cached.isConsentRequired();
}
@Override
public void setConsentRequired(boolean consentRequired) {
getDelegateForUpdate();
updated.setConsentRequired(consentRequired);
}
@Override
public boolean isStandardFlowEnabled() {
if (updated != null) return updated.isStandardFlowEnabled();
return cached.isStandardFlowEnabled();
}
@Override
public void setStandardFlowEnabled(boolean standardFlowEnabled) {
getDelegateForUpdate();
updated.setStandardFlowEnabled(standardFlowEnabled);
}
@Override
public boolean isImplicitFlowEnabled() {
if (updated != null) return updated.isImplicitFlowEnabled();
return cached.isImplicitFlowEnabled();
}
@Override
public void setImplicitFlowEnabled(boolean implicitFlowEnabled) {
getDelegateForUpdate();
updated.setImplicitFlowEnabled(implicitFlowEnabled);
}
@Override
public boolean isDirectAccessGrantsEnabled() {
if (updated != null) return updated.isDirectAccessGrantsEnabled();
return cached.isDirectAccessGrantsEnabled();
}
@Override
public void setDirectAccessGrantsEnabled(boolean directAccessGrantsEnabled) {
getDelegateForUpdate();
updated.setDirectAccessGrantsEnabled(directAccessGrantsEnabled);
}
@Override
public boolean isServiceAccountsEnabled() {
if (updated != null) return updated.isServiceAccountsEnabled();
return cached.isServiceAccountsEnabled();
}
@Override
public void setServiceAccountsEnabled(boolean serviceAccountsEnabled) {
getDelegateForUpdate();
updated.setServiceAccountsEnabled(serviceAccountsEnabled);
}
@Override

View file

@ -29,8 +29,17 @@ public class CachedClientTemplate implements Serializable {
private String realm;
private String protocol;
private boolean fullScopeAllowed;
private boolean publicClient;
private boolean frontchannelLogout;
private boolean bearerOnly;
private boolean consentRequired;
private boolean standardFlowEnabled;
private boolean implicitFlowEnabled;
private boolean directAccessGrantsEnabled;
private boolean serviceAccountsEnabled;
private Set<String> scope = new HashSet<String>();
private Set<ProtocolMapperModel> protocolMappers = new HashSet<ProtocolMapperModel>();
private Map<String, String> attributes = new HashMap<String, String>();
public CachedClientTemplate(RealmCache cache, RealmProvider delegate, RealmModel realm, ClientTemplateModel model) {
id = model.getId();
@ -45,6 +54,15 @@ public class CachedClientTemplate implements Serializable {
for (RoleModel role : model.getScopeMappings()) {
scope.add(role.getId());
}
attributes.putAll(model.getAttributes());
frontchannelLogout = model.isFrontchannelLogout();
publicClient = model.isPublicClient();
bearerOnly = model.isBearerOnly();
consentRequired = model.isConsentRequired();
standardFlowEnabled = model.isStandardFlowEnabled();
implicitFlowEnabled = model.isImplicitFlowEnabled();
directAccessGrantsEnabled = model.isDirectAccessGrantsEnabled();
serviceAccountsEnabled = model.isServiceAccountsEnabled();
}
public String getId() {
return id;
@ -77,4 +95,40 @@ public class CachedClientTemplate implements Serializable {
public Set<String> getScope() {
return scope;
}
public boolean isPublicClient() {
return publicClient;
}
public boolean isFrontchannelLogout() {
return frontchannelLogout;
}
public boolean isBearerOnly() {
return bearerOnly;
}
public boolean isConsentRequired() {
return consentRequired;
}
public boolean isStandardFlowEnabled() {
return standardFlowEnabled;
}
public boolean isImplicitFlowEnabled() {
return implicitFlowEnabled;
}
public boolean isDirectAccessGrantsEnabled() {
return directAccessGrantsEnabled;
}
public boolean isServiceAccountsEnabled() {
return serviceAccountsEnabled;
}
public Map<String, String> getAttributes() {
return attributes;
}
}

View file

@ -287,6 +287,111 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
return false;
}
@Override
public boolean isPublicClient() {
return entity.isPublicClient();
}
@Override
public void setPublicClient(boolean flag) {
entity.setPublicClient(flag);
}
@Override
public boolean isFrontchannelLogout() {
return entity.isFrontchannelLogout();
}
@Override
public void setFrontchannelLogout(boolean flag) {
entity.setFrontchannelLogout(flag);
}
@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<String, String> getAttributes() {
Map<String, String> copy = new HashMap<>();
copy.putAll(entity.getAttributes());
return copy;
}
@Override
public boolean isBearerOnly() {
return entity.isBearerOnly();
}
@Override
public void setBearerOnly(boolean only) {
entity.setBearerOnly(only);
}
@Override
public boolean isConsentRequired() {
return entity.isConsentRequired();
}
@Override
public void setConsentRequired(boolean consentRequired) {
entity.setConsentRequired(consentRequired);
}
@Override
public boolean isStandardFlowEnabled() {
return entity.isStandardFlowEnabled();
}
@Override
public void setStandardFlowEnabled(boolean standardFlowEnabled) {
entity.setStandardFlowEnabled(standardFlowEnabled);
}
@Override
public boolean isImplicitFlowEnabled() {
return entity.isImplicitFlowEnabled();
}
@Override
public void setImplicitFlowEnabled(boolean implicitFlowEnabled) {
entity.setImplicitFlowEnabled(implicitFlowEnabled);
}
@Override
public boolean isDirectAccessGrantsEnabled() {
return entity.isDirectAccessGrantsEnabled();
}
@Override
public void setDirectAccessGrantsEnabled(boolean directAccessGrantsEnabled) {
entity.setDirectAccessGrantsEnabled(directAccessGrantsEnabled);
}
@Override
public boolean isServiceAccountsEnabled() {
return entity.isServiceAccountsEnabled();
}
@Override
public void setServiceAccountsEnabled(boolean serviceAccountsEnabled) {
entity.setServiceAccountsEnabled(serviceAccountsEnabled);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;

View file

@ -48,6 +48,35 @@ public class ClientTemplateEntity {
@Column(name="FULL_SCOPE_ALLOWED")
private boolean fullScopeAllowed;
@Column(name="CONSENT_REQUIRED")
private boolean consentRequired;
@Column(name="STANDARD_FLOW_ENABLED")
private boolean standardFlowEnabled;
@Column(name="IMPLICIT_FLOW_ENABLED")
private boolean implicitFlowEnabled;
@Column(name="DIRECT_ACCESS_GRANTS_ENABLED")
private boolean directAccessGrantsEnabled;
@Column(name="SERVICE_ACCOUNTS_ENABLED")
private boolean serviceAccountsEnabled;
@Column(name="FRONTCHANNEL_LOGOUT")
private boolean frontchannelLogout;
@Column(name="PUBLIC_CLIENT")
private boolean publicClient;
@Column(name="BEARER_ONLY")
private boolean bearerOnly;
@ElementCollection
@MapKeyColumn(name="NAME")
@Column(name="VALUE", length = 2048)
@CollectionTable(name="CLIENT_TEMPLATE_ATTRIBUTES", joinColumns={ @JoinColumn(name="TEMPLATE_ID") })
protected Map<String, String> attributes = new HashMap<String, String>();
public RealmEntity getRealm() {
return realm;
}
@ -103,4 +132,76 @@ public class ClientTemplateEntity {
public void setFullScopeAllowed(boolean fullScopeAllowed) {
this.fullScopeAllowed = fullScopeAllowed;
}
public Map<String, String> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, String> attributes) {
this.attributes = attributes;
}
public boolean isConsentRequired() {
return consentRequired;
}
public void setConsentRequired(boolean consentRequired) {
this.consentRequired = consentRequired;
}
public boolean isStandardFlowEnabled() {
return standardFlowEnabled;
}
public void setStandardFlowEnabled(boolean standardFlowEnabled) {
this.standardFlowEnabled = standardFlowEnabled;
}
public boolean isImplicitFlowEnabled() {
return implicitFlowEnabled;
}
public void setImplicitFlowEnabled(boolean implicitFlowEnabled) {
this.implicitFlowEnabled = implicitFlowEnabled;
}
public boolean isDirectAccessGrantsEnabled() {
return directAccessGrantsEnabled;
}
public void setDirectAccessGrantsEnabled(boolean directAccessGrantsEnabled) {
this.directAccessGrantsEnabled = directAccessGrantsEnabled;
}
public boolean isServiceAccountsEnabled() {
return serviceAccountsEnabled;
}
public void setServiceAccountsEnabled(boolean serviceAccountsEnabled) {
this.serviceAccountsEnabled = serviceAccountsEnabled;
}
public boolean isFrontchannelLogout() {
return frontchannelLogout;
}
public void setFrontchannelLogout(boolean frontchannelLogout) {
this.frontchannelLogout = frontchannelLogout;
}
public boolean isPublicClient() {
return publicClient;
}
public void setPublicClient(boolean publicClient) {
this.publicClient = publicClient;
}
public boolean isBearerOnly() {
return bearerOnly;
}
public void setBearerOnly(boolean bearerOnly) {
this.bearerOnly = bearerOnly;
}
}

View file

@ -274,6 +274,121 @@ public class ClientTemplateAdapter extends AbstractMongoAdapter<MongoClientTempl
return false;
}
@Override
public boolean isPublicClient() {
return getMongoEntity().isPublicClient();
}
@Override
public void setPublicClient(boolean flag) {
getMongoEntity().setPublicClient(flag);
updateMongoEntity();
}
@Override
public boolean isFrontchannelLogout() {
return getMongoEntity().isFrontchannelLogout();
}
@Override
public void setFrontchannelLogout(boolean flag) {
getMongoEntity().setFrontchannelLogout(flag);
updateMongoEntity();
}
@Override
public void setAttribute(String name, String value) {
getMongoEntity().getAttributes().put(name, value);
updateMongoEntity();
}
@Override
public void removeAttribute(String name) {
getMongoEntity().getAttributes().remove(name);
updateMongoEntity();
}
@Override
public String getAttribute(String name) {
return getMongoEntity().getAttributes().get(name);
}
@Override
public Map<String, String> getAttributes() {
Map<String, String> copy = new HashMap<String, String>();
copy.putAll(getMongoEntity().getAttributes());
return copy;
}
@Override
public boolean isBearerOnly() {
return getMongoEntity().isBearerOnly();
}
@Override
public void setBearerOnly(boolean only) {
getMongoEntity().setBearerOnly(only);
updateMongoEntity();
}
@Override
public boolean isConsentRequired() {
return getMongoEntity().isConsentRequired();
}
@Override
public void setConsentRequired(boolean consentRequired) {
getMongoEntity().setConsentRequired(consentRequired);
updateMongoEntity();
}
@Override
public boolean isStandardFlowEnabled() {
return getMongoEntity().isStandardFlowEnabled();
}
@Override
public void setStandardFlowEnabled(boolean standardFlowEnabled) {
getMongoEntity().setStandardFlowEnabled(standardFlowEnabled);
updateMongoEntity();
}
@Override
public boolean isImplicitFlowEnabled() {
return getMongoEntity().isImplicitFlowEnabled();
}
@Override
public void setImplicitFlowEnabled(boolean implicitFlowEnabled) {
getMongoEntity().setImplicitFlowEnabled(implicitFlowEnabled);
updateMongoEntity();
}
@Override
public boolean isDirectAccessGrantsEnabled() {
return getMongoEntity().isDirectAccessGrantsEnabled();
}
@Override
public void setDirectAccessGrantsEnabled(boolean directAccessGrantsEnabled) {
getMongoEntity().setDirectAccessGrantsEnabled(directAccessGrantsEnabled);
updateMongoEntity();
}
@Override
public boolean isServiceAccountsEnabled() {
return getMongoEntity().isServiceAccountsEnabled();
}
@Override
public void setServiceAccountsEnabled(boolean serviceAccountsEnabled) {
getMongoEntity().setServiceAccountsEnabled(serviceAccountsEnabled);
updateMongoEntity();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;

View file

@ -4,10 +4,8 @@ import org.keycloak.Config;
import org.keycloak.dom.saml.v2.metadata.*;
import org.keycloak.exportimport.ClientDescriptionConverter;
import org.keycloak.exportimport.ClientDescriptionConverterFactory;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.saml.SignatureAlgorithm;
@ -80,12 +78,12 @@ public class EntityDescriptorDescriptionConverter implements ClientDescriptionCo
app.setFullScopeAllowed(true);
app.setProtocol(SamlProtocol.LOGIN_PROTOCOL);
attributes.put(SamlProtocol.SAML_SERVER_SIGNATURE, SamlProtocol.ATTRIBUTE_TRUE_VALUE); // default to true
attributes.put(SamlProtocol.SAML_SIGNATURE_ALGORITHM, SignatureAlgorithm.RSA_SHA256.toString());
attributes.put(SamlProtocol.SAML_AUTHNSTATEMENT, SamlProtocol.ATTRIBUTE_TRUE_VALUE);
attributes.put(SamlConfigAttributes.SAML_SERVER_SIGNATURE, SamlProtocol.ATTRIBUTE_TRUE_VALUE); // default to true
attributes.put(SamlConfigAttributes.SAML_SIGNATURE_ALGORITHM, SignatureAlgorithm.RSA_SHA256.toString());
attributes.put(SamlConfigAttributes.SAML_AUTHNSTATEMENT, SamlProtocol.ATTRIBUTE_TRUE_VALUE);
SPSSODescriptorType spDescriptorType = CoreConfigUtil.getSPDescriptor(entity);
if (spDescriptorType.isWantAssertionsSigned()) {
attributes.put(SamlProtocol.SAML_ASSERTION_SIGNATURE, SamlProtocol.ATTRIBUTE_TRUE_VALUE);
attributes.put(SamlConfigAttributes.SAML_ASSERTION_SIGNATURE, SamlProtocol.ATTRIBUTE_TRUE_VALUE);
}
String logoutPost = getLogoutLocation(spDescriptorType, JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get());
if (logoutPost != null) attributes.put(SamlProtocol.SAML_SINGLE_LOGOUT_SERVICE_URL_POST_ATTRIBUTE, logoutPost);
@ -114,10 +112,10 @@ public class EntityDescriptorDescriptionConverter implements ClientDescriptionCo
}
String certPem = KeycloakModelUtils.getPemFromCertificate(cert);
if (keyDescriptor.getUse() == KeyTypes.SIGNING) {
attributes.put(SamlProtocol.SAML_CLIENT_SIGNATURE_ATTRIBUTE, SamlProtocol.ATTRIBUTE_TRUE_VALUE);
attributes.put(SamlProtocol.SAML_SIGNING_CERTIFICATE_ATTRIBUTE, certPem);
attributes.put(SamlConfigAttributes.SAML_CLIENT_SIGNATURE_ATTRIBUTE, SamlProtocol.ATTRIBUTE_TRUE_VALUE);
attributes.put(SamlConfigAttributes.SAML_SIGNING_CERTIFICATE_ATTRIBUTE, certPem);
} else if (keyDescriptor.getUse() == KeyTypes.ENCRYPTION) {
attributes.put(SamlProtocol.SAML_ENCRYPT, SamlProtocol.ATTRIBUTE_TRUE_VALUE);
attributes.put(SamlConfigAttributes.SAML_ENCRYPT, SamlProtocol.ATTRIBUTE_TRUE_VALUE);
attributes.put(SamlProtocol.SAML_ENCRYPTION_CERTIFICATE_ATTRIBUTE, certPem);
}
}

View file

@ -1,5 +1,6 @@
package org.keycloak.protocol.saml;
import org.keycloak.models.ClientConfigResolver;
import org.keycloak.models.ClientModel;
import org.keycloak.saml.SignatureAlgorithm;
@ -7,24 +8,22 @@ import org.keycloak.saml.SignatureAlgorithm;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class SamlClient {
public static final String SAML_SIGNING_PRIVATE_KEY = "saml.signing.private.key";
protected ClientModel client;
public class SamlClient extends ClientConfigResolver {
public SamlClient(ClientModel client) {
this.client = client;
super(client);
}
public String getCanonicalizationMethod() {
return client.getAttribute(SamlProtocol.SAML_CANONICALIZATION_METHOD_ATTRIBUTE);
return resolveAttribute(SamlConfigAttributes.SAML_CANONICALIZATION_METHOD_ATTRIBUTE);
}
public void setCanonicalizationMethod(String value) {
client.setAttribute(SamlProtocol.SAML_CANONICALIZATION_METHOD_ATTRIBUTE, value);
client.setAttribute(SamlConfigAttributes.SAML_CANONICALIZATION_METHOD_ATTRIBUTE, value);
}
public SignatureAlgorithm getSignatureAlgorithm() {
String alg = client.getAttribute(SamlProtocol.SAML_SIGNATURE_ALGORITHM);
String alg = resolveAttribute(SamlConfigAttributes.SAML_SIGNATURE_ALGORITHM);
if (alg != null) {
SignatureAlgorithm algorithm = SignatureAlgorithm.valueOf(alg);
if (algorithm != null)
@ -34,94 +33,92 @@ public class SamlClient {
}
public void setSignatureAlgorithm(SignatureAlgorithm algorithm) {
client.setAttribute(SamlProtocol.SAML_SIGNATURE_ALGORITHM, algorithm.name());
client.setAttribute(SamlConfigAttributes.SAML_SIGNATURE_ALGORITHM, algorithm.name());
}
public String getNameIDFormat() {
return client.getAttributes().get(SamlProtocol.SAML_NAME_ID_FORMAT_ATTRIBUTE);
return resolveAttribute(SamlConfigAttributes.SAML_NAME_ID_FORMAT_ATTRIBUTE);
}
public void setNameIDFormat(String format) {
client.setAttribute(SamlProtocol.SAML_NAME_ID_FORMAT_ATTRIBUTE, format);
client.setAttribute(SamlConfigAttributes.SAML_NAME_ID_FORMAT_ATTRIBUTE, format);
}
public boolean includeAuthnStatement() {
return "true".equals(client.getAttribute(SamlProtocol.SAML_AUTHNSTATEMENT));
return "true".equals(resolveAttribute(SamlConfigAttributes.SAML_AUTHNSTATEMENT));
}
public void setIncludeAuthnStatement(boolean val) {
client.setAttribute(SamlProtocol.SAML_AUTHNSTATEMENT, Boolean.toString(val));
client.setAttribute(SamlConfigAttributes.SAML_AUTHNSTATEMENT, Boolean.toString(val));
}
public boolean forceNameIDFormat() {
return "true".equals(client.getAttribute(SamlProtocol.SAML_FORCE_NAME_ID_FORMAT_ATTRIBUTE));
return "true".equals(resolveAttribute(SamlConfigAttributes.SAML_FORCE_NAME_ID_FORMAT_ATTRIBUTE));
}
public void setForceNameIDFormat(boolean val) {
client.setAttribute(SamlProtocol.SAML_FORCE_NAME_ID_FORMAT_ATTRIBUTE, Boolean.toString(val));
client.setAttribute(SamlConfigAttributes.SAML_FORCE_NAME_ID_FORMAT_ATTRIBUTE, Boolean.toString(val));
}
public boolean requiresRealmSignature(ClientModel client) {
return "true".equals(client.getAttribute(SamlProtocol.SAML_SERVER_SIGNATURE));
public boolean requiresRealmSignature() {
return "true".equals(resolveAttribute(SamlConfigAttributes.SAML_SERVER_SIGNATURE));
}
public void setRequiresRealmSignature(boolean val) {
client.setAttribute(SamlProtocol.SAML_SERVER_SIGNATURE, Boolean.toString(val));
client.setAttribute(SamlConfigAttributes.SAML_SERVER_SIGNATURE, Boolean.toString(val));
}
public boolean forcePostBinding(ClientModel client) {
return "true".equals(client.getAttribute(SamlProtocol.SAML_FORCE_POST_BINDING));
public boolean forcePostBinding() {
return "true".equals(resolveAttribute(SamlConfigAttributes.SAML_FORCE_POST_BINDING));
}
public void setForcePostBinding(boolean val) {
client.setAttribute(SamlProtocol.SAML_FORCE_POST_BINDING, Boolean.toString(val));
client.setAttribute(SamlConfigAttributes.SAML_FORCE_POST_BINDING, Boolean.toString(val));
}
public boolean samlAssertionSignature(ClientModel client) {
return "true".equals(client.getAttribute(SamlProtocol.SAML_ASSERTION_SIGNATURE));
public boolean requiresAssertionSignature() {
return "true".equals(resolveAttribute(SamlConfigAttributes.SAML_ASSERTION_SIGNATURE));
}
public void setAssertionSignature(boolean val) {
client.setAttribute(SamlProtocol.SAML_ASSERTION_SIGNATURE , Boolean.toString(val));
public void setRequiresAssertionSignature(boolean val) {
client.setAttribute(SamlConfigAttributes.SAML_ASSERTION_SIGNATURE , Boolean.toString(val));
}
public boolean requiresEncryption(ClientModel client) {
return "true".equals(client.getAttribute(SamlProtocol.SAML_ENCRYPT));
public boolean requiresEncryption() {
return "true".equals(resolveAttribute(SamlConfigAttributes.SAML_ENCRYPT));
}
public void setRequiresEncryption(boolean val) {
client.setAttribute(SamlProtocol.SAML_ENCRYPT, Boolean.toString(val));
client.setAttribute(SamlConfigAttributes.SAML_ENCRYPT, Boolean.toString(val));
}
public boolean requiresClientSignature(ClientModel client) {
return "true".equals(client.getAttribute(SamlProtocol.SAML_CLIENT_SIGNATURE_ATTRIBUTE));
public boolean requiresClientSignature() {
return "true".equals(resolveAttribute(SamlConfigAttributes.SAML_CLIENT_SIGNATURE_ATTRIBUTE));
}
public void setRequiresClientSignature(boolean val) {
client.setAttribute(SamlProtocol.SAML_CLIENT_SIGNATURE_ATTRIBUTE , Boolean.toString(val));
client.setAttribute(SamlConfigAttributes.SAML_CLIENT_SIGNATURE_ATTRIBUTE , Boolean.toString(val));
}
public String getClientSigningCertificate() {
return client.getAttribute(SamlProtocol.SAML_SIGNING_CERTIFICATE_ATTRIBUTE);
return client.getAttribute(SamlConfigAttributes.SAML_SIGNING_CERTIFICATE_ATTRIBUTE);
}
public void setClientSigningCertificate(String val) {
client.setAttribute(SamlProtocol.SAML_SIGNING_CERTIFICATE_ATTRIBUTE, val);
client.setAttribute(SamlConfigAttributes.SAML_SIGNING_CERTIFICATE_ATTRIBUTE, val);
}
public String getClientSigningPrivateKey() {
return client.getAttribute(SAML_SIGNING_PRIVATE_KEY);
return client.getAttribute(SamlConfigAttributes.SAML_SIGNING_PRIVATE_KEY);
}
public void setClientSigningPrivateKey(String val) {
client.setAttribute(SAML_SIGNING_PRIVATE_KEY, val);
client.setAttribute(SamlConfigAttributes.SAML_SIGNING_PRIVATE_KEY, val);
}
}

View file

@ -1,60 +0,0 @@
package org.keycloak.protocol.saml;
import org.keycloak.models.ClientModel;
import org.keycloak.representations.idm.ClientRepresentation;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class SamlClientRepresentation {
protected ClientRepresentation rep;
public SamlClientRepresentation(ClientRepresentation rep) {
this.rep = rep;
}
public String getCanonicalizationMethod() {
if (rep.getAttributes() == null) return null;
return rep.getAttributes().get(SamlProtocol.SAML_CANONICALIZATION_METHOD_ATTRIBUTE);
}
public String getSignatureAlgorithm() {
if (rep.getAttributes() == null) return null;
return rep.getAttributes().get(SamlProtocol.SAML_SIGNATURE_ALGORITHM);
}
public String getNameIDFormat() {
if (rep.getAttributes() == null) return null;
return rep.getAttributes().get(SamlProtocol.SAML_NAME_ID_FORMAT_ATTRIBUTE);
}
public String getIncludeAuthnStatement() {
if (rep.getAttributes() == null) return null;
return rep.getAttributes().get(SamlProtocol.SAML_AUTHNSTATEMENT);
}
public String getForceNameIDFormat() {
if (rep.getAttributes() == null) return null;
return rep.getAttributes().get(SamlProtocol.SAML_FORCE_NAME_ID_FORMAT_ATTRIBUTE);
}
public String getSamlServerSignature() {
if (rep.getAttributes() == null) return null;
return rep.getAttributes().get(SamlProtocol.SAML_SERVER_SIGNATURE);
}
public String getForcePostBinding() {
if (rep.getAttributes() == null) return null;
return rep.getAttributes().get(SamlProtocol.SAML_FORCE_POST_BINDING);
}
public String getClientSignature() {
if (rep.getAttributes() == null) return null;
return rep.getAttributes().get(SamlProtocol.SAML_CLIENT_SIGNATURE_ATTRIBUTE);
}
}

View file

@ -0,0 +1,131 @@
package org.keycloak.protocol.saml;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.saml.SignatureAlgorithm;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class SamlClientTemplate {
protected ClientTemplateModel clientTemplate;
public SamlClientTemplate(ClientTemplateModel template) {
this.clientTemplate = template;
}
public String getId() {
return clientTemplate.getId();
}
//
public String getCanonicalizationMethod() {
return clientTemplate.getAttribute(SamlConfigAttributes.SAML_CANONICALIZATION_METHOD_ATTRIBUTE);
}
public void setCanonicalizationMethod(String value) {
clientTemplate.setAttribute(SamlConfigAttributes.SAML_CANONICALIZATION_METHOD_ATTRIBUTE, value);
}
public SignatureAlgorithm getSignatureAlgorithm() {
String alg = null;
alg = clientTemplate.getAttribute(SamlConfigAttributes.SAML_CANONICALIZATION_METHOD_ATTRIBUTE);
if (alg != null) {
SignatureAlgorithm algorithm = SignatureAlgorithm.valueOf(alg);
if (algorithm != null)
return algorithm;
}
return SignatureAlgorithm.RSA_SHA256;
}
public void setSignatureAlgorithm(SignatureAlgorithm algorithm) {
clientTemplate.setAttribute(SamlConfigAttributes.SAML_SIGNATURE_ALGORITHM, algorithm.name());
}
public String getNameIDFormat() {
return clientTemplate.getAttributes().get(SamlConfigAttributes.SAML_NAME_ID_FORMAT_ATTRIBUTE);
}
public void setNameIDFormat(String format) {
clientTemplate.setAttribute(SamlConfigAttributes.SAML_NAME_ID_FORMAT_ATTRIBUTE, format);
}
public boolean includeAuthnStatement() {
return "true".equals(clientTemplate.getAttribute(SamlConfigAttributes.SAML_AUTHNSTATEMENT));
}
public void setIncludeAuthnStatement(boolean val) {
clientTemplate.setAttribute(SamlConfigAttributes.SAML_AUTHNSTATEMENT, Boolean.toString(val));
}
public boolean forceNameIDFormat() {
return "true".equals(clientTemplate.getAttribute(SamlConfigAttributes.SAML_FORCE_NAME_ID_FORMAT_ATTRIBUTE));
}
public void setForceNameIDFormat(boolean val) {
clientTemplate.setAttribute(SamlConfigAttributes.SAML_FORCE_NAME_ID_FORMAT_ATTRIBUTE, Boolean.toString(val));
}
public boolean requiresRealmSignature() {
return "true".equals(clientTemplate.getAttribute(SamlConfigAttributes.SAML_SERVER_SIGNATURE));
}
public void setRequiresRealmSignature(boolean val) {
clientTemplate.setAttribute(SamlConfigAttributes.SAML_SERVER_SIGNATURE, Boolean.toString(val));
}
public boolean forcePostBinding() {
return "true".equals(clientTemplate.getAttribute(SamlConfigAttributes.SAML_FORCE_POST_BINDING));
}
public void setForcePostBinding(boolean val) {
clientTemplate.setAttribute(SamlConfigAttributes.SAML_FORCE_POST_BINDING, Boolean.toString(val));
}
public boolean requiresAssertionSignature() {
return "true".equals(clientTemplate.getAttribute(SamlConfigAttributes.SAML_ASSERTION_SIGNATURE));
}
public void setRequiresAssertionSignature(boolean val) {
clientTemplate.setAttribute(SamlConfigAttributes.SAML_ASSERTION_SIGNATURE , Boolean.toString(val));
}
public boolean requiresEncryption() {
return "true".equals(clientTemplate.getAttribute(SamlConfigAttributes.SAML_ENCRYPT));
}
public void setRequiresEncryption(boolean val) {
clientTemplate.setAttribute(SamlConfigAttributes.SAML_ENCRYPT, Boolean.toString(val));
}
public boolean requiresClientSignature() {
return "true".equals(clientTemplate.getAttribute(SamlConfigAttributes.SAML_CLIENT_SIGNATURE_ATTRIBUTE));
}
public void setRequiresClientSignature(boolean val) {
clientTemplate.setAttribute(SamlConfigAttributes.SAML_CLIENT_SIGNATURE_ATTRIBUTE , Boolean.toString(val));
}
public String getClientSigningCertificate() {
return clientTemplate.getAttribute(SamlConfigAttributes.SAML_SIGNING_CERTIFICATE_ATTRIBUTE);
}
public void setClientSigningCertificate(String val) {
clientTemplate.setAttribute(SamlConfigAttributes.SAML_SIGNING_CERTIFICATE_ATTRIBUTE, val);
}
public String getClientSigningPrivateKey() {
return clientTemplate.getAttribute(SamlConfigAttributes.SAML_SIGNING_PRIVATE_KEY);
}
public void setClientSigningPrivateKey(String val) {
clientTemplate.setAttribute(SamlConfigAttributes.SAML_SIGNING_PRIVATE_KEY, val);
}
}

View file

@ -0,0 +1,22 @@
package org.keycloak.protocol.saml;
import org.keycloak.services.resources.admin.ClientAttributeCertificateResource;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface SamlConfigAttributes {
String SAML_SIGNING_PRIVATE_KEY = "saml.signing.private.key";
String SAML_CANONICALIZATION_METHOD_ATTRIBUTE = "saml_signature_canonicalization_method";
String SAML_SIGNATURE_ALGORITHM = "saml.signature.algorithm";
String SAML_NAME_ID_FORMAT_ATTRIBUTE = "saml_name_id_format";
String SAML_AUTHNSTATEMENT = "saml.authnstatement";
String SAML_FORCE_NAME_ID_FORMAT_ATTRIBUTE = "saml_force_name_id_format";
String SAML_SERVER_SIGNATURE = "saml.server.signature";
String SAML_FORCE_POST_BINDING = "saml.force.post.binding";
String SAML_ASSERTION_SIGNATURE = "saml.assertion.signature";
String SAML_ENCRYPT = "saml.encrypt";
String SAML_CLIENT_SIGNATURE_ATTRIBUTE = "saml.client.signature";
String SAML_SIGNING_CERTIFICATE_ATTRIBUTE = "saml.signing." + ClientAttributeCertificateResource.X509CERTIFICATE;
}

View file

@ -70,28 +70,17 @@ public class SamlProtocol implements LoginProtocol {
public static final String ATTRIBUTE_TRUE_VALUE = "true";
public static final String ATTRIBUTE_FALSE_VALUE = "false";
public static final String SAML_SIGNING_CERTIFICATE_ATTRIBUTE = "saml.signing." + ClientAttributeCertificateResource.X509CERTIFICATE;
public static final String SAML_ENCRYPTION_CERTIFICATE_ATTRIBUTE = "saml.encryption." + ClientAttributeCertificateResource.X509CERTIFICATE;
public static final String SAML_CLIENT_SIGNATURE_ATTRIBUTE = "saml.client.signature";
public static final String SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE = "saml_assertion_consumer_url_post";
public static final String SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE = "saml_assertion_consumer_url_redirect";
public static final String SAML_SINGLE_LOGOUT_SERVICE_URL_POST_ATTRIBUTE = "saml_single_logout_service_url_post";
public static final String SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE = "saml_single_logout_service_url_redirect";
public static final String SAML_FORCE_NAME_ID_FORMAT_ATTRIBUTE = "saml_force_name_id_format";
public static final String SAML_NAME_ID_FORMAT_ATTRIBUTE = "saml_name_id_format";
public static final String SAML_CANONICALIZATION_METHOD_ATTRIBUTE = "saml_signature_canonicalization_method";
public static final String LOGIN_PROTOCOL = "saml";
public static final String SAML_BINDING = "saml_binding";
public static final String SAML_IDP_INITIATED_LOGIN = "saml_idp_initiated_login";
public static final String SAML_POST_BINDING = "post";
public static final String SAML_SOAP_BINDING = "soap";
public static final String SAML_REDIRECT_BINDING = "get";
public static final String SAML_SERVER_SIGNATURE = "saml.server.signature";
public static final String SAML_ASSERTION_SIGNATURE = "saml.assertion.signature";
public static final String SAML_AUTHNSTATEMENT = "saml.authnstatement";
public static final String SAML_SIGNATURE_ALGORITHM = "saml.signature.algorithm";
public static final String SAML_ENCRYPT = "saml.encrypt";
public static final String SAML_FORCE_POST_BINDING = "saml.force.post.binding";
public static final String SAML_REQUEST_ID = "SAML_REQUEST_ID";
public static final String SAML_LOGOUT_BINDING = "saml.logout.binding";
public static final String SAML_LOGOUT_REQUEST_ID = "SAML_LOGOUT_REQUEST_ID";
@ -218,7 +207,8 @@ public class SamlProtocol implements LoginProtocol {
protected boolean isPostBinding(ClientSessionModel clientSession) {
ClientModel client = clientSession.getClient();
return SamlProtocol.SAML_POST_BINDING.equals(clientSession.getNote(SamlProtocol.SAML_BINDING)) || forcePostBinding(client);
SamlClient samlClient = new SamlClient(client);
return SamlProtocol.SAML_POST_BINDING.equals(clientSession.getNote(SamlProtocol.SAML_BINDING)) || samlClient.forcePostBinding();
}
public static boolean isLogoutPostBindingForInitiator(UserSessionModel session) {
@ -228,6 +218,7 @@ public class SamlProtocol implements LoginProtocol {
protected boolean isLogoutPostBindingForClient(ClientSessionModel clientSession) {
ClientModel client = clientSession.getClient();
SamlClient samlClient = new SamlClient(client);
String logoutPostUrl = client.getAttribute(SAML_SINGLE_LOGOUT_SERVICE_URL_POST_ATTRIBUTE);
String logoutRedirectUrl = client.getAttribute(SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE);
@ -238,7 +229,7 @@ public class SamlProtocol implements LoginProtocol {
return false;
}
if (forcePostBinding(client)) {
if (samlClient.forcePostBinding()) {
return true; // configured to force a post binding and post binding logout url is not null
}
@ -255,15 +246,11 @@ public class SamlProtocol implements LoginProtocol {
}
public static boolean forcePostBinding(ClientModel client) {
return "true".equals(client.getAttribute(SamlProtocol.SAML_FORCE_POST_BINDING));
}
protected String getNameIdFormat(ClientSessionModel clientSession) {
protected String getNameIdFormat(SamlClient samlClient, ClientSessionModel clientSession) {
String nameIdFormat = clientSession.getNote(GeneralConstants.NAMEID_FORMAT);
ClientModel client = clientSession.getClient();
boolean forceFormat = forceNameIdFormat(client);
String configuredNameIdFormat = client.getAttribute(SAML_NAME_ID_FORMAT_ATTRIBUTE);
boolean forceFormat = samlClient.forceNameIDFormat();
String configuredNameIdFormat = samlClient.getNameIDFormat();
if ((nameIdFormat == null || forceFormat) && configuredNameIdFormat != null) {
if (configuredNameIdFormat.equals("email")) {
nameIdFormat = JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get();
@ -282,10 +269,6 @@ public class SamlProtocol implements LoginProtocol {
return nameIdFormat;
}
public static boolean forceNameIdFormat(ClientModel client) {
return "true".equals(client.getAttribute(SAML_FORCE_NAME_ID_FORMAT_ATTRIBUTE));
}
protected String getNameId(String nameIdFormat, ClientSessionModel clientSession, UserSessionModel userSession) {
if (nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get())) {
return userSession.getUser().getEmail();
@ -315,11 +298,12 @@ public class SamlProtocol implements LoginProtocol {
public Response authenticated(UserSessionModel userSession, ClientSessionCode accessCode) {
ClientSessionModel clientSession = accessCode.getClientSession();
ClientModel client = clientSession.getClient();
SamlClient samlClient = new SamlClient(client);
String requestID = clientSession.getNote(SAML_REQUEST_ID);
String relayState = clientSession.getNote(GeneralConstants.RELAY_STATE);
String redirectUri = clientSession.getRedirectUri();
String responseIssuer = getResponseIssuer(realm);
String nameIdFormat = getNameIdFormat(clientSession);
String nameIdFormat = getNameIdFormat(samlClient, clientSession);
String nameId = getNameId(nameIdFormat, clientSession, userSession);
// save NAME_ID and format in clientSession as they may be persistent or transient or email and not username
@ -330,7 +314,7 @@ public class SamlProtocol implements LoginProtocol {
SAML2LoginResponseBuilder builder = new SAML2LoginResponseBuilder();
builder.requestID(requestID).destination(redirectUri).issuer(responseIssuer).assertionExpiration(realm.getAccessCodeLifespan()).subjectExpiration(realm.getAccessTokenLifespan()).sessionIndex(clientSession.getId())
.requestIssuer(clientSession.getClient().getClientId()).nameIdentifier(nameIdFormat, nameId).authMethod(JBossSAMLURIConstants.AC_UNSPECIFIED.get());
if (!includeAuthnStatement(client)) {
if (!samlClient.includeAuthnStatement()) {
builder.disableAuthnStatement(true);
}
@ -370,21 +354,21 @@ public class SamlProtocol implements LoginProtocol {
JaxrsSAML2BindingBuilder bindingBuilder = new JaxrsSAML2BindingBuilder();
bindingBuilder.relayState(relayState);
if (requiresRealmSignature(client)) {
String canonicalization = client.getAttribute(SAML_CANONICALIZATION_METHOD_ATTRIBUTE);
if (samlClient.requiresRealmSignature()) {
String canonicalization = samlClient.getCanonicalizationMethod();
if (canonicalization != null) {
bindingBuilder.canonicalizationMethod(canonicalization);
}
bindingBuilder.signatureAlgorithm(getSignatureAlgorithm(client)).signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate()).signDocument();
bindingBuilder.signatureAlgorithm(samlClient.getSignatureAlgorithm()).signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate()).signDocument();
}
if (requiresAssertionSignature(client)) {
String canonicalization = client.getAttribute(SAML_CANONICALIZATION_METHOD_ATTRIBUTE);
if (samlClient.requiresAssertionSignature()) {
String canonicalization = samlClient.getCanonicalizationMethod();
if (canonicalization != null) {
bindingBuilder.canonicalizationMethod(canonicalization);
}
bindingBuilder.signatureAlgorithm(getSignatureAlgorithm(client)).signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate()).signAssertions();
bindingBuilder.signatureAlgorithm(samlClient.getSignatureAlgorithm()).signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate()).signAssertions();
}
if (requiresEncryption(client)) {
if (samlClient.requiresEncryption()) {
PublicKey publicKey = null;
try {
publicKey = SamlProtocolUtils.getEncryptionValidationKey(client);
@ -410,32 +394,6 @@ public class SamlProtocol implements LoginProtocol {
}
}
public static boolean requiresRealmSignature(ClientModel client) {
return "true".equals(client.getAttribute(SAML_SERVER_SIGNATURE));
}
public static boolean requiresAssertionSignature(ClientModel client) {
return "true".equals(client.getAttribute(SAML_ASSERTION_SIGNATURE));
}
public static boolean includeAuthnStatement(ClientModel client) {
return "true".equals(client.getAttribute(SAML_AUTHNSTATEMENT));
}
public static SignatureAlgorithm getSignatureAlgorithm(ClientModel client) {
String alg = client.getAttribute(SAML_SIGNATURE_ALGORITHM);
if (alg != null) {
SignatureAlgorithm algorithm = SignatureAlgorithm.valueOf(alg);
if (algorithm != null)
return algorithm;
}
return SignatureAlgorithm.RSA_SHA256;
}
private boolean requiresEncryption(ClientModel client) {
return "true".equals(client.getAttribute(SAML_ENCRYPT));
}
public static class ProtocolMapperProcessor<T> {
final public T mapper;
final public ProtocolMapperModel model;
@ -499,19 +457,20 @@ public class SamlProtocol implements LoginProtocol {
@Override
public Response frontchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) {
ClientModel client = clientSession.getClient();
SamlClient samlClient = new SamlClient(client);
if (!(client instanceof ClientModel))
return null;
try {
if (isLogoutPostBindingForClient(clientSession)) {
String bindingUri = getLogoutServiceUrl(uriInfo, client, SAML_POST_BINDING);
SAML2LogoutRequestBuilder logoutBuilder = createLogoutRequest(bindingUri, clientSession, client);
JaxrsSAML2BindingBuilder binding = createBindingBuilder(client);
JaxrsSAML2BindingBuilder binding = createBindingBuilder(samlClient);
return binding.postBinding(logoutBuilder.buildDocument()).request(bindingUri);
} else {
logger.debug("frontchannel redirect binding");
String bindingUri = getLogoutServiceUrl(uriInfo, client, SAML_REDIRECT_BINDING);
SAML2LogoutRequestBuilder logoutBuilder = createLogoutRequest(bindingUri, clientSession, client);
JaxrsSAML2BindingBuilder binding = createBindingBuilder(client);
JaxrsSAML2BindingBuilder binding = createBindingBuilder(samlClient);
return binding.redirectBinding(logoutBuilder.buildDocument()).request(bindingUri);
}
} catch (ConfigurationException e) {
@ -574,6 +533,7 @@ public class SamlProtocol implements LoginProtocol {
@Override
public void backchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) {
ClientModel client = clientSession.getClient();
SamlClient samlClient = new SamlClient(client);
String logoutUrl = getLogoutServiceUrl(uriInfo, client, SAML_POST_BINDING);
if (logoutUrl == null) {
logger.warnv("Can't do backchannel logout. No SingleLogoutService POST Binding registered for client: {1}", client.getClientId());
@ -583,7 +543,7 @@ public class SamlProtocol implements LoginProtocol {
String logoutRequestString = null;
try {
JaxrsSAML2BindingBuilder binding = createBindingBuilder(client);
JaxrsSAML2BindingBuilder binding = createBindingBuilder(samlClient);
logoutRequestString = binding.postBinding(logoutBuilder.buildDocument()).encoded();
} catch (Exception e) {
logger.warn("failed to send saml logout", e);
@ -636,10 +596,10 @@ public class SamlProtocol implements LoginProtocol {
return logoutBuilder;
}
private JaxrsSAML2BindingBuilder createBindingBuilder(ClientModel client) {
private JaxrsSAML2BindingBuilder createBindingBuilder(SamlClient samlClient) {
JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder();
if (requiresRealmSignature(client)) {
binding.signatureAlgorithm(getSignatureAlgorithm(client)).signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate()).signDocument();
if (samlClient.requiresRealmSignature()) {
binding.signatureAlgorithm(samlClient.getSignatureAlgorithm()).signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate()).signDocument();
}
return binding;
}

View file

@ -3,6 +3,7 @@ package org.keycloak.protocol.saml;
import org.keycloak.Config;
import org.keycloak.events.EventBuilder;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
@ -14,6 +15,7 @@ import org.keycloak.protocol.saml.mappers.RoleListMapper;
import org.keycloak.protocol.saml.mappers.UserPropertyAttributeStatementMapper;
import org.keycloak.representations.idm.CertificateRepresentation;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ClientTemplateRepresentation;
import org.keycloak.saml.SignatureAlgorithm;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
@ -103,7 +105,7 @@ public class SamlProtocolFactory extends AbstractLoginProtocolFactory {
@Override
public void setupClientDefaults(ClientRepresentation clientRep, ClientModel newClient) {
SamlClientRepresentation rep = new SamlClientRepresentation(clientRep);
SamlRepresentationAttributes rep = new SamlRepresentationAttributes(clientRep.getAttributes());
SamlClient client = new SamlClient(newClient);
if (clientRep.isStandardFlowEnabled() == null) newClient.setStandardFlowEnabled(true);
if (rep.getCanonicalizationMethod() == null) {
@ -134,9 +136,53 @@ public class SamlProtocolFactory extends AbstractLoginProtocolFactory {
if (rep.getClientSignature() == null) {
client.setRequiresClientSignature(true);
}
if (client.requiresClientSignature() && client.getClientSigningCertificate() == null) {
CertificateRepresentation info = KeycloakModelUtils.generateKeyPairCertificate(newClient.getClientId());
client.setClientSigningCertificate(info.getCertificate());
client.setClientSigningPrivateKey(info.getPrivateKey());
}
if (clientRep.isFrontchannelLogout() == null) {
newClient.setFrontchannelLogout(true);
}
}
@Override
public void setupTemplateDefaults(ClientTemplateRepresentation clientRep, ClientTemplateModel newClient) {
SamlRepresentationAttributes rep = new SamlRepresentationAttributes(clientRep.getAttributes());
SamlClientTemplate client = new SamlClientTemplate(newClient);
if (clientRep.isStandardFlowEnabled() == null) newClient.setStandardFlowEnabled(true);
if (rep.getCanonicalizationMethod() == null) {
client.setCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE);
}
if (rep.getSignatureAlgorithm() == null) {
client.setSignatureAlgorithm(SignatureAlgorithm.RSA_SHA256);
}
if (rep.getNameIDFormat() == null) {
client.setNameIDFormat("username");
}
if (rep.getIncludeAuthnStatement() == null) {
client.setIncludeAuthnStatement(true);
}
if (rep.getForceNameIDFormat() == null) {
client.setForceNameIDFormat(false);
}
if (rep.getSamlServerSignature() == null) {
client.setRequiresRealmSignature(true);
}
if (rep.getForcePostBinding() == null) {
client.setForcePostBinding(true);
}
if (rep.getClientSignature() == null) {
client.setRequiresClientSignature(true);
}
if (clientRep.isFrontchannelLogout() == null) {

View file

@ -25,7 +25,8 @@ public class SamlProtocolUtils {
public static void verifyDocumentSignature(ClientModel client, Document document) throws VerificationException {
if (!"true".equals(client.getAttribute(SamlProtocol.SAML_CLIENT_SIGNATURE_ATTRIBUTE))) {
SamlClient samlClient = new SamlClient(client);
if (!samlClient.requiresClientSignature()) {
return;
}
PublicKey publicKey = getSignatureValidationKey(client);
@ -44,7 +45,7 @@ public class SamlProtocolUtils {
}
public static PublicKey getSignatureValidationKey(ClientModel client) throws VerificationException {
return getPublicKey(client, SamlProtocol.SAML_SIGNING_CERTIFICATE_ATTRIBUTE);
return getPublicKey(new SamlClient(client).getClientSigningCertificate());
}
public static PublicKey getEncryptionValidationKey(ClientModel client) throws VerificationException {
@ -53,6 +54,10 @@ public class SamlProtocolUtils {
public static PublicKey getPublicKey(ClientModel client, String attribute) throws VerificationException {
String certPem = client.getAttribute(attribute);
return getPublicKey(certPem);
}
private static PublicKey getPublicKey(String certPem) throws VerificationException {
if (certPem == null) throw new VerificationException("Client does not have a public key.");
Certificate cert = null;
try {

View file

@ -0,0 +1,65 @@
package org.keycloak.protocol.saml;
import org.keycloak.representations.idm.ClientRepresentation;
import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class SamlRepresentationAttributes {
protected Map<String, String> attributes;
public SamlRepresentationAttributes(Map<String, String> attributes) {
this.attributes = attributes;
}
public String getCanonicalizationMethod() {
if (getAttributes() == null) return null;
return getAttributes().get(SamlConfigAttributes.SAML_CANONICALIZATION_METHOD_ATTRIBUTE);
}
protected Map<String, String> getAttributes() {
return attributes;
}
public String getSignatureAlgorithm() {
if (getAttributes() == null) return null;
return getAttributes().get(SamlConfigAttributes.SAML_SIGNATURE_ALGORITHM);
}
public String getNameIDFormat() {
if (getAttributes() == null) return null;
return getAttributes().get(SamlConfigAttributes.SAML_NAME_ID_FORMAT_ATTRIBUTE);
}
public String getIncludeAuthnStatement() {
if (getAttributes() == null) return null;
return getAttributes().get(SamlConfigAttributes.SAML_AUTHNSTATEMENT);
}
public String getForceNameIDFormat() {
if (getAttributes() == null) return null;
return getAttributes().get(SamlConfigAttributes.SAML_FORCE_NAME_ID_FORMAT_ATTRIBUTE);
}
public String getSamlServerSignature() {
if (getAttributes() == null) return null;
return getAttributes().get(SamlConfigAttributes.SAML_SERVER_SIGNATURE);
}
public String getForcePostBinding() {
if (getAttributes() == null) return null;
return getAttributes().get(SamlConfigAttributes.SAML_FORCE_POST_BINDING);
}
public String getClientSignature() {
if (getAttributes() == null) return null;
return getAttributes().get(SamlConfigAttributes.SAML_CLIENT_SIGNATURE_ATTRIBUTE);
}
}

View file

@ -192,6 +192,7 @@ public class SamlService extends AuthorizationEndpointBase {
protected abstract SAMLDocumentHolder extractResponseDocument(String response);
protected Response loginRequest(String relayState, AuthnRequestType requestAbstractType, ClientModel client) {
SamlClient samlClient = new SamlClient(client);
// validate destination
if (requestAbstractType.getDestination() != null && !uriInfo.getAbsolutePath().equals(requestAbstractType.getDestination())) {
event.detail(Details.REASON, "invalid_destination");
@ -199,7 +200,7 @@ public class SamlService extends AuthorizationEndpointBase {
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
String bindingType = getBindingType(requestAbstractType);
if ("true".equals(client.getAttribute(SamlProtocol.SAML_FORCE_POST_BINDING)))
if (samlClient.forcePostBinding())
bindingType = SamlProtocol.SAML_POST_BINDING;
String redirect = null;
URI redirectUri = requestAbstractType.getAssertionConsumerServiceURL();
@ -233,7 +234,7 @@ public class SamlService extends AuthorizationEndpointBase {
// Handle NameIDPolicy from SP
NameIDPolicyType nameIdPolicy = requestAbstractType.getNameIDPolicy();
if (nameIdPolicy != null && !SamlProtocol.forceNameIdFormat(client)) {
if (nameIdPolicy != null && !samlClient.forceNameIDFormat()) {
String nameIdFormat = nameIdPolicy.getFormat().toString();
// TODO: Handle AllowCreate too, relevant for persistent NameID.
if (isSupportedNameIdFormat(nameIdFormat)) {
@ -273,6 +274,7 @@ public class SamlService extends AuthorizationEndpointBase {
protected abstract String getBindingType();
protected Response logoutRequest(LogoutRequestType logoutRequest, ClientModel client, String relayState) {
SamlClient samlClient = new SamlClient(client);
// validate destination
if (logoutRequest.getDestination() != null && !uriInfo.getAbsolutePath().equals(logoutRequest.getDestination())) {
event.detail(Details.REASON, "invalid_destination");
@ -284,20 +286,20 @@ public class SamlService extends AuthorizationEndpointBase {
AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm, false);
if (authResult != null) {
String logoutBinding = getBindingType();
if ("true".equals(client.getAttribute(SamlProtocol.SAML_FORCE_POST_BINDING)))
if ("true".equals(samlClient.forcePostBinding()))
logoutBinding = SamlProtocol.SAML_POST_BINDING;
String bindingUri = SamlProtocol.getLogoutServiceUrl(uriInfo, client, logoutBinding);
UserSessionModel userSession = authResult.getSession();
userSession.setNote(SamlProtocol.SAML_LOGOUT_BINDING_URI, bindingUri);
if (SamlProtocol.requiresRealmSignature(client)) {
userSession.setNote(SamlProtocol.SAML_LOGOUT_SIGNATURE_ALGORITHM, SamlProtocol.getSignatureAlgorithm(client).toString());
if (samlClient.requiresRealmSignature()) {
userSession.setNote(SamlProtocol.SAML_LOGOUT_SIGNATURE_ALGORITHM, samlClient.getSignatureAlgorithm().toString());
}
if (relayState != null)
userSession.setNote(SamlProtocol.SAML_LOGOUT_RELAY_STATE, relayState);
userSession.setNote(SamlProtocol.SAML_LOGOUT_REQUEST_ID, logoutRequest.getID());
userSession.setNote(SamlProtocol.SAML_LOGOUT_BINDING, logoutBinding);
userSession.setNote(SamlProtocol.SAML_LOGOUT_CANONICALIZATION, client.getAttribute(SamlProtocol.SAML_CANONICALIZATION_METHOD_ATTRIBUTE));
userSession.setNote(SamlProtocol.SAML_LOGOUT_CANONICALIZATION, samlClient.getCanonicalizationMethod());
userSession.setNote(AuthenticationManager.KEYCLOAK_LOGOUT_PROTOCOL, SamlProtocol.LOGIN_PROTOCOL);
// remove client from logout requests
for (ClientSessionModel clientSession : userSession.getClientSessions()) {
@ -347,8 +349,8 @@ public class SamlService extends AuthorizationEndpointBase {
builder.destination(logoutBindingUri);
builder.issuer(RealmsResource.realmBaseUrl(uriInfo).build(realm.getName()).toString());
JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder().relayState(logoutRelayState);
if (SamlProtocol.requiresRealmSignature(client)) {
SignatureAlgorithm algorithm = SamlProtocol.getSignatureAlgorithm(client);
if (samlClient.requiresRealmSignature()) {
SignatureAlgorithm algorithm = samlClient.getSignatureAlgorithm();
binding.signatureAlgorithm(algorithm).signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate()).signDocument();
}
@ -410,7 +412,8 @@ public class SamlService extends AuthorizationEndpointBase {
@Override
protected void verifySignature(SAMLDocumentHolder documentHolder, ClientModel client) throws VerificationException {
if (!"true".equals(client.getAttribute("saml.client.signature"))) {
SamlClient samlClient = new SamlClient(client);
if (!samlClient.requiresClientSignature()) {
return;
}
PublicKey publicKey = SamlProtocolUtils.getSignatureValidationKey(client);

View file

@ -9,6 +9,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.utils.DefaultAuthenticationFlows;
import org.keycloak.protocol.saml.JaxrsSAML2BindingBuilder;
import org.keycloak.protocol.saml.SamlConfigAttributes;
import org.keycloak.protocol.saml.SamlProtocol;
import org.keycloak.protocol.saml.SamlService;
import org.keycloak.protocol.saml.profile.ecp.util.Soap;
@ -99,7 +100,7 @@ public class SamlEcpProfileService extends SamlService {
private void createRequestAuthenticatedHeader(ClientSessionModel clientSession, Soap.SoapMessageBuilder messageBuilder) {
ClientModel client = clientSession.getClient();
if ("true".equals(client.getAttribute(SamlProtocol.SAML_CLIENT_SIGNATURE_ATTRIBUTE))) {
if ("true".equals(client.getAttribute(SamlConfigAttributes.SAML_CLIENT_SIGNATURE_ATTRIBUTE))) {
SOAPHeaderElement ecpRequestAuthenticated = messageBuilder.addHeader(JBossSAMLConstants.REQUEST_AUTHENTICATED.get(), NS_PREFIX_PROFILE_ECP);
ecpRequestAuthenticated.setMustUnderstand(true);

View file

@ -2,10 +2,12 @@ package org.keycloak.protocol;
import org.keycloak.events.EventBuilder;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ClientTemplateRepresentation;
import org.keycloak.services.managers.AuthenticationManager;
import java.util.List;
@ -31,10 +33,18 @@ public interface LoginProtocolFactory extends ProviderFactory<LoginProtocol> {
Object createProtocolEndpoint(RealmModel realm, EventBuilder event, AuthenticationManager authManager);
/**
* Setup default values for new clients.
* Setup default values for new clients. This expects that the representation has already set up the client
*
* @param rep
* @param newClient
*/
void setupClientDefaults(ClientRepresentation rep, ClientModel newClient);
/**
* Setup default values for new templates. This expects that the representation has already set up the template
*
* @param clientRep
* @param newClient
*/
void setupTemplateDefaults(ClientTemplateRepresentation clientRep, ClientTemplateModel newClient);
}

View file

@ -21,6 +21,7 @@ import org.keycloak.common.constants.KerberosConstants;
import org.keycloak.common.util.UriUtils;
import org.keycloak.events.EventBuilder;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
@ -32,6 +33,7 @@ import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
import org.keycloak.protocol.oidc.mappers.UserPropertyMapper;
import org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ClientTemplateRepresentation;
import org.keycloak.services.managers.AuthenticationManager;
import java.util.ArrayList;
@ -206,4 +208,9 @@ public class OIDCLoginProtocolFactory extends AbstractLoginProtocolFactory {
if (rep.isPublicClient() == null) newClient.setPublicClient(true);
if (rep.isFrontchannelLogout() == null) newClient.setFrontchannelLogout(false);
}
@Override
public void setupTemplateDefaults(ClientTemplateRepresentation clientRep, ClientTemplateModel newClient) {
}
}