From b629a569f948b23f7e9069b34c1cb259f95ecd61 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Wed, 21 Sep 2022 15:04:41 -0700 Subject: [PATCH] SHIBUI-2380 Incremental commit: - Removed X509Certificates from the security representation (functionally handled by key descriptors - Updated parsing representation into EntityDescriptor entity to handle new oidc values --- .../admin/ui/domain/RoleDescriptor.java | 9 +- .../frontend/SecurityInfoRepresentation.java | 12 -- .../admin/ui/domain/oidc/DefaultAcrValue.java | 5 + .../ui/domain/oidc/OAuthRPExtensions.java | 8 +- .../ui/domain/oidc/PostLogoutRedirectUri.java | 5 + .../admin/ui/domain/oidc/RequestUri.java | 5 + .../JPAEntityDescriptorServiceImpl.java | 13 +- .../util/EntityDescriptorConversionUtils.java | 165 +++++++++++++----- .../shibboleth/admin/util/MDDCConstants.java | 4 +- .../EntityDescriptorControllerTests.groovy | 23 +++ .../service/AuxiliaryIntegrationTests.groovy | 2 +- ...JPAEntityDescriptorServiceImplTests.groovy | 23 ++- ...ntityDescriptorConversionUtilsTests.groovy | 45 ++--- .../src/test/resources/json/SHIBUI-187.json | 2 +- .../src/test/resources/json/SHIBUI-211.json | 2 +- .../src/test/resources/json/SHIBUI-219-1.json | 2 +- .../src/test/resources/json/SHIBUI-219-2.json | 2 +- .../src/test/resources/json/SHIBUI-219-3.json | 2 +- .../src/test/resources/json/SHIBUI-223.json | 8 +- .../test/resources/json/SHIBUI-2380-1.json | 90 ++++++++++ .../src/test/resources/json/SHIBUI-2380.json | 96 ++++++++++ .../src/test/resources/json/SHIBUI-855.json | 2 +- 22 files changed, 418 insertions(+), 107 deletions(-) create mode 100644 backend/src/test/resources/json/SHIBUI-2380-1.json create mode 100644 backend/src/test/resources/json/SHIBUI-2380.json diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/RoleDescriptor.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/RoleDescriptor.java index c64edb0ad..383d7237b 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/RoleDescriptor.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/RoleDescriptor.java @@ -77,10 +77,6 @@ public void setID(String id) { @Override public List getSupportedProtocols() { - // This protocol must be included if this is OIDC data - if (isOidcType() && !supportedProtocols.contains("http://openid.net/specs/openid-connect-core-1_0.html")) { - supportedProtocols.add("http://openid.net/specs/openid-connect-core-1_0.html"); - } return supportedProtocols; } @@ -203,7 +199,10 @@ public List getOrderedChildren() { @Transient public boolean isOidcType() { - if (getExtensions().getOrderedChildren().size() > 0) { + if (getExtensions() == null || getExtensions().getOrderedChildren() == null || getExtensions().getOrderedChildren().isEmpty()){ + return false; + } + else { for (XMLObject e : getExtensions().getOrderedChildren()) { if (e.getElementQName().getLocalPart().equals(OAuthRPExtensions.TYPE_LOCAL_NAME)) { return true; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/frontend/SecurityInfoRepresentation.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/frontend/SecurityInfoRepresentation.java index 7ba875678..ec1d8e62d 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/frontend/SecurityInfoRepresentation.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/frontend/SecurityInfoRepresentation.java @@ -14,22 +14,10 @@ public class SecurityInfoRepresentation implements Serializable { private boolean authenticationRequestsSigned; private boolean wantAssertionsSigned; - private List x509Certificates = new ArrayList<>(); private List keyDescriptors = new ArrayList<>(); public void addKeyDescriptor(KeyDescriptorRepresentation keyDescriptorRep) { keyDescriptors.add(keyDescriptorRep); } - @Getter - @Setter - @Deprecated - public static class X509CertificateRepresentation implements Serializable { - private static final long serialVersionUID = -4893206348572998788L; - - private String name; - private String value; - //TODO refactor into Enum? - private String type; - } } \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/oidc/DefaultAcrValue.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/oidc/DefaultAcrValue.java index b1a2542f9..954fa9db5 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/oidc/DefaultAcrValue.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/oidc/DefaultAcrValue.java @@ -1,12 +1,17 @@ package edu.internet2.tier.shibboleth.admin.ui.domain.oidc; import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; import org.hibernate.envers.Audited; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) +@NoArgsConstructor @Audited public class DefaultAcrValue extends AbstractValueXMLObject implements net.shibboleth.oidc.saml.xmlobject.DefaultAcrValue { + public DefaultAcrValue(String value) { + this.setValue(value); + } } \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/oidc/OAuthRPExtensions.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/oidc/OAuthRPExtensions.java index 02e40cb58..45fdcf650 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/oidc/OAuthRPExtensions.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/oidc/OAuthRPExtensions.java @@ -4,6 +4,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import net.shibboleth.oidc.saml.xmlobject.MetadataValueSAMLObject; import org.hibernate.envers.Audited; import org.opensaml.core.xml.XMLObject; import org.opensaml.core.xml.util.AttributeMap; @@ -22,7 +23,6 @@ @Entity @Data @EqualsAndHashCode(callSuper=false) -@NoArgsConstructor @Audited public class OAuthRPExtensions extends AbstractXMLObject implements net.shibboleth.oidc.saml.xmlobject.OAuthRPExtensions { public static final String DEFAULT_ELEMENT_LOCAL_NAME = TYPE_LOCAL_NAME; @@ -88,6 +88,12 @@ public class OAuthRPExtensions extends AbstractXMLObject implements net.shibbole private String userInfoEncryptedResponseEnc; + public OAuthRPExtensions() { + setNamespacePrefix(MetadataValueSAMLObject.SAML20MDOIDCMD_PREFIX); + setNamespaceURI(MetadataValueSAMLObject.SAML20MDOIDCMD_NS); + setElementLocalName(TYPE_LOCAL_NAME); + } + @Override public List getOrderedChildren() { List result = new ArrayList<>(); diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/oidc/PostLogoutRedirectUri.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/oidc/PostLogoutRedirectUri.java index b6f2380cd..2c66e75e3 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/oidc/PostLogoutRedirectUri.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/oidc/PostLogoutRedirectUri.java @@ -1,12 +1,17 @@ package edu.internet2.tier.shibboleth.admin.ui.domain.oidc; import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; import org.hibernate.envers.Audited; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) +@NoArgsConstructor @Audited public class PostLogoutRedirectUri extends AbstractValueXMLObject implements net.shibboleth.oidc.saml.xmlobject.PostLogoutRedirectUri { + public PostLogoutRedirectUri(String value) { + this.setValue(value); + } } \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/oidc/RequestUri.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/oidc/RequestUri.java index 386c4e040..ee9885ebd 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/oidc/RequestUri.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/oidc/RequestUri.java @@ -1,12 +1,17 @@ package edu.internet2.tier.shibboleth.admin.ui.domain.oidc; import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; import org.hibernate.envers.Audited; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) +@NoArgsConstructor @Audited public class RequestUri extends AbstractValueXMLObject implements net.shibboleth.oidc.saml.xmlobject.RequestUri { + public RequestUri(String value) { + this.setValue(value); + } } \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImpl.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImpl.java index d40fd9255..f456c3248 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImpl.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImpl.java @@ -98,6 +98,9 @@ private EntityDescriptor buildDescriptorFromRepresentation(final EntityDescripto setupLogout(ed, representation); setupRelyingPartyOverrides(ed, representation); + if (ed.getProtocol() == EntityDescriptorProtocol.OIDC) { + ed.getSPSSODescriptor("").addSupportedProtocol("http://openid.net/specs/openid-connect-core-1_0.html"); + } //Let envers recognize update revision type for EntityDescriptor type //when modifying Attributes and SPSSODescriptor inside RoleDescriptors collection ed.setVersionModifiedTimestamp(System.currentTimeMillis()); @@ -311,7 +314,6 @@ public EntityDescriptorRepresentation createRepresentationFromDescriptor(org.ope } } - // set up security - this block assumes too much like there will be a cert. With OIDC could not be some... setupSecurityRepresentationFromEntityDescriptor(ed, representation); // set up ACSs @@ -513,15 +515,6 @@ private void setupSecurityRepresentationFromEntityDescriptor(EntityDescriptor ed keyDescriptorRep.setValue(((ValueXMLObject) obj).getValue()); securityInfoRepresentation.addKeyDescriptor(keyDescriptorRep); } - - // TODO remove this when done. - if (keyInfoType == KeyDescriptorRepresentation.ElementType.X509Data) { - SecurityInfoRepresentation.X509CertificateRepresentation x509CertificateRepresentation = new SecurityInfoRepresentation.X509CertificateRepresentation(); - x509CertificateRepresentation.setName(name); - x509CertificateRepresentation.setType(useType); - x509CertificateRepresentation.setValue(keyDescriptorRep.getValue()); - securityInfoRepresentation.getX509Certificates().add(x509CertificateRepresentation); - } } } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/EntityDescriptorConversionUtils.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/EntityDescriptorConversionUtils.java index f2ed82f82..d2f18d348 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/EntityDescriptorConversionUtils.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/EntityDescriptorConversionUtils.java @@ -1,24 +1,7 @@ package edu.internet2.tier.shibboleth.admin.util; -import static edu.internet2.tier.shibboleth.admin.util.EntityDescriptorConversionUtils.getEntityAttributes; -import static edu.internet2.tier.shibboleth.admin.util.EntityDescriptorConversionUtils.getSPSSODescriptorFromEntityDescriptor; - -import java.util.Arrays; -import java.util.Collections; -import java.util.Optional; -import java.util.stream.Collectors; - -import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptorProtocol; -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ServiceProviderSsoDescriptorRepresentation; -import lombok.NonNull; -import org.opensaml.xmlsec.signature.KeyInfo; -import org.opensaml.xmlsec.signature.X509Certificate; -import org.opensaml.xmlsec.signature.X509Data; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Strings; - import edu.internet2.tier.shibboleth.admin.ui.domain.AssertionConsumerService; import edu.internet2.tier.shibboleth.admin.ui.domain.ContactPerson; import edu.internet2.tier.shibboleth.admin.ui.domain.ContactPersonBuilder; @@ -28,6 +11,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributes; import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesBuilder; import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor; +import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptorProtocol; import edu.internet2.tier.shibboleth.admin.ui.domain.Extensions; import edu.internet2.tier.shibboleth.admin.ui.domain.GivenName; import edu.internet2.tier.shibboleth.admin.ui.domain.InformationURL; @@ -45,13 +29,38 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.AssertionConsumerServiceRepresentation; import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ContactRepresentation; import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation; +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.KeyDescriptorRepresentation; import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.LogoutEndpointRepresentation; import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.MduiRepresentation; import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.OrganizationRepresentation; import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.SecurityInfoRepresentation; +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ServiceProviderSsoDescriptorRepresentation; +import edu.internet2.tier.shibboleth.admin.ui.domain.oidc.AbstractValueXMLObject; +import edu.internet2.tier.shibboleth.admin.ui.domain.oidc.DefaultAcrValue; +import edu.internet2.tier.shibboleth.admin.ui.domain.oidc.JwksData; +import edu.internet2.tier.shibboleth.admin.ui.domain.oidc.OAuthRPExtensions; +import edu.internet2.tier.shibboleth.admin.ui.domain.oidc.PostLogoutRedirectUri; +import edu.internet2.tier.shibboleth.admin.ui.domain.oidc.RequestUri; +import edu.internet2.tier.shibboleth.admin.ui.domain.oidc.ValueXMLObject; import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects; import edu.internet2.tier.shibboleth.admin.ui.service.EntityService; +import lombok.NonNull; import lombok.Setter; +import org.opensaml.core.xml.XMLObject; +import org.opensaml.xmlsec.signature.KeyInfo; +import org.opensaml.xmlsec.signature.X509Certificate; +import org.opensaml.xmlsec.signature.X509Data; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; @Service public class EntityDescriptorConversionUtils { @@ -62,31 +71,58 @@ public class EntityDescriptorConversionUtils { @Autowired @Setter private static EntityService entityService; - - public static KeyDescriptor createKeyDescriptor(String name, String type, String value) { + + public static KeyDescriptor createKeyDescriptor(String name, String usageType, String value, KeyDescriptorRepresentation.ElementType elementType) { KeyDescriptor keyDescriptor = openSamlObjects.buildDefaultInstanceOfType(KeyDescriptor.class); if (!Strings.isNullOrEmpty(name)) { keyDescriptor.setName(name); } - if (!"both".equals(type)) { - keyDescriptor.setUsageType(type); + if (!"both".equals(usageType)) { + keyDescriptor.setUsageType(usageType); } KeyInfo keyInfo = openSamlObjects.buildDefaultInstanceOfType(KeyInfo.class); - keyDescriptor.setKeyInfo(keyInfo); - - X509Data x509Data = openSamlObjects.buildDefaultInstanceOfType(X509Data.class); - keyInfo.getXMLObjects().add(x509Data); - - X509Certificate x509Certificate = openSamlObjects.buildDefaultInstanceOfType(X509Certificate.class); - x509Data.getXMLObjects().add(x509Certificate); - x509Certificate.setValue(value); + AbstractValueXMLObject xmlObject; + switch (elementType) { + case X509Data: + X509Data x509Data = openSamlObjects.buildDefaultInstanceOfType(X509Data.class); + X509Certificate x509Certificate = openSamlObjects.buildDefaultInstanceOfType(X509Certificate.class); + x509Data.getXMLObjects().add(x509Certificate); + x509Certificate.setValue(value); + keyInfo.getXMLObjects().add(x509Data); + break; + case jwksData: + xmlObject = openSamlObjects.buildDefaultInstanceOfType(JwksData.class); + xmlObject.setValue(value); + keyInfo.getXMLObjects().add(xmlObject); + break; + case jwksUri: + xmlObject = openSamlObjects.buildDefaultInstanceOfType(JwksData.class); + xmlObject.setValue(value); + keyInfo.getXMLObjects().add(xmlObject); + break; + case clientSecret: + xmlObject = openSamlObjects.buildDefaultInstanceOfType(JwksData.class); + xmlObject.setValue(value); + keyInfo.getXMLObjects().add(xmlObject); + break; + case clientSecretKeyReference: + xmlObject = openSamlObjects.buildDefaultInstanceOfType(JwksData.class); + xmlObject.setValue(value); + keyInfo.getXMLObjects().add(xmlObject); + break; + } + keyDescriptor.setKeyInfo(keyInfo); return keyDescriptor; } - + + private static KeyDescriptor createKeyDescriptor(KeyDescriptorRepresentation keyDescRep) { + return createKeyDescriptor(keyDescRep.getName(), keyDescRep.getType(), keyDescRep.getValue(), keyDescRep.getElementType()); + } + public static EntityAttributes getEntityAttributes(EntityDescriptor ed) { return getEntityAttributes(ed, true); } @@ -267,10 +303,11 @@ public static void setupSecurity(EntityDescriptor ed, EntityDescriptorRepresenta } } ed.getOptionalSPSSODescriptor().ifPresent( i -> i.getKeyDescriptors().clear()); - // TODO will need to fill in keydescriptors from generic list not the x509 list - for (SecurityInfoRepresentation.X509CertificateRepresentation x509CertificateRepresentation : securityInfoRepresentation.getX509Certificates()) { - KeyDescriptor keyDescriptor = createKeyDescriptor(x509CertificateRepresentation.getName(), x509CertificateRepresentation.getType(), x509CertificateRepresentation.getValue()); - getSPSSODescriptorFromEntityDescriptor(ed).addKeyDescriptor(keyDescriptor); + if (securityInfoRepresentation.getKeyDescriptors().size() > 0) { + SPSSODescriptor spssoDescriptor = getSPSSODescriptorFromEntityDescriptor(ed); + securityInfoRepresentation.getKeyDescriptors().forEach(keyDescRep -> { + spssoDescriptor.addKeyDescriptor(createKeyDescriptor(keyDescRep)); + }); } } else { ed.getOptionalSPSSODescriptor().ifPresent( spssoDescriptor -> { @@ -280,12 +317,12 @@ public static void setupSecurity(EntityDescriptor ed, EntityDescriptorRepresenta }); } } - + public static void setupSPSSODescriptor(EntityDescriptor ed, EntityDescriptorRepresentation representation) { if (representation.getServiceProviderSsoDescriptor() != null || representation.getProtocol() == EntityDescriptorProtocol.OIDC) { SPSSODescriptor spssoDescriptor = getSPSSODescriptorFromEntityDescriptor(ed); - spssoDescriptor.setSupportedProtocols(Collections.EMPTY_LIST); + spssoDescriptor.setSupportedProtocols(new ArrayList<>()); if (!Strings.isNullOrEmpty(representation.getServiceProviderSsoDescriptor().getProtocolSupportEnum())) { spssoDescriptor.setSupportedProtocols( Arrays.stream(representation.getServiceProviderSsoDescriptor().getProtocolSupportEnum().split(",")).map(p -> MDDCConstants.PROTOCOL_BINDINGS.get(p.trim())).collect(Collectors.toList()) @@ -303,17 +340,65 @@ public static void setupSPSSODescriptor(EntityDescriptor ed, EntityDescriptorRep } } + // Setup Extensions if (representation.getProtocol() == EntityDescriptorProtocol.OIDC) { - spssoDescriptor.setExtensions(buildOidcExtensionsFromRepresentation(representation.getServiceProviderSsoDescriptor(false))); + spssoDescriptor.setExtensions(buildOAuthRPExtensionsFromRepresentation(representation.getServiceProviderSsoDescriptor(false))); } } else { ed.setRoleDescriptors(null); } } - private static Extensions buildOidcExtensionsFromRepresentation(@NonNull ServiceProviderSsoDescriptorRepresentation representation) { + private static Extensions buildOAuthRPExtensionsFromRepresentation(@NonNull ServiceProviderSsoDescriptorRepresentation representation) { Extensions result = new Extensions(); - + HashMap oauthrpextMap = (HashMap) representation.getExtensions().get("OAuthRPExtensions"); + OAuthRPExtensions oAuthRPExtensions = new OAuthRPExtensions(); + oauthrpextMap.keySet().forEach(key -> { + try { + if ("requestUris".equals(key) || "defaultAcrValues".equals(key) || "postLogoutRedirectUris".equals(key)){ + Field field = oAuthRPExtensions.getClass().getDeclaredField(key); + field.setAccessible(true); + ((List) oauthrpextMap.get(key)).forEach(value -> { + switch (key) { + case "requestUris": + oAuthRPExtensions.addRequestUri(new RequestUri((value))); + break; + case "defaultAcrValues": + oAuthRPExtensions.addDefaultAcrValue(new DefaultAcrValue((value))); + break; + case "postLogoutRedirectUris": + oAuthRPExtensions.addPostLogoutRedirectUri(new PostLogoutRedirectUri((value))); + break; + } + }); + } + else if ("attributes".equals(key)) { + HashMap attributes = (HashMap) oauthrpextMap.get(key); + attributes.keySet().forEach(attKey -> { + try { + Field attField = oAuthRPExtensions.getClass().getDeclaredField(attKey); + attField.setAccessible(true); + if ("requireAuthTime".equals(attKey)) { + Boolean value = Boolean.valueOf(attributes.get(attKey).toString()); + attField.set(oAuthRPExtensions, value); + } else if ("defaultMaxAge".equals(attKey)) { + Integer value = Integer.valueOf(attributes.get(attKey).toString()); + attField.setInt(oAuthRPExtensions, value); + } else { + attField.set(oAuthRPExtensions, attributes.get(attKey).toString()); + } + } + catch (IllegalAccessException | NoSuchFieldException e) { + // skip it + } + }); + } + } + catch (NoSuchFieldException e) { + // skip it + } + }); + result.addUnknownXMLObject(oAuthRPExtensions); return result; } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/MDDCConstants.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/MDDCConstants.java index 05953056a..6cf0c8bea 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/MDDCConstants.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/MDDCConstants.java @@ -51,6 +51,8 @@ public class MDDCConstants { map.put(SAMLConstants.SAML20P_NS, "SAML 2"); map.put(SAMLConstants.SAML11P_NS, "SAML 1.1"); + map.put("http://openid.net/specs/openid-connect-core-1_0.html", "http://openid.net/specs/openid-connect-core-1_0.html"); + PROTOCOL_BINDINGS = Collections.unmodifiableMap(map); } -} +} \ No newline at end of file diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy index 3ffbe12e0..c59e87c2a 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy @@ -3,6 +3,7 @@ package edu.internet2.tier.shibboleth.admin.ui.controller import com.fasterxml.jackson.databind.ObjectMapper import edu.internet2.tier.shibboleth.admin.ui.AbstractBaseDataJpaTest import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptorProtocol import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.AssertionConsumerServiceRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound @@ -22,7 +23,10 @@ import edu.internet2.tier.shibboleth.admin.ui.util.RandomGenerator import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator import edu.internet2.tier.shibboleth.admin.ui.util.WithMockAdmin import edu.internet2.tier.shibboleth.admin.util.EntityDescriptorConversionUtils +import groovy.json.JsonSlurper +import lombok.SneakyThrows import org.springframework.beans.factory.annotation.Autowired +import org.springframework.core.io.ClassPathResource import org.springframework.security.test.context.support.WithMockUser import org.springframework.test.web.servlet.setup.MockMvcBuilders import org.springframework.transaction.annotation.Transactional @@ -702,4 +706,23 @@ class EntityDescriptorControllerTests extends AbstractBaseDataJpaTest { e instanceof ConcurrentModificationException } } + + @WithMockAdmin + def "POST /EntityDescriptor OIDC descriptor"() { + when: + def result = mockMvc.perform(post('/api/EntityDescriptor').contentType(APPLICATION_JSON).content(fromFile("/json/SHIBUI-2380-1.json"))) + + then: + result.andExpect(status().isCreated()) + .andExpect(content().contentType(APPLICATION_JSON)) + .andExpect(jsonPath("\$.entityId").value("mockSamlClientId2")) + .andExpect(jsonPath("\$.serviceEnabled").value(false)) + .andExpect(jsonPath("\$.idOfOwner").value("admingroup")) + .andExpect(jsonPath("\$.serviceProviderSsoDescriptor.protocolSupportEnum").value("http://openid.net/specs/openid-connect-core-1_0.html")) + } + + @SneakyThrows + private byte[] fromFile(String path) { + return new ClassPathResource(path).getInputStream().readAllBytes() + } } \ No newline at end of file diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/AuxiliaryIntegrationTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/AuxiliaryIntegrationTests.groovy index 4c572e2ad..25873b638 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/AuxiliaryIntegrationTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/AuxiliaryIntegrationTests.groovy @@ -41,7 +41,7 @@ class AuxiliaryIntegrationTests extends Specification { def entityDescriptorRepresentation = entityDescriptorService.createRepresentationFromDescriptor(entityDescriptor).with { it.serviceProviderName = 'testme' it.contacts = [] - it.securityInfo.x509Certificates[0].name = 'testcert' + it.securityInfo.keyDescriptors[0].name = 'testcert' it.createdBy = 'root' it.setCreatedDate(LocalDateTime.now()) it.setModifiedDate(LocalDateTime.now()) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImplTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImplTests.groovy index 004e873ab..8de2ac759 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImplTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImplTests.groovy @@ -3,9 +3,11 @@ package edu.internet2.tier.shibboleth.admin.ui.service import com.fasterxml.jackson.databind.ObjectMapper import edu.internet2.tier.shibboleth.admin.ui.AbstractBaseDataJpaTest import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptorProtocol import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.AssertionConsumerServiceRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ContactRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.KeyDescriptorRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.LogoutEndpointRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.MduiRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.OrganizationRepresentation @@ -302,9 +304,10 @@ class JPAEntityDescriptorServiceImplTests extends AbstractBaseDataJpaTest { def test = openSamlObjects.marshalToXmlString(service.createDescriptorFromRepresentation(new EntityDescriptorRepresentation().with { it.entityId = 'http://test.example.org/test1' it.securityInfo = new SecurityInfoRepresentation().with { - it.x509Certificates = [new SecurityInfoRepresentation.X509CertificateRepresentation().with { + it.keyDescriptors = [new KeyDescriptorRepresentation().with { it.type = 'signing' it.value = 'certificate' + it.elementType = KeyDescriptorRepresentation.ElementType.X509Data it }] it @@ -341,9 +344,10 @@ class JPAEntityDescriptorServiceImplTests extends AbstractBaseDataJpaTest { def test = openSamlObjects.marshalToXmlString(service.createDescriptorFromRepresentation(new EntityDescriptorRepresentation().with { it.entityId = 'http://test.example.org/test1' it.securityInfo = new SecurityInfoRepresentation().with { - it.x509Certificates = [new SecurityInfoRepresentation.X509CertificateRepresentation().with { + it.keyDescriptors = [new KeyDescriptorRepresentation().with { it.type = 'encryption' it.value = 'certificate' + it.elementType = KeyDescriptorRepresentation.ElementType.X509Data it }] it @@ -380,9 +384,10 @@ class JPAEntityDescriptorServiceImplTests extends AbstractBaseDataJpaTest { def test = openSamlObjects.marshalToXmlString(service.createDescriptorFromRepresentation(new EntityDescriptorRepresentation().with { it.entityId = 'http://test.example.org/test1' it.securityInfo = new SecurityInfoRepresentation().with { - it.x509Certificates = [new SecurityInfoRepresentation.X509CertificateRepresentation().with { + it.keyDescriptors = [new KeyDescriptorRepresentation().with { it.type = 'both' it.value = 'certificate' + it.elementType = KeyDescriptorRepresentation.ElementType.X509Data it }] it @@ -648,9 +653,6 @@ class JPAEntityDescriptorServiceImplTests extends AbstractBaseDataJpaTest { def output = service.createRepresentationFromDescriptor(descriptor) then: - assert output.securityInfo.x509Certificates.size() == 1 - assert output.securityInfo.x509Certificates[0].type == 'both' - assert descriptor.getSPSSODescriptor('').getKeyDescriptors().size() == 1 assert descriptor.getSPSSODescriptor('').getKeyDescriptors()[0].getUse() == null } @@ -760,4 +762,13 @@ class JPAEntityDescriptorServiceImplTests extends AbstractBaseDataJpaTest { return ed } + + def "SHIBUI-2830 OIDC"() { + when: + def representation = new ObjectMapper().readValue(this.class.getResource('/json/SHIBUI-2380.json').bytes, EntityDescriptorRepresentation) + def ed = service.createDescriptorFromRepresentation(representation) + + then: + assert ed.getProtocol() == EntityDescriptorProtocol.OIDC + } } \ No newline at end of file diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/EntityDescriptorConversionUtilsTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/EntityDescriptorConversionUtilsTests.groovy index ca2296299..c04106582 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/EntityDescriptorConversionUtilsTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/EntityDescriptorConversionUtilsTests.groovy @@ -18,6 +18,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.SingleLogoutService import edu.internet2.tier.shibboleth.admin.ui.domain.UIInfo import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ContactRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.KeyDescriptorRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.LogoutEndpointRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.MduiRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.SecurityInfoRepresentation @@ -59,7 +60,7 @@ class EntityDescriptorConversionUtilsTests extends Specification { expected.name = 'testName' when: - def keyDescriptor = EntityDescriptorConversionUtils.createKeyDescriptor('testName', 'signing', 'testValue') + def keyDescriptor = EntityDescriptorConversionUtils.createKeyDescriptor('testName', 'signing', 'testValue', KeyDescriptorRepresentation.ElementType.X509Data) then: assert keyDescriptor == expected @@ -78,15 +79,15 @@ class EntityDescriptorConversionUtilsTests extends Specification { expected.name = 'testName' when: - def keyDescriptor = EntityDescriptorConversionUtils.createKeyDescriptor('testName', 'both', 'testValue') + def keyDescriptor = EntityDescriptorConversionUtils.createKeyDescriptor('testName', 'both', 'testValue', KeyDescriptorRepresentation.ElementType.X509Data) then: assert keyDescriptor == expected } def 'test createKeyDescriptor equality'() { when: - def key1 = EntityDescriptorConversionUtils.createKeyDescriptor('test', 'signing', 'test') - def key2 = EntityDescriptorConversionUtils.createKeyDescriptor('test', 'signing', 'test') + def key1 = EntityDescriptorConversionUtils.createKeyDescriptor('test', 'signing', 'test', KeyDescriptorRepresentation.ElementType.X509Data) + def key2 = EntityDescriptorConversionUtils.createKeyDescriptor('test', 'signing', 'test', KeyDescriptorRepresentation.ElementType.X509Data) then: assert key1 == key2 @@ -592,8 +593,8 @@ class EntityDescriptorConversionUtilsTests extends Specification { description: 'add signing certificate', representation: new EntityDescriptorRepresentation().with { it.securityInfo = new SecurityInfoRepresentation().with { - it.x509Certificates = [ - new SecurityInfoRepresentation.X509CertificateRepresentation(name: 'test', type: 'signing', value: 'test') + it.keyDescriptors = [ + new KeyDescriptorRepresentation(name: 'test', type: 'signing', value: 'test', elementType: KeyDescriptorRepresentation.ElementType.X509Data) ] it } @@ -604,7 +605,7 @@ class EntityDescriptorConversionUtilsTests extends Specification { it.getRoleDescriptors().add( openSAMLObjects.buildDefaultInstanceOfType(SPSSODescriptor.class).with { it.addKeyDescriptor( - utilsUnderTest.createKeyDescriptor('test', 'signing', 'test')) + utilsUnderTest.createKeyDescriptor('test', 'signing', 'test', KeyDescriptorRepresentation.ElementType.X509Data)) it } ) @@ -616,9 +617,9 @@ class EntityDescriptorConversionUtilsTests extends Specification { description: 'add another certificate', representation: new EntityDescriptorRepresentation().with { it.securityInfo = new SecurityInfoRepresentation().with { - it.x509Certificates = [ - new SecurityInfoRepresentation.X509CertificateRepresentation(name: 'test', type: 'signing', value: 'test'), - new SecurityInfoRepresentation.X509CertificateRepresentation(name: 'test2', type: 'encryption', value: 'test2') + it.keyDescriptors = [ + new KeyDescriptorRepresentation(name: 'test', type: 'signing', value: 'test', elementType: KeyDescriptorRepresentation.ElementType.X509Data), + new KeyDescriptorRepresentation(name: 'test2', type: 'encryption', value: 'test2', elementType: KeyDescriptorRepresentation.ElementType.X509Data) ] it } @@ -627,7 +628,7 @@ class EntityDescriptorConversionUtilsTests extends Specification { starter: openSAMLObjects.buildDefaultInstanceOfType(EntityDescriptor.class).with { it.getRoleDescriptors().add( openSAMLObjects.buildDefaultInstanceOfType(SPSSODescriptor.class).with { - it.addKeyDescriptor(utilsUnderTest.createKeyDescriptor('test', 'signing', 'test')) + it.addKeyDescriptor(utilsUnderTest.createKeyDescriptor('test', 'signing', 'test', KeyDescriptorRepresentation.ElementType.X509Data)) it } ) @@ -636,8 +637,8 @@ class EntityDescriptorConversionUtilsTests extends Specification { expected: openSAMLObjects.buildDefaultInstanceOfType(EntityDescriptor.class).with { it.getRoleDescriptors().add( openSAMLObjects.buildDefaultInstanceOfType(SPSSODescriptor.class).with { - it.addKeyDescriptor(utilsUnderTest.createKeyDescriptor('test', 'signing', 'test')) - it.addKeyDescriptor(utilsUnderTest.createKeyDescriptor('test2', 'encryption', 'test2')) + it.addKeyDescriptor(utilsUnderTest.createKeyDescriptor('test', 'signing', 'test', KeyDescriptorRepresentation.ElementType.X509Data)) + it.addKeyDescriptor(utilsUnderTest.createKeyDescriptor('test2', 'encryption', 'test2', KeyDescriptorRepresentation.ElementType.X509Data)) it } ) @@ -649,8 +650,8 @@ class EntityDescriptorConversionUtilsTests extends Specification { description: 'remove a certificate', representation: new EntityDescriptorRepresentation().with { it.securityInfo = new SecurityInfoRepresentation().with { - it.x509Certificates = [ - new SecurityInfoRepresentation.X509CertificateRepresentation(name: 'test2', type: 'encryption', value: 'test2') + it.keyDescriptors = [ + new KeyDescriptorRepresentation(name: 'test2', type: 'encryption', value: 'test2', elementType: KeyDescriptorRepresentation.ElementType.X509Data) ] it } @@ -659,8 +660,8 @@ class EntityDescriptorConversionUtilsTests extends Specification { starter: openSAMLObjects.buildDefaultInstanceOfType(EntityDescriptor.class).with { it.getRoleDescriptors().add( openSAMLObjects.buildDefaultInstanceOfType(SPSSODescriptor.class).with { - it.addKeyDescriptor(utilsUnderTest.createKeyDescriptor('test', 'signing', 'test')) - it.addKeyDescriptor(utilsUnderTest.createKeyDescriptor('test2', 'encryption', 'test2')) + it.addKeyDescriptor(utilsUnderTest.createKeyDescriptor('test', 'signing', 'test', KeyDescriptorRepresentation.ElementType.X509Data)) + it.addKeyDescriptor(utilsUnderTest.createKeyDescriptor('test2', 'encryption', 'test2', KeyDescriptorRepresentation.ElementType.X509Data)) it } ) @@ -669,7 +670,7 @@ class EntityDescriptorConversionUtilsTests extends Specification { expected: openSAMLObjects.buildDefaultInstanceOfType(EntityDescriptor.class).with { it.getRoleDescriptors().add( openSAMLObjects.buildDefaultInstanceOfType(SPSSODescriptor.class).with { - it.addKeyDescriptor(utilsUnderTest.createKeyDescriptor('test2', 'encryption', 'test2')) + it.addKeyDescriptor(utilsUnderTest.createKeyDescriptor('test2', 'encryption', 'test2', KeyDescriptorRepresentation.ElementType.X509Data)) it } ) @@ -688,8 +689,8 @@ class EntityDescriptorConversionUtilsTests extends Specification { starter: openSAMLObjects.buildDefaultInstanceOfType(EntityDescriptor.class).with { it.getRoleDescriptors().add( openSAMLObjects.buildDefaultInstanceOfType(SPSSODescriptor.class).with { - it.addKeyDescriptor(utilsUnderTest.createKeyDescriptor('test', 'signing', 'test')) - it.addKeyDescriptor(utilsUnderTest.createKeyDescriptor('test', 'encryption', 'test')) + it.addKeyDescriptor(utilsUnderTest.createKeyDescriptor('test', 'signing', 'test', KeyDescriptorRepresentation.ElementType.X509Data)) + it.addKeyDescriptor(utilsUnderTest.createKeyDescriptor('test', 'encryption', 'test', KeyDescriptorRepresentation.ElementType.X509Data)) it } ) @@ -709,8 +710,8 @@ class EntityDescriptorConversionUtilsTests extends Specification { starter: openSAMLObjects.buildDefaultInstanceOfType(EntityDescriptor.class).with { it.getRoleDescriptors().add( openSAMLObjects.buildDefaultInstanceOfType(SPSSODescriptor.class).with { - it.addKeyDescriptor(utilsUnderTest.createKeyDescriptor('test', 'signing', 'test')) - it.addKeyDescriptor(utilsUnderTest.createKeyDescriptor('test', 'encryption', 'test')) + it.addKeyDescriptor(utilsUnderTest.createKeyDescriptor('test', 'signing', 'test', KeyDescriptorRepresentation.ElementType.X509Data)) + it.addKeyDescriptor(utilsUnderTest.createKeyDescriptor('test', 'encryption', 'test', KeyDescriptorRepresentation.ElementType.X509Data)) it } ) diff --git a/backend/src/test/resources/json/SHIBUI-187.json b/backend/src/test/resources/json/SHIBUI-187.json index 74c42bf34..bf3a284b1 100644 --- a/backend/src/test/resources/json/SHIBUI-187.json +++ b/backend/src/test/resources/json/SHIBUI-187.json @@ -20,7 +20,7 @@ "securityInfo": { "authenticationRequestsSigned": false, "wantAssertionsSigned": false, - "x509Certificates": [] + "keyDescriptors": [] }, "assertionConsumerServices": [ { diff --git a/backend/src/test/resources/json/SHIBUI-211.json b/backend/src/test/resources/json/SHIBUI-211.json index 835860a9a..0bebe96fc 100644 --- a/backend/src/test/resources/json/SHIBUI-211.json +++ b/backend/src/test/resources/json/SHIBUI-211.json @@ -20,7 +20,7 @@ "securityInfo": { "authenticationRequestsSigned": false, "wantAssertionsSigned": false, - "x509Certificates": [] + "keyDescriptors": [] }, "assertionConsumerServices": [], "serviceProviderSsoDescriptor": { diff --git a/backend/src/test/resources/json/SHIBUI-219-1.json b/backend/src/test/resources/json/SHIBUI-219-1.json index 6d5a32587..b0261431b 100644 --- a/backend/src/test/resources/json/SHIBUI-219-1.json +++ b/backend/src/test/resources/json/SHIBUI-219-1.json @@ -20,7 +20,7 @@ "securityInfo": { "authenticationRequestsSigned": false, "wantAssertionsSigned": false, - "x509Certificates": [] + "keyDescriptors": [] }, "assertionConsumerServices": [], "serviceProviderSsoDescriptor": { diff --git a/backend/src/test/resources/json/SHIBUI-219-2.json b/backend/src/test/resources/json/SHIBUI-219-2.json index f2dd93df1..bc3034ce7 100644 --- a/backend/src/test/resources/json/SHIBUI-219-2.json +++ b/backend/src/test/resources/json/SHIBUI-219-2.json @@ -20,7 +20,7 @@ "securityInfo": { "authenticationRequestsSigned": true, "wantAssertionsSigned": false, - "x509Certificates": [] + "keyDescriptors": [] }, "assertionConsumerServices": [], "serviceProviderSsoDescriptor": { diff --git a/backend/src/test/resources/json/SHIBUI-219-3.json b/backend/src/test/resources/json/SHIBUI-219-3.json index ae2e6ba70..08b082da2 100644 --- a/backend/src/test/resources/json/SHIBUI-219-3.json +++ b/backend/src/test/resources/json/SHIBUI-219-3.json @@ -20,7 +20,7 @@ "securityInfo": { "authenticationRequestsSigned": false, "wantAssertionsSigned": false, - "x509Certificates": [] + "keyDescriptors": [] }, "assertionConsumerServices": [ { diff --git a/backend/src/test/resources/json/SHIBUI-223.json b/backend/src/test/resources/json/SHIBUI-223.json index 829a4c832..73f2c6a07 100644 --- a/backend/src/test/resources/json/SHIBUI-223.json +++ b/backend/src/test/resources/json/SHIBUI-223.json @@ -20,11 +20,12 @@ "securityInfo": { "authenticationRequestsSigned": false, "wantAssertionsSigned": false, - "x509Certificates": [ + "keyDescriptors": [ { "name": "test cert", "type": "both", - "value": "testcert" + "value": "testcert", + "elementType": "X509Data" } ] }, @@ -39,5 +40,6 @@ "nameIdFormats": [], "authenticationMethods": [] }, - "attributeRelease": [] + "attributeRelease": [], + "protocol": "SAML" } \ No newline at end of file diff --git a/backend/src/test/resources/json/SHIBUI-2380-1.json b/backend/src/test/resources/json/SHIBUI-2380-1.json new file mode 100644 index 000000000..2e83f768b --- /dev/null +++ b/backend/src/test/resources/json/SHIBUI-2380-1.json @@ -0,0 +1,90 @@ +{ + "assertionConsumerServices": [ + { + "locationUrl": "https://example.org/cb", + "binding": "https://tools.ietf.org/html/rfc6749#section-3.1.2", + "makeDefault": false + }, + { + "locationUrl": "https://example.org/cb2", + "binding": "https://tools.ietf.org/html/rfc6749#section-3.1.2", + "makeDefault": false + } + ], + "entityId": "mockSamlClientId2", + "idOfOwner": "admingroup", + "organization": {}, + "securityInfo": { + "authenticationRequestsSigned": false, + "wantAssertionsSigned": false, + "keyDescriptors": [ + { + "value": "MIIEQDCCAqigAwIBAgIVAIarXvdvyS47KJR7U40FlTufyD8vMA0GCSqGSIb3DQEB", + "type": "signing", + "elementType": "X509Data" + }, + { + "value": "MIIBKDCBzgIJAOYlspXlaqguMAoGCCqGSM49BAMCMBwxCzAJBgNVBAYTAkZJMQ0w", + "type": "signing", + "elementType": "X509Data" + }, + { + "value": "ewogICJrdHkiOiAiUlNBIiwKICAiZSI6ICJBUUFCIiwKICAia2lkIjogIm1vY2siLAogICJhbGci", + "type": "signing", + "elementType": "jwksData" + }, + { + "value": "mockClientSecretValue", + "type": "both", + "elementType": "clientSecret" + } + ] + }, + "serviceEnabled": false, + "serviceProviderName": "charlesTest", + "serviceProviderSsoDescriptor": { + "nameIdFormats": [ + "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent", + "urn:mace:shibboleth:metadata:oidc:1.0:nameid-format:pairwise" + ], + "extensions": { + "OAuthRPExtensions": { + "postLogoutRedirectUris": [ + "https://example.org/postLogout" + ], + "defaultAcrValues": [ + "password", + "mfa" + ], + "attributes": { + "clientUri": "https://example.org/clientUri", + "responseTypes": "code id_token", + "sectorIdentifierUri": "https://example.org/sectorIdentifier", + "idTokenEncryptedResponseAlg": "A256KW", + "applicationType": "web", + "tokenEndpointAuthSigningAlg": "RS512", + "idTokenEncryptedResponseEnc": "A256GCM", + "requireAuthTime": false, + "userInfoEncryptedResponseEnc": "A192GCM", + "userInfoSignedResponseAlg": "RS384", + "userInfoEncryptedResponseAlg": "A192KW", + "grantTypes": "authorization_code", + "softwareId": "mockSoftwareId", + "requestObjectEncryptionEnc": "A128GCM", + "initiateLoginUri": "https://example.org/initiateLogin", + "requestObjectEncryptionAlg": "A128KW", + "tokenEndpointAuthMethod": "client_secret_basic", + "requestObjectSigningAlg": "RS256", + "scopes": "openid profile", + "idTokenSignedResponseAlg": "RS512", + "softwareVersion": "mockSoftwareVersion", + "defaultMaxAge": 0 + }, + "requestUris": [ + "https://example.org/request" + ] + } + } + }, + "protocol": "OIDC" +} \ No newline at end of file diff --git a/backend/src/test/resources/json/SHIBUI-2380.json b/backend/src/test/resources/json/SHIBUI-2380.json new file mode 100644 index 000000000..1f73d2e23 --- /dev/null +++ b/backend/src/test/resources/json/SHIBUI-2380.json @@ -0,0 +1,96 @@ +{ + "assertionConsumerServices": [ + { + "locationUrl": "https://example.org/cb", + "binding": "https://tools.ietf.org/html/rfc6749#section-3.1.2", + "makeDefault": false + }, + { + "locationUrl": "https://example.org/cb2", + "binding": "https://tools.ietf.org/html/rfc6749#section-3.1.2", + "makeDefault": false + }, + { + "locationUrl": "https://example.org/cb3", + "binding": "http://example.org/not/supported/profile/id", + "makeDefault": false + } + ], + "entityId": "mockSamlClientId", + "idOfOwner": "admingroup", + "organization": {}, + "securityInfo": { + "authenticationRequestsSigned": false, + "wantAssertionsSigned": false, + "keyDescriptors": [ + { + "value": "MIIEQDCCAqigAwIBAgIVAIarXvdvyS47KJR7U40FlTufyD8vMA0GCSqGSIb3DQEB", + "type": "signing", + "elementType": "X509Data" + }, + { + "value": "MIIBKDCBzgIJAOYlspXlaqguMAoGCCqGSM49BAMCMBwxCzAJBgNVBAYTAkZJMQ0w", + "type": "signing", + "elementType": "X509Data" + }, + { + "value": "https://example.org/jwks", + "type": "both", + "elementType": "jwksUri" + }, + { + "value": "mockClientSecretValue", + "type": "both", + "elementType": "clientSecret" + } + ] + }, + "serviceEnabled": false, + "serviceProviderName": "charlesTest3", + "serviceProviderSsoDescriptor": { + "protocolSupportEnum": "http://openid.net/specs/openid-connect-core-1_0.html", + "nameIdFormats": [ + "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent", + "urn:mace:shibboleth:metadata:oidc:1.0:nameid-format:pairwise" + ], + "extensions": { + "OAuthRPExtensions": { + "postLogoutRedirectUris": [ + "https://example.org/postLogout" + ], + "defaultAcrValues": [ + "password", + "mfa" + ], + "attributes": { + "clientUri": "https://example.org/clientUri", + "responseTypes": "code id_token", + "sectorIdentifierUri": "https://example.org/sectorIdentifier", + "idTokenEncryptedResponseAlg": "A256KW", + "applicationType": "web", + "tokenEndpointAuthSigningAlg": "RS512", + "idTokenEncryptedResponseEnc": "A256GCM", + "requireAuthTime": false, + "userInfoEncryptedResponseEnc": "A192GCM", + "userInfoSignedResponseAlg": "RS384", + "userInfoEncryptedResponseAlg": "A192KW", + "grantTypes": "authorization_code", + "softwareId": "mockSoftwareId", + "requestObjectEncryptionEnc": "A128GCM", + "initiateLoginUri": "https://example.org/initiateLogin", + "requestObjectEncryptionAlg": "A128KW", + "tokenEndpointAuthMethod": "client_secret_basic", + "requestObjectSigningAlg": "RS256", + "scopes": "openid profile", + "idTokenSignedResponseAlg": "RS512", + "softwareVersion": "mockSoftwareVersion", + "defaultMaxAge": 0 + }, + "requestUris": [ + "https://example.org/request" + ] + } + } + }, + "protocol": "OIDC" +} \ No newline at end of file diff --git a/backend/src/test/resources/json/SHIBUI-855.json b/backend/src/test/resources/json/SHIBUI-855.json index 96207fafa..23e329146 100644 --- a/backend/src/test/resources/json/SHIBUI-855.json +++ b/backend/src/test/resources/json/SHIBUI-855.json @@ -20,7 +20,7 @@ "securityInfo": { "authenticationRequestsSigned": false, "wantAssertionsSigned": false, - "x509Certificates": [] + "keyDescriptors": [] }, "assertionConsumerServices": [ {