From 3bacbdf6ff5007c5aca0bb4719202e71741b7514 Mon Sep 17 00:00:00 2001 From: Bill Burke Date: Mon, 4 Jan 2016 17:13:15 -0500 Subject: [PATCH] set framework for template config --- .../idm/ClientTemplateRepresentation.java | 82 +++++++++++ .../keycloak/models/ClientConfigResolver.java | 55 ++++++++ .../models/utils/RepresentationToModel.java | 36 ++++- .../keycloak/protocol/saml/SamlClient.java | 36 ++--- .../saml/SamlClientRepresentation.java | 59 -------- .../protocol/saml/SamlClientTemplate.java | 131 ++++++++++++++++++ .../protocol/saml/SamlProtocolFactory.java | 46 +++++- .../saml/SamlRepresentationAttributes.java | 65 +++++++++ .../keycloak/protocol/saml/SamlService.java | 3 +- .../profile/ecp/SamlEcpProfileService.java | 3 +- .../protocol/LoginProtocolFactory.java | 12 +- .../oidc/OIDCLoginProtocolFactory.java | 7 + 12 files changed, 449 insertions(+), 86 deletions(-) create mode 100755 model/api/src/main/java/org/keycloak/models/ClientConfigResolver.java delete mode 100755 saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlClientRepresentation.java create mode 100755 saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlClientTemplate.java create mode 100755 saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlRepresentationAttributes.java mode change 100644 => 100755 saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java diff --git a/core/src/main/java/org/keycloak/representations/idm/ClientTemplateRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ClientTemplateRepresentation.java index dc575c4109..e478c27600 100755 --- a/core/src/main/java/org/keycloak/representations/idm/ClientTemplateRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/ClientTemplateRepresentation.java @@ -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 attributes; + protected List 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 getAttributes() { + return attributes; + } + + public void setAttributes(Map attributes) { + this.attributes = attributes; + } } diff --git a/model/api/src/main/java/org/keycloak/models/ClientConfigResolver.java b/model/api/src/main/java/org/keycloak/models/ClientConfigResolver.java new file mode 100755 index 0000000000..8ec8728da7 --- /dev/null +++ b/model/api/src/main/java/org/keycloak/models/ClientConfigResolver.java @@ -0,0 +1,55 @@ +package org.keycloak.models; + +/** + * @author Bill Burke + * @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(); + } +} 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 2432fc1274..3b2cfdc5db 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 @@ -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 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 entry : rep.getAttributes().entrySet()) { + resource.setAttribute(entry.getKey(), entry.getValue()); + } + } + } public static long getClaimsMask(ClaimRepresentation rep) { diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlClient.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlClient.java index df27de2fbc..d935f83e2a 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlClient.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlClient.java @@ -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,14 @@ import org.keycloak.saml.SignatureAlgorithm; * @author Bill Burke * @version $Revision: 1 $ */ -public class SamlClient { - protected ClientModel client; +public class SamlClient extends ClientConfigResolver { public SamlClient(ClientModel client) { - this.client = client; + super(client); } - public String getId() { - return client.getId(); - } - - public String getClientId() { - return client.getClientId(); - } -// - public String getCanonicalizationMethod() { - return client.getAttribute(SamlConfigAttributes.SAML_CANONICALIZATION_METHOD_ATTRIBUTE); + return resolveAttribute(SamlConfigAttributes.SAML_CANONICALIZATION_METHOD_ATTRIBUTE); } public void setCanonicalizationMethod(String value) { @@ -32,7 +23,7 @@ public class SamlClient { } public SignatureAlgorithm getSignatureAlgorithm() { - String alg = client.getAttribute(SamlConfigAttributes.SAML_SIGNATURE_ALGORITHM); + String alg = resolveAttribute(SamlConfigAttributes.SAML_SIGNATURE_ALGORITHM); if (alg != null) { SignatureAlgorithm algorithm = SignatureAlgorithm.valueOf(alg); if (algorithm != null) @@ -46,14 +37,14 @@ public class SamlClient { } public String getNameIDFormat() { - return client.getAttributes().get(SamlConfigAttributes.SAML_NAME_ID_FORMAT_ATTRIBUTE); + return resolveAttribute(SamlConfigAttributes.SAML_NAME_ID_FORMAT_ATTRIBUTE); } public void setNameIDFormat(String format) { client.setAttribute(SamlConfigAttributes.SAML_NAME_ID_FORMAT_ATTRIBUTE, format); } public boolean includeAuthnStatement() { - return "true".equals(client.getAttribute(SamlConfigAttributes.SAML_AUTHNSTATEMENT)); + return "true".equals(resolveAttribute(SamlConfigAttributes.SAML_AUTHNSTATEMENT)); } public void setIncludeAuthnStatement(boolean val) { @@ -61,7 +52,7 @@ public class SamlClient { } public boolean forceNameIDFormat() { - return "true".equals(client.getAttribute(SamlConfigAttributes.SAML_FORCE_NAME_ID_FORMAT_ATTRIBUTE)); + return "true".equals(resolveAttribute(SamlConfigAttributes.SAML_FORCE_NAME_ID_FORMAT_ATTRIBUTE)); } public void setForceNameIDFormat(boolean val) { @@ -69,7 +60,7 @@ public class SamlClient { } public boolean requiresRealmSignature() { - return "true".equals(client.getAttribute(SamlConfigAttributes.SAML_SERVER_SIGNATURE)); + return "true".equals(resolveAttribute(SamlConfigAttributes.SAML_SERVER_SIGNATURE)); } public void setRequiresRealmSignature(boolean val) { @@ -78,7 +69,7 @@ public class SamlClient { } public boolean forcePostBinding() { - return "true".equals(client.getAttribute(SamlConfigAttributes.SAML_FORCE_POST_BINDING)); + return "true".equals(resolveAttribute(SamlConfigAttributes.SAML_FORCE_POST_BINDING)); } public void setForcePostBinding(boolean val) { @@ -86,7 +77,7 @@ public class SamlClient { } public boolean requiresAssertionSignature() { - return "true".equals(client.getAttribute(SamlConfigAttributes.SAML_ASSERTION_SIGNATURE)); + return "true".equals(resolveAttribute(SamlConfigAttributes.SAML_ASSERTION_SIGNATURE)); } public void setRequiresAssertionSignature(boolean val) { @@ -94,7 +85,7 @@ public class SamlClient { } public boolean requiresEncryption() { - return "true".equals(client.getAttribute(SamlConfigAttributes.SAML_ENCRYPT)); + return "true".equals(resolveAttribute(SamlConfigAttributes.SAML_ENCRYPT)); } @@ -104,7 +95,7 @@ public class SamlClient { } public boolean requiresClientSignature() { - return "true".equals(client.getAttribute(SamlConfigAttributes.SAML_CLIENT_SIGNATURE_ATTRIBUTE)); + return "true".equals(resolveAttribute(SamlConfigAttributes.SAML_CLIENT_SIGNATURE_ATTRIBUTE)); } public void setRequiresClientSignature(boolean val) { @@ -129,4 +120,5 @@ public class SamlClient { client.setAttribute(SamlConfigAttributes.SAML_SIGNING_PRIVATE_KEY, val); } + } diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlClientRepresentation.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlClientRepresentation.java deleted file mode 100755 index 0ce4beba43..0000000000 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlClientRepresentation.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.keycloak.protocol.saml; - -import org.keycloak.representations.idm.ClientRepresentation; - -/** - * @author Bill Burke - * @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(SamlConfigAttributes.SAML_CANONICALIZATION_METHOD_ATTRIBUTE); - } - - public String getSignatureAlgorithm() { - if (rep.getAttributes() == null) return null; - return rep.getAttributes().get(SamlConfigAttributes.SAML_SIGNATURE_ALGORITHM); - } - - public String getNameIDFormat() { - if (rep.getAttributes() == null) return null; - return rep.getAttributes().get(SamlConfigAttributes.SAML_NAME_ID_FORMAT_ATTRIBUTE); - - } - - public String getIncludeAuthnStatement() { - if (rep.getAttributes() == null) return null; - return rep.getAttributes().get(SamlConfigAttributes.SAML_AUTHNSTATEMENT); - - } - - public String getForceNameIDFormat() { - if (rep.getAttributes() == null) return null; - return rep.getAttributes().get(SamlConfigAttributes.SAML_FORCE_NAME_ID_FORMAT_ATTRIBUTE); - } - - public String getSamlServerSignature() { - if (rep.getAttributes() == null) return null; - return rep.getAttributes().get(SamlConfigAttributes.SAML_SERVER_SIGNATURE); - - } - - public String getForcePostBinding() { - if (rep.getAttributes() == null) return null; - return rep.getAttributes().get(SamlConfigAttributes.SAML_FORCE_POST_BINDING); - - } - public String getClientSignature() { - if (rep.getAttributes() == null) return null; - return rep.getAttributes().get(SamlConfigAttributes.SAML_CLIENT_SIGNATURE_ATTRIBUTE); - - } -} diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlClientTemplate.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlClientTemplate.java new file mode 100755 index 0000000000..ae6d491795 --- /dev/null +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlClientTemplate.java @@ -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 Bill Burke + * @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); + + } +} diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolFactory.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolFactory.java index 6ec5a1abd3..1de9f456aa 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolFactory.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolFactory.java @@ -105,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) { @@ -136,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) { diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlRepresentationAttributes.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlRepresentationAttributes.java new file mode 100755 index 0000000000..5933773d3d --- /dev/null +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlRepresentationAttributes.java @@ -0,0 +1,65 @@ +package org.keycloak.protocol.saml; + +import org.keycloak.representations.idm.ClientRepresentation; + +import java.util.Map; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class SamlRepresentationAttributes { + protected Map attributes; + + public SamlRepresentationAttributes(Map attributes) { + this.attributes = attributes; + } + + public String getCanonicalizationMethod() { + if (getAttributes() == null) return null; + return getAttributes().get(SamlConfigAttributes.SAML_CANONICALIZATION_METHOD_ATTRIBUTE); + } + + protected Map 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); + + } +} diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java index a09dd390cd..bd6e84693f 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java @@ -412,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); diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java old mode 100644 new mode 100755 index 52b855702b..f2623464b9 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java @@ -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); diff --git a/services/src/main/java/org/keycloak/protocol/LoginProtocolFactory.java b/services/src/main/java/org/keycloak/protocol/LoginProtocolFactory.java index a876b194b5..2238e6f21f 100755 --- a/services/src/main/java/org/keycloak/protocol/LoginProtocolFactory.java +++ b/services/src/main/java/org/keycloak/protocol/LoginProtocolFactory.java @@ -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 { 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); } diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java index 8cd0d8fed5..ee710cec48 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java @@ -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) { + + } }