KEYCLOAK-14304 Enhance SAML Identity Provider Metadata processing

This commit is contained in:
Konstantinos Georgilakis 2020-05-27 11:06:31 +03:00 committed by Hynek Mlnařík
parent aad3bdcb88
commit 1fa93db1b4
14 changed files with 295 additions and 28 deletions

View file

@ -0,0 +1,61 @@
package org.keycloak.dom.saml.v2.mdattr;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
/**
*
* *
* <p>
* Java class for EntityAttributes complex type.
*
* <p>
* The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* &lt;element name="EntityAttributes" type="mdattr:EntityAttributesType"/>
* &lt;complexType name="EntityAttributesType">
* &lt;choice maxOccurs="unbounded">
* &lt;element ref="saml:Attribute"/>
* &lt;element ref="saml:Assertion"/>
* &lt;/sequence>
* &lt;/complexType>
*
* </pre>
*
*/
public class EntityAttributes implements Serializable {
protected List<AttributeType> attribute = new ArrayList<>();
protected List<AssertionType> assertion = new ArrayList<>();
public List<AttributeType> getAttribute() {
return attribute;
}
public void addAttribute(AttributeType attributeType) {
attribute.add(attributeType);
}
public void removeAttribute(AttributeType attributeType) {
attribute.remove(attributeType);
}
public List<AssertionType> getAssertion() {
return assertion;
}
public void addAssertion(AssertionType attributeType) {
assertion.add(attributeType);
}
public void removeAssertion(AttributeType attributeType) {
assertion.remove(attributeType);
}
}

View file

@ -16,12 +16,13 @@
*/
package org.keycloak.dom.saml.v2.metadata;
import org.w3c.dom.Element;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.keycloak.dom.saml.v2.mdattr.EntityAttributes;
import org.w3c.dom.Element;
/**
* <p>
* Java class for ExtensionsType complex type.
@ -88,4 +89,14 @@ public class ExtensionsType {
public List<Object> getAny() {
return Collections.unmodifiableList(this.any);
}
}
public EntityAttributes getEntityAttributes() {
for (Object o : this.any) {
if (o instanceof EntityAttributes) {
return (EntityAttributes) o;
}
}
return null;
}
}

View file

@ -65,6 +65,8 @@ public enum JBossSAMLURIConstants {
HOLDER_OF_KEY("urn:oasis:names:tc:SAML:2.0:cm:holder-of-key"),
METADATA_NSURI("urn:oasis:names:tc:SAML:2.0:metadata"),
// http://docs.oasis-open.org/security/saml/Post2.0/sstc-metadata-attr-cd-01.pdf
METADATA_ENTITY_ATTRIBUTES_NSURI("urn:oasis:names:tc:SAML:metadata:attribute"),
NAMEID_FORMAT_TRANSIENT("urn:oasis:names:tc:SAML:2.0:nameid-format:transient"),
NAMEID_FORMAT_PERSISTENT("urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"),

View file

@ -0,0 +1,46 @@
package org.keycloak.saml.processing.core.parsers.saml.mdattr;
import java.io.Serializable;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
import org.keycloak.dom.saml.v2.mdattr.EntityAttributes;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAssertionParser;
import org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAttributeParser;
import org.keycloak.saml.processing.core.parsers.saml.metadata.AbstractStaxSamlMetadataParser;
import org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLMetadataQNames;
public class SAMLEntityAttributesParser extends AbstractStaxSamlMetadataParser<EntityAttributes> implements Serializable {
private static final SAMLEntityAttributesParser INSTANCE = new SAMLEntityAttributesParser();
private SAMLEntityAttributesParser() {
super(SAMLMetadataQNames.ENTITY_ATTRIBUTES);
}
public static SAMLEntityAttributesParser getInstance() {
return INSTANCE;
}
@Override
protected EntityAttributes instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
return new EntityAttributes();
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, EntityAttributes target, SAMLMetadataQNames element,
StartElement elementDetail) throws ParsingException {
switch (element) {
case ATTRIBUTE:
target.addAttribute(SAMLAttributeParser.getInstance().parse(xmlEventReader));
break;
case ASSERTION:
target.addAssertion(SAMLAssertionParser.getInstance().parse(xmlEventReader));
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}

View file

@ -16,12 +16,13 @@
*/
package org.keycloak.saml.processing.core.parsers.saml.metadata;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
import org.keycloak.dom.saml.v2.metadata.ExtensionsType;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.StaxParserUtil;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
import org.keycloak.saml.processing.core.parsers.saml.mdattr.SAMLEntityAttributesParser;
/**
* Parses &lt;samlp:Extensions&gt; SAML2 element into series of DOM nodes.
@ -46,7 +47,16 @@ public class SAMLExtensionsParser extends AbstractStaxSamlMetadataParser<Extensi
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, ExtensionsType target, SAMLMetadataQNames element, StartElement elementDetail) throws ParsingException {
target.addExtension(StaxParserUtil.getDOMElement(xmlEventReader));
protected void processSubElement(XMLEventReader xmlEventReader, ExtensionsType target, SAMLMetadataQNames element,
StartElement elementDetail) throws ParsingException {
switch (element) {
case ENTITY_ATTRIBUTES:
target.addExtension(SAMLEntityAttributesParser.getInstance().parse(xmlEventReader));
break;
default:
target.addExtension(StaxParserUtil.getDOMElement(xmlEventReader));
}
}
}

View file

@ -77,7 +77,6 @@ public enum SAMLMetadataQNames implements HasQName {
ATTR_IS_REQUIRED(null, "isRequired"),
ATTR_NAME(null, "Name"),
ATTR_NAME_FORMAT(null, "NameFormat"),
// Elements from other namespaces that can be direct subelements of this namespace's elements
SIGNATURE(XmlDSigQNames.SIGNATURE),
KEY_INFO(XmlDSigQNames.KEY_INFO),
@ -85,6 +84,8 @@ public enum SAMLMetadataQNames implements HasQName {
OAEP_PARAMS(JBossSAMLURIConstants.XMLENC_NSURI, "OAEPparams"),
ATTR_X500_ENCODING(JBossSAMLURIConstants.X500_NSURI, "Encoding"),
ATTRIBUTE(SAMLAssertionQNames.ATTRIBUTE),
ASSERTION(SAMLAssertionQNames.ASSERTION),
ENTITY_ATTRIBUTES(JBossSAMLURIConstants.METADATA_ENTITY_ATTRIBUTES_NSURI, "EntityAttributes"),
UNKNOWN_ELEMENT("");

View file

@ -32,6 +32,8 @@ public class IdentityProviderModel implements Serializable {
public static final String LOGIN_HINT = "loginHint";
public static final String SYNC_MODE = "syncMode";
public static final String HIDE_ON_LOGIN = "hideOnLoginPage";
private String internalId;
@ -227,4 +229,13 @@ public class IdentityProviderModel implements Serializable {
public void setLoginHint(boolean loginHint) {
getConfig().put(LOGIN_HINT, String.valueOf(loginHint));
}
public boolean isHideOnLogin() {
return Boolean.valueOf(getConfig().get(HIDE_ON_LOGIN));
}
public void setHideOnLogin(boolean hideOnLogin) {
getConfig().put(HIDE_ON_LOGIN, String.valueOf(hideOnLogin));
}
}

View file

@ -52,6 +52,7 @@ public class SAMLIdentityProviderConfig extends IdentityProviderModel {
public static final String WANT_ASSERTIONS_SIGNED = "wantAssertionsSigned";
public static final String WANT_AUTHN_REQUESTS_SIGNED = "wantAuthnRequestsSigned";
public static final String XML_SIG_KEY_INFO_KEY_NAME_TRANSFORMER = "xmlSigKeyInfoKeyNameTransformer";
public static final String ENABLED_FROM_METADATA = "enabledFromMetadata";
public SAMLIdentityProviderConfig() {
}
@ -280,6 +281,14 @@ public class SAMLIdentityProviderConfig extends IdentityProviderModel {
public void setPrincipalAttribute(String principalAttribute) {
getConfig().put(PRINCIPAL_ATTRIBUTE, principalAttribute);
}
public boolean isEnabledFromMetadata() {
return Boolean.valueOf(getConfig().get(ENABLED_FROM_METADATA ));
}
public void setEnabledFromMetadata(boolean enabled) {
getConfig().put(ENABLED_FROM_METADATA , String.valueOf(enabled));
}
@Override
public void validate(RealmModel realm) {

View file

@ -16,8 +16,18 @@
*/
package org.keycloak.broker.saml;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.namespace.QName;
import org.keycloak.Config.Scope;
import org.keycloak.broker.provider.AbstractIdentityProviderFactory;
import org.keycloak.common.util.Time;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
import org.keycloak.dom.saml.v2.metadata.EndpointType;
import org.keycloak.dom.saml.v2.metadata.EntitiesDescriptorType;
import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType;
@ -33,12 +43,6 @@ import org.keycloak.saml.processing.core.parsers.saml.SAMLParser;
import org.keycloak.saml.validators.DestinationValidator;
import org.w3c.dom.Element;
import javax.xml.namespace.QName;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Pedro Igor
*/
@ -46,6 +50,9 @@ public class SAMLIdentityProviderFactory extends AbstractIdentityProviderFactory
public static final String PROVIDER_ID = "saml";
private static final String MACEDIR_ENTITY_CATEGORY = "http://macedir.org/entity-category";
private static final String REFEDS_HIDE_FROM_DISCOVERY = "http://refeds.org/category/hide-from-discovery";
private DestinationValidator destinationValidator;
@Override
@ -158,6 +165,20 @@ public class SAMLIdentityProviderFactory extends AbstractIdentityProviderFactory
}
}
samlIdentityProviderConfig.setEnabledFromMetadata(entityType.getValidUntil() == null
|| entityType.getValidUntil().toGregorianCalendar().getTime().after(new Date(System.currentTimeMillis())));
// check for hide on login attribute
if (entityType.getExtensions() != null && entityType.getExtensions().getEntityAttributes() != null) {
for (AttributeType attribute : entityType.getExtensions().getEntityAttributes().getAttribute()) {
if (MACEDIR_ENTITY_CATEGORY.equals(attribute.getName())
&& attribute.getAttributeValue().contains(REFEDS_HIDE_FROM_DISCOVERY)) {
samlIdentityProviderConfig.setHideOnLogin(true);
}
}
}
return samlIdentityProviderConfig.getConfig();
}
}

View file

@ -20,7 +20,9 @@ package org.keycloak.testsuite.admin;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput;
import org.junit.Test;
import org.keycloak.admin.client.resource.IdentityProviderResource;
import org.keycloak.broker.saml.SAMLIdentityProviderConfig;
import org.keycloak.common.enums.SslRequired;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
import org.keycloak.dom.saml.v2.metadata.EndpointType;
import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType;
import org.keycloak.dom.saml.v2.metadata.IndexedEndpointType;
@ -494,16 +496,16 @@ public class IdentityProviderTest extends AbstractAdminTest {
}
private IdentityProviderRepresentation createRep(String id, String providerId) {
return createRep(id, providerId, null);
return createRep(id, providerId,true, null);
}
private IdentityProviderRepresentation createRep(String id, String providerId, Map<String, String> config) {
private IdentityProviderRepresentation createRep(String id, String providerId,boolean enabled, Map<String, String> config) {
IdentityProviderRepresentation idp = new IdentityProviderRepresentation();
idp.setAlias(id);
idp.setDisplayName(id);
idp.setProviderId(providerId);
idp.setEnabled(true);
idp.setEnabled(enabled);
if (config != null) {
idp.setConfig(config);
}
@ -603,14 +605,14 @@ public class IdentityProviderTest extends AbstractAdminTest {
form.addFormData("file", body, MediaType.APPLICATION_XML_TYPE, "saml-idp-metadata.xml");
Map<String, String> result = realm.identityProviders().importFrom(form);
assertSamlImport(result, SIGNING_CERT_1);
assertSamlImport(result, SIGNING_CERT_1,true);
// Create new SAML identity provider using configuration retrieved from import-config
create(createRep("saml", "saml", result));
create(createRep("saml", "saml",true, result));
IdentityProviderResource provider = realm.identityProviders().get("saml");
IdentityProviderRepresentation rep = provider.toRepresentation();
assertCreatedSamlIdp(rep);
assertCreatedSamlIdp(rep,true);
// Now list the providers - we should see the one just created
List<IdentityProviderRepresentation> providers = realm.identityProviders().findAll();
@ -626,6 +628,32 @@ public class IdentityProviderTest extends AbstractAdminTest {
assertSamlExport(body);
}
@Test
public void testSamlImportAndExportDisabled() throws URISyntaxException, IOException, ParsingException {
// Use import-config to convert IDPSSODescriptor file into key value pairs
// to use when creating a SAML Identity Provider
MultipartFormDataOutput form = new MultipartFormDataOutput();
form.addFormData("providerId", "saml", MediaType.TEXT_PLAIN_TYPE);
URL idpMeta = getClass().getClassLoader().getResource("admin-test/saml-idp-metadata-disabled.xml");
byte[] content = Files.readAllBytes(Paths.get(idpMeta.toURI()));
String body = new String(content, Charset.forName("utf-8"));
form.addFormData("file", body, MediaType.APPLICATION_XML_TYPE, "saml-idp-metadata-disabled.xml");
Map<String, String> result = realm.identityProviders().importFrom(form);
assertSamlImport(result, SIGNING_CERT_1, false);
// Create new SAML identity provider using configuration retrieved from import-config
create(createRep("saml", "saml", false, result));
IdentityProviderResource provider = realm.identityProviders().get("saml");
IdentityProviderRepresentation rep = provider.toRepresentation();
assertCreatedSamlIdp(rep, false);
}
@Test
public void testSamlImportAndExportMultipleSigningKeys() throws URISyntaxException, IOException, ParsingException {
@ -641,14 +669,14 @@ public class IdentityProviderTest extends AbstractAdminTest {
form.addFormData("file", body, MediaType.APPLICATION_XML_TYPE, "saml-idp-metadata-two-signing-certs");
Map<String, String> result = realm.identityProviders().importFrom(form);
assertSamlImport(result, SIGNING_CERT_1 + "," + SIGNING_CERT_2);
assertSamlImport(result, SIGNING_CERT_1 + "," + SIGNING_CERT_2,true);
// Create new SAML identity provider using configuration retrieved from import-config
create(createRep("saml", "saml", result));
create(createRep("saml", "saml",true, result));
IdentityProviderResource provider = realm.identityProviders().get("saml");
IdentityProviderRepresentation rep = provider.toRepresentation();
assertCreatedSamlIdp(rep);
assertCreatedSamlIdp(rep,true);
// Now list the providers - we should see the one just created
List<IdentityProviderRepresentation> providers = realm.identityProviders().findAll();
@ -863,13 +891,13 @@ public class IdentityProviderTest extends AbstractAdminTest {
Assert.assertEquals("config", expected.getConfig(), actual.getConfig());
}
private void assertCreatedSamlIdp(IdentityProviderRepresentation idp) {
private void assertCreatedSamlIdp(IdentityProviderRepresentation idp,boolean enabled) {
//System.out.println("idp: " + idp);
Assert.assertNotNull("IdentityProviderRepresentation not null", idp);
Assert.assertNotNull("internalId", idp.getInternalId());
Assert.assertEquals("alias", "saml", idp.getAlias());
Assert.assertEquals("providerId", "saml", idp.getProviderId());
Assert.assertTrue("enabled", idp.isEnabled());
Assert.assertEquals("enabled",enabled, idp.isEnabled());
Assert.assertEquals("firstBrokerLoginFlowAlias", "first broker login",idp.getFirstBrokerLoginFlowAlias());
assertSamlConfig(idp.getConfig());
}
@ -889,7 +917,8 @@ public class IdentityProviderTest extends AbstractAdminTest {
"nameIDPolicyFormat",
"signingCertificate",
"addExtensionsElementWithKeyInfo",
"loginHint"
"loginHint",
"hideOnLoginPage"
));
assertThat(config, hasEntry("validateSignature", "true"));
assertThat(config, hasEntry("singleLogoutServiceUrl", "http://localhost:8080/auth/realms/master/protocol/saml"));
@ -899,10 +928,15 @@ public class IdentityProviderTest extends AbstractAdminTest {
assertThat(config, hasEntry("wantAuthnRequestsSigned", "true"));
assertThat(config, hasEntry("addExtensionsElementWithKeyInfo", "false"));
assertThat(config, hasEntry("nameIDPolicyFormat", "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"));
assertThat(config, hasEntry("hideOnLoginPage", "true"));
assertThat(config, hasEntry(is("signingCertificate"), notNullValue()));
}
private void assertSamlImport(Map<String, String> config, String expectedSigningCertificates) {
private void assertSamlImport(Map<String, String> config, String expectedSigningCertificates,boolean enabled) {
//firtsly check and remove enabledFromMetadata from config
boolean enabledFromMetadata = Boolean.valueOf(config.get(SAMLIdentityProviderConfig.ENABLED_FROM_METADATA));
config.remove(SAMLIdentityProviderConfig.ENABLED_FROM_METADATA);
Assert.assertEquals(enabledFromMetadata,enabled);
assertSamlConfig(config);
assertThat(config, hasEntry("signingCertificate", expectedSigningCertificates));
}

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<EntityDescriptor entityID="http://localhost:8080/auth/realms/master"
xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"
validUntil="2019-12-10T04:48:55Z"
>
<Extensions>
<mdattr:EntityAttributes>
<saml:Attribute Name="http://macedir.org/entity-category" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml:AttributeValue>http://refeds.org/category/hide-from-discovery</saml:AttributeValue>
</saml:Attribute>
</mdattr:EntityAttributes>
</Extensions>
<IDPSSODescriptor WantAuthnRequestsSigned="true"
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="http://localhost:8080/auth/realms/master/protocol/saml" />
<SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="http://localhost:8080/auth/realms/master/protocol/saml" />
<KeyDescriptor use="signing">
<dsig:KeyInfo xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
<dsig:X509Data>
<dsig:X509Certificate>
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=
</dsig:X509Certificate>
</dsig:X509Data>
</dsig:KeyInfo>
</KeyDescriptor>
</IDPSSODescriptor>
</EntityDescriptor>

View file

@ -1,8 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<EntityDescriptor entityID="http://localhost:8080/auth/realms/master"
xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"
>
<Extensions>
<mdattr:EntityAttributes>
<saml:Attribute Name="http://macedir.org/entity-category" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml:AttributeValue>http://refeds.org/category/hide-from-discovery</saml:AttributeValue>
</saml:Attribute>
</mdattr:EntityAttributes>
</Extensions>
<IDPSSODescriptor WantAuthnRequestsSigned="true"
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">

View file

@ -1,8 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<EntityDescriptor entityID="http://localhost:8080/auth/realms/master"
xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"
>
<Extensions>
<mdattr:EntityAttributes>
<saml:Attribute Name="http://macedir.org/entity-category" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml:AttributeValue>http://refeds.org/category/hide-from-discovery</saml:AttributeValue>
</saml:Attribute>
</mdattr:EntityAttributes>
</Extensions>
<IDPSSODescriptor WantAuthnRequestsSigned="true"
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<KeyDescriptor use="signing">

View file

@ -962,9 +962,14 @@ module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload
};
var setConfig = function(data) {
if (data["enabledFromMetadata"] !== undefined ) {
$scope.identityProvider.enabled = data["enabledFromMetadata"] == "true";
delete data["enabledFromMetadata"];
}
for (var key in data) {
$scope.identityProvider.config[key] = data[key];
}
}
$scope.uploadFile = function() {