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 +