diff --git a/saml-core-api/src/main/java/org/keycloak/saml/common/constants/JBossSAMLURIConstants.java b/saml-core-api/src/main/java/org/keycloak/saml/common/constants/JBossSAMLURIConstants.java
index 795f32e201..988fe36b29 100755
--- a/saml-core-api/src/main/java/org/keycloak/saml/common/constants/JBossSAMLURIConstants.java
+++ b/saml-core-api/src/main/java/org/keycloak/saml/common/constants/JBossSAMLURIConstants.java
@@ -177,4 +177,4 @@ public enum JBossSAMLURIConstants {
public static JBossSAMLURIConstants from(String key) {
return REVERSE_LOOKUP.from(key);
}
-}
\ No newline at end of file
+}
diff --git a/saml-core/src/main/java/org/keycloak/saml/SPMetadataDescriptor.java b/saml-core/src/main/java/org/keycloak/saml/SPMetadataDescriptor.java
index b020eb73f3..724a64962f 100755
--- a/saml-core/src/main/java/org/keycloak/saml/SPMetadataDescriptor.java
+++ b/saml-core/src/main/java/org/keycloak/saml/SPMetadataDescriptor.java
@@ -17,59 +17,111 @@
package org.keycloak.saml;
+import org.keycloak.dom.saml.v2.metadata.EndpointType;
+import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType;
+import org.keycloak.dom.saml.v2.metadata.IndexedEndpointType;
+import org.keycloak.dom.saml.v2.metadata.KeyDescriptorType;
+import org.keycloak.dom.saml.v2.metadata.KeyTypes;
+import org.keycloak.dom.saml.v2.metadata.SPSSODescriptorType;
+
+import java.io.StringWriter;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import org.keycloak.saml.common.util.StaxUtil;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.processing.core.saml.v2.writers.SAMLMetadataWriter;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.XMLDSIG_NSURI;
+import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.PROTOCOL_NSURI;
+
/**
* @author Bill Burke
* @version $Revision: 1 $
*/
public class SPMetadataDescriptor {
- public static String getSPDescriptor(String binding, String assertionEndpoint, String logoutEndpoint,
- boolean wantAuthnRequestsSigned, boolean wantAssertionsSigned, boolean wantAssertionsEncrypted,
- String entityId, String nameIDPolicyFormat, String signingCerts, String encryptionCerts) {
- String descriptor =
- "\n" +
- " \n";
+ public static String getSPDescriptor(URI binding, URI assertionEndpoint, URI logoutEndpoint,
+ boolean wantAuthnRequestsSigned, boolean wantAssertionsSigned, boolean wantAssertionsEncrypted,
+ String entityId, String nameIDPolicyFormat, List signingCerts, List encryptionCerts)
+ throws XMLStreamException, ProcessingException, ParserConfigurationException
+ {
+
+ StringWriter sw = new StringWriter();
+ XMLStreamWriter writer = StaxUtil.getXMLStreamWriter(sw);
+ SAMLMetadataWriter metadataWriter = new SAMLMetadataWriter(writer);
+
+ EntityDescriptorType entityDescriptor = new EntityDescriptorType(entityId);
+
+ SPSSODescriptorType spSSODescriptor = new SPSSODescriptorType(Arrays.asList(PROTOCOL_NSURI.get()));
+ spSSODescriptor.setAuthnRequestsSigned(wantAuthnRequestsSigned);
+ spSSODescriptor.setWantAssertionsSigned(wantAssertionsSigned);
+ spSSODescriptor.addNameIDFormat(nameIDPolicyFormat);
+ spSSODescriptor.addSingleLogoutService(new EndpointType(binding, logoutEndpoint));
+
if (wantAuthnRequestsSigned && signingCerts != null) {
- descriptor += signingCerts;
+ for (Element key: signingCerts)
+ {
+ KeyDescriptorType keyDescriptor = new KeyDescriptorType();
+ keyDescriptor.setUse(KeyTypes.SIGNING);
+ keyDescriptor.setKeyInfo(key);
+ spSSODescriptor.addKeyDescriptor(keyDescriptor);
+ }
}
+
if (wantAssertionsEncrypted && encryptionCerts != null) {
- descriptor += encryptionCerts;
+ for (Element key: encryptionCerts)
+ {
+ KeyDescriptorType keyDescriptor = new KeyDescriptorType();
+ keyDescriptor.setUse(KeyTypes.ENCRYPTION);
+ keyDescriptor.setKeyInfo(key);
+ spSSODescriptor.addKeyDescriptor(keyDescriptor);
+ }
}
- descriptor +=
- " \n" +
- " " + nameIDPolicyFormat + "\n" +
- " \n" +
- " \n" +
- " \n" +
- "\n";
- return descriptor;
+
+ IndexedEndpointType assertionConsumerEndpoint = new IndexedEndpointType(binding, assertionEndpoint);
+ assertionConsumerEndpoint.setIsDefault(true);
+ assertionConsumerEndpoint.setIndex(1);
+ spSSODescriptor.addAssertionConsumerService(assertionConsumerEndpoint);
+
+ entityDescriptor.addChoiceType(new EntityDescriptorType.EDTChoiceType(Arrays.asList(new EntityDescriptorType.EDTDescriptorChoiceType(spSSODescriptor))));
+ metadataWriter.writeEntityDescriptor(entityDescriptor);
+
+ return sw.toString();
}
- public static String xmlKeyInfo(String indentation, String keyId, String pemEncodedCertificate, String purpose, boolean declareDSigNamespace) {
- if (pemEncodedCertificate == null) {
- return "";
+ public static Element buildKeyInfoElement(String keyName, String pemEncodedCertificate)
+ throws javax.xml.parsers.ParserConfigurationException
+ {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ Document doc = db.newDocument();
+
+ Element keyInfo = doc.createElementNS(XMLDSIG_NSURI.get(), "ds:KeyInfo");
+
+ if (keyName != null) {
+ Element keyNameElement = doc.createElementNS(XMLDSIG_NSURI.get(), "ds:KeyName");
+ keyNameElement.setTextContent(keyName);
+ keyInfo.appendChild(keyNameElement);
}
- StringBuilder target = new StringBuilder()
- .append(indentation).append("\n")
- .append(indentation).append(" \n" : ">\n");
+ Element x509Data = doc.createElementNS(XMLDSIG_NSURI.get(), "ds:X509Data");
- if (keyId != null) {
- target.append(indentation).append(" ").append(keyId).append("\n");
- }
+ Element x509Certificate = doc.createElementNS(XMLDSIG_NSURI.get(), "ds:X509Certificate");
+ x509Certificate.setTextContent(pemEncodedCertificate);
+
+ x509Data.appendChild(x509Certificate);
- target
- .append(indentation).append(" \n")
- .append(indentation).append(" ").append(pemEncodedCertificate).append("\n")
- .append(indentation).append(" \n")
- .append(indentation).append(" \n")
- .append(indentation).append("\n")
- ;
+ keyInfo.appendChild(x509Data);
- return target.toString();
+ return keyInfo;
}
-
}
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLMetadataWriter.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLMetadataWriter.java
index 42fa79456e..81ad6d82e4 100755
--- a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLMetadataWriter.java
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLMetadataWriter.java
@@ -187,8 +187,7 @@ public class SAMLMetadataWriter extends BaseWriter {
public void write(SPSSODescriptorType spSSODescriptor) throws ProcessingException {
StaxUtil.writeStartElement(writer, METADATA_PREFIX, JBossSAMLConstants.SP_SSO_DESCRIPTOR.get(), JBossSAMLURIConstants.METADATA_NSURI.get());
- StaxUtil.writeAttribute(writer, new QName(JBossSAMLConstants.PROTOCOL_SUPPORT_ENUMERATION.get()), spSSODescriptor
- .getProtocolSupportEnumeration().get(0));
+ writeProtocolSupportEnumeration(spSSODescriptor.getProtocolSupportEnumeration());
// Write the attributes
Boolean authnSigned = spSSODescriptor.isAuthnRequestsSigned();
@@ -250,6 +249,12 @@ public class SAMLMetadataWriter extends BaseWriter {
}
writeProtocolSupportEnumeration(idpSSODescriptor.getProtocolSupportEnumeration());
+ // Get the key descriptors
+ List keyDescriptors = idpSSODescriptor.getKeyDescriptor();
+ for (KeyDescriptorType keyDescriptor : keyDescriptors) {
+ writeKeyDescriptor(keyDescriptor);
+ }
+
List artifactResolutionServices = idpSSODescriptor.getArtifactResolutionService();
for (IndexedEndpointType indexedEndpoint : artifactResolutionServices) {
writeArtifactResolutionService(indexedEndpoint);
@@ -260,16 +265,16 @@ public class SAMLMetadataWriter extends BaseWriter {
writeSingleLogoutService(endpoint);
}
- List ssoServices = idpSSODescriptor.getSingleSignOnService();
- for (EndpointType endpoint : ssoServices) {
- writeSingleSignOnService(endpoint);
- }
-
List nameIDFormats = idpSSODescriptor.getNameIDFormat();
for (String nameIDFormat : nameIDFormats) {
writeNameIDFormat(nameIDFormat);
}
+ List ssoServices = idpSSODescriptor.getSingleSignOnService();
+ for (EndpointType endpoint : ssoServices) {
+ writeSingleSignOnService(endpoint);
+ }
+
List attributes = idpSSODescriptor.getAttribute();
for (AttributeType attribType : attributes) {
write(attribType);
@@ -550,7 +555,10 @@ public class SAMLMetadataWriter extends BaseWriter {
private void writeNameIDFormat(String nameIDFormat) throws ProcessingException {
StaxUtil.writeStartElement(writer, METADATA_PREFIX, JBossSAMLConstants.NAMEID_FORMAT.get(), JBossSAMLURIConstants.METADATA_NSURI.get());
- StaxUtil.writeCharacters(writer, nameIDFormat);
+ if (nameIDFormat != null) {
+ StaxUtil.writeCharacters(writer, nameIDFormat);
+ }
+
StaxUtil.writeEndElement(writer);
}
}
\ No newline at end of file
diff --git a/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java b/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java
index 5fb9a721b0..3a7903690a 100755
--- a/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java
+++ b/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java
@@ -45,12 +45,17 @@ import org.keycloak.saml.processing.core.util.KeycloakKeySamlExtensionGenerator;
import org.keycloak.saml.validators.DestinationValidator;
import org.keycloak.sessions.AuthenticationSessionModel;
+import org.w3c.dom.Element;
+
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
+import java.net.URI;
import java.security.KeyPair;
+import java.util.ArrayList;
import java.util.Iterator;
+import java.util.List;
import java.util.Set;
import java.util.TreeSet;
@@ -230,53 +235,52 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider keys = new TreeSet<>((o1, o2) -> o1.getStatus() == o2.getStatus() // Status can be only PASSIVE OR ACTIVE, push PASSIVE to end of list
- ? (int) (o2.getProviderPriority() - o1.getProviderPriority())
- : (o1.getStatus() == KeyStatus.PASSIVE ? 1 : -1));
- keys.addAll(session.keys().getRsaKeys(realm));
- for (RsaKeyMetadata key : keys) {
- addKeyInfo(signingKeysString, key, KeyTypes.SIGNING.value());
-
- if (key.getStatus() == KeyStatus.ACTIVE) {
- addKeyInfo(encryptionKeysString, key, KeyTypes.ENCRYPTION.value());
+ if (getConfig().isPostBindingAuthnRequest()) {
+ authnBinding = JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.getUri();
}
+
+ URI endpoint = uriInfo.getBaseUriBuilder()
+ .path("realms").path(realm.getName())
+ .path("broker")
+ .path(getConfig().getAlias())
+ .path("endpoint")
+ .build();
+
+
+ boolean wantAuthnRequestsSigned = getConfig().isWantAuthnRequestsSigned();
+ boolean wantAssertionsSigned = getConfig().isWantAssertionsSigned();
+ boolean wantAssertionsEncrypted = getConfig().isWantAssertionsEncrypted();
+ String entityId = getEntityId(uriInfo, realm);
+ String nameIDPolicyFormat = getConfig().getNameIDPolicyFormat();
+
+ List signingKeys = new ArrayList();
+ List encryptionKeys = new ArrayList();
+
+ Set keys = new TreeSet<>((o1, o2) -> o1.getStatus() == o2.getStatus() // Status can be only PASSIVE OR ACTIVE, push PASSIVE to end of list
+ ? (int) (o2.getProviderPriority() - o1.getProviderPriority())
+ : (o1.getStatus() == KeyStatus.PASSIVE ? 1 : -1));
+ keys.addAll(session.keys().getRsaKeys(realm));
+ for (RsaKeyMetadata key : keys) {
+ if (key == null || key.getCertificate() == null) continue;
+
+ signingKeys.add(SPMetadataDescriptor.buildKeyInfoElement(key.getKid(), PemUtils.encodeCertificate(key.getCertificate())));
+
+ if (key.getStatus() == KeyStatus.ACTIVE)
+ encryptionKeys.add(SPMetadataDescriptor.buildKeyInfoElement(key.getKid(), PemUtils.encodeCertificate(key.getCertificate())));
+ }
+ String descriptor = SPMetadataDescriptor.getSPDescriptor(authnBinding, endpoint, endpoint,
+ wantAuthnRequestsSigned, wantAssertionsSigned, wantAssertionsEncrypted,
+ entityId, nameIDPolicyFormat, signingKeys, encryptionKeys);
+
+ return Response.ok(descriptor, MediaType.APPLICATION_XML_TYPE).build();
+ } catch (Exception e) {
+ logger.warn("Failed to export SAML SP Metadata!", e);
+ throw new RuntimeException(e);
}
- String descriptor = SPMetadataDescriptor.getSPDescriptor(authnBinding, endpoint, endpoint,
- wantAuthnRequestsSigned, wantAssertionsSigned, wantAssertionsEncrypted,
- entityId, nameIDPolicyFormat, signingKeysString.toString(), encryptionKeysString.toString());
-
- return Response.ok(descriptor, MediaType.APPLICATION_XML_TYPE).build();
- }
-
- private static void addKeyInfo(StringBuilder target, RsaKeyMetadata key, String purpose) {
- if (key == null) {
- return;
- }
-
- target.append(SPMetadataDescriptor.xmlKeyInfo(" ", key.getKid(), PemUtils.encodeCertificate(key.getCertificate()), purpose, true));
}
public SignatureAlgorithm getSignatureAlgorithm() {
diff --git a/services/src/main/java/org/keycloak/protocol/saml/IDPMetadataDescriptor.java b/services/src/main/java/org/keycloak/protocol/saml/IDPMetadataDescriptor.java
new file mode 100644
index 0000000000..1f95c81c69
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/saml/IDPMetadataDescriptor.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.protocol.saml;
+
+import org.keycloak.dom.saml.v2.metadata.EndpointType;
+import org.keycloak.dom.saml.v2.metadata.EntitiesDescriptorType;
+import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType;
+import org.keycloak.dom.saml.v2.metadata.IDPSSODescriptorType;
+import org.keycloak.dom.saml.v2.metadata.KeyDescriptorType;
+import org.keycloak.dom.saml.v2.metadata.KeyTypes;
+
+import java.io.StringWriter;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.processing.core.saml.v2.writers.SAMLMetadataWriter;
+import org.keycloak.saml.common.util.StaxUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.SAML_HTTP_POST_BINDING;
+import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING;
+import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.SAML_SOAP_BINDING;
+import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.NAMEID_FORMAT_PERSISTENT;
+import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.NAMEID_FORMAT_TRANSIENT;
+import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.NAMEID_FORMAT_UNSPECIFIED;
+import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL;
+import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.XMLDSIG_NSURI;
+import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.PROTOCOL_NSURI;
+
+/**
+ * @version $Revision: 1 $
+ */
+public class IDPMetadataDescriptor {
+
+ public static String getIDPDescriptor(URI loginPostEndpoint, URI loginRedirectEndpoint, URI logoutEndpoint,
+ String entityId, boolean wantAuthnRequestsSigned, List signingCerts, List encryptionCerts)
+ throws XMLStreamException, ProcessingException, ParserConfigurationException
+ {
+
+ StringWriter sw = new StringWriter();
+ XMLStreamWriter writer = StaxUtil.getXMLStreamWriter(sw);
+ SAMLMetadataWriter metadataWriter = new SAMLMetadataWriter(writer);
+
+ EntitiesDescriptorType entitiesDescriptor = new EntitiesDescriptorType();
+ entitiesDescriptor.setName("urn:keycloak");
+
+ EntityDescriptorType entityDescriptor = new EntityDescriptorType(entityId);
+
+ IDPSSODescriptorType spIDPDescriptor = new IDPSSODescriptorType(Arrays.asList(PROTOCOL_NSURI.get()));
+ spIDPDescriptor.setWantAuthnRequestsSigned(wantAuthnRequestsSigned);
+ spIDPDescriptor.addNameIDFormat(NAMEID_FORMAT_PERSISTENT.get());
+ spIDPDescriptor.addNameIDFormat(NAMEID_FORMAT_TRANSIENT.get());
+ spIDPDescriptor.addNameIDFormat(NAMEID_FORMAT_UNSPECIFIED.get());
+ spIDPDescriptor.addNameIDFormat(NAMEID_FORMAT_EMAIL.get());
+
+ spIDPDescriptor.addSingleLogoutService(new EndpointType(SAML_HTTP_POST_BINDING.getUri(), logoutEndpoint));
+ spIDPDescriptor.addSingleLogoutService(new EndpointType(SAML_HTTP_REDIRECT_BINDING.getUri(), logoutEndpoint));
+ spIDPDescriptor.addSingleSignOnService(new EndpointType(SAML_HTTP_POST_BINDING.getUri(), loginPostEndpoint));
+ spIDPDescriptor.addSingleSignOnService(new EndpointType(SAML_HTTP_REDIRECT_BINDING.getUri(), loginRedirectEndpoint));
+ spIDPDescriptor.addSingleSignOnService(new EndpointType(SAML_SOAP_BINDING.getUri(), loginPostEndpoint));
+
+ if (wantAuthnRequestsSigned && signingCerts != null) {
+ for (Element key: signingCerts)
+ {
+ KeyDescriptorType keyDescriptor = new KeyDescriptorType();
+ keyDescriptor.setUse(KeyTypes.SIGNING);
+ keyDescriptor.setKeyInfo(key);
+ spIDPDescriptor.addKeyDescriptor(keyDescriptor);
+ }
+ }
+
+ entityDescriptor.addChoiceType(new EntityDescriptorType.EDTChoiceType(Arrays.asList(new EntityDescriptorType.EDTDescriptorChoiceType(spIDPDescriptor))));
+
+ entitiesDescriptor.addEntityDescriptor(entityDescriptor);
+
+ metadataWriter.writeEntitiesDescriptor(entitiesDescriptor);
+
+ return sw.toString();
+ }
+
+ public static Element buildKeyInfoElement(String keyName, String pemEncodedCertificate)
+ throws javax.xml.parsers.ParserConfigurationException
+ {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ Document doc = db.newDocument();
+
+ Element keyInfo = doc.createElementNS(XMLDSIG_NSURI.get(), "ds:KeyInfo");
+
+ if (keyName != null) {
+ Element keyNameElement = doc.createElementNS(XMLDSIG_NSURI.get(), "ds:KeyName");
+ keyNameElement.setTextContent(keyName);
+ keyInfo.appendChild(keyNameElement);
+ }
+
+ Element x509Data = doc.createElementNS(XMLDSIG_NSURI.get(), "ds:X509Data");
+
+ Element x509Certificate = doc.createElementNS(XMLDSIG_NSURI.get(), "ds:X509Certificate");
+ x509Certificate.setTextContent(pemEncodedCertificate);
+
+ x509Data.appendChild(x509Certificate);
+
+ keyInfo.appendChild(x509Data);
+
+ return keyInfo;
+ }
+}
diff --git a/services/src/main/java/org/keycloak/protocol/saml/SamlService.java b/services/src/main/java/org/keycloak/protocol/saml/SamlService.java
index 2c267143ce..3842ed5a66 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/SamlService.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/SamlService.java
@@ -63,6 +63,8 @@ import org.keycloak.services.resources.RealmsResource;
import org.keycloak.services.util.CacheControlUtil;
import org.keycloak.utils.MediaType;
+import org.w3c.dom.Element;
+
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
@@ -77,7 +79,9 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.security.PublicKey;
+import java.util.ArrayList;
import java.util.Iterator;
+import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
@@ -656,38 +660,28 @@ public class SamlService extends AuthorizationEndpointBase {
}
public static String getIDPMetadataDescriptor(UriInfo uriInfo, KeycloakSession session, RealmModel realm) {
- InputStream is = SamlService.class.getResourceAsStream("/idp-metadata-template.xml");
- String template;
- try {
- template = StreamUtil.readString(is, StandardCharsets.UTF_8);
- } catch (IOException ex) {
- logger.error("Cannot generate IdP metadata", ex);
- return "";
- }
- Properties props = new Properties();
- props.put("idp.entityID", RealmsResource.realmBaseUrl(uriInfo).build(realm.getName()).toString());
- props.put("idp.sso.HTTP-POST", RealmsResource.protocolUrl(uriInfo).build(realm.getName(), SamlProtocol.LOGIN_PROTOCOL).toString());
- props.put("idp.sso.HTTP-Redirect", RealmsResource.protocolUrl(uriInfo).build(realm.getName(), SamlProtocol.LOGIN_PROTOCOL).toString());
- props.put("idp.sls.HTTP-POST", RealmsResource.protocolUrl(uriInfo).build(realm.getName(), SamlProtocol.LOGIN_PROTOCOL).toString());
- StringBuilder keysString = new StringBuilder();
Set keys = new TreeSet<>((o1, o2) -> o1.getStatus() == o2.getStatus() // Status can be only PASSIVE OR ACTIVE, push PASSIVE to end of list
? (int) (o2.getProviderPriority() - o1.getProviderPriority())
: (o1.getStatus() == KeyStatus.PASSIVE ? 1 : -1));
keys.addAll(session.keys().getKeys(realm, KeyUse.SIG, Algorithm.RS256));
- for (KeyWrapper key : keys) {
- addKeyInfo(keysString, key, KeyTypes.SIGNING.value());
- }
- props.put("idp.signing.certificates", keysString.toString());
- return StringPropertyReplacer.replaceProperties(template, props);
- }
- private static void addKeyInfo(StringBuilder target, KeyWrapper key, String purpose) {
- if (key == null) {
- return;
- }
+ try {
+ List signingKeys = new ArrayList();
+ for (KeyWrapper key : keys) {
+ signingKeys.add(IDPMetadataDescriptor.buildKeyInfoElement(key.getKid(), PemUtils.encodeCertificate(key.getCertificate())));
+ }
- target.append(SPMetadataDescriptor.xmlKeyInfo(" ",
- key.getKid(), PemUtils.encodeCertificate(key.getCertificate()), purpose, false));
+ return IDPMetadataDescriptor.getIDPDescriptor(
+ RealmsResource.protocolUrl(uriInfo).build(realm.getName(), SamlProtocol.LOGIN_PROTOCOL),
+ RealmsResource.protocolUrl(uriInfo).build(realm.getName(), SamlProtocol.LOGIN_PROTOCOL),
+ RealmsResource.protocolUrl(uriInfo).build(realm.getName(), SamlProtocol.LOGIN_PROTOCOL),
+ RealmsResource.realmBaseUrl(uriInfo).build(realm.getName()).toString(),
+ true,
+ signingKeys, null);
+ } catch (Exception ex) {
+ logger.error("Cannot generate IdP metadata", ex);
+ return "";
+ }
}
private boolean isClientProtocolCorrect(ClientModel clientModel) {
diff --git a/services/src/main/java/org/keycloak/protocol/saml/installation/SamlSPDescriptorClientInstallation.java b/services/src/main/java/org/keycloak/protocol/saml/installation/SamlSPDescriptorClientInstallation.java
index 8d89c9d2a2..584fc4ba4b 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/installation/SamlSPDescriptorClientInstallation.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/installation/SamlSPDescriptorClientInstallation.java
@@ -17,7 +17,9 @@
package org.keycloak.protocol.saml.installation;
+import org.jboss.logging.Logger;
import org.keycloak.Config;
+import org.keycloak.dom.saml.v2.metadata.KeyTypes;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
@@ -28,10 +30,13 @@ import org.keycloak.protocol.saml.SamlProtocol;
import org.keycloak.saml.SPMetadataDescriptor;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
+import org.w3c.dom.Element;
+
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.net.URI;
-import org.keycloak.dom.saml.v2.metadata.KeyTypes;
+import java.util.Arrays;
+
/**
* @author Bill Burke
@@ -39,34 +44,41 @@ import org.keycloak.dom.saml.v2.metadata.KeyTypes;
*/
public class SamlSPDescriptorClientInstallation implements ClientInstallationProvider {
+ protected static final Logger logger = Logger.getLogger(SamlSPDescriptorClientInstallation.class);
+
public static final String SAML_CLIENT_INSTALATION_SP_DESCRIPTOR = "saml-sp-descriptor";
- private static final String FALLBACK_ERROR_URL_STRING = "ERROR:ENDPOINT NOT SET";
+ private static final String FALLBACK_ERROR_URL_STRING = "ERROR:ENDPOINT_NOT_SET";
public static String getSPDescriptorForClient(ClientModel client) {
- SamlClient samlClient = new SamlClient(client);
- String assertionUrl;
- String logoutUrl;
- String binding;
- if (samlClient.forcePostBinding()) {
- assertionUrl = client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE);
- logoutUrl = client.getAttribute(SamlProtocol.SAML_SINGLE_LOGOUT_SERVICE_URL_POST_ATTRIBUTE);
- binding = JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get();
- } else { //redirect binding
- assertionUrl = client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE);
- logoutUrl = client.getAttribute(SamlProtocol.SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE);
- binding = JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get();
+ try {
+ SamlClient samlClient = new SamlClient(client);
+ String assertionUrl;
+ String logoutUrl;
+ URI binding;
+ if (samlClient.forcePostBinding()) {
+ assertionUrl = client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE);
+ logoutUrl = client.getAttribute(SamlProtocol.SAML_SINGLE_LOGOUT_SERVICE_URL_POST_ATTRIBUTE);
+ binding = JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.getUri();
+ } else { //redirect binding
+ assertionUrl = client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE);
+ logoutUrl = client.getAttribute(SamlProtocol.SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE);
+ binding = JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.getUri();
+ }
+ if (assertionUrl == null || assertionUrl.trim().isEmpty()) assertionUrl = client.getManagementUrl();
+ if (assertionUrl == null || assertionUrl.trim().isEmpty()) assertionUrl = FALLBACK_ERROR_URL_STRING;
+ if (logoutUrl == null || logoutUrl.trim().isEmpty()) logoutUrl = client.getManagementUrl();
+ if (logoutUrl == null || logoutUrl.trim().isEmpty()) logoutUrl = FALLBACK_ERROR_URL_STRING;
+ String nameIdFormat = samlClient.getNameIDFormat();
+ if (nameIdFormat == null) nameIdFormat = SamlProtocol.SAML_DEFAULT_NAMEID_FORMAT;
+ Element spCertificate = SPMetadataDescriptor.buildKeyInfoElement(null, samlClient.getClientSigningCertificate());
+ Element encCertificate = SPMetadataDescriptor.buildKeyInfoElement(null, samlClient.getClientEncryptingCertificate());
+ return SPMetadataDescriptor.getSPDescriptor(binding, new URI(assertionUrl), new URI(logoutUrl), samlClient.requiresClientSignature(),
+ samlClient.requiresAssertionSignature(), samlClient.requiresEncryption(),
+ client.getClientId(), nameIdFormat, Arrays.asList(spCertificate), Arrays.asList(encCertificate));
+ } catch (Exception ex) {
+ logger.error("Cannot generate SP metadata", ex);
+ return "";
}
- if (assertionUrl == null || assertionUrl.trim().isEmpty()) assertionUrl = client.getManagementUrl();
- if (assertionUrl == null || assertionUrl.trim().isEmpty()) assertionUrl = FALLBACK_ERROR_URL_STRING;
- if (logoutUrl == null || logoutUrl.trim().isEmpty()) logoutUrl = client.getManagementUrl();
- if (logoutUrl == null || logoutUrl.trim().isEmpty()) logoutUrl = FALLBACK_ERROR_URL_STRING;
- String nameIdFormat = samlClient.getNameIDFormat();
- if (nameIdFormat == null) nameIdFormat = SamlProtocol.SAML_DEFAULT_NAMEID_FORMAT;
- String spCertificate = SPMetadataDescriptor.xmlKeyInfo(" ", null, samlClient.getClientSigningCertificate(), KeyTypes.SIGNING.value(), true);
- String encCertificate = SPMetadataDescriptor.xmlKeyInfo(" ", null, samlClient.getClientEncryptingCertificate(), KeyTypes.ENCRYPTION.value(), true);
- return SPMetadataDescriptor.getSPDescriptor(binding, assertionUrl, logoutUrl, samlClient.requiresClientSignature(),
- samlClient.requiresAssertionSignature(), samlClient.requiresEncryption(),
- client.getClientId(), nameIdFormat, spCertificate, encCertificate);
}
@Override
diff --git a/services/src/main/resources/idp-metadata-template.xml b/services/src/main/resources/idp-metadata-template.xml
deleted file mode 100755
index a4416cdaa9..0000000000
--- a/services/src/main/resources/idp-metadata-template.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-
-
-
-${idp.signing.certificates}
-
-
- urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
- urn:oasis:names:tc:SAML:2.0:nameid-format:transient
- urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
- urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
-
-
-
-
-
-
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java
index 779c404d28..f8493f0efb 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java
@@ -933,9 +933,7 @@ public class IdentityProviderTest extends AbstractAdminTest {
Assert.assertTrue("AuthnRequestsSigned", desc.isAuthnRequestsSigned());
Set expected = new HashSet<>(Arrays.asList(
- "urn:oasis:names:tc:SAML:2.0:protocol",
- "urn:oasis:names:tc:SAML:1.1:protocol",
- "http://schemas.xmlsoap.org/ws/2003/07/secext"));
+ "urn:oasis:names:tc:SAML:2.0:protocol"));
Set actual = new HashSet<>(desc.getProtocolSupportEnumeration());
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/InstallationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/InstallationTest.java
index 1bef985190..368e37f515 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/InstallationTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/InstallationTest.java
@@ -48,6 +48,8 @@ import static org.junit.Assert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.keycloak.testsuite.util.ServerURLs.getAuthServerContextRoot;
+import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.METADATA_NSURI;
+
/**
* Test getting the installation/configuration files for OIDC and SAML.
*
@@ -189,10 +191,11 @@ public class InstallationTest extends AbstractClientTest {
}
@Test
- public void testSamlMetadataSpDescriptor() {
+ public void testSamlMetadataSpDescriptor() throws Exception {
String xml = samlClient.getInstallationProvider(SamlSPDescriptorClientInstallation.SAML_CLIENT_INSTALATION_SP_DESCRIPTOR);
- assertThat(xml, containsString(" attrNamesAndValues = new HashMap<>();
attrNamesAndValues.put("Binding", JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get());
- attrNamesAndValues.put("Location", "ERROR:ENDPOINT NOT SET");
- assertElements(doc, "SingleLogoutService", attrNamesAndValues);
- assertElements(doc, "AssertionConsumerService", attrNamesAndValues);
+ attrNamesAndValues.put("Location", "ERROR:ENDPOINT_NOT_SET");
+ assertElements(doc, METADATA_NSURI.get(), "SingleLogoutService", attrNamesAndValues);
+ assertElements(doc, METADATA_NSURI.get(), "AssertionConsumerService", attrNamesAndValues);
attrNamesAndValues.clear();
//fallback to adminUrl
@@ -226,8 +229,8 @@ public class InstallationTest extends AbstractClientTest {
doc = getDocumentFromXmlString(updater.getResource().getInstallationProvider(SamlSPDescriptorClientInstallation.SAML_CLIENT_INSTALATION_SP_DESCRIPTOR));
attrNamesAndValues.put("Binding", JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get());
attrNamesAndValues.put("Location", "admin-url");
- assertElements(doc, "SingleLogoutService", attrNamesAndValues);
- assertElements(doc, "AssertionConsumerService", attrNamesAndValues);
+ assertElements(doc, METADATA_NSURI.get(), "SingleLogoutService", attrNamesAndValues);
+ assertElements(doc, METADATA_NSURI.get(), "AssertionConsumerService", attrNamesAndValues);
attrNamesAndValues.clear();
//fine grained
@@ -241,11 +244,11 @@ public class InstallationTest extends AbstractClientTest {
doc = getDocumentFromXmlString(updater.getResource().getInstallationProvider(SamlSPDescriptorClientInstallation.SAML_CLIENT_INSTALATION_SP_DESCRIPTOR));
attrNamesAndValues.put("Binding", JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get());
attrNamesAndValues.put("Location", "saml-logout-post-url");
- assertElements(doc, "SingleLogoutService", attrNamesAndValues);
+ assertElements(doc, METADATA_NSURI.get(), "SingleLogoutService", attrNamesAndValues);
attrNamesAndValues.clear();
attrNamesAndValues.put("Binding", JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get());
attrNamesAndValues.put("Location", "saml-assertion-post-url");
- assertElements(doc, "AssertionConsumerService", attrNamesAndValues);
+ assertElements(doc, METADATA_NSURI.get(), "AssertionConsumerService", attrNamesAndValues);
}
assertAdminEvents.assertEvent(getRealmId(), OperationType.UPDATE, AdminEventPaths.clientResourcePath(samlClientId), ResourceType.CLIENT);
}
@@ -263,9 +266,9 @@ public class InstallationTest extends AbstractClientTest {
Document doc = getDocumentFromXmlString(updater.getResource().getInstallationProvider(SamlSPDescriptorClientInstallation.SAML_CLIENT_INSTALATION_SP_DESCRIPTOR));
Map attrNamesAndValues = new HashMap<>();
attrNamesAndValues.put("Binding", JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get());
- attrNamesAndValues.put("Location", "ERROR:ENDPOINT NOT SET");
- assertElements(doc, "SingleLogoutService", attrNamesAndValues);
- assertElements(doc, "AssertionConsumerService", attrNamesAndValues);
+ attrNamesAndValues.put("Location", "ERROR:ENDPOINT_NOT_SET");
+ assertElements(doc, METADATA_NSURI.get(), "SingleLogoutService", attrNamesAndValues);
+ assertElements(doc, METADATA_NSURI.get(), "AssertionConsumerService", attrNamesAndValues);
attrNamesAndValues.clear();
//fallback to adminUrl
@@ -274,8 +277,8 @@ public class InstallationTest extends AbstractClientTest {
doc = getDocumentFromXmlString(updater.getResource().getInstallationProvider(SamlSPDescriptorClientInstallation.SAML_CLIENT_INSTALATION_SP_DESCRIPTOR));
attrNamesAndValues.put("Binding", JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get());
attrNamesAndValues.put("Location", "admin-url");
- assertElements(doc, "SingleLogoutService", attrNamesAndValues);
- assertElements(doc, "AssertionConsumerService", attrNamesAndValues);
+ assertElements(doc, METADATA_NSURI.get(), "SingleLogoutService", attrNamesAndValues);
+ assertElements(doc, METADATA_NSURI.get(), "AssertionConsumerService", attrNamesAndValues);
attrNamesAndValues.clear();
//fine grained
@@ -288,29 +291,33 @@ public class InstallationTest extends AbstractClientTest {
doc = getDocumentFromXmlString(updater.getResource().getInstallationProvider(SamlSPDescriptorClientInstallation.SAML_CLIENT_INSTALATION_SP_DESCRIPTOR));
attrNamesAndValues.put("Binding", JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get());
attrNamesAndValues.put("Location", "saml-logout-redirect-url");
- assertElements(doc, "SingleLogoutService", attrNamesAndValues);
+ assertElements(doc, METADATA_NSURI.get(), "SingleLogoutService", attrNamesAndValues);
attrNamesAndValues.clear();
attrNamesAndValues.put("Binding", JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get());
attrNamesAndValues.put("Location", "saml-assertion-redirect-url");
- assertElements(doc, "AssertionConsumerService", attrNamesAndValues);
+ assertElements(doc, METADATA_NSURI.get(), "AssertionConsumerService", attrNamesAndValues);
}
assertAdminEvents.assertEvent(getRealmId(), OperationType.UPDATE, AdminEventPaths.clientResourcePath(samlClientId), ResourceType.CLIENT);
}
private Document getDocumentFromXmlString(String xml) throws SAXException, ParserConfigurationException, IOException {
- DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(xml));
return db.parse(is);
}
- private void assertElements(Document doc, String tagName, Map attrNamesAndValues) {
- NodeList elementsByTagName = doc.getElementsByTagName(tagName);
+ private void assertElements(Document doc, String tagNamespace, String tagName, Map attrNamesAndValues) {
+ NodeList elementsByTagName = doc.getElementsByTagNameNS(tagNamespace, tagName);
assertThat("Expected exactly one " + tagName + " element!", elementsByTagName.getLength(), is(equalTo(1)));
Node element = elementsByTagName.item(0);
- for (String attrName : attrNamesAndValues.keySet()) {
- assertThat(element.getAttributes().getNamedItem(attrName).getNodeValue(), containsString(attrNamesAndValues.get(attrName)));
+ if (attrNamesAndValues != null) {
+ for (String attrName : attrNamesAndValues.keySet()) {
+ assertThat(element.getAttributes().getNamedItem(attrName).getNodeValue(), containsString(attrNamesAndValues.get(attrName)));
+ }
}
}
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/admin-test/saml-idp-metadata-two-signing-certs.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/admin-test/saml-idp-metadata-two-signing-certs.xml
index dba0d5a0cb..5b5f8f68c6 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/admin-test/saml-idp-metadata-two-signing-certs.xml
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/admin-test/saml-idp-metadata-two-signing-certs.xml
@@ -5,35 +5,35 @@
>
- urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
- urn:oasis:names:tc:SAML:2.0:nameid-format:transient
- urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
- urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
-
+
+
+ hAoy_sBtpu6FdRVCk7ykihF6Ug-o0pKPK3LN9RYkeqs
+
+
+ MIICmzCCAYMCBgFUYnC0OjANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMTYwNDI5MTQzMjEzWhcNMjYwNDI5MTQzMzUzWjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCN25AW1poMEZRbuMAHG58AThZmCwMV6/Gcui4mjGacRFyudgqzLjQ2rxpoW41JAtLjbjeAhuWvirUcFVcOeS3gM/ZC27qCpYighAcylZz6MYocnEe1+e8rPPk4JlID6Wv62dgu+pL/vYsQpRhvD3Y2c/ytgr5D32xF+KnzDehUy5BSyzypvu12Wq9mS5vK5tzkN37EjkhpY2ZxaXPubjDIITCAL4Q8M/m5IlacBaUZbzI4AQrHnMP1O1IH2dHSWuMiBe+xSDTco72PmuYPJKTV4wQdeBUIkYbfLc4RxVmXEvgkQgyW86EoMPxlWJpj7+mTIR+l+2thZPr/VgwTs82rAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAA/Ip/Hi8RoVu5ouaFFlc5whT7ltuK8slfLGW4tM4vJXhInYwsqIRQKBNDYW/64xle3eII4u1yAH1OYRRwEs7Em1pr4QuFuTY1at+aE0sE46XDlyESI0txJjWxYoT133vM0We2pj1b2nxgU30rwjKA3whnKEfTEYT/n3JBSqNggy6l8ZGw/oPSgvPaR4+xeB1tfQFC4VrLoYKoqH6hAL530nKxL+qV8AIfL64NDEE8ankIAEDAAFe8x3CPUfXR/p4KOANKkpz8ieQaHDb1eITkAwUwjESj6UF9D1aePlhWls/HX0gujFXtWfWfrJ8CU/ogwlH8y1jgRuLjFQYZk6llc=
+
+
+
+
+
+
+ FJ86GcF3jTbNLOco4NvZkUCIUmfYCqoqtOQeMfbhNlE
+
+
+ MIIBnDCCAQUCBgFYKXKsPTANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAlzYW1sLWRlbW8wHhcNMTYxMTAzMDkwNzEwWhcNMjYxMTAzMDkwODUwWjAUMRIwEAYDVQQDDAlzYW1sLWRlbW8wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKtWsK5O0CtuBpnMvWG+HTG0vmZzujQ2o9WdheQu+BzCILcGMsbDW0YQaglpcO5JpGWWhubnckGGPHfdQ2/7nP9QwbiTK0FbGF41UqcvoaCqU1psxoV88s8IXyQCAqeyLv00yj6foqdJjxh5SZ5z+na+M7Y2OxIBVxYRAxWEnfUvAgMBAAEwDQYJKoZIhvcNAQELBQADgYEAhetvOU8TyqfZF5jpv0IcrviLl/DoFrbjByeHR+pu/vClcAOjL/u7oQELuuTfNsBI4tpexUj5G8q/YbEz0gk7idfLXrAUVcsR73oTngrhRfwUSmPrjjK0kjcRb6HL9V/+wh3R/6mEd59U08ExT8N38rhmn0CI3ehMdebReprP7U8=
+
+
+
+
-
-
- hAoy_sBtpu6FdRVCk7ykihF6Ug-o0pKPK3LN9RYkeqs
-
-
- MIICmzCCAYMCBgFUYnC0OjANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMTYwNDI5MTQzMjEzWhcNMjYwNDI5MTQzMzUzWjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCN25AW1poMEZRbuMAHG58AThZmCwMV6/Gcui4mjGacRFyudgqzLjQ2rxpoW41JAtLjbjeAhuWvirUcFVcOeS3gM/ZC27qCpYighAcylZz6MYocnEe1+e8rPPk4JlID6Wv62dgu+pL/vYsQpRhvD3Y2c/ytgr5D32xF+KnzDehUy5BSyzypvu12Wq9mS5vK5tzkN37EjkhpY2ZxaXPubjDIITCAL4Q8M/m5IlacBaUZbzI4AQrHnMP1O1IH2dHSWuMiBe+xSDTco72PmuYPJKTV4wQdeBUIkYbfLc4RxVmXEvgkQgyW86EoMPxlWJpj7+mTIR+l+2thZPr/VgwTs82rAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAA/Ip/Hi8RoVu5ouaFFlc5whT7ltuK8slfLGW4tM4vJXhInYwsqIRQKBNDYW/64xle3eII4u1yAH1OYRRwEs7Em1pr4QuFuTY1at+aE0sE46XDlyESI0txJjWxYoT133vM0We2pj1b2nxgU30rwjKA3whnKEfTEYT/n3JBSqNggy6l8ZGw/oPSgvPaR4+xeB1tfQFC4VrLoYKoqH6hAL530nKxL+qV8AIfL64NDEE8ankIAEDAAFe8x3CPUfXR/p4KOANKkpz8ieQaHDb1eITkAwUwjESj6UF9D1aePlhWls/HX0gujFXtWfWfrJ8CU/ogwlH8y1jgRuLjFQYZk6llc=
-
-
-
-
-
-
- FJ86GcF3jTbNLOco4NvZkUCIUmfYCqoqtOQeMfbhNlE
-
-
- MIIBnDCCAQUCBgFYKXKsPTANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAlzYW1sLWRlbW8wHhcNMTYxMTAzMDkwNzEwWhcNMjYxMTAzMDkwODUwWjAUMRIwEAYDVQQDDAlzYW1sLWRlbW8wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKtWsK5O0CtuBpnMvWG+HTG0vmZzujQ2o9WdheQu+BzCILcGMsbDW0YQaglpcO5JpGWWhubnckGGPHfdQ2/7nP9QwbiTK0FbGF41UqcvoaCqU1psxoV88s8IXyQCAqeyLv00yj6foqdJjxh5SZ5z+na+M7Y2OxIBVxYRAxWEnfUvAgMBAAEwDQYJKoZIhvcNAQELBQADgYEAhetvOU8TyqfZF5jpv0IcrviLl/DoFrbjByeHR+pu/vClcAOjL/u7oQELuuTfNsBI4tpexUj5G8q/YbEz0gk7idfLXrAUVcsR73oTngrhRfwUSmPrjjK0kjcRb6HL9V/+wh3R/6mEd59U08ExT8N38rhmn0CI3ehMdebReprP7U8=
-
-
-
-
+ urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
+ urn:oasis:names:tc:SAML:2.0:nameid-format:transient
+ urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
+ urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
+
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/admin-test/saml-idp-metadata.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/admin-test/saml-idp-metadata.xml
index f28e206717..13681c1b1c 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/admin-test/saml-idp-metadata.xml
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/admin-test/saml-idp-metadata.xml
@@ -5,16 +5,6 @@
>
- urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
- urn:oasis:names:tc:SAML:2.0:nameid-format:transient
- urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
- urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
-
-
-
@@ -24,5 +14,14 @@
+
+ urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
+ urn:oasis:names:tc:SAML:2.0:nameid-format:transient
+ urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
+ urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
+