From 2369e036b04bdd1067018a3742ab1fe1ef4b656a Mon Sep 17 00:00:00 2001 From: chasegawa Date: Fri, 23 Sep 2022 15:02:19 -0700 Subject: [PATCH] SHIBUI-2380 Incremental commit: - added ability to get metadata schema by type (oidc | saml) - unit tests and code corrections --- ...tadataSourcesUiDefinitionController.groovy | 25 +- ...torSchemaValidatingControllerAdvice.groovy | 6 +- .../JsonSchemaComponentsConfiguration.java | 20 +- .../jsonschema/JsonSchemaLocationLookup.java | 20 +- .../JsonSchemaResourceLocation.java | 3 +- .../src/main/resources/application.properties | 3 +- .../metadata-sources-ui-schema-oidc.json | 529 ++++++++++++++++++ .../metadata-sources-ui-schema-saml.json | 529 ++++++++++++++++++ ...efinitionControllerIntegrationTests.groovy | 24 +- .../service/AuxiliaryIntegrationTests.groovy | 5 +- .../metadata-sources-ui-schema.json.old | 442 --------------- 11 files changed, 1127 insertions(+), 479 deletions(-) create mode 100644 backend/src/main/resources/metadata-sources-ui-schema-oidc.json create mode 100644 backend/src/main/resources/metadata-sources-ui-schema-saml.json delete mode 100644 backend/src/test/resources/metadata-sources-ui-schema.json.old diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataSourcesUiDefinitionController.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataSourcesUiDefinitionController.groovy index fa21d8a31..a5c6ecdf3 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataSourcesUiDefinitionController.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataSourcesUiDefinitionController.groovy @@ -12,11 +12,13 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.RestController import javax.annotation.PostConstruct -import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocationLookup.metadataSourcesSchema +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocationLookup.metadataSourcesOIDCSchema +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocationLookup.metadataSourcesSAMLSchema import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR /** @@ -30,13 +32,13 @@ import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR @RequestMapping('/api/ui/MetadataSources') @Tags(value = [@Tag(name = "ui")]) class MetadataSourcesUiDefinitionController { - - private static final Logger logger = LoggerFactory.getLogger(MetadataSourcesUiDefinitionController.class); + private static final Logger log = LoggerFactory.getLogger(MetadataSourcesUiDefinitionController.class); @Autowired JsonSchemaResourceLocationRegistry jsonSchemaResourceLocationRegistry - JsonSchemaResourceLocation jsonSchemaLocation + private JsonSchemaResourceLocation oidcJsonSchemaLocation + private JsonSchemaResourceLocation samlJsonSchemaLocation @Autowired ObjectMapper jacksonObjectMapper @@ -45,10 +47,10 @@ class MetadataSourcesUiDefinitionController { JsonSchemaBuilderService jsonSchemaBuilderService @GetMapping - // TODO - CHARLES add type ( SAML|OIDC ) variable to return the correct one - default to saml... - ResponseEntity getUiDefinitionJsonSchema() { + ResponseEntity getUiDefinitionJsonSchema(@RequestParam(defaultValue = "saml") String protocol) { + URL url = protocol.equals("oidc") ? oidcJsonSchemaLocation.url : samlJsonSchemaLocation.url try { - def parsedJson = jacksonObjectMapper.readValue(this.jsonSchemaLocation.url, Map) + def parsedJson = jacksonObjectMapper.readValue(url, Map) jsonSchemaBuilderService.hideServiceEnabledFromNonAdmins(parsedJson) jsonSchemaBuilderService.addReleaseAttributesToJson(parsedJson['properties']['attributeRelease']['items']) jsonSchemaBuilderService.addRelyingPartyOverridesToJson(parsedJson['properties']['relyingPartyOverrides']) @@ -56,15 +58,14 @@ class MetadataSourcesUiDefinitionController { return ResponseEntity.ok(parsedJson) } catch (IOException e) { - logger.error("An error occurred while attempting to get json schema for metadata sources!", e) - return ResponseEntity.status(INTERNAL_SERVER_ERROR) - .body([jsonParseError : e.getMessage(), - sourceUiSchemaDefinitionFile: this.jsonSchemaLocation.url]) + log.error("An error occurred while attempting to get json schema for metadata sources!", e) + return ResponseEntity.status(INTERNAL_SERVER_ERROR).body([jsonParseError : e.getMessage(), sourceUiSchemaDefinitionFile: this.samlJsonSchemaLocation.url]) } } @PostConstruct void init() { - this.jsonSchemaLocation = metadataSourcesSchema(this.jsonSchemaResourceLocationRegistry); + this.samlJsonSchemaLocation = metadataSourcesSAMLSchema(this.jsonSchemaResourceLocationRegistry); + this.oidcJsonSchemaLocation = metadataSourcesOIDCSchema(this.jsonSchemaResourceLocationRegistry); } } \ No newline at end of file diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/jsonschema/EntityDescriptorSchemaValidatingControllerAdvice.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/jsonschema/EntityDescriptorSchemaValidatingControllerAdvice.groovy index f25950256..8dca94fdc 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/jsonschema/EntityDescriptorSchemaValidatingControllerAdvice.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/jsonschema/EntityDescriptorSchemaValidatingControllerAdvice.groovy @@ -12,7 +12,7 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdviceAd import javax.annotation.PostConstruct import java.lang.reflect.Type -import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocationLookup.metadataSourcesSchema +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocationLookup.metadataSourcesSAMLSchema import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.LowLevelJsonSchemaValidator.validatePayloadAgainstSchema /** @@ -44,6 +44,6 @@ class EntityDescriptorSchemaValidatingControllerAdvice extends RequestBodyAdvice @PostConstruct void init() { - this.jsonSchemaLocation = metadataSourcesSchema(this.jsonSchemaResourceLocationRegistry) + this.jsonSchemaLocation = metadataSourcesSAMLSchema(this.jsonSchemaResourceLocationRegistry) } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/JsonSchemaComponentsConfiguration.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/JsonSchemaComponentsConfiguration.java index 23fbaaa30..fa8f5db18 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/JsonSchemaComponentsConfiguration.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/JsonSchemaComponentsConfiguration.java @@ -17,7 +17,8 @@ import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.EXTERNAL_METADATA_RESOLVER; import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.FILESYSTEM_METADATA_RESOLVER; import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.LOCAL_DYNAMIC_METADATA_RESOLVER; -import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.METADATA_SOURCES; +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.METADATA_SOURCES_OIDC; +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.METADATA_SOURCES_SAML; import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.NAME_ID_FORMAT_FILTER; /** @@ -27,10 +28,15 @@ @ConfigurationProperties("shibui") public class JsonSchemaComponentsConfiguration { + //Configured via @ConfigurationProperties (using setter method) with 'shibui.metadata-sources-oidc-ui-schema-location' property and default + //value set here if that property is not explicitly set in application.properties + @Setter + private String metadataSourcesOidcUiSchemaLocation = "classpath:metadata-sources-ui-schema-oidc.json"; + //Configured via @ConfigurationProperties (using setter method) with 'shibui.metadata-sources-ui-schema-location' property and default //value set here if that property is not explicitly set in application.properties @Setter - private String metadataSourcesUiSchemaLocation = "classpath:metadata-sources-ui-schema.json"; + private String metadataSourcesSamlUiSchemaLocation = "classpath:metadata-sources-ui-schema-saml.json"; //Configured via @ConfigurationProperties (using setter method) with 'shibui.entity-attributes-filters-ui-schema-location' property and // default value set here if that property is not explicitly set in application.properties @@ -70,8 +76,14 @@ public class JsonSchemaComponentsConfiguration { @Bean public JsonSchemaResourceLocationRegistry jsonSchemaResourceLocationRegistry(ResourceLoader resourceLoader, ObjectMapper jacksonMapper) { return JsonSchemaResourceLocationRegistry.inMemory() - .register(METADATA_SOURCES, JsonSchemaLocationBuilder.with() - .jsonSchemaLocation(metadataSourcesUiSchemaLocation) + .register(METADATA_SOURCES_OIDC, JsonSchemaLocationBuilder.with() + .jsonSchemaLocation(metadataSourcesOidcUiSchemaLocation) + .resourceLoader(resourceLoader) + .jacksonMapper(jacksonMapper) + .detectMalformedJson(true) + .build()) + .register(METADATA_SOURCES_SAML, JsonSchemaLocationBuilder.with() + .jsonSchemaLocation(metadataSourcesSamlUiSchemaLocation) .resourceLoader(resourceLoader) .jacksonMapper(jacksonMapper) .detectMalformedJson(true) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaLocationLookup.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaLocationLookup.java index bdb781d9a..a5e5406ef 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaLocationLookup.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaLocationLookup.java @@ -6,7 +6,8 @@ import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.EXTERNAL_METADATA_RESOLVER; import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.FILESYSTEM_METADATA_RESOLVER; import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.LOCAL_DYNAMIC_METADATA_RESOLVER; -import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.METADATA_SOURCES; +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.METADATA_SOURCES_OIDC; +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.METADATA_SOURCES_SAML; import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.NAME_ID_FORMAT_FILTER; /** @@ -23,9 +24,22 @@ public abstract class JsonSchemaLocationLookup { * @return metadata sources JSON schema resource location object * @throws IllegalStateException if schema is not found in the given registry */ - public static JsonSchemaResourceLocation metadataSourcesSchema(JsonSchemaResourceLocationRegistry resourceLocationRegistry) { + public static JsonSchemaResourceLocation metadataSourcesOIDCSchema(JsonSchemaResourceLocationRegistry resourceLocationRegistry) { return resourceLocationRegistry - .lookup(METADATA_SOURCES) + .lookup(METADATA_SOURCES_OIDC) + .orElseThrow(() -> new IllegalStateException("JSON schema resource location for metadata sources is not registered.")); + } + + /** + * Searches metadata sources JSON schema resource location object in the given location registry. + * + * @param resourceLocationRegistry + * @return metadata sources JSON schema resource location object + * @throws IllegalStateException if schema is not found in the given registry + */ + public static JsonSchemaResourceLocation metadataSourcesSAMLSchema(JsonSchemaResourceLocationRegistry resourceLocationRegistry) { + return resourceLocationRegistry + .lookup(METADATA_SOURCES_SAML) .orElseThrow(() -> new IllegalStateException("JSON schema resource location for metadata sources is not registered.")); } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaResourceLocation.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaResourceLocation.java index 02e3da1d8..58b1e2d66 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaResourceLocation.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaResourceLocation.java @@ -94,7 +94,8 @@ public static JsonSchemaResourceLocation newSchemaLocation(String jsonSchemaLoca public enum SchemaType { // common types - METADATA_SOURCES("MetadataSources"), + METADATA_SOURCES_SAML("MetadataSourcesSAML"), + METADATA_SOURCES_OIDC("MetadataSourcesOIDC"), // filter types ENTITY_ATTRIBUTES_FILTERS("EntityAttributesFilters"), diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 109e7c30f..ed752b5f5 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -69,7 +69,8 @@ shibui.logout-url=/dashboard #shibui.default-password={noop}somepassword shibui.default-rootuser=root -shibui.metadata-sources-ui-schema-location=classpath:metadata-sources-ui-schema.json +shibui.metadata-sources-saml-ui-schema-location=classpath:metadata-sources-ui-schema-saml.json +shibui.metadata-sources-oidc-ui-schema-location=classpath:metadata-sources-ui-schema-oidc.json shibui.entity-attributes-filters-ui-schema-location=classpath:entity-attributes-filters-ui-schema.json shibui.nameid-filter-ui-schema-location=classpath:nameid-filter.schema.json diff --git a/backend/src/main/resources/metadata-sources-ui-schema-oidc.json b/backend/src/main/resources/metadata-sources-ui-schema-oidc.json new file mode 100644 index 000000000..48c6af864 --- /dev/null +++ b/backend/src/main/resources/metadata-sources-ui-schema-oidc.json @@ -0,0 +1,529 @@ +{ + "type": "object", + "required": [ + "serviceProviderName", + "entityId" + ], + "properties": { + "serviceProviderName": { + "title": "label.service-provider-name", + "description": "tooltip.service-provider-name", + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "entityId": { + "title": "label.entity-id", + "description": "tooltip.entity-id", + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "serviceEnabled": { + "title": "label.enable-this-service", + "description": "tooltip.enable-this-service-upon-saving", + "type": "boolean" + }, + "organization": { + "$ref": "#/definitions/Organization" + }, + "contacts": { + "title": "label.contact-information", + "description": "tooltip.contact-information", + "type": "array", + "items": { + "$ref": "#/definitions/Contact" + } + }, + "mdui": { + "$ref": "#/definitions/MDUI" + }, + "securityInfo": { + "type": "object", + "widget": { + "id": "fieldset" + }, + "dependencies": { + "authenticationRequestsSigned": { + "oneOf": [ + { + "properties": { + "authenticationRequestsSigned": { + "enum": [true] + }, + "x509Certificates": { + "minItems": 1 + } + } + }, + { + "properties": { + "authenticationRequestsSigned": { + "enum": [false] + }, + "x509Certificates": { + "minItems": 0 + } + } + } + ] + } + }, + "properties": { + "x509CertificateAvailable": { + "type": "boolean" + }, + "authenticationRequestsSigned": { + "title": "label.authentication-requests-signed", + "description": "tooltip.authentication-requests-signed", + "type": "boolean", + "enumNames": [ + "value.true", + "value.false" + ] + }, + "wantAssertionsSigned": { + "title": "label.want-assertions-signed", + "description": "tooltip.want-assertions-signed", + "type": "boolean", + "enumNames": [ + "value.true", + "value.false" + ] + }, + "x509Certificates": { + "title": "label.x509-certificates", + "description": "tooltip.x509-certificates", + "type": "array", + "items": { + "$ref": "#/definitions/Certificate" + } + } + } + }, + "assertionConsumerServices": { + "title": "label.assertion-consumer-service-endpoints", + "description": "tooltip.assertion-consumer-service-endpoints", + "type": "array", + "items": { + "$ref": "#/definitions/AssertionConsumerService" + } + }, + "serviceProviderSsoDescriptor": { + "type": "object", + "properties": { + "protocolSupportEnum": { + "title": "label.protocol-support-enumeration", + "description": "tooltip.protocol-support-enumeration", + "type": "string", + "widget": { + "id": "select" + }, + "oneOf": [ + { + "enum": [ + "SAML 2" + ], + "description": "SAML 2" + }, + { + "enum": [ + "SAML 1.1" + ], + "description": "SAML 1.1" + } + ] + }, + "nameIdFormats": { + "$ref": "#/definitions/nameIdFormats" + } + } + }, + "logoutEndpoints": { + "title": "label.logout-endpoints", + "description": "tooltip.logout-endpoints", + "type": "array", + "items": { + "$ref": "#/definitions/LogoutEndpoint" + } + }, + "relyingPartyOverrides": { + "type": "object", + "properties": {} + }, + "attributeRelease": { + "type": "array", + "title": "label.attribute-release", + "description": "Attribute release table - select the attributes you want to release (default unchecked)", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + "definitions": { + "Contact": { + "type": "object", + "required": [ + "name", + "type", + "emailAddress" + ], + "properties": { + "name": { + "title": "label.contact-name", + "description": "tooltip.contact-name", + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "type": { + "title": "label.contact-type", + "description": "tooltip.contact-type", + "type": "string", + "widget": "select", + "minLength": 1, + "oneOf": [ + { + "enum": [ + "support" + ], + "description": "value.support" + }, + { + "enum": [ + "technical" + ], + "description": "value.technical" + }, + { + "enum": [ + "administrative" + ], + "description": "value.administrative" + }, + { + "enum": [ + "other" + ], + "description": "value.other" + } + ] + }, + "emailAddress": { + "title": "label.contact-email-address", + "description": "tooltip.contact-email", + "type": "string", + "pattern": "^(mailto:)?(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(\\.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$", + "minLength": 1, + "maxLength": 255 + } + } + }, + "Certificate": { + "type": "object", + "required": [ + "type", + "value" + ], + "properties": { + "name": { + "title": "label.certificate-name-display-only", + "description": "tooltip.certificate-name", + "type": "string", + "maxLength": 255 + }, + "type": { + "title": "label.certificate-type", + "type": "string", + "widget": { + "id": "radio", + "class": "form-check-inline" + }, + "oneOf": [ + { + "enum": [ + "signing" + ], + "description": "value.signing" + }, + { + "enum": [ + "encryption" + ], + "description": "value.encryption" + }, + { + "enum": [ + "both" + ], + "description": "value.both" + } + ] + }, + "value": { + "title": "label.certificate", + "description": "tooltip.certificate", + "type": "string", + "widget": "textarea", + "minLength": 1 + } + } + }, + "AssertionConsumerService": { + "type": "object", + "required": [ + "locationUrl", + "binding" + ], + "properties": { + "locationUrl": { + "title": "label.assertion-consumer-service-location", + "description": "tooltip.assertion-consumer-service-location", + "type": "string", + "widget": { + "id": "string", + "help": "message.valid-url" + }, + "minLength": 1, + "maxLength": 255 + }, + "binding": { + "title": "label.assertion-consumer-service-location-binding", + "description": "tooltip.assertion-consumer-service-location-binding", + "type": "string", + "widget": "select", + "oneOf": [ + { + "enum": [ + "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" + ], + "description": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" + }, + { + "enum": [ + "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" + ], + "description": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" + }, + { + "enum": [ + "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" + ], + "description": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" + }, + { + "enum": [ + "urn:oasis:names:tc:SAML:2.0:bindings:PAOS" + ], + "description": "urn:oasis:names:tc:SAML:2.0:bindings:PAOS" + }, + { + "enum": [ + "urn:oasis:names:tc:SAML:1.0:profiles:browser-post" + ], + "description": "urn:oasis:names:tc:SAML:1.0:profiles:browser-post" + }, + { + "enum": [ + "urn:oasis:names:tc:SAML:1.0:profiles:artifact-01" + ], + "description": "urn:oasis:names:tc:SAML:1.0:profiles:artifact-01" + }, + { + "enum": [ + "https://tools.ietf.org/html/rfc6749#section-3.1.2" + ], + "description": "OIDC / OAUTH Binding" + } + ] + }, + "makeDefault": { + "title": "label.mark-as-default", + "description": "tooltip.mark-as-default", + "type": "boolean" + } + } + }, + "LogoutEndpoint": { + "description": "tooltip.new-endpoint", + "type": "object", + "fieldsets": [ + { + "fields": [ + "url", + "bindingType" + ] + } + ], + "required": [ + "url", + "bindingType" + ], + "properties": { + "url": { + "title": "label.url", + "description": "tooltip.url", + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "bindingType": { + "title": "label.binding-type", + "description": "tooltip.binding-type", + "type": "string", + "widget": "select", + "oneOf": [ + { + "enum": [ + "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" + ], + "description": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" + }, + { + "enum": [ + "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" + ], + "description": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" + }, + { + "enum": [ + "urn:oasis:names:tc:SAML:2.0:bindings:SOAP" + ], + "description": "urn:oasis:names:tc:SAML:2.0:bindings:SOAP" + }, + { + "enum": [ + "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" + ], + "description": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" + } + ] + } + } + }, + "MDUI": { + "type": "object", + "widget": { + "id": "fieldset" + }, + "fieldsets": [ + { + "type": "group", + "fields": [ + "displayName", + "informationUrl", + "description" + ] + }, + { + "type": "group", + "fields": [ + "privacyStatementUrl", + "logoUrl", + "logoWidth", + "logoHeight" + ] + } + ], + "properties": { + "displayName": { + "title": "label.display-name", + "description": "tooltip.mdui-display-name", + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "informationUrl": { + "title": "label.information-url", + "description": "tooltip.mdui-information-url", + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "privacyStatementUrl": { + "title": "label.privacy-statement-url", + "description": "tooltip.mdui-privacy-statement-url", + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "description": { + "title": "label.description", + "description": "tooltip.mdui-description", + "type": "string", + "widget": { + "id": "textarea" + }, + "minLength": 1, + "maxLength": 255 + }, + "logoUrl": { + "title": "label.logo-url", + "description": "tooltip.mdui-logo-url", + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "logoHeight": { + "title": "label.logo-height", + "description": "tooltip.mdui-logo-height", + "minimum": 0, + "type": "integer" + }, + "logoWidth": { + "title": "label.logo-width", + "description": "tooltip.mdui-logo-width", + "minimum": 0, + "type": "integer" + } + } + }, + "Organization": { + "type": "object", + "properties": { + "name": { + "title": "label.organization-name", + "description": "tooltip.organization-name", + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "displayName": { + "title": "label.organization-display-name", + "description": "tooltip.organization-display-name", + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "url": { + "title": "label.organization-url", + "description": "tooltip.organization-url", + "type": "string", + "minLength": 1, + "maxLength": 255 + } + }, + "dependencies": { + "name": { + "required": [ + "displayName", + "url" + ] + }, + "displayName": { + "required": [ + "name", + "url" + ] + }, + "url": { + "required": [ + "name", + "displayName" + ] + } + } + } + } +} \ No newline at end of file diff --git a/backend/src/main/resources/metadata-sources-ui-schema-saml.json b/backend/src/main/resources/metadata-sources-ui-schema-saml.json new file mode 100644 index 000000000..48c6af864 --- /dev/null +++ b/backend/src/main/resources/metadata-sources-ui-schema-saml.json @@ -0,0 +1,529 @@ +{ + "type": "object", + "required": [ + "serviceProviderName", + "entityId" + ], + "properties": { + "serviceProviderName": { + "title": "label.service-provider-name", + "description": "tooltip.service-provider-name", + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "entityId": { + "title": "label.entity-id", + "description": "tooltip.entity-id", + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "serviceEnabled": { + "title": "label.enable-this-service", + "description": "tooltip.enable-this-service-upon-saving", + "type": "boolean" + }, + "organization": { + "$ref": "#/definitions/Organization" + }, + "contacts": { + "title": "label.contact-information", + "description": "tooltip.contact-information", + "type": "array", + "items": { + "$ref": "#/definitions/Contact" + } + }, + "mdui": { + "$ref": "#/definitions/MDUI" + }, + "securityInfo": { + "type": "object", + "widget": { + "id": "fieldset" + }, + "dependencies": { + "authenticationRequestsSigned": { + "oneOf": [ + { + "properties": { + "authenticationRequestsSigned": { + "enum": [true] + }, + "x509Certificates": { + "minItems": 1 + } + } + }, + { + "properties": { + "authenticationRequestsSigned": { + "enum": [false] + }, + "x509Certificates": { + "minItems": 0 + } + } + } + ] + } + }, + "properties": { + "x509CertificateAvailable": { + "type": "boolean" + }, + "authenticationRequestsSigned": { + "title": "label.authentication-requests-signed", + "description": "tooltip.authentication-requests-signed", + "type": "boolean", + "enumNames": [ + "value.true", + "value.false" + ] + }, + "wantAssertionsSigned": { + "title": "label.want-assertions-signed", + "description": "tooltip.want-assertions-signed", + "type": "boolean", + "enumNames": [ + "value.true", + "value.false" + ] + }, + "x509Certificates": { + "title": "label.x509-certificates", + "description": "tooltip.x509-certificates", + "type": "array", + "items": { + "$ref": "#/definitions/Certificate" + } + } + } + }, + "assertionConsumerServices": { + "title": "label.assertion-consumer-service-endpoints", + "description": "tooltip.assertion-consumer-service-endpoints", + "type": "array", + "items": { + "$ref": "#/definitions/AssertionConsumerService" + } + }, + "serviceProviderSsoDescriptor": { + "type": "object", + "properties": { + "protocolSupportEnum": { + "title": "label.protocol-support-enumeration", + "description": "tooltip.protocol-support-enumeration", + "type": "string", + "widget": { + "id": "select" + }, + "oneOf": [ + { + "enum": [ + "SAML 2" + ], + "description": "SAML 2" + }, + { + "enum": [ + "SAML 1.1" + ], + "description": "SAML 1.1" + } + ] + }, + "nameIdFormats": { + "$ref": "#/definitions/nameIdFormats" + } + } + }, + "logoutEndpoints": { + "title": "label.logout-endpoints", + "description": "tooltip.logout-endpoints", + "type": "array", + "items": { + "$ref": "#/definitions/LogoutEndpoint" + } + }, + "relyingPartyOverrides": { + "type": "object", + "properties": {} + }, + "attributeRelease": { + "type": "array", + "title": "label.attribute-release", + "description": "Attribute release table - select the attributes you want to release (default unchecked)", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + "definitions": { + "Contact": { + "type": "object", + "required": [ + "name", + "type", + "emailAddress" + ], + "properties": { + "name": { + "title": "label.contact-name", + "description": "tooltip.contact-name", + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "type": { + "title": "label.contact-type", + "description": "tooltip.contact-type", + "type": "string", + "widget": "select", + "minLength": 1, + "oneOf": [ + { + "enum": [ + "support" + ], + "description": "value.support" + }, + { + "enum": [ + "technical" + ], + "description": "value.technical" + }, + { + "enum": [ + "administrative" + ], + "description": "value.administrative" + }, + { + "enum": [ + "other" + ], + "description": "value.other" + } + ] + }, + "emailAddress": { + "title": "label.contact-email-address", + "description": "tooltip.contact-email", + "type": "string", + "pattern": "^(mailto:)?(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(\\.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$", + "minLength": 1, + "maxLength": 255 + } + } + }, + "Certificate": { + "type": "object", + "required": [ + "type", + "value" + ], + "properties": { + "name": { + "title": "label.certificate-name-display-only", + "description": "tooltip.certificate-name", + "type": "string", + "maxLength": 255 + }, + "type": { + "title": "label.certificate-type", + "type": "string", + "widget": { + "id": "radio", + "class": "form-check-inline" + }, + "oneOf": [ + { + "enum": [ + "signing" + ], + "description": "value.signing" + }, + { + "enum": [ + "encryption" + ], + "description": "value.encryption" + }, + { + "enum": [ + "both" + ], + "description": "value.both" + } + ] + }, + "value": { + "title": "label.certificate", + "description": "tooltip.certificate", + "type": "string", + "widget": "textarea", + "minLength": 1 + } + } + }, + "AssertionConsumerService": { + "type": "object", + "required": [ + "locationUrl", + "binding" + ], + "properties": { + "locationUrl": { + "title": "label.assertion-consumer-service-location", + "description": "tooltip.assertion-consumer-service-location", + "type": "string", + "widget": { + "id": "string", + "help": "message.valid-url" + }, + "minLength": 1, + "maxLength": 255 + }, + "binding": { + "title": "label.assertion-consumer-service-location-binding", + "description": "tooltip.assertion-consumer-service-location-binding", + "type": "string", + "widget": "select", + "oneOf": [ + { + "enum": [ + "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" + ], + "description": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" + }, + { + "enum": [ + "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" + ], + "description": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" + }, + { + "enum": [ + "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" + ], + "description": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" + }, + { + "enum": [ + "urn:oasis:names:tc:SAML:2.0:bindings:PAOS" + ], + "description": "urn:oasis:names:tc:SAML:2.0:bindings:PAOS" + }, + { + "enum": [ + "urn:oasis:names:tc:SAML:1.0:profiles:browser-post" + ], + "description": "urn:oasis:names:tc:SAML:1.0:profiles:browser-post" + }, + { + "enum": [ + "urn:oasis:names:tc:SAML:1.0:profiles:artifact-01" + ], + "description": "urn:oasis:names:tc:SAML:1.0:profiles:artifact-01" + }, + { + "enum": [ + "https://tools.ietf.org/html/rfc6749#section-3.1.2" + ], + "description": "OIDC / OAUTH Binding" + } + ] + }, + "makeDefault": { + "title": "label.mark-as-default", + "description": "tooltip.mark-as-default", + "type": "boolean" + } + } + }, + "LogoutEndpoint": { + "description": "tooltip.new-endpoint", + "type": "object", + "fieldsets": [ + { + "fields": [ + "url", + "bindingType" + ] + } + ], + "required": [ + "url", + "bindingType" + ], + "properties": { + "url": { + "title": "label.url", + "description": "tooltip.url", + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "bindingType": { + "title": "label.binding-type", + "description": "tooltip.binding-type", + "type": "string", + "widget": "select", + "oneOf": [ + { + "enum": [ + "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" + ], + "description": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" + }, + { + "enum": [ + "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" + ], + "description": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" + }, + { + "enum": [ + "urn:oasis:names:tc:SAML:2.0:bindings:SOAP" + ], + "description": "urn:oasis:names:tc:SAML:2.0:bindings:SOAP" + }, + { + "enum": [ + "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" + ], + "description": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" + } + ] + } + } + }, + "MDUI": { + "type": "object", + "widget": { + "id": "fieldset" + }, + "fieldsets": [ + { + "type": "group", + "fields": [ + "displayName", + "informationUrl", + "description" + ] + }, + { + "type": "group", + "fields": [ + "privacyStatementUrl", + "logoUrl", + "logoWidth", + "logoHeight" + ] + } + ], + "properties": { + "displayName": { + "title": "label.display-name", + "description": "tooltip.mdui-display-name", + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "informationUrl": { + "title": "label.information-url", + "description": "tooltip.mdui-information-url", + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "privacyStatementUrl": { + "title": "label.privacy-statement-url", + "description": "tooltip.mdui-privacy-statement-url", + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "description": { + "title": "label.description", + "description": "tooltip.mdui-description", + "type": "string", + "widget": { + "id": "textarea" + }, + "minLength": 1, + "maxLength": 255 + }, + "logoUrl": { + "title": "label.logo-url", + "description": "tooltip.mdui-logo-url", + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "logoHeight": { + "title": "label.logo-height", + "description": "tooltip.mdui-logo-height", + "minimum": 0, + "type": "integer" + }, + "logoWidth": { + "title": "label.logo-width", + "description": "tooltip.mdui-logo-width", + "minimum": 0, + "type": "integer" + } + } + }, + "Organization": { + "type": "object", + "properties": { + "name": { + "title": "label.organization-name", + "description": "tooltip.organization-name", + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "displayName": { + "title": "label.organization-display-name", + "description": "tooltip.organization-display-name", + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "url": { + "title": "label.organization-url", + "description": "tooltip.organization-url", + "type": "string", + "minLength": 1, + "maxLength": 255 + } + }, + "dependencies": { + "name": { + "required": [ + "displayName", + "url" + ] + }, + "displayName": { + "required": [ + "name", + "url" + ] + }, + "url": { + "required": [ + "name", + "displayName" + ] + } + } + } + } +} \ No newline at end of file diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/BadJSONMetadataSourcesUiDefinitionControllerIntegrationTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/BadJSONMetadataSourcesUiDefinitionControllerIntegrationTests.groovy index 14f5d9a16..1bcf387b2 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/BadJSONMetadataSourcesUiDefinitionControllerIntegrationTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/BadJSONMetadataSourcesUiDefinitionControllerIntegrationTests.groovy @@ -18,7 +18,8 @@ import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResour import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.ENTITY_ATTRIBUTES_FILTERS import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.FILESYSTEM_METADATA_RESOLVER import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.LOCAL_DYNAMIC_METADATA_RESOLVER -import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.METADATA_SOURCES +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.METADATA_SOURCES_OIDC +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.METADATA_SOURCES_SAML import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.NAME_ID_FORMAT_FILTER /** @@ -47,11 +48,16 @@ class BadJSONMetadataSourcesUiDefinitionControllerIntegrationTests extends Speci @Profile('badjson') static class Config { @Bean - JsonSchemaResourceLocationRegistry jsonSchemaResourceLocationRegistry(ResourceLoader resourceLoader, - ObjectMapper jacksonMapper) { + JsonSchemaResourceLocationRegistry jsonSchemaResourceLocationRegistry(ResourceLoader resourceLoader, ObjectMapper jacksonMapper) { JsonSchemaResourceLocationRegistry.inMemory() - .register(METADATA_SOURCES, JsonSchemaLocationBuilder.with() + .register(METADATA_SOURCES_OIDC, JsonSchemaLocationBuilder.with() + .jsonSchemaLocation('classpath:metadata-sources-ui-schema_MALFORMED.json') + .resourceLoader(resourceLoader) + .jacksonMapper(jacksonMapper) + .detectMalformedJson(false) + .build()) + .register(METADATA_SOURCES_SAML, JsonSchemaLocationBuilder.with() .jsonSchemaLocation('classpath:metadata-sources-ui-schema_MALFORMED.json') .resourceLoader(resourceLoader) .jacksonMapper(jacksonMapper) @@ -89,11 +95,11 @@ class BadJSONMetadataSourcesUiDefinitionControllerIntegrationTests extends Speci .detectMalformedJson(false) .build()) .register(ALGORITHM_FILTER, JsonSchemaLocationBuilder.with() - .jsonSchemaLocation('classpath:algorithm-filter.schema.json') - .resourceLoader(resourceLoader) - .jacksonMapper(jacksonMapper) - .detectMalformedJson(false) - .build()) + .jsonSchemaLocation('classpath:algorithm-filter.schema.json') + .resourceLoader(resourceLoader) + .jacksonMapper(jacksonMapper) + .detectMalformedJson(false) + .build()) } } 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 25873b638..257df79ee 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 @@ -6,12 +6,9 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor import edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocationLookup import edu.internet2.tier.shibboleth.admin.ui.jsonschema.LowLevelJsonSchemaValidator import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects -import edu.internet2.tier.shibboleth.admin.ui.security.model.Group - import org.springframework.core.io.DefaultResourceLoader import org.springframework.core.io.ResourceLoader import org.springframework.mock.http.MockHttpInputMessage -import spock.lang.Shared import spock.lang.Specification import java.time.LocalDateTime @@ -48,7 +45,7 @@ class AuxiliaryIntegrationTests extends Specification { it } def json = objectMapper.writeValueAsString(entityDescriptorRepresentation) - def schemaUri = JsonSchemaLocationLookup.metadataSourcesSchema(new JsonSchemaComponentsConfiguration().jsonSchemaResourceLocationRegistry(this.resourceLoader, this.objectMapper)).uri + def schemaUri = JsonSchemaLocationLookup.metadataSourcesSAMLSchema(new JsonSchemaComponentsConfiguration().jsonSchemaResourceLocationRegistry(this.resourceLoader, this.objectMapper)).uri when: LowLevelJsonSchemaValidator.validatePayloadAgainstSchema(new MockHttpInputMessage(json.bytes), schemaUri) diff --git a/backend/src/test/resources/metadata-sources-ui-schema.json.old b/backend/src/test/resources/metadata-sources-ui-schema.json.old deleted file mode 100644 index 5766e298f..000000000 --- a/backend/src/test/resources/metadata-sources-ui-schema.json.old +++ /dev/null @@ -1,442 +0,0 @@ -{ - "type": "object", - "properties": { - "entityId": { - "title": "label.entity-id", - "description": "tooltip.entity-id", - "type": "string" - }, - "serviceProviderName": { - "title": "label.service-provider-name", - "description": "tooltip.service-provider-name", - "type": "string" - }, - "serviceEnabled": { - "title": "label.enable-this-service-opon-saving", - "description": "tooltip.enable-this-service-upon-saving", - "type": "boolean" - }, - "organization": { - "type": "object", - "properties": { - "name": { - "title": "label.organization-name", - "description": "tooltip.organization-name", - "type": "string" - }, - "displayName": { - "title": "label.organization-display-name", - "description": "tooltip.organization-display-name", - "type": "string" - }, - "url": { - "title": "label.organization-display-name", - "description": "tooltip.organization-display-name", - "type": "string" - } - }, - "dependencies": { - "name": [ - "displayName", - "url" - ], - "displayName": [ - "name", - "url" - ], - "url": [ - "name", - "displayName" - ] - } - }, - "contacts": { - "title": "label.contact-information", - "description": "tooltip.contact-information", - "type": "array", - "items": { - "$ref": "#/definitions/Contact" - } - }, - "mdui": { - "type": "object", - "properties": { - "displayName": { - "title": "label.display-name", - "description": "tooltip.mdui-display-name", - "type": "string" - }, - "informationUrl": { - "title": "label.information-url", - "description": "tooltip.mdui-information-url", - "type": "string" - }, - "privacyStatementUrl": { - "title": "label.privacy-statement-url", - "description": "tooltip.mdui-privacy-statement-url", - "type": "string" - }, - "description": { - "title": "label.description", - "description": "tooltip.mdui-description", - "type": "string" - }, - "logoUrl": { - "title": "label.logo-url", - "description": "tooltip.mdui-logo-url", - "type": "string" - }, - "logoHeight": { - "title": "label.logo-height", - "description": "tooltip.mdui-logo-height", - "min": 0, - "type": "integer" - }, - "logoWidth": { - "title": "label.logo-width", - "description": "tooltip.mdui-logo-width", - "min": 0, - "type": "integer" - } - } - }, - "securityInfo": { - "type": "object", - "properties": { - "x509CertificateAvailable": { - "title": "label.is-there-a-x509-certificate", - "description": "tooltip.is-there-a-x509-certificate", - "type": "boolean", - "default": false - }, - "authenticationRequestsSigned": { - "title": "label.authentication-requests-signed", - "description": "tooltip.authentication-requests-signed", - "type": "boolean", - "default": false - }, - "wantAssertionsSigned": { - "title": "label.want-assertions-signed", - "description": "tooltip.want-assertions-signed", - "type": "boolean", - "default": false - }, - "x509Certificates": { - "title": "label.x509-certificates", - "type": "array", - "items": { - "$ref": "#/definitions/Certificate" - } - } - } - }, - "assertionConsumerServices": { - "title": "label.assertion-consumer-service-endpoints", - "description": "", - "type": "array", - "items": { - "$ref": "#/definitions/AssertionConsumerService" - } - }, - "serviceProviderSsoDescriptor": { - "type": "object", - "properties": { - "protocolSupportEnum": { - "title": "label.protocol-support-enumeration", - "description": "tooltip.protocol-support-enumeration", - "type": "string", - "placeholder": "label.select-protocol", - "oneOf": [ - { - "enum": [ - "SAML 2" - ], - "description": "SAML 2" - }, - { - "enum": [ - "SAML 1.1" - ], - "description": "SAML 1.1" - } - ] - } - }, - "nameIdFormats": { - "$ref": "#/definitions/NameIdFormatList" - } - }, - "logoutEndpoints": { - "title": "label.logout-endpoints", - "description": "tooltip.logout-endpoints", - "type": "array", - "items": { - "$ref": "#/definitions/LogoutEndpoint" - } - }, - "relyingPartyOverrides": { - "type": "object", - "properties": { - "signAssertion": { - "title": "label.sign-the-assertion", - "description": "tooltip.sign-assertion", - "type": "boolean", - "default": false - }, - "dontSignResponse": { - "title": "label.dont-sign-the-response", - "description": "tooltip.dont-sign-response", - "type": "boolean", - "default": false - }, - "turnOffEncryption": { - "title": "label.turn-off-encryption-of-response", - "description": "tooltip.turn-off-encryption", - "type": "boolean", - "default": false - }, - "useSha": { - "title": "label.use-sha1-signing-algorithm", - "description": "tooltip.usa-sha-algorithm", - "type": "boolean", - "default": false - }, - "ignoreAuthenticationMethod": { - "title": "label.ignore-any-sp-requested-authentication-method", - "description": "tooltip.ignore-auth-method", - "type": "boolean", - "default": false - }, - "forceAuthn": { - "title": "label.force-authn", - "description": "tooltip.force-authn", - "type": "boolean", - "default": false - }, - "omitNotBefore": { - "title": "label.omit-not-before-condition", - "type": "boolean", - "description": "tooltip.omit-not-before-condition", - "default": false - }, - "responderId": { - "title": "label.responder-id", - "description": "tooltip.responder-id", - "type": "string" - }, - "nameIdFormats": { - "$ref": "#/definitions/NameIdFormatList" - }, - "authenticationMethods": { - "$ref": "#/definitions/AuthenticationMethodList" - } - } - }, - "attributeRelease": { - "type": "array", - "description": "Attribute release table - select the attributes you want to release (default unchecked)", - "widget": { - "id": "checklist", - "dataUrl": "/customAttributes" - }, - "items": { - "type": "string" - } - } - }, - "definitions": { - "Contact": { - "type": "object", - "properties": { - "name": { - "title": "label.contact-name", - "description": "tooltip.contact-name", - "type": "string" - }, - "type": { - "title": "label.contact-type", - "description": "tooltip.contact-type", - "type": "string", - "oneOf": [ - { - "enum": [ - "support" - ], - "description": "value.support" - }, - { - "enum": [ - "technical" - ], - "description": "value.technical" - }, - { - "enum": [ - "administrative" - ], - "description": "value.administrative" - }, - { - "enum": [ - "other" - ], - "description": "value.other" - } - ] - }, - "emailAddress": { - "title": "label.contact-email-address", - "description": "tooltip.contact-email", - "type": "string", - "pattern": "^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(\\.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$" - } - } - }, - "Certificate": { - "name": { - "title": "label.certificate-name-display-only", - "description": "tooltip.certificate-name", - "type": "string" - }, - "type": { - "title": "label.type", - "description": "tooltip.certificate-type", - "type": "string", - "oneOf": [ - { - "enum": [ - "signing" - ], - "description": "value.signing" - }, - { - "enum": [ - "encryption" - ], - "description": "value.encryption" - }, - { - "enum": [ - "both" - ], - "description": "value.both" - } - ], - "default": "both" - }, - "value": { - "title": "label.certificate", - "description": "tooltip.certificate", - "type": "string" - } - }, - "AssertionConsumerService": { - "type": "object", - "properties": { - "locationUrl": { - "title": "label.assertion-consumer-services-location", - "description": "tooltip.assertion-consumer-service-location", - "type": "string", - "widget": { - "id": "string", - "help": "message.valid-url" - } - }, - "binding": { - "title": "label.assertion-consumer-service-location-binding", - "description": "tooltip.assertion-consumer-service-location-binding", - "type": "string", - "oneOf": [ - { - "enum": [ - "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" - ], - "description": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" - }, - { - "enum": [ - "urn:oasis:names:tc:SAML:1.0:profiles:browser-post" - ], - "description": "urn:oasis:names:tc:SAML:1.0:profiles:browser-post" - } - ] - }, - "makeDefault": { - "title": "label.mark-as-default", - "description": "tooltip.mark-as-default", - "type": "boolean" - } - } - }, - "NameIdFormatList": { - "title": "label.nameid-format-to-send", - "placeholder": "label.nameid-format", - "description": "tooltip.nameid-format", - "type": "array", - "uniqueItems": true, - "items": { - "type": "string", - "widget": "datalist", - "data": [ - "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified", - "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", - "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent", - "urn:oasis:names:tc:SAML:2.0:nameid-format:transient" - ] - }, - "default": null - }, - "AuthenticationMethodList": { - "title": "label.authentication-methods-to-use", - "description": "tooltip.authentication-methods-to-use", - "type": "array", - "placeholder": "label.authentication-method", - "uniqueItems": true, - "items": { - "type": "string", - "title": "label.authentication-method", - "widget": { - "id": "datalist", - "data": [ - "https://refeds.org/profile/mfa", - "urn:oasis:names:tc:SAML:2.0:ac:classes:TimeSyncToken", - "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport" - ] - } - }, - "default": null - }, - "LogoutEndpoint": { - "title": "label.new-endpoint", - "description": "tooltip.new-endpoint", - "type": "object", - "properties": { - "url": { - "title": "label.url", - "description": "tooltip.url", - "type": "string" - }, - "bindingType": { - "title": "label.binding-type", - "description": "tooltip.binding-type", - "type": "string", - "oneOf": [ - { - "enum": [ - "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" - ], - "description": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" - }, - { - "enum": [ - "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" - ], - "description": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" - } - ] - - } - } - } - } -} \ No newline at end of file