keycloak-uncached
Changes
forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js 9(+8 -1)
forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html 12(+12 -0)
saml/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java 130(+5 -125)
Details
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
index 0b599bf..61eefd9 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
@@ -570,6 +570,13 @@ module.controller('ClientDetailCtrl', function($scope, realm, client, $route, se
"persistent"
];
+ $scope.canonicalization = [
+ {name: "EXCLUSIVE", value: "http://www.w3.org/2001/10/xml-exc-c14n#" },
+ {name: "EXCLUSIVE_WITH_COMMENTS", value: "http://www.w3.org/2001/10/xml-exc-c14n#WithComments"},
+ {name: "INCLUSIVE", value: "http://www.w3.org/TR/2001/REC-xml-c14n-20010315" },
+ {name: "INCLUSIVE_WITH_COMMENTS", value: "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"}
+ ];
+
$scope.realm = realm;
$scope.create = !client.clientId;
$scope.samlAuthnStatement = false;
@@ -614,9 +621,9 @@ module.controller('ClientDetailCtrl', function($scope, realm, client, $route, se
} else if (client.attributes['saml_name_id_format'] == 'persistent') {
$scope.nameIdFormat = $scope.nameIdFormats[3];
}
-
} else {
$scope.client = { enabled: true, attributes: {}};
+ $scope.client.attributes['saml_signature_canonicalization_method'] = $scope.canonicalization[0].value;
$scope.client.redirectUris = [];
$scope.accessType = $scope.accessTypes[0];
$scope.protocol = $scope.protocols[0];
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
index 727c66d..06c939b 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
@@ -113,6 +113,18 @@
</div>
<kc-tooltip>The signature algorithm to use to sign documents.</kc-tooltip>
</div>
+ <div class="form-group" data-ng-show="(samlAssertionSignature || samlServerSignature) && protocol == 'saml'">
+ <label class="col-md-2 control-label" for="canonicalization">Canonicalization Method</label>
+ <div class="col-sm-6">
+ <div>
+ <select class="form-control" id="canonicalization"
+ ng-model="client.attributes['saml_signature_canonicalization_method']"
+ ng-options="canon.value as canon.name for canon in canonicalization">
+ </select>
+ </div>
+ </div>
+ <kc-tooltip>Canonicalization Method for XML signatures.</kc-tooltip>
+ </div>
<div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
<label class="col-md-2 control-label" for="samlEncrypt">Encrypt Assertions</label>
<div class="col-sm-6">
diff --git a/saml/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java b/saml/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java
index cb86c19..b4cf8a5 100755
--- a/saml/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java
+++ b/saml/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java
@@ -120,72 +120,9 @@ public class SAML2Signature {
}
/**
- * Sign an RequestType at the root
- *
- * @param request
- * @param keypair Key Pair
- * @param digestMethod (Example: DigestMethod.SHA1)
- * @param signatureMethod (Example: SignatureMethod.DSA_SHA1)
- *
- * @return
- *
- * @throws ParserConfigurationException
- * @throws IOException
- * @throws SAXException
- * @throws XMLSignatureException
- * @throws MarshalException
- * @throws GeneralSecurityException
- */
- public Document sign(RequestAbstractType request, KeyPair keypair) throws SAXException, IOException,
- ParserConfigurationException, GeneralSecurityException, MarshalException, XMLSignatureException {
- SAML2Request saml2Request = new SAML2Request();
- Document doc = saml2Request.convert(request);
- doc.normalize();
-
- Node theSibling = getNextSiblingOfIssuer(doc);
- if (theSibling != null) {
- this.sibling = theSibling;
- }
-
- return sign(doc, request.getID(), keypair);
- }
-
- /**
- * Sign an ResponseType at the root
- *
- * @param response
- * @param keypair Key Pair
- * @param digestMethod (Example: DigestMethod.SHA1)
- * @param signatureMethod (Example: SignatureMethod.DSA_SHA1)
- *
- * @return
- *
- * @throws ParserConfigurationException
- * @throws XMLSignatureException
- * @throws MarshalException
- * @throws GeneralSecurityException
- */
- public Document sign(ResponseType response, KeyPair keypair) throws ParserConfigurationException, GeneralSecurityException,
- MarshalException, XMLSignatureException {
- SAML2Response saml2Request = new SAML2Response();
- Document doc = saml2Request.convert(response);
- doc.normalize();
-
- Node theSibling = getNextSiblingOfIssuer(doc);
- if (theSibling != null) {
- this.sibling = theSibling;
- }
-
- return sign(doc, response.getID(), keypair);
- }
-
- /**
* Sign an Document at the root
*
- * @param response
* @param keyPair Key Pair
- * @param digestMethod (Example: DigestMethod.SHA1)
- * @param signatureMethod (Example: SignatureMethod.DSA_SHA1)
*
* @return
*
@@ -194,7 +131,7 @@ public class SAML2Signature {
* @throws MarshalException
* @throws GeneralSecurityException
*/
- public Document sign(Document doc, String referenceID, KeyPair keyPair) throws ParserConfigurationException,
+ public Document sign(Document doc, String referenceID, KeyPair keyPair, String canonicalizationMethodType) throws ParserConfigurationException,
GeneralSecurityException, MarshalException, XMLSignatureException {
String referenceURI = "#" + referenceID;
@@ -213,66 +150,9 @@ public class SAML2Signature {
dto.setX509Certificate(x509Certificate);
}
- return XMLSignatureUtil.sign(dto);
- }
- return XMLSignatureUtil.sign(doc, keyPair, digestMethod, signatureMethod, referenceURI);
- }
-
- /**
- * Sign an assertion whose id value is provided in the response type
- *
- * @param response
- * @param idValueOfAssertion
- * @param keypair
- * @param referenceURI
- *
- * @return
- *
- * @throws ParserConfigurationException
- * @throws TransformerException
- * @throws TransformerFactoryConfigurationError
- * @throws XPathException
- * @throws XMLSignatureException
- * @throws MarshalException
- * @throws GeneralSecurityException
- */
- public Document sign(ResponseType response, String idValueOfAssertion, KeyPair keypair, String referenceURI)
- throws ParserConfigurationException, XPathException, TransformerFactoryConfigurationError, TransformerException,
- GeneralSecurityException, MarshalException, XMLSignatureException {
- SAML2Response saml2Response = new SAML2Response();
- Document doc = saml2Response.convert(response);
- doc.normalize();
-
- Node theSibling = getNextSiblingOfIssuer(doc);
- if (theSibling != null) {
- this.sibling = theSibling;
+ return XMLSignatureUtil.sign(dto, canonicalizationMethodType);
}
-
- return sign(doc, idValueOfAssertion, keypair, referenceURI);
- }
-
- /**
- * Sign a document
- *
- * @param doc
- * @param idValueOfAssertion
- * @param keypair
- * @param referenceURI
- *
- * @return
- *
- * @throws ParserConfigurationException
- * @throws XPathException
- * @throws TransformerFactoryConfigurationError
- * @throws TransformerException
- * @throws GeneralSecurityException
- * @throws MarshalException
- * @throws XMLSignatureException
- */
- public Document sign(Document doc, String idValueOfAssertion, KeyPair keypair, String referenceURI)
- throws ParserConfigurationException, XPathException, TransformerFactoryConfigurationError, TransformerException,
- GeneralSecurityException, MarshalException, XMLSignatureException {
- return sign(doc, idValueOfAssertion, keypair);
+ return XMLSignatureUtil.sign(doc, keyPair, digestMethod, signatureMethod, referenceURI, canonicalizationMethodType);
}
/**
@@ -283,11 +163,11 @@ public class SAML2Signature {
*
* @throws org.keycloak.saml.common.exceptions.ProcessingException
*/
- public void signSAMLDocument(Document samlDocument, KeyPair keypair) throws ProcessingException {
+ public void signSAMLDocument(Document samlDocument, KeyPair keypair, String canonicalizationMethodType) throws ProcessingException {
// Get the ID from the root
String id = samlDocument.getDocumentElement().getAttribute(ID_ATTRIBUTE_NAME);
try {
- sign(samlDocument, id, keypair);
+ sign(samlDocument, id, keypair, canonicalizationMethodType);
} catch (Exception e) {
throw new ProcessingException(logger.signatureError(e));
}
diff --git a/saml/saml-core/src/main/java/org/keycloak/saml/processing/core/util/XMLSignatureUtil.java b/saml/saml-core/src/main/java/org/keycloak/saml/processing/core/util/XMLSignatureUtil.java
index aa4322e..42437f1 100755
--- a/saml/saml-core/src/main/java/org/keycloak/saml/processing/core/util/XMLSignatureUtil.java
+++ b/saml/saml-core/src/main/java/org/keycloak/saml/processing/core/util/XMLSignatureUtil.java
@@ -106,7 +106,7 @@ public class XMLSignatureUtil {
;
- private static String canonicalizationMethodType = CanonicalizationMethod.EXCLUSIVE_WITH_COMMENTS;
+ private static String canonicalizationMethodType = CanonicalizationMethod.EXCLUSIVE;
private static XMLSignatureFactory fac = getXMLSignatureFactory();
@@ -131,16 +131,6 @@ public class XMLSignatureUtil {
}
/**
- * Set the canonicalization method type
- *
- * @param canonical
- */
- public static void setCanonicalizationMethodType(String canonical) {
- if (canonical != null)
- canonicalizationMethodType = canonical;
- }
-
- /**
* Use this method to not include the KeyInfo in the signature
*
* @param includeKeyInfoInSignature
@@ -152,115 +142,11 @@ public class XMLSignatureUtil {
}
/**
- * Precheck whether the document that will be validated has the right signedinfo
- *
- * @param doc
- *
- * @return
- */
- public static boolean preCheckSignedInfo(Document doc) {
- NodeList nl = doc.getElementsByTagNameNS(JBossSAMLURIConstants.XMLDSIG_NSURI.get(), "SignedInfo");
- return nl != null ? nl.getLength() > 0 : false;
- }
-
- /**
- * Sign a node in a document
- *
- * @param doc Document
- * @param parentOfNodeToBeSigned Parent Node of the node to be signed
- * @param signingKey Private Key
- * @param certificate X509 Certificate holding the public key
- * @param digestMethod (Example: DigestMethod.SHA1)
- * @param signatureMethod (Example: SignatureMethod.DSA_SHA1)
- * @param referenceURI
- *
- * @return Document that contains the signed node
- *
- * @throws XMLSignatureException
- * @throws MarshalException
- * @throws GeneralSecurityException
- * @throws ParserConfigurationException
- */
- public static Document sign(Document doc, Node parentOfNodeToBeSigned, PrivateKey signingKey, X509Certificate certificate,
- String digestMethod, String signatureMethod, String referenceURI) throws ParserConfigurationException,
- GeneralSecurityException, MarshalException, XMLSignatureException {
- KeyPair keyPair = new KeyPair(certificate.getPublicKey(), signingKey);
- return sign(doc, parentOfNodeToBeSigned, keyPair, digestMethod, signatureMethod, referenceURI);
- }
-
- /**
- * Sign a node in a document
- *
- * @param doc
- * @param nodeToBeSigned
- * @param keyPair
- * @param publicKey
- * @param digestMethod
- * @param signatureMethod
- * @param referenceURI
- *
- * @return
- *
- * @throws ParserConfigurationException
- * @throws XMLSignatureException
- * @throws MarshalException
- * @throws GeneralSecurityException
- */
- public static Document sign(Document doc, Node nodeToBeSigned, KeyPair keyPair, String digestMethod,
- String signatureMethod, String referenceURI) throws ParserConfigurationException, GeneralSecurityException,
- MarshalException, XMLSignatureException {
- if (nodeToBeSigned == null)
- throw logger.nullArgumentError("Node to be signed");
-
- if (logger.isTraceEnabled()) {
- logger.trace("Document to be signed=" + DocumentUtil.asString(doc));
- }
-
- Node parentNode = nodeToBeSigned.getParentNode();
-
- // Let us create a new Document
- Document newDoc = DocumentUtil.createDocument();
- // Import the node
- Node signingNode = newDoc.importNode(nodeToBeSigned, true);
- newDoc.appendChild(signingNode);
-
- if (!referenceURI.isEmpty()) {
- propagateIDAttributeSetup(nodeToBeSigned, newDoc.getDocumentElement());
- }
- newDoc = sign(newDoc, keyPair, digestMethod, signatureMethod, referenceURI);
-
- // if the signed element is a SAMLv2.0 assertion we need to move the signature element to the position
- // specified in the schema (before the assertion subject element).
- if (nodeToBeSigned.getLocalName().equals("Assertion")
- && WSTrustConstants.SAML2_ASSERTION_NS.equals(nodeToBeSigned.getNamespaceURI())) {
- Node signatureNode = DocumentUtil.getElement(newDoc, new QName(WSTrustConstants.DSIG_NS, "Signature"));
- Node subjectNode = DocumentUtil.getElement(newDoc, new QName(WSTrustConstants.SAML2_ASSERTION_NS, "Subject"));
- if (signatureNode != null && subjectNode != null) {
- newDoc.getDocumentElement().removeChild(signatureNode);
- newDoc.getDocumentElement().insertBefore(signatureNode, subjectNode);
- }
- }
-
- // Now let us import this signed doc into the original document we got in the method call
- Node signedNode = doc.importNode(newDoc.getFirstChild(), true);
-
- if (!referenceURI.isEmpty()) {
- propagateIDAttributeSetup(newDoc.getDocumentElement(), (Element) signedNode);
- }
-
- parentNode.replaceChild(signedNode, nodeToBeSigned);
- // doc.getDocumentElement().replaceChild(signedNode, nodeToBeSigned);
-
- return doc;
- }
-
- /**
* Sign a node in a document
*
* @param doc
* @param nodeToBeSigned
* @param keyPair
- * @param publicKey
* @param digestMethod
* @param signatureMethod
* @param referenceURI
@@ -273,7 +159,8 @@ public class XMLSignatureUtil {
* @throws GeneralSecurityException
*/
public static Document sign(Document doc, Node nodeToBeSigned, KeyPair keyPair, String digestMethod,
- String signatureMethod, String referenceURI, X509Certificate x509Certificate) throws ParserConfigurationException, GeneralSecurityException,
+ String signatureMethod, String referenceURI, X509Certificate x509Certificate,
+ String canonicalizationMethodType) throws ParserConfigurationException, GeneralSecurityException,
MarshalException, XMLSignatureException {
if (nodeToBeSigned == null)
throw logger.nullArgumentError("Node to be signed");
@@ -293,7 +180,7 @@ public class XMLSignatureUtil {
if (!referenceURI.isEmpty()) {
propagateIDAttributeSetup(nodeToBeSigned, newDoc.getDocumentElement());
}
- newDoc = sign(newDoc, keyPair, digestMethod, signatureMethod, referenceURI, x509Certificate);
+ newDoc = sign(newDoc, keyPair, digestMethod, signatureMethod, referenceURI, x509Certificate, canonicalizationMethodType);
// if the signed element is a SAMLv2.0 assertion we need to move the signature element to the position
// specified in the schema (before the assertion subject element).
@@ -335,9 +222,9 @@ public class XMLSignatureUtil {
* @throws XMLSignatureException
*/
public static void sign(Element elementToSign, Node nextSibling, KeyPair keyPair, String digestMethod,
- String signatureMethod, String referenceURI)
+ String signatureMethod, String referenceURI, String canonicalizationMethodType)
throws GeneralSecurityException, MarshalException, XMLSignatureException {
- sign(elementToSign, nextSibling, keyPair, digestMethod, signatureMethod, referenceURI, null);
+ sign(elementToSign, nextSibling, keyPair, digestMethod, signatureMethod, referenceURI, null, canonicalizationMethodType);
}
/**
@@ -357,14 +244,14 @@ public class XMLSignatureUtil {
* @since 2.5.0
*/
public static void sign(Element elementToSign, Node nextSibling, KeyPair keyPair, String digestMethod,
- String signatureMethod, String referenceURI, X509Certificate x509Certificate)
+ String signatureMethod, String referenceURI, X509Certificate x509Certificate, String canonicalizationMethodType)
throws GeneralSecurityException, MarshalException, XMLSignatureException {
PrivateKey signingKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
DOMSignContext dsc = new DOMSignContext(signingKey, elementToSign, nextSibling);
- signImpl(dsc, digestMethod, signatureMethod, referenceURI, publicKey, x509Certificate);
+ signImpl(dsc, digestMethod, signatureMethod, referenceURI, publicKey, x509Certificate, canonicalizationMethodType);
}
/**
@@ -372,7 +259,6 @@ public class XMLSignatureUtil {
* <code>sourceNode</code>.
*
* @param sourceNode
- * @param destDocElement
*/
public static void propagateIDAttributeSetup(Node sourceNode, Element destElement) {
NamedNodeMap nnm = sourceNode.getAttributes();
@@ -389,8 +275,6 @@ public class XMLSignatureUtil {
* Sign the root element
*
* @param doc
- * @param signingKey
- * @param publicKey
* @param digestMethod
* @param signatureMethod
* @param referenceURI
@@ -401,17 +285,15 @@ public class XMLSignatureUtil {
* @throws XMLSignatureException
* @throws MarshalException
*/
- public static Document sign(Document doc, KeyPair keyPair, String digestMethod, String signatureMethod, String referenceURI)
+ public static Document sign(Document doc, KeyPair keyPair, String digestMethod, String signatureMethod, String referenceURI, String canonicalizationMethodType)
throws GeneralSecurityException, MarshalException, XMLSignatureException {
- return sign(doc, keyPair, digestMethod, signatureMethod, referenceURI, null);
+ return sign(doc, keyPair, digestMethod, signatureMethod, referenceURI, null, canonicalizationMethodType);
}
/**
* Sign the root element
*
* @param doc
- * @param signingKey
- * @param publicKey
* @param digestMethod
* @param signatureMethod
* @param referenceURI
@@ -424,7 +306,7 @@ public class XMLSignatureUtil {
* @since 2.5.0
*/
public static Document sign(Document doc, KeyPair keyPair, String digestMethod, String signatureMethod, String referenceURI,
- X509Certificate x509Certificate)
+ X509Certificate x509Certificate, String canonicalizationMethodType)
throws GeneralSecurityException, MarshalException, XMLSignatureException {
logger.trace("Document to be signed=" + DocumentUtil.asString(doc));
PrivateKey signingKey = keyPair.getPrivate();
@@ -432,7 +314,7 @@ public class XMLSignatureUtil {
DOMSignContext dsc = new DOMSignContext(signingKey, doc.getDocumentElement());
- signImpl(dsc, digestMethod, signatureMethod, referenceURI, publicKey, x509Certificate);
+ signImpl(dsc, digestMethod, signatureMethod, referenceURI, publicKey, x509Certificate, canonicalizationMethodType);
return doc;
}
@@ -440,12 +322,6 @@ public class XMLSignatureUtil {
/**
* Sign the root element
*
- * @param doc
- * @param signingKey
- * @param publicKey
- * @param digestMethod
- * @param signatureMethod
- * @param referenceURI
*
* @return
*
@@ -453,7 +329,7 @@ public class XMLSignatureUtil {
* @throws XMLSignatureException
* @throws MarshalException
*/
- public static Document sign(SignatureUtilTransferObject dto) throws GeneralSecurityException, MarshalException,
+ public static Document sign(SignatureUtilTransferObject dto, String canonicalizationMethodType) throws GeneralSecurityException, MarshalException,
XMLSignatureException {
Document doc = dto.getDocumentToBeSigned();
KeyPair keyPair = dto.getKeyPair();
@@ -469,7 +345,7 @@ public class XMLSignatureUtil {
DOMSignContext dsc = new DOMSignContext(signingKey, doc.getDocumentElement(), nextSibling);
- signImpl(dsc, digestMethod, signatureMethod, referenceURI, publicKey, dto.getX509Certificate());
+ signImpl(dsc, digestMethod, signatureMethod, referenceURI, publicKey, dto.getX509Certificate(), canonicalizationMethodType);
return doc;
}
@@ -697,7 +573,7 @@ public class XMLSignatureUtil {
}
private static void signImpl(DOMSignContext dsc, String digestMethod, String signatureMethod, String referenceURI, PublicKey publicKey,
- X509Certificate x509Certificate)
+ X509Certificate x509Certificate, String canonicalizationMethodType)
throws GeneralSecurityException, MarshalException, XMLSignatureException {
dsc.setDefaultNamespacePrefix("dsig");
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java
index c59cd34..d2f3545 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java
@@ -21,6 +21,7 @@ import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
+import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.namespace.QName;
import java.io.IOException;
import java.net.URI;
@@ -53,6 +54,12 @@ public class SAML2BindingBuilder<T extends SAML2BindingBuilder> {
protected PublicKey encryptionPublicKey;
protected String encryptionAlgorithm = "AES";
protected boolean encrypt;
+ protected String canonicalizationMethodType = CanonicalizationMethod.EXCLUSIVE;
+
+ public T canonicalizationMethod(String method) {
+ this.canonicalizationMethodType = method;
+ return (T)this;
+ }
public T signDocument() {
this.sign = true;
@@ -260,7 +267,7 @@ public class SAML2BindingBuilder<T extends SAML2BindingBuilder> {
samlSignature.setX509Certificate(signingCertificate);
}
- samlSignature.signSAMLDocument(samlDocument, signingKeyPair);
+ samlSignature.signSAMLDocument(samlDocument, signingKeyPair, canonicalizationMethodType);
}
protected void signAssertion(Document samlDocument) throws ProcessingException {
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder2.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder2.java
index 56c94ca..c377206 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder2.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder2.java
@@ -21,6 +21,7 @@ import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
+import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.namespace.QName;
import java.io.IOException;
import java.net.URI;
@@ -50,6 +51,12 @@ public class SAML2BindingBuilder2<T extends SAML2BindingBuilder2> {
protected PublicKey encryptionPublicKey;
protected String encryptionAlgorithm = "AES";
protected boolean encrypt;
+ protected String canonicalizationMethodType = CanonicalizationMethod.EXCLUSIVE;
+
+ public T canonicalizationMethod(String method) {
+ this.canonicalizationMethodType = method;
+ return (T)this;
+ }
public T signDocument() {
this.sign = true;
@@ -237,7 +244,7 @@ public class SAML2BindingBuilder2<T extends SAML2BindingBuilder2> {
samlSignature.setX509Certificate(signingCertificate);
}
- samlSignature.signSAMLDocument(samlDocument, signingKeyPair);
+ samlSignature.signSAMLDocument(samlDocument, signingKeyPair, canonicalizationMethodType);
}
protected void signAssertion(Document samlDocument) throws ProcessingException {
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
index 13233b3..e4e8f6e 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
@@ -74,6 +74,7 @@ public class SamlProtocol implements LoginProtocol {
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";
@@ -89,6 +90,7 @@ public class SamlProtocol implements LoginProtocol {
public static final String SAML_LOGOUT_BINDING = "saml.logout.binding";
public static final String SAML_LOGOUT_REQUEST_ID = "SAML_LOGOUT_REQUEST_ID";
public static final String SAML_LOGOUT_RELAY_STATE = "SAML_LOGOUT_RELAY_STATE";
+ public static final String SAML_LOGOUT_CANONICALIZATION = "SAML_LOGOUT_CANONICALIZATION";
public static final String SAML_LOGOUT_BINDING_URI = "SAML_LOGOUT_BINDING_URI";
public static final String SAML_LOGOUT_SIGNATURE_ALGORITHM = "saml.logout.signature.algorithm";
public static final String SAML_NAME_ID = "SAML_NAME_ID";
@@ -338,11 +340,19 @@ public class SamlProtocol implements LoginProtocol {
bindingBuilder.relayState(relayState);
if (requiresRealmSignature(client)) {
+ String canonicalization = client.getAttribute(SAML_CANONICALIZATION_METHOD_ATTRIBUTE);
+ if (canonicalization != null) {
+ bindingBuilder.canonicalizationMethod(canonicalization);
+ }
bindingBuilder.signatureAlgorithm(getSignatureAlgorithm(client))
.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
.signDocument();
}
if (requiresAssertionSignature(client)) {
+ String canonicalization = client.getAttribute(SAML_CANONICALIZATION_METHOD_ATTRIBUTE);
+ if (canonicalization != null) {
+ bindingBuilder.canonicalizationMethod(canonicalization);
+ }
bindingBuilder.signatureAlgorithm(getSignatureAlgorithm(client))
.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
.signAssertions();
@@ -513,6 +523,10 @@ public class SamlProtocol implements LoginProtocol {
String signingAlgorithm = userSession.getNote(SAML_LOGOUT_SIGNATURE_ALGORITHM);
if (signingAlgorithm != null) {
SignatureAlgorithm algorithm = SignatureAlgorithm.valueOf(signingAlgorithm);
+ String canonicalization = userSession.getNote(SAML_LOGOUT_CANONICALIZATION);
+ if (canonicalization != null) {
+ builder.canonicalizationMethod(canonicalization);
+ }
builder.signatureAlgorithm(algorithm)
.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
.signDocument();
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 fe4b13e..9b93942 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
@@ -340,6 +340,7 @@ public class SamlService {
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(AuthenticationManager.KEYCLOAK_LOGOUT_PROTOCOL, SamlProtocol.LOGIN_PROTOCOL);
// remove client from logout requests
for (ClientSessionModel clientSession : userSession.getClientSessions()) {