diff --git a/.github/workflows/interoperability.yml b/.github/workflows/interoperability.yml index 7d31ebe28..352a6739b 100644 --- a/.github/workflows/interoperability.yml +++ b/.github/workflows/interoperability.yml @@ -82,6 +82,12 @@ jobs: wget https://mds.edugain.org/edugain-v2.xml -O /tmp/metadata/edugain.xml wget https://technical.edugain.org/mds-v2.cer -O /tmp/metadata/edugain-pub.crt + - name: Download eduID metadata & public key + if: steps.cache-metadata.outputs.cache-hit != 'true' + run: | + mkdir -p /tmp/metadata + wget https://metadata.eduid.cz/entities/eduid -O /tmp/metadata/eduid.xml + wget https://www.eduid.cz/docs/eduid/metadata/metadata.eduid.cz.crt.pem -O /tmp/metadata/eduid.crt - name: Download eduID metadata & public key if: steps.cache-metadata.outputs.cache-hit != 'true' diff --git a/composer.json b/composer.json index 908784ab9..327164cfc 100644 --- a/composer.json +++ b/composer.json @@ -26,21 +26,21 @@ "ext-pcre": "*", "ext-zlib": "*", - "nyholm/psr7": "~1.8.2", - "psr/clock": "~1.0.0", + "nyholm/psr7": "~1.8", + "psr/clock": "~1.0", "psr/http-message": "~2.0", - "psr/log": "~2.3.1 || ~3.0.0", - "simplesamlphp/assert": "~1.8.1", - "simplesamlphp/xml-common": "~1.25.0", - "simplesamlphp/xml-security": "~1.13.4", - "simplesamlphp/xml-soap": "~1.7.0" + "psr/log": "~2.3 || ~3.0", + "simplesamlphp/assert": "~1.9", + "simplesamlphp/xml-common": "~2.3", + "simplesamlphp/xml-security": "~2.0", + "simplesamlphp/xml-soap": "~2.0" }, "require-dev": { "ext-intl": "*", - "beste/clock": "~3.0.0", - "mockery/mockery": "~1.6.12", - "simplesamlphp/simplesamlphp-test-framework": "~1.10.2" + "beste/clock": "~3.0", + "mockery/mockery": "~1.6", + "simplesamlphp/simplesamlphp-test-framework": "~1.10" }, "suggest": { "ext-soap": "*" @@ -58,7 +58,7 @@ }, "extra": { "branch-alias": { - "dev-master": "v6.0.x-dev" + "dev-master": "v5.1.x-dev" } }, "config": { @@ -69,5 +69,15 @@ "phpstan/extension-installer": true, "simplesamlphp/composer-xmlprovider-installer": true } + }, + "scripts": { + "pre-commit": [ + "vendor/bin/phpcs -p", + "vendor/bin/composer-require-checker check --config-file=tools/composer-require-checker.json composer.json", + "vendor/bin/phpstan analyze -c phpstan.neon", + "vendor/bin/phpstan analyze -c phpstan-dev.neon", + "vendor/bin/composer-unused", + "vendor/bin/phpunit --no-coverage --testdox" + ] } } diff --git a/phpcs.xml b/phpcs.xml index 5eabf531b..da40d31fe 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -41,6 +41,8 @@ tests/SAML2/XML/saml/AuthnContextTest.php tests/SAML2/XML/saml/EncryptedAssertionTest.php tests/SAML2/XML/saml/EncryptedIDTest.php + tests/SAML2/XML/saml/SubjectConfirmationTest.php + tests/SAML2/XML/samlp/AuthnRequestTest.php tests/SAML2/XML/samlp/RequestedAuthnContextTest.php tests/SAML2/XML/samlp/StatusDetailTest.php tests/SAML2/XML/shibmd/KeyAuthorityTest.php diff --git a/phpstan-baseline-dev.neon b/phpstan-baseline-dev.neon index 15d7c20a3..c73bcfb01 100644 --- a/phpstan-baseline-dev.neon +++ b/phpstan-baseline-dev.neon @@ -1,5 +1,17 @@ parameters: ignoreErrors: + - + message: '#^Dead catch \- SimpleSAML\\Assert\\AssertionFailedException is never thrown in the try block\.$#' + identifier: catch.neverThrown + count: 1 + path: tests/InterOperability/EntityDescriptorTest.php + + - + message: '#^Call to static method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''SimpleSAML\\\\SAML2\\\\Utilities\\\\ArrayCollection'' and SimpleSAML\\SAML2\\Utilities\\ArrayCollection will always evaluate to true\.$#' + identifier: staticMethod.alreadyNarrowedType + count: 1 + path: tests/SAML2/Assertion/ProcessorTest.php + - message: '#^PHPDoc tag @var for property SimpleSAML\\Test\\SAML2\\Assertion\\Transformer\\NameIdDecryptionTransformerTest\:\:\$validator with type SimpleSAML\\SAML2\\Response\\Validation\\Validator is incompatible with native type SimpleSAML\\SAML2\\Signature\\Validator\.$#' identifier: property.phpDocType @@ -30,12 +42,24 @@ parameters: count: 1 path: tests/SAML2/Assertion/Validation/AssertionValidatorTest.php + - + message: '#^Missing call to parent\:\:setUp\(\) method\.$#' + identifier: phpunit.callParent + count: 1 + path: tests/SAML2/Assertion/Validation/ConstraintValidator/SpIsValidAudienceTest.php + - message: '#^Parameter \#1 \$serviceProvider of method SimpleSAML\\SAML2\\Assertion\\Validation\\ConstraintValidator\\SpIsValidAudience\:\:setServiceProvider\(\) expects SimpleSAML\\SAML2\\Configuration\\ServiceProvider, Mockery\\MockInterface given\.$#' identifier: argument.type count: 3 path: tests/SAML2/Assertion/Validation/ConstraintValidator/SpIsValidAudienceTest.php + - + message: '#^Missing call to parent\:\:setUp\(\) method\.$#' + identifier: phpunit.callParent + count: 1 + path: tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationResponseToMatchesTest.php + - message: '#^Parameter \#1 \$response of class SimpleSAML\\SAML2\\Assertion\\Validation\\ConstraintValidator\\SubjectConfirmationResponseToMatches constructor expects SimpleSAML\\SAML2\\XML\\samlp\\Response, Mockery\\MockInterface given\.$#' identifier: argument.type @@ -60,18 +84,48 @@ parameters: count: 3 path: tests/SAML2/Certificate/KeyLoaderTest.php + - + message: '#^Missing call to parent\:\:setUp\(\) method\.$#' + identifier: phpunit.callParent + count: 1 + path: tests/SAML2/Certificate/KeyLoaderTest.php + - message: '#^Parameter \#1 \$config of method SimpleSAML\\SAML2\\Certificate\\KeyLoader\:\:loadKeysFromConfiguration\(\) expects SimpleSAML\\SAML2\\Configuration\\CertificateProvider, Mockery\\MockInterface given\.$#' identifier: argument.type count: 3 path: tests/SAML2/Certificate/KeyLoaderTest.php + - + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''SimpleSAML\\\\XMLSecurity\\\\Key\\\\PrivateKey'' and SimpleSAML\\XMLSecurity\\Key\\PrivateKey will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType + count: 1 + path: tests/SAML2/Certificate/PrivateKeyLoaderTest.php + + - + message: '#^Missing call to parent\:\:setUp\(\) method\.$#' + identifier: phpunit.callParent + count: 1 + path: tests/SAML2/Response/SignatureValidationTest.php + + - + message: '#^Missing call to parent\:\:setUp\(\) method\.$#' + identifier: phpunit.callParent + count: 1 + path: tests/SAML2/Response/Validation/ConstraintValidator/DestinationMatchesTest.php + - message: '#^Parameter \#1 \$response of method SimpleSAML\\SAML2\\Response\\Validation\\ConstraintValidator\\DestinationMatches\:\:validate\(\) expects SimpleSAML\\SAML2\\XML\\samlp\\Response, Mockery\\MockInterface given\.$#' identifier: argument.type count: 2 path: tests/SAML2/Response/Validation/ConstraintValidator/DestinationMatchesTest.php + - + message: '#^Missing call to parent\:\:setUp\(\) method\.$#' + identifier: phpunit.callParent + count: 1 + path: tests/SAML2/Response/Validation/ConstraintValidator/IsSuccessfulTest.php + - message: '#^Parameter \#1 \$response of method SimpleSAML\\SAML2\\Response\\Validation\\ConstraintValidator\\IsSuccessful\:\:validate\(\) expects SimpleSAML\\SAML2\\XML\\samlp\\Response, Mockery\\MockInterface given\.$#' identifier: argument.type @@ -79,13 +133,73 @@ parameters: path: tests/SAML2/Response/Validation/ConstraintValidator/IsSuccessfulTest.php - - message: '#^Parameter \#1 \$xml of static method SimpleSAML\\SAML2\\XML\\saml\\Assertion\:\:fromXML\(\) expects DOMElement, DOMNode\|null given\.$#' - identifier: argument.type + message: '#^Missing call to parent\:\:setUp\(\) method\.$#' + identifier: phpunit.callParent + count: 1 + path: tests/SAML2/Signature/PublicKeyValidatorTest.php + + - + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''ArrayIterator'' and ArrayIterator will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType + count: 1 + path: tests/SAML2/Utilities/ArrayCollectionTest.php + + - + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''SimpleSAML\\\\SAML2\\\\Utilities\\\\ArrayCollection'' and SimpleSAML\\SAML2\\Utilities\\ArrayCollection will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType count: 2 - path: tests/SAML2/Response/XmlSignatureWrappingTest.php + path: tests/SAML2/Utilities/ArrayCollectionTest.php - - message: '#^Parameter \#1 \$requestedAuthnContexts of class SimpleSAML\\SAML2\\XML\\samlp\\RequestedAuthnContext constructor expects array\, array\ given\.$#' - identifier: argument.type + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''SimpleSAML\\\\SAML2\\\\XML\\\\md\\\\AdditionalMetadataLocation'' and SimpleSAML\\SAML2\\XML\\md\\AdditionalMetadataLocation will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType + count: 2 + path: tests/SAML2/XML/md/EntityDescriptorTest.php + + - + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''SimpleSAML\\\\SAML2\\\\XML\\\\md\\\\ContactPerson'' and SimpleSAML\\SAML2\\XML\\md\\ContactPerson will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType + count: 3 + path: tests/SAML2/XML/md/EntityDescriptorTest.php + + - + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''SimpleSAML\\\\SAML2\\\\XML\\\\md\\\\SingleSignOnService'' and SimpleSAML\\SAML2\\XML\\md\\SingleSignOnService will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType + count: 1 + path: tests/SAML2/XML/md/IDPSSODescriptorTest.php + + - + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''SimpleSAML\\\\SAML2\\\\XML\\\\md\\\\AbstractRoleDescriptor'' and SimpleSAML\\SAML2\\XML\\md\\AbstractRoleDescriptor will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType + count: 1 + path: tests/SAML2/XML/md/RoleDescriptorTest.php + + - + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''SimpleSAML\\\\SAML2\\\\XML\\\\md\\\\ContactPerson'' and SimpleSAML\\SAML2\\XML\\md\\ContactPerson will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType + count: 4 + path: tests/SAML2/XML/md/RoleDescriptorTest.php + + - + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''SimpleSAML\\\\SAML2\\\\XML\\\\md\\\\KeyDescriptor'' and SimpleSAML\\SAML2\\XML\\md\\KeyDescriptor will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType + count: 4 + path: tests/SAML2/XML/md/RoleDescriptorTest.php + + - + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''SimpleSAML\\\\SAML2\\\\XML\\\\saml\\\\NameID'' and SimpleSAML\\SAML2\\XML\\saml\\NameID will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType + count: 1 + path: tests/SAML2/XML/saml/AssertionTest.php + + - + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''SimpleSAML\\\\SAML2\\\\XML\\\\saml\\\\NameID'' and array\ will always evaluate to false\.$#' + identifier: method.impossibleType + count: 4 + path: tests/SAML2/XML/saml/AssertionTest.php + + - + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''SimpleSAML\\\\Test\\\\SAML2\\\\CustomStatement'' and SimpleSAML\\Test\\SAML2\\CustomStatement will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType count: 1 - path: tests/SAML2/XML/samlp/RequestedAuthnContextTest.php + path: tests/SAML2/XML/saml/StatementTest.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index d03a5b32a..267c5d7fe 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,5 +1,29 @@ parameters: ignoreErrors: + - + message: '#^Call to an undefined method SimpleSAML\\SAML2\\XML\\samlp\\AbstractMessage\:\:addValidator\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Binding/HTTPArtifact.php + + - + message: '#^Call to an undefined method SimpleSAML\\SAML2\\XML\\samlp\\ArtifactResponse\:\:validate\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Binding/HTTPArtifact.php + + - + message: '#^Call to method addURLparameters\(\) on an unknown class SimpleSAML\\Utils\\HTTP\.$#' + identifier: class.notFound + count: 1 + path: src/Binding/HTTPArtifact.php + + - + message: '#^Call to method getString\(\) on an unknown class SimpleSAML\\Configuration\.$#' + identifier: class.notFound + count: 1 + path: src/Binding/HTTPArtifact.php + - message: '#^Call to static method addSign\(\) on an unknown class SimpleSAML\\Module\\saml\\Message\.$#' identifier: class.notFound @@ -33,56 +57,74 @@ parameters: - message: '#^Parameter \$key of method SimpleSAML\\SAML2\\Binding\\HTTPArtifact\:\:validateSignature\(\) has invalid type SimpleSAML\\XMLSecurity\\XMLSecurityKey\.$#' identifier: class.notFound - count: 1 + count: 2 path: src/Binding/HTTPArtifact.php - message: '#^Parameter \$sp of method SimpleSAML\\SAML2\\Binding\\HTTPArtifact\:\:setSPMetadata\(\) has invalid type SimpleSAML\\Configuration\.$#' identifier: class.notFound - count: 1 + count: 2 path: src/Binding/HTTPArtifact.php - message: '#^Property SimpleSAML\\SAML2\\Binding\\HTTPArtifact\:\:\$spMetadata has unknown class SimpleSAML\\Configuration as its type\.$#' identifier: class.notFound - count: 1 + count: 2 path: src/Binding/HTTPArtifact.php - - message: '#^Parameter \$configuration of method SimpleSAML\\SAML2\\Configuration\\SimpleSAMLConverter\:\:convertToIdentityProvider\(\) has invalid type SimpleSAML\\Configuration\.$#' + message: '#^Access to property \$key on an unknown class SimpleSAML\\XMLSecurity\\XMLSecurityKey\.$#' identifier: class.notFound count: 1 - path: src/Configuration/SimpleSAMLConverter.php + path: src/SOAPClient.php - - message: '#^Parameter \$configuration of method SimpleSAML\\SAML2\\Configuration\\SimpleSAMLConverter\:\:convertToServiceProvider\(\) has invalid type SimpleSAML\\Configuration\.$#' - identifier: class.notFound + message: '#^Call to an undefined method SimpleSAML\\SAML2\\XML\\samlp\\AbstractMessage\:\:addValidator\(\)\.$#' + identifier: method.notFound count: 1 - path: src/Configuration/SimpleSAMLConverter.php + path: src/SOAPClient.php - - message: '#^Parameter \$configuration of method SimpleSAML\\SAML2\\Configuration\\SimpleSAMLConverter\:\:enrichForDecryptionProvider\(\) has invalid type SimpleSAML\\Configuration\.$#' + message: '#^Call to method getCertPath\(\) on an unknown class SimpleSAML\\Utils\\Config\.$#' identifier: class.notFound count: 1 - path: src/Configuration/SimpleSAMLConverter.php + path: src/SOAPClient.php - - message: '#^Parameter \$configuration of method SimpleSAML\\SAML2\\Configuration\\SimpleSAMLConverter\:\:enrichForIdentityProvider\(\) has invalid type SimpleSAML\\Configuration\.$#' + message: '#^Call to method getPublicKeys\(\) on an unknown class SimpleSAML\\Configuration\.$#' identifier: class.notFound count: 1 - path: src/Configuration/SimpleSAMLConverter.php + path: src/SOAPClient.php + + - + message: '#^Call to method getString\(\) on an unknown class SimpleSAML\\Configuration\.$#' + identifier: class.notFound + count: 3 + path: src/SOAPClient.php + + - + message: '#^Call to method getValue\(\) on an unknown class SimpleSAML\\Configuration\.$#' + identifier: class.notFound + count: 3 + path: src/SOAPClient.php - - message: '#^Parameter \$configuration of method SimpleSAML\\SAML2\\Configuration\\SimpleSAMLConverter\:\:enrichForServiceProvider\(\) has invalid type SimpleSAML\\Configuration\.$#' + message: '#^Call to method hasValue\(\) on an unknown class SimpleSAML\\Configuration\.$#' + identifier: class.notFound + count: 5 + path: src/SOAPClient.php + + - + message: '#^Call to method loadPrivateKey\(\) on an unknown class SimpleSAML\\Utils\\Crypto\.$#' identifier: class.notFound count: 1 - path: src/Configuration/SimpleSAMLConverter.php + path: src/SOAPClient.php - - message: '#^Parameter \$configuration of method SimpleSAML\\SAML2\\Configuration\\SimpleSAMLConverter\:\:pluckConfiguration\(\) has invalid type SimpleSAML\\Configuration\.$#' + message: '#^Call to method loadPublicKey\(\) on an unknown class SimpleSAML\\Utils\\Crypto\.$#' identifier: class.notFound count: 1 - path: src/Configuration/SimpleSAMLConverter.php + path: src/SOAPClient.php - message: '#^Instantiated class SimpleSAML\\Utils\\Config not found\.$#' @@ -99,19 +141,19 @@ parameters: - message: '#^Parameter \$dstMetadata of method SimpleSAML\\SAML2\\SOAPClient\:\:send\(\) has invalid type SimpleSAML\\Configuration\.$#' identifier: class.notFound - count: 1 + count: 2 path: src/SOAPClient.php - message: '#^Parameter \$key of method SimpleSAML\\SAML2\\SOAPClient\:\:validateSSL\(\) has invalid type SimpleSAML\\XMLSecurity\\XMLSecurityKey\.$#' identifier: class.notFound - count: 1 + count: 2 path: src/SOAPClient.php - message: '#^Parameter \$srcMetadata of method SimpleSAML\\SAML2\\SOAPClient\:\:send\(\) has invalid type SimpleSAML\\Configuration\.$#' identifier: class.notFound - count: 1 + count: 2 path: src/SOAPClient.php - @@ -127,22 +169,10 @@ parameters: path: src/XML/md/AbstractIndexedEndpointType.php - - message: '#^Access to undefined constant static\(SimpleSAML\\SAML2\\XML\\md\\AbstractRoleDescriptor\)\:\:XSI_TYPE_NAME\.$#' - identifier: classConstant.notFound - count: 2 - path: src/XML/md/AbstractRoleDescriptor.php - - - - message: '#^Access to undefined constant static\(SimpleSAML\\SAML2\\XML\\md\\AbstractRoleDescriptor\)\:\:XSI_TYPE_NAMESPACE\.$#' - identifier: classConstant.notFound - count: 2 - path: src/XML/md/AbstractRoleDescriptor.php - - - - message: '#^Access to undefined constant static\(SimpleSAML\\SAML2\\XML\\md\\AbstractRoleDescriptor\)\:\:XSI_TYPE_PREFIX\.$#' - identifier: classConstant.notFound + message: '#^Unsafe usage of new static\(\)\.$#' + identifier: new.static count: 2 - path: src/XML/md/AbstractRoleDescriptor.php + path: src/XML/md/AbstractLocalizedName.php - message: '#^Call to an undefined static method SimpleSAML\\SAML2\\XML\\md\\AbstractSignedMdElement\:\:getXsiTypeNamespaceURI\(\)\.$#' @@ -151,76 +181,28 @@ parameters: path: src/XML/md/AbstractSignedMdElement.php - - message: '#^Access to undefined constant static\(SimpleSAML\\SAML2\\XML\\saml\\AbstractBaseID\)\:\:XSI_TYPE_NAME\.$#' - identifier: classConstant.notFound - count: 2 - path: src/XML/saml/AbstractBaseID.php - - - - message: '#^Access to undefined constant static\(SimpleSAML\\SAML2\\XML\\saml\\AbstractBaseID\)\:\:XSI_TYPE_NAMESPACE\.$#' - identifier: classConstant.notFound - count: 2 - path: src/XML/saml/AbstractBaseID.php - - - - message: '#^Access to undefined constant static\(SimpleSAML\\SAML2\\XML\\saml\\AbstractBaseID\)\:\:XSI_TYPE_PREFIX\.$#' - identifier: classConstant.notFound - count: 2 - path: src/XML/saml/AbstractBaseID.php - - - - message: '#^Access to undefined constant static\(SimpleSAML\\SAML2\\XML\\saml\\AbstractCondition\)\:\:XSI_TYPE_NAME\.$#' - identifier: classConstant.notFound - count: 2 - path: src/XML/saml/AbstractCondition.php - - - - message: '#^Access to undefined constant static\(SimpleSAML\\SAML2\\XML\\saml\\AbstractCondition\)\:\:XSI_TYPE_NAMESPACE\.$#' - identifier: classConstant.notFound - count: 2 - path: src/XML/saml/AbstractCondition.php - - - - message: '#^Access to undefined constant static\(SimpleSAML\\SAML2\\XML\\saml\\AbstractCondition\)\:\:XSI_TYPE_PREFIX\.$#' - identifier: classConstant.notFound - count: 2 - path: src/XML/saml/AbstractCondition.php - - - - message: '#^Access to undefined constant static\(SimpleSAML\\SAML2\\XML\\saml\\AbstractStatement\)\:\:XSI_TYPE_NAME\.$#' - identifier: classConstant.notFound - count: 2 - path: src/XML/saml/AbstractStatement.php - - - - message: '#^Access to undefined constant static\(SimpleSAML\\SAML2\\XML\\saml\\AbstractStatement\)\:\:XSI_TYPE_NAMESPACE\.$#' - identifier: classConstant.notFound - count: 2 - path: src/XML/saml/AbstractStatement.php - - - - message: '#^Access to undefined constant static\(SimpleSAML\\SAML2\\XML\\saml\\AbstractStatement\)\:\:XSI_TYPE_PREFIX\.$#' - identifier: classConstant.notFound - count: 2 - path: src/XML/saml/AbstractStatement.php + message: '#^Call to an undefined method SimpleSAML\\XML\\AbstractElement\:\:getList\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/XML/md/ContactPerson.php - - message: '#^Unsafe usage of new static\(\)\.$#' - identifier: new.static + message: '#^Call to an undefined method SimpleSAML\\XML\\AbstractElement\:\:getList\(\)\.$#' + identifier: method.notFound count: 1 - path: src/XML/saml/Attribute.php + path: src/XML/md/EntitiesDescriptor.php - - message: '#^Unsafe usage of new static\(\)\.$#' - identifier: new.static + message: '#^Call to an undefined method SimpleSAML\\XML\\AbstractElement\:\:getList\(\)\.$#' + identifier: method.notFound count: 1 - path: src/XML/saml/EncryptedAttribute.php + path: src/XML/md/Organization.php - message: '#^Unsafe usage of new static\(\)\.$#' identifier: new.static count: 1 - path: src/XML/saml/EncryptedID.php + path: src/XML/saml/Attribute.php - message: '#^Unsafe usage of new static\(\)\.$#' diff --git a/phpstan.neon b/phpstan.neon index e4c4cf7f5..de03d2c72 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,5 @@ parameters: - level: 1 + level: 2 paths: - src includes: diff --git a/src/Assert/Assert.php b/src/Assert/Assert.php index cb166eebe..a2a30c295 100644 --- a/src/Assert/Assert.php +++ b/src/Assert/Assert.php @@ -11,21 +11,39 @@ * * @package simplesamlphp/saml2 * - * @method static void validDateTime(mixed $value, string $message = '', string $exception = '') + * @method static void validCIDR(mixed $value, string $message = '', string $exception = '') + * @method static void validDomain(mixed $value, string $message = '', string $exception = '') * @method static void validEntityID(mixed $value, string $message = '', string $exception = '') - * @method static void validURI(mixed $value, string $message = '', string $exception = '') + * @method static void validGeolocation(mixed $value, string $message = '', string $exception = '') * @method static void validRelayState(mixed $value, string $message = '', string $exception = '') - * @method static void nullOrValidDateTime(mixed $value, string $message = '', string $exception = '') + * @method static void validSAMLAnyURI(mixed $value, string $message = '', string $exception = '') + * @method static void validSAMLDateTime(mixed $value, string $message = '', string $exception = '') + * @method static void validSAMLString(mixed $value, string $message = '', string $exception = '') + * @method static void nullOrValidCIDR(mixed $value, string $message = '', string $exception = '') + * @method static void nullOrValidDomain(mixed $value, string $message = '', string $exception = '') * @method static void nullOrValidEntityID(mixed $value, string $message = '', string $exception = '') + * @method static void nullOrValidGeolocation(mixed $value, string $message = '', string $exception = '') * @method static void nullOrValidRelayState(mixed $value, string $message = '', string $exception = '') - * @method static void nullOrValidURI(mixed $value, string $message = '', string $exception = '') - * @method static void allValidDateTime(mixed $value, string $message = '', string $exception = '') + * @method static void nullOrValidSAMLAnyURI(mixed $value, string $message = '', string $exception = '') + * @method static void nullOrValidSAMLDateTime(mixed $value, string $message = '', string $exception = '') + * @method static void nullOrValidSAMLString(mixed $value, string $message = '', string $exception = '') + * @method static void allValidCIDR(mixed $value, string $message = '', string $exception = '') + * @method static void allValidDomain(mixed $value, string $message = '', string $exception = '') * @method static void allValidEntityID(mixed $value, string $message = '', string $exception = '') + * @method static void allValidGeolocation(mixed $value, string $message = '', string $exception = '') * @method static void allValidRelayState(mixed $value, string $message = '', string $exception = '') - * @method static void allValidURI(mixed $value, string $message = '', string $exception = '') + * @method static void allValidSAMLAnyURI(mixed $value, string $message = '', string $exception = '') + * @method static void allValidSAMLDateTime(mixed $value, string $message = '', string $exception = '') + * @method static void allValidSAMLString(mixed $value, string $message = '', string $exception = '') */ class Assert extends BaseAssert { - use CustomAssertionTrait; + use CIDRTrait; + use DomainTrait; + use EntityIDTrait; + use GeolocationTrait; use RelayStateTrait; + use SAMLAnyURITrait; + use SAMLDateTimeTrait; + use SAMLStringTrait; } diff --git a/src/Assert/CIDRTrait.php b/src/Assert/CIDRTrait.php new file mode 100644 index 000000000..8f9bee225 --- /dev/null +++ b/src/Assert/CIDRTrait.php @@ -0,0 +1,60 @@ +getMessage()); + } + } +} diff --git a/src/Assert/CustomAssertionTrait.php b/src/Assert/CustomAssertionTrait.php deleted file mode 100644 index d2b676eb5..000000000 --- a/src/Assert/CustomAssertionTrait.php +++ /dev/null @@ -1,84 +0,0 @@ -getMessage()); - } - } - - - /** - * @param string $value - * @param string $message - */ - protected static function validURI(string $value, string $message = ''): void - { - parent::validURI($value); - - try { - // If it doesn't have a scheme, it's not an absolute URI - parent::regex($value, self::$scheme_regex, $message ?: '%s is not a SAML2-compliant URI'); - } catch (AssertionFailedException $e) { - throw new ProtocolViolationException($e->getMessage()); - } - } - - - /** - * @param string $value - * @param string $message - */ - protected static function validEntityID(string $value, string $message = ''): void - { - static::validURI($value); - - try { - parent::notWhitespaceOnly($value); - parent::maxLength( - $value, - C::ENTITYID_MAX_LENGTH, - sprintf('An entityID cannot be longer than %d characters.', C::ENTITYID_MAX_LENGTH), - ); - } catch (AssertionFailedException $e) { - throw new ProtocolViolationException($e->getMessage()); - } - } -} diff --git a/src/Assert/DomainTrait.php b/src/Assert/DomainTrait.php new file mode 100644 index 000000000..7b1f43190 --- /dev/null +++ b/src/Assert/DomainTrait.php @@ -0,0 +1,38 @@ +getMessage()); + } + } +} diff --git a/src/Assert/EntityIDTrait.php b/src/Assert/EntityIDTrait.php new file mode 100644 index 000000000..3f1072636 --- /dev/null +++ b/src/Assert/EntityIDTrait.php @@ -0,0 +1,37 @@ +getMessage()); + } + } +} diff --git a/src/Assert/GeolocationTrait.php b/src/Assert/GeolocationTrait.php new file mode 100644 index 000000000..97f0df63c --- /dev/null +++ b/src/Assert/GeolocationTrait.php @@ -0,0 +1,37 @@ +getMessage()); + } + } +} diff --git a/src/Assert/SAMLAnyURITrait.php b/src/Assert/SAMLAnyURITrait.php new file mode 100644 index 000000000..dcc9769c6 --- /dev/null +++ b/src/Assert/SAMLAnyURITrait.php @@ -0,0 +1,33 @@ +getMessage()); + } + } +} diff --git a/src/Assert/SAMLDateTimeTrait.php b/src/Assert/SAMLDateTimeTrait.php new file mode 100644 index 000000000..63bda593c --- /dev/null +++ b/src/Assert/SAMLDateTimeTrait.php @@ -0,0 +1,33 @@ +getMessage()); + } + } +} diff --git a/src/Assert/SAMLStringTrait.php b/src/Assert/SAMLStringTrait.php new file mode 100644 index 000000000..00386a89f --- /dev/null +++ b/src/Assert/SAMLStringTrait.php @@ -0,0 +1,35 @@ +getMessage()); + } + } +} diff --git a/src/Assertion/Transformer/NameIdDecryptionTransformer.php b/src/Assertion/Transformer/NameIdDecryptionTransformer.php index 008ca995a..ab1441ea4 100644 --- a/src/Assertion/Transformer/NameIdDecryptionTransformer.php +++ b/src/Assertion/Transformer/NameIdDecryptionTransformer.php @@ -6,7 +6,7 @@ use Exception; use Psr\Log\LoggerInterface; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Assertion\Exception\NotDecryptedException; use SimpleSAML\SAML2\Certificate\PrivateKeyLoader; use SimpleSAML\SAML2\Configuration\IdentityProvider; diff --git a/src/Assertion/Validation/ConstraintValidator/NotBefore.php b/src/Assertion/Validation/ConstraintValidator/NotBefore.php index b61546302..807e6b883 100644 --- a/src/Assertion/Validation/ConstraintValidator/NotBefore.php +++ b/src/Assertion/Validation/ConstraintValidator/NotBefore.php @@ -18,18 +18,13 @@ class NotBefore implements AssertionConstraintValidator */ public function validate(Assertion $assertion, Result $result): void { - $conditions = $assertion->getConditions(); - if ($conditions !== null) { - $notBeforeTimestamp = $conditions->getNotBefore(); - $clock = Utils::getContainer()->getClock(); - if ( - ($notBeforeTimestamp !== null) && - ($notBeforeTimestamp > ($clock->now()->add(new DateInterval('PT60S')))) - ) { - $result->addError( - 'Received an assertion that is valid in the future. Check clock synchronization on IdP and SP.', - ); - } + $notBefore = $assertion->getConditions()?->getNotBefore()?->toDateTime(); + $clock = Utils::getContainer()->getClock(); + + if (($notBefore !== null) && ($notBefore > ($clock->now()->add(new DateInterval('PT60S'))))) { + $result->addError( + 'Received an assertion that is valid in the future. Check clock synchronization on IdP and SP.', + ); } } } diff --git a/src/Assertion/Validation/ConstraintValidator/NotOnOrAfter.php b/src/Assertion/Validation/ConstraintValidator/NotOnOrAfter.php index 29e5fe5d1..f86c0619b 100644 --- a/src/Assertion/Validation/ConstraintValidator/NotOnOrAfter.php +++ b/src/Assertion/Validation/ConstraintValidator/NotOnOrAfter.php @@ -18,18 +18,13 @@ class NotOnOrAfter implements AssertionConstraintValidator */ public function validate(Assertion $assertion, Result $result): void { - $conditions = $assertion->getConditions(); - if ($conditions !== null) { - $notValidOnOrAfterTimestamp = $conditions->getNotOnOrAfter(); - $clock = Utils::getContainer()->getClock(); - if ( - ($notValidOnOrAfterTimestamp !== null) && - ($notValidOnOrAfterTimestamp <= ($clock->now()->sub(new DateInterval('PT60S')))) - ) { - $result->addError( - 'Received an assertion that has expired. Check clock synchronization on IdP and SP.', - ); - } + $notOnOrAfter = $assertion->getConditions()?->getNotOnOrAfter()?->toDateTime(); + $clock = Utils::getContainer()->getClock(); + + if (($notOnOrAfter !== null) && ($notOnOrAfter <= ($clock->now()->sub(new DateInterval('PT60S'))))) { + $result->addError( + 'Received an assertion that has expired. Check clock synchronization on IdP and SP.', + ); } } } diff --git a/src/Assertion/Validation/ConstraintValidator/SpIsValidAudience.php b/src/Assertion/Validation/ConstraintValidator/SpIsValidAudience.php index 503d5a2a4..1fdedd831 100644 --- a/src/Assertion/Validation/ConstraintValidator/SpIsValidAudience.php +++ b/src/Assertion/Validation/ConstraintValidator/SpIsValidAudience.php @@ -4,7 +4,7 @@ namespace SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Assertion\Validation\AssertionConstraintValidator; use SimpleSAML\SAML2\Assertion\Validation\Result; use SimpleSAML\SAML2\Configuration\ServiceProvider; @@ -60,10 +60,10 @@ public function validate(Assertion $assertion, Result $result): void foreach ($audienceRestrictions as $audienceRestriction) { $audiences = $audienceRestriction->getAudience(); foreach ($audiences as $audience) { - if ($entityId === $audience->getContent()) { + if ($entityId === $audience->getContent()->getValue()) { return; } - $all[] = $audience->getContent(); + $all[] = $audience->getContent()->getValue(); } } diff --git a/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationMethod.php b/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationMethod.php index 7252258b6..9d427a76a 100644 --- a/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationMethod.php +++ b/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationMethod.php @@ -21,9 +21,9 @@ public function validate( SubjectConfirmation $subjectConfirmation, Result $result, ): void { - if ($subjectConfirmation->getMethod() !== C::CM_BEARER) { + if ($subjectConfirmation->getMethod()->getValue() !== C::CM_BEARER) { $result->addError(sprintf( - 'Invalid Method on SubjectConfirmation, current;y only Bearer (%s) is supported', + 'Invalid Method on SubjectConfirmation, currently only Bearer (%s) is supported', C::CM_BEARER, )); } diff --git a/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotBefore.php b/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotBefore.php index ac92d7d70..1d8f0f21f 100644 --- a/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotBefore.php +++ b/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotBefore.php @@ -5,7 +5,6 @@ namespace SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator; use DateInterval; -use SimpleSAML\Assert\Assert; use SimpleSAML\SAML2\Assertion\Validation\Result; use SimpleSAML\SAML2\Assertion\Validation\SubjectConfirmationConstraintValidator; use SimpleSAML\SAML2\Utils; @@ -23,12 +22,9 @@ public function validate( SubjectConfirmation $subjectConfirmation, Result $result, ): void { - $data = $subjectConfirmation->getSubjectConfirmationData(); - Assert::notNull($data); - - /** @psalm-suppress PossiblyNullReference */ - $notBefore = $data->getNotBefore(); + $notBefore = $subjectConfirmation->getSubjectConfirmationData()?->getNotBefore()?->toDateTime(); $clock = Utils::getContainer()->getClock(); + if ($notBefore !== null && $notBefore > ($clock->now()->add(new DateInterval('PT60S')))) { $result->addError('NotBefore in SubjectConfirmationData is in the future'); } diff --git a/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotOnOrAfter.php b/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotOnOrAfter.php index bd3d85025..f7dfb346f 100644 --- a/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotOnOrAfter.php +++ b/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotOnOrAfter.php @@ -5,7 +5,6 @@ namespace SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator; use DateInterval; -use SimpleSAML\Assert\Assert; use SimpleSAML\SAML2\Assertion\Validation\Result; use SimpleSAML\SAML2\Assertion\Validation\SubjectConfirmationConstraintValidator; use SimpleSAML\SAML2\Utils; @@ -23,12 +22,9 @@ public function validate( SubjectConfirmation $subjectConfirmation, Result $result, ): void { - $data = $subjectConfirmation->getSubjectConfirmationData(); - Assert::notNull($data); - - /** @psalm-suppress PossiblyNullReference */ - $notOnOrAfter = $data->getNotOnOrAfter(); + $notOnOrAfter = $subjectConfirmation->getSubjectConfirmationData()?->getNotOnOrAfter()?->toDateTime(); $clock = Utils::getContainer()->getClock(); + if ($notOnOrAfter !== null && $notOnOrAfter <= ($clock->now()->sub(new DateInterval('PT60S')))) { $result->addError('NotOnOrAfter in SubjectConfirmationData is in the past'); } diff --git a/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationRecipientMatches.php b/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationRecipientMatches.php index 358ba5e4a..d2b85ca29 100644 --- a/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationRecipientMatches.php +++ b/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationRecipientMatches.php @@ -4,14 +4,12 @@ namespace SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator; -use SimpleSAML\Assert\Assert; use SimpleSAML\SAML2\Assertion\Validation\Result; use SimpleSAML\SAML2\Assertion\Validation\SubjectConfirmationConstraintValidator; use SimpleSAML\SAML2\Configuration\Destination; use SimpleSAML\SAML2\XML\saml\SubjectConfirmation; use function sprintf; -use function strval; class SubjectConfirmationRecipientMatches implements SubjectConfirmationConstraintValidator { @@ -33,16 +31,13 @@ public function __construct( */ public function validate(SubjectConfirmation $subjectConfirmation, Result $result): void { - $data = $subjectConfirmation->getSubjectConfirmationData(); - Assert::notNull($data); + $recipient = $subjectConfirmation->getSubjectConfirmationData()?->getRecipient(); - /** @psalm-suppress PossiblyNullReference */ - $recipient = $data->getRecipient(); - if ($recipient && !$this->destination->equals(new Destination($recipient))) { + if ($recipient !== null && !$recipient->equals((string)$this->destination)) { $result->addError(sprintf( 'Recipient in SubjectConfirmationData ("%s") does not match the current destination ("%s")', $recipient, - strval($this->destination), + (string)$this->destination, )); } } diff --git a/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationResponseToMatches.php b/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationResponseToMatches.php index 5c9463aff..015847324 100644 --- a/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationResponseToMatches.php +++ b/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationResponseToMatches.php @@ -4,14 +4,12 @@ namespace SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator; -use SimpleSAML\Assert\Assert; use SimpleSAML\SAML2\Assertion\Validation\Result; use SimpleSAML\SAML2\Assertion\Validation\SubjectConfirmationConstraintValidator; use SimpleSAML\SAML2\XML\saml\SubjectConfirmation; use SimpleSAML\SAML2\XML\samlp\Response; use function sprintf; -use function strval; class SubjectConfirmationResponseToMatches implements SubjectConfirmationConstraintValidator { @@ -34,31 +32,27 @@ public function __construct( */ public function validate(SubjectConfirmation $subjectConfirmation, Result $result): void { - $data = $subjectConfirmation->getSubjectConfirmationData(); - Assert::notNull($data); + $inResponseTo = $subjectConfirmation->getSubjectConfirmationData()?->getInResponseTo(); - /** @psalm-suppress PossiblyNullReference */ - $inResponseTo = $data->getInResponseTo(); - if ($inResponseTo && ($this->getInResponseTo() !== false) && ($this->getInResponseTo() !== $inResponseTo)) { + if ( + $inResponseTo !== null + && $this->getInResponseTo() !== null + && !$inResponseTo->equals($this->getInResponseTo()) + ) { $result->addError(sprintf( 'InResponseTo in SubjectConfirmationData ("%s") does not match the Response InResponseTo ("%s")', $inResponseTo, - strval($this->getInResponseTo()), + $this->getInResponseTo(), )); } } /** - * @return string|bool + * @return string|null */ - private function getInResponseTo() + private function getInResponseTo(): ?string { - $inResponseTo = $this->response->getInResponseTo(); - if ($inResponseTo === null) { - return false; - } - - return $inResponseTo; + return $this->response->getInResponseTo()?->getValue(); } } diff --git a/src/Binding/HTTPArtifact.php b/src/Binding/HTTPArtifact.php index 7dd64cbf1..ed8be8d3a 100644 --- a/src/Binding/HTTPArtifact.php +++ b/src/Binding/HTTPArtifact.php @@ -9,10 +9,10 @@ use Nyholm\Psr7\Response; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use SimpleSAML\Assert\Assert; use SimpleSAML\Configuration; use SimpleSAML\Metadata\MetaDataStorageHandler; use SimpleSAML\Module\saml\Message as MSG; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Binding; use SimpleSAML\SAML2\Binding\RelayStateTrait; use SimpleSAML\SAML2\SOAPClient; diff --git a/src/Binding/HTTPPost.php b/src/Binding/HTTPPost.php index ed96a73ce..136c913c8 100644 --- a/src/Binding/HTTPPost.php +++ b/src/Binding/HTTPPost.php @@ -8,7 +8,7 @@ use Nyholm\Psr7\Response; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Binding; use SimpleSAML\SAML2\Binding\RelayStateTrait; use SimpleSAML\SAML2\Exception\ProtocolViolationException; @@ -41,7 +41,7 @@ class HTTPPost extends Binding implements AsynchronousBindingInterface, RelaySta public function send(AbstractMessage $message): ResponseInterface { if ($this->destination === null) { - $destination = $message->getDestination(); + $destination = $message->getDestination()?->getValue(); if ($destination === null) { throw new Exception('Cannot send message, no destination set.'); } diff --git a/src/Binding/HTTPRedirect.php b/src/Binding/HTTPRedirect.php index a4b365f14..998315784 100644 --- a/src/Binding/HTTPRedirect.php +++ b/src/Binding/HTTPRedirect.php @@ -8,7 +8,7 @@ use Nyholm\Psr7\Response; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Binding; use SimpleSAML\SAML2\Binding\RelayStateTrait; use SimpleSAML\SAML2\Compat\ContainerSingleton; @@ -55,6 +55,8 @@ public function getRedirectURL(AbstractMessage $message): string $destination = $message->getDestination(); if ($destination === null) { throw new Exception('Cannot build a redirect URL, no destination set.'); + } else { + $destination = $destination->getValue(); } } else { $destination = $this->destination; @@ -84,8 +86,11 @@ public function getRedirectURL(AbstractMessage $message): string $signature = $message->getSignature(); if ($signature !== null) { // add the signature - $msg .= '&SigAlg=' . urlencode($signature->getSignedInfo()->getSignatureMethod()->getAlgorithm()); - $msg .= '&Signature=' . urlencode($signature->getSignatureValue()->getContent()); + $signatureMethod = $signature->getSignedInfo()->getSignatureMethod(); + $signatureValue = $signature->getSignatureValue(); + + $msg .= '&SigAlg=' . urlencode($signatureMethod->getAlgorithm()->getValue()); + $msg .= '&Signature=' . urlencode($signatureValue->getValue()->getValue()); } if (str_contains($destination, '?')) { diff --git a/src/Binding/SOAP.php b/src/Binding/SOAP.php index f9b456e40..4bf651a23 100644 --- a/src/Binding/SOAP.php +++ b/src/Binding/SOAP.php @@ -10,16 +10,18 @@ use Psr\Http\Message\ServerRequestInterface; use SimpleSAML\SAML2\Binding; use SimpleSAML\SAML2\Exception\Protocol\UnsupportedBindingException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\XML\ecp\RequestAuthenticated; use SimpleSAML\SAML2\XML\ecp\Response as ECPResponse; use SimpleSAML\SAML2\XML\samlp\AbstractMessage; use SimpleSAML\SAML2\XML\samlp\MessageFactory; use SimpleSAML\SAML2\XML\samlp\Response as SAML2_Response; -use SimpleSAML\SOAP\Utils\XPath; -use SimpleSAML\SOAP\XML\env_200106\Body; -use SimpleSAML\SOAP\XML\env_200106\Envelope; -use SimpleSAML\SOAP\XML\env_200106\Header; +use SimpleSAML\SOAP11\Type\MustUnderstandValue; +use SimpleSAML\SOAP11\Utils\XPath; +use SimpleSAML\SOAP11\XML\Body; +use SimpleSAML\SOAP11\XML\Envelope; +use SimpleSAML\SOAP11\XML\Header; use SimpleSAML\XML\DOMDocumentFactory; use function file_get_contents; @@ -44,13 +46,15 @@ public function getOutputToSend(AbstractMessage $message) // containing another message (e.g. a Response), however in the ECP // profile, this is the Response itself. if ($message instanceof SAML2_Response) { - $requestAuthenticated = new RequestAuthenticated(true); + $requestAuthenticated = new RequestAuthenticated( + MustUnderstandValue::fromBoolean(true), + ); - $destination = $this->destination ?: $message->getDestination(); + $destination = $this->destination ?: $message->getDestination()?->getValue(); if ($destination === null) { throw new Exception('No destination available for SOAP message.'); } - $response = new ECPResponse($destination); + $response = new ECPResponse(SAMLAnyURIValue::fromString($destination)); $header = new Header([$requestAuthenticated, $response]); } diff --git a/src/Certificate/Key.php b/src/Certificate/Key.php index 47aefe883..486e85d8a 100644 --- a/src/Certificate/Key.php +++ b/src/Certificate/Key.php @@ -5,7 +5,7 @@ namespace SimpleSAML\SAML2\Certificate; use ArrayAccess; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Certificate\Exception\InvalidKeyUsageException; use SimpleSAML\SAML2\Exception\InvalidArgumentException; diff --git a/src/Certificate/KeyCollection.php b/src/Certificate/KeyCollection.php index 8fc8b2526..f5331c3b3 100644 --- a/src/Certificate/KeyCollection.php +++ b/src/Certificate/KeyCollection.php @@ -4,7 +4,7 @@ namespace SimpleSAML\SAML2\Certificate; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Utilities\ArrayCollection; /** diff --git a/src/Compat/AbstractContainer.php b/src/Compat/AbstractContainer.php index 9d1d97b06..1e7660df7 100644 --- a/src/Compat/AbstractContainer.php +++ b/src/Compat/AbstractContainer.php @@ -9,24 +9,23 @@ use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\XML\ExtensionPointInterface; use SimpleSAML\XML\AbstractElement; -use SimpleSAML\XML\Exception\SchemaViolationException; +use SimpleSAML\XML\ElementInterface; +use SimpleSAML\XMLSchema\Type\QNameValue; use SimpleSAML\XMLSecurity\Alg\Encryption\EncryptionAlgorithmFactory; use SimpleSAML\XMLSecurity\Alg\KeyTransport\KeyTransportAlgorithmFactory; use SimpleSAML\XMLSecurity\Alg\Signature\SignatureAlgorithmFactory; use function array_key_exists; -use function implode; -use function is_subclass_of; +use function constant; abstract class AbstractContainer { - /** @var string */ - private const XSI_TYPE_PREFIX = ''; - - /** @var array */ protected array $registry = []; + /** @var array */ + protected array $extRegistry = []; + /** @var array|null */ protected ?array $blacklistedEncryptionAlgorithms = [ EncryptionAlgorithmFactory::DEFAULT_BLACKLIST, @@ -47,6 +46,20 @@ public function getBlacklistedEncryptionAlgorithms(): ?array } + /** + * Register a class that can handle a given element. + * + * @param string $class The class name of a class extending AbstractElement + * @psalm-param class-string $class + */ + public function registerElementHandler(string $class): void + { + Assert::subclassOf($class, AbstractElement::class); + $key = '{' . constant($class::NS) . '}' . AbstractElement::getClassName($class); + $this->registry[$key] = $class; + } + + /** * Register a class that can handle given extension points of the standard. * @@ -55,37 +68,29 @@ public function getBlacklistedEncryptionAlgorithms(): ?array */ public function registerExtensionHandler(string $class): void { - Assert::subclassOf($class, AbstractElement::class); - if (is_subclass_of($class, ExtensionPointInterface::class, true)) { - $key = implode(':', [self::XSI_TYPE_PREFIX, $class::getXsiTypeNamespaceURI(), $class::getXsiTypeName()]); - } else { - $className = AbstractElement::getClassName($class); - $key = ($class::NS === null) ? $className : implode(':', [$class::NS, $className]); - } - $this->registry[$key] = $class; + Assert::subclassOf($class, ExtensionPointInterface::class); + $key = '{' . $class::getXsiTypeNamespaceURI() . '}' . $class::getXsiTypeName(); + $this->extRegistry[$key] = $class; } /** - * Search for a class that implements an $element in the given $namespace. + * Search for a class that implements an element in the given $namespace. * * Such classes must have been registered previously by calling registerExtensionHandler(), and they must * extend \SimpleSAML\XML\AbstractElement. * - * @param string|null $namespace The namespace URI for the given element. - * @param string $element The local name of the element. + * @param \SimpleSAML\XMLSchema\Type\QNameValue $qName The qualified name of the element. * * @return string|null The fully-qualified name of a class extending \SimpleSAML\XML\AbstractElement and * implementing support for the given element, or null if no such class has been registered before. * @psalm-return class-string|null */ - public function getElementHandler(?string $namespace, string $element): ?string + public function getElementHandler(QNameValue $qName): ?string { - Assert::nullOrValidURI($namespace, SchemaViolationException::class); - Assert::validNCName($element, SchemaViolationException::class); - - $key = ($namespace === null) ? $element : implode(':', [$namespace, $element]); + $key = '{' . $qName->getNameSpaceURI()->getValue() . '}' . $qName->getLocalName()->getValue(); if (array_key_exists($key, $this->registry) === true) { + Assert::implementsInterface($this->registry[$key], ElementInterface::class); return $this->registry[$key]; } @@ -97,23 +102,22 @@ public function getElementHandler(?string $namespace, string $element): ?string * Search for a class that implements a custom element type. * * Such classes must have been registered previously by calling registerExtensionHandler(), and they must - * implement \SimpleSAML\SAML2\XML\saml\ExtensionPointInterface. - * - * @param string $type The type of the identifier (xsi:type of a BaseID element). + * implement \SimpleSAML\SAML11\XML\saml\ExtensionPointInterface. * + * @param \SimpleSAML\XMLSchema\Type\QNameValue $qName The qualified name of the extension. * @return string|null The fully-qualified name of a class implementing - * \SimpleSAML\SAML2\XML\saml\ExtensionPointInterface or null if no such class has been registered before. + * \SimpleSAML\SAML11\XML\saml\ExtensionPointInterface or null if no such class has been registered before. * @psalm-return class-string|null */ - public function getExtensionHandler(string $type): ?string + public function getExtensionHandler(QNameValue $qName): ?string { - Assert::notEmpty($type, 'Cannot search for identifier handlers with an empty type.'); - $type = implode(':', [self::XSI_TYPE_PREFIX, $type]); - if (!array_key_exists($type, $this->registry)) { - return null; + $key = '{' . $qName->getNameSpaceURI()->getValue() . '}' . $qName->getLocalName()->getValue(); + if (array_key_exists($key, $this->extRegistry) === true) { + Assert::implementsInterface($this->extRegistry[$key], ExtensionPointInterface::class); + return $this->extRegistry[$key]; } - Assert::implementsInterface($this->registry[$type], ExtensionPointInterface::class); - return $this->registry[$type]; + + return null; } diff --git a/src/Compat/ContainerSingleton.php b/src/Compat/ContainerSingleton.php index 1e6f0dae2..06c07d3c0 100644 --- a/src/Compat/ContainerSingleton.php +++ b/src/Compat/ContainerSingleton.php @@ -4,7 +4,7 @@ namespace SimpleSAML\SAML2\Compat; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; class ContainerSingleton { diff --git a/src/Configuration/PrivateKey.php b/src/Configuration/PrivateKey.php index 456119303..1707bbe01 100644 --- a/src/Configuration/PrivateKey.php +++ b/src/Configuration/PrivateKey.php @@ -4,7 +4,7 @@ namespace SimpleSAML\SAML2\Configuration; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; /** * Configuration of a private key. diff --git a/src/Configuration/SimpleSAMLConverter.php b/src/Configuration/SimpleSAMLConverter.php deleted file mode 100644 index bf19e6857..000000000 --- a/src/Configuration/SimpleSAMLConverter.php +++ /dev/null @@ -1,157 +0,0 @@ -hasValue($prefix . 'keys')) { - $extracted['keys'] = $configuration->getArray($prefix . 'keys'); - } - - // ported from - // https://github.com/simplesamlphp/simplesamlphp/blob/3d735912342767d391297cc5e13272a76730aca0/lib/SimpleSAML/Configuration.php#L1108 - if ($configuration->hasValue($prefix . 'certData')) { - $extracted['certificateData'] = $configuration->getString($prefix . 'certData'); - } - - // ported from - // https://github.com/simplesamlphp/simplesamlphp/blob/3d735912342767d391297cc5e13272a76730aca0/lib/SimpleSAML/Configuration.php#L1119 - if ($configuration->hasValue($prefix . 'certificate')) { - $extracted['certificateData'] = $configuration->getString($prefix . 'certificate'); - } - - $extracted['assertionEncryptionEnabled'] = $configuration->getBoolean('assertion.encryption', false); - - if ($configuration->hasValue('sharedKey')) { - $extracted['sharedKey'] = $configuration->getString('sharedKey'); - } - - return $extracted; - } - - - /** - * @param \SimpleSAML\Configuration $configuration - * @param array $baseConfiguration - * - * - * @psalm-suppress UndefinedClass - */ - protected static function enrichForIdentityProvider(Configuration $configuration, array &$baseConfiguration): void - { - $baseConfiguration['entityId'] = $configuration->getString('entityid'); - } - - - /** - * @param \SimpleSAML\Configuration $configuration - * @param array $baseConfiguration - * - * - * @psalm-suppress UndefinedClass - */ - protected static function enrichForServiceProvider(Configuration $configuration, array &$baseConfiguration): void - { - $baseConfiguration['entityId'] = $configuration->getString('entityid'); - } - - - /** - * @param \SimpleSAML\Configuration $configuration - * @param array $baseConfiguration - * - * - * @psalm-suppress UndefinedClass - */ - protected static function enrichForDecryptionProvider( - Configuration $configuration, - array &$baseConfiguration, - ): void { - if ($configuration->hasValue('sharedKey')) { - $baseConfiguration['sharedKey'] = $configuration->getString('sharedKey', null); - } - - if ($configuration->hasValue('new_privatekey')) { - $baseConfiguration['privateKeys'][] = new PrivateKey( - $configuration->getString('new_privatekey'), - PrivateKey::NAME_NEW, - $configuration->getString('new_privatekey_pass', null), - ); - } - - if ($configuration->getBoolean('assertion.encryption', false)) { - $baseConfiguration['privateKeys'][] = new PrivateKey( - $configuration->getString('privatekey'), - PrivateKey::NAME_DEFAULT, - $configuration->getString('privatekey_pass', null), - ); - - if ($configuration->hasValue('encryption.blacklisted-algorithms')) { - $baseConfiguration['blacklistedEncryptionAlgorithms'] = $configuration->getValue( - 'encryption.blacklisted-algorithms', - ); - } - } - } -} diff --git a/src/Response/Validation/ConstraintValidator/DestinationMatches.php b/src/Response/Validation/ConstraintValidator/DestinationMatches.php index 94cd16680..716b4fcf3 100644 --- a/src/Response/Validation/ConstraintValidator/DestinationMatches.php +++ b/src/Response/Validation/ConstraintValidator/DestinationMatches.php @@ -36,7 +36,7 @@ public function validate(Response $response, Result $result): void if ($destination === null) { throw new Exception('No destination set in the response.'); } - if (!$this->expectedDestination->equals(new Destination($destination))) { + if (!$this->expectedDestination->equals(new Destination($destination->getValue()))) { $result->addError(sprintf( 'Destination in response "%s" does not match the expected destination "%s"', $destination, diff --git a/src/Response/Validation/ConstraintValidator/IsSuccessful.php b/src/Response/Validation/ConstraintValidator/IsSuccessful.php index 23b411ca6..ec95529ec 100644 --- a/src/Response/Validation/ConstraintValidator/IsSuccessful.php +++ b/src/Response/Validation/ConstraintValidator/IsSuccessful.php @@ -44,16 +44,16 @@ private function buildMessage(Status $responseStatus): string $codes = $statusCode->getSubCodes(); if (!empty($codes)) { foreach ($codes as $code) { - $subCodes[] = $this->truncateStatus($code->getValue()); + $subCodes[] = $this->truncateStatus($code->getValue()->getValue()); } } $statusMessage = $responseStatus->getStatusMessage(); return sprintf( '%s%s%s', - $this->truncateStatus($statusCode->getValue()), + $this->truncateStatus($statusCode->getValue()->getValue()), $subCodes ? '/' . implode('/', $subCodes) : '', - $statusMessage ? ' ' . $statusMessage->getContent() : '', + $statusMessage ? ' ' . $statusMessage->getContent()->getValue() : '', ); } diff --git a/src/SOAPClient.php b/src/SOAPClient.php index 96fc762c8..5ab61ab95 100644 --- a/src/SOAPClient.php +++ b/src/SOAPClient.php @@ -10,10 +10,10 @@ use SimpleSAML\SAML2\Compat\ContainerSingleton; use SimpleSAML\SAML2\XML\samlp\AbstractMessage; use SimpleSAML\SAML2\XML\samlp\MessageFactory; -use SimpleSAML\SOAP\Utils\XPath; -use SimpleSAML\SOAP\XML\env_200106\Body; -use SimpleSAML\SOAP\XML\env_200106\Envelope; -use SimpleSAML\SOAP\XML\env_200106\Fault; +use SimpleSAML\SOAP11\Utils\XPath; +use SimpleSAML\SOAP11\XML\Body; +use SimpleSAML\SOAP11\XML\Envelope; +use SimpleSAML\SOAP11\XML\Fault; use SimpleSAML\Utils\Config; use SimpleSAML\Utils\Crypto; use SimpleSAML\XML\Chunk; @@ -255,7 +255,7 @@ public static function validateSSL(string $data, XMLSecurityKey $key): void * Extracts the SOAP Fault from SOAP message * * @param \DOMDocument $soapMessage Soap response needs to be type DOMDocument - * @return \SimpleSAML\SOAP\XML\env_200106\Fault|null + * @return \SimpleSAML\SOAP11\XML\Fault|null */ private function getSOAPFault(DOMDocument $soapMessage): ?Fault { diff --git a/src/Signature/AbstractChainedValidator.php b/src/Signature/AbstractChainedValidator.php index d2f0fea93..4e5be4fb1 100644 --- a/src/Signature/AbstractChainedValidator.php +++ b/src/Signature/AbstractChainedValidator.php @@ -45,7 +45,7 @@ protected function validateElementWithKeys( foreach ($pemCandidates as $index => $candidateKey) { $cert = new X509(PEM::fromString($candidateKey->getCertificate())); $verifier = (new SignatureAlgorithmFactory([]))->getAlgorithm( - $element->getSignature()?->getSignedInfo()->getSignatureMethod()->getAlgorithm(), + $element->getSignature()?->getSignedInfo()->getSignatureMethod()->getAlgorithm()->getValue(), $cert->getPublicKey(), ); diff --git a/src/Signature/PublicKeyValidator.php b/src/Signature/PublicKeyValidator.php index 9e0bd8d47..2bc949c99 100644 --- a/src/Signature/PublicKeyValidator.php +++ b/src/Signature/PublicKeyValidator.php @@ -5,7 +5,7 @@ namespace SimpleSAML\SAML2\Signature; use Psr\Log\LoggerInterface; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Certificate\Key; use SimpleSAML\SAML2\Certificate\KeyCollection; use SimpleSAML\SAML2\Certificate\KeyLoader; diff --git a/src/Type/AnyURIListValue.php b/src/Type/AnyURIListValue.php new file mode 100644 index 000000000..4c92c2e6b --- /dev/null +++ b/src/Type/AnyURIListValue.php @@ -0,0 +1,74 @@ +sanitizeValue($value); + Assert::stringNotEmpty($sanitized, ProtocolViolationException::class); + + $uris = preg_split('/[\s]+/', $sanitized, C::UNBOUNDED_LIMIT); + Assert::allValidAnyURI($uris, SchemaViolationException::class); + } + + + /** + * Convert an array of xs:anyURI items into a saml:AnyURIList + * + * @param string[] $uris + * @return static + */ + public static function fromArray(array $uris): static + { + $str = ''; + foreach ($uris as $uri) { + $str .= str_replace(' ', '+', $uri) . ' '; + } + + return new static(trim($str)); + } + + + /** + * Convert this saml:AnyURIList to an array of xs:anyURI items + * + * @return array<\SimpleSAML\SAML2\Type\SAMLAnyURIValue> + */ + public function toArray(): array + { + $uris = preg_split('/[\s]+/', $this->getValue(), C::UNBOUNDED_LIMIT); + $uris = str_replace('+', ' ', $uris); + + return array_map([SAMLAnyURIValue::class, 'fromString'], $uris); + } +} diff --git a/src/Type/AuthnContextComparisonTypeValue.php b/src/Type/AuthnContextComparisonTypeValue.php new file mode 100644 index 000000000..9b450d8ef --- /dev/null +++ b/src/Type/AuthnContextComparisonTypeValue.php @@ -0,0 +1,57 @@ +sanitizeValue($value), + array_column(AuthnContextComparisonTypeEnum::cases(), 'value'), + SchemaViolationException::class, + ); + } + + + /** + * @param \SimpleSAML\SAML2\XML\samlp\AuthnContextComparisonTypeEnum $value + * @return static + */ + public static function fromEnum(AuthnContextComparisonTypeEnum $value): static + { + return new static($value->value); + } + + + /** + * @return \SimpleSAML\SAML2\XML\samlp\AuthnContextComparisonTypeEnum $value + */ + public function toEnum(): AuthnContextComparisonTypeEnum + { + return AuthnContextComparisonTypeEnum::from($this->getValue()); + } +} diff --git a/src/Type/CIDRValue.php b/src/Type/CIDRValue.php new file mode 100644 index 000000000..687462ce7 --- /dev/null +++ b/src/Type/CIDRValue.php @@ -0,0 +1,38 @@ +sanitizeValue($value)); + } +} diff --git a/src/Type/DecisionTypeValue.php b/src/Type/DecisionTypeValue.php new file mode 100644 index 000000000..3ec6a0376 --- /dev/null +++ b/src/Type/DecisionTypeValue.php @@ -0,0 +1,57 @@ +sanitizeValue($value), + array_column(DecisionTypeEnum::cases(), 'value'), + SchemaViolationException::class, + ); + } + + + /** + * @param \SimpleSAML\SAML2\XML\saml\DecisionTypeEnum $value + * @return static + */ + public static function fromEnum(DecisionTypeEnum $value): static + { + return new static($value->value); + } + + + /** + * @return \SimpleSAML\SAML2\XML\saml\DecisionTypeEnum $value + */ + public function toEnum(): DecisionTypeEnum + { + return DecisionTypeEnum::from($this->getValue()); + } +} diff --git a/src/Type/DomainValue.php b/src/Type/DomainValue.php new file mode 100644 index 000000000..a6f4182fa --- /dev/null +++ b/src/Type/DomainValue.php @@ -0,0 +1,43 @@ +sanitizeValue($value)); + } +} diff --git a/src/Type/EmailAddressValue.php b/src/Type/EmailAddressValue.php new file mode 100644 index 000000000..833f27e31 --- /dev/null +++ b/src/Type/EmailAddressValue.php @@ -0,0 +1,43 @@ +sanitizeValue($value)); + } +} diff --git a/src/Type/EntityIDValue.php b/src/Type/EntityIDValue.php new file mode 100644 index 000000000..33f96e1a9 --- /dev/null +++ b/src/Type/EntityIDValue.php @@ -0,0 +1,38 @@ +sanitizeValue($value)); + } +} diff --git a/src/Type/GeolocationValue.php b/src/Type/GeolocationValue.php new file mode 100644 index 000000000..cc4bd929c --- /dev/null +++ b/src/Type/GeolocationValue.php @@ -0,0 +1,41 @@ +sanitizeValue($value)); + } +} diff --git a/src/Type/KeyTypesValue.php b/src/Type/KeyTypesValue.php new file mode 100644 index 000000000..e800e4be8 --- /dev/null +++ b/src/Type/KeyTypesValue.php @@ -0,0 +1,51 @@ +sanitizeValue($content), + array_column(KeyTypesEnum::cases(), 'value'), + SchemaViolationException::class, + ); + } + + + /** + * Convert enum to value type + */ + public static function fromEnum(KeyTypesEnum $use): static + { + return static::fromString($use->value); + } + + + /** + * Convert this value type to enum + */ + public function toEnum(): KeyTypesEnum + { + return KeyTypesEnum::from($this->getValue()); + } +} diff --git a/src/Type/ListOfStringsValue.php b/src/Type/ListOfStringsValue.php new file mode 100644 index 000000000..40d90c301 --- /dev/null +++ b/src/Type/ListOfStringsValue.php @@ -0,0 +1,79 @@ +sanitizeValue($value), C::UNBOUNDED_LIMIT); + + Assert::allValidString($strings, SchemaViolationException::class); + } + + + /** + * Convert an array of xs:string items into a mdui:ListOfStrings + * + * @param string[] $keywords + * @return static + */ + public static function fromArray(array $keywords): static + { + Assert::allNotContains($keywords, '+', ProtocolViolationException::class); + + $str = ''; + foreach ($keywords as $keyword) { + $str .= str_replace(' ', '+', $keyword) . ' '; + } + + return new static(trim($str)); + } + + + /** + * Convert this mdui:ListOfStrings to an array of xs:string items + * + * @return array<\SimpleSAML\SAML2\Type\SAMLStringValue> + */ + public function toArray(): array + { + $strings = preg_split('/[\s]+/', $this->getValue(), C::UNBOUNDED_LIMIT); + $strings = str_replace('+', ' ', $strings); + + return array_map([SAMLStringValue::class, 'fromString'], $strings); + } +} diff --git a/src/Type/SAMLAnyURIValue.php b/src/Type/SAMLAnyURIValue.php new file mode 100644 index 000000000..a43e42500 --- /dev/null +++ b/src/Type/SAMLAnyURIValue.php @@ -0,0 +1,26 @@ +sanitizeValue($value)); + } +} diff --git a/src/Type/SAMLDateTimeValue.php b/src/Type/SAMLDateTimeValue.php new file mode 100644 index 000000000..3c01cf70b --- /dev/null +++ b/src/Type/SAMLDateTimeValue.php @@ -0,0 +1,31 @@ +sanitizeValue($value), ProtocolViolationException::class); + } +} diff --git a/src/Type/SAMLStringValue.php b/src/Type/SAMLStringValue.php new file mode 100644 index 000000000..8754257e8 --- /dev/null +++ b/src/Type/SAMLStringValue.php @@ -0,0 +1,26 @@ +sanitizeValue($value)); + } +} diff --git a/src/Utilities/ArrayCollection.php b/src/Utilities/ArrayCollection.php index 54a0ef6c5..63a36fbbd 100644 --- a/src/Utilities/ArrayCollection.php +++ b/src/Utilities/ArrayCollection.php @@ -54,7 +54,7 @@ public function get($key) /** - * @param \Closure $f + * @param \Closure $filterFunction * * @return \SimpleSAML\SAML2\Utilities\ArrayCollection */ diff --git a/src/XML/Decision.php b/src/XML/Decision.php deleted file mode 100644 index cc5716ba7..000000000 --- a/src/XML/Decision.php +++ /dev/null @@ -1,15 +0,0 @@ - element's Type attribute SHOULD be used and, if it is * present, MUST have the value http://www.w3.org/2001/04/xmlenc#Element. + * */ - Assert::nullOrSame($encryptedData->getType(), C::XMLENC_ELEMENT); + Assert::nullOrSame($encryptedData->getType()->getValue(), C::XMLENC_ELEMENT); $keyInfo = $this->encryptedData->getKeyInfo(); if ($keyInfo === null) { @@ -52,7 +53,7 @@ public function __construct( foreach ($keyInfo->getInfo() as $info) { if ($info instanceof EncryptedKey) { - $this->encryptedKey = $info; + $this->encryptedKey = [$info]; break; } } @@ -83,7 +84,7 @@ public function getDecryptionKeys(): array /** * @inheritDoc * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * If the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -117,10 +118,13 @@ public static function fromXML(DOMElement $xml): static public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); + $this->encryptedData->toXML($e); + foreach ($this->getDecryptionKeys() as $key) { $key->toXML($e); } + return $e; } } diff --git a/src/XML/ExtensionPointInterface.php b/src/XML/ExtensionPointInterface.php index b7945f2d3..887458a1b 100644 --- a/src/XML/ExtensionPointInterface.php +++ b/src/XML/ExtensionPointInterface.php @@ -4,6 +4,10 @@ namespace SimpleSAML\SAML2\XML; +use SimpleSAML\XMLSchema\Type\AnyURIValue; +use SimpleSAML\XMLSchema\Type\NCNameValue; +use SimpleSAML\XMLSchema\Type\QNameValue; + /** * Interface for several extension points objects. * @@ -14,31 +18,31 @@ interface ExtensionPointInterface /** * Get the local name for the element's xsi:type. * - * @return string + * @return \SimpleSAML\XMLSchema\Type\NCNameValue */ - public static function getXsiTypeName(): string; + public static function getXsiTypeName(): NCNameValue; /** * Get the namespace for the element's xsi:type. * - * @return string + * @return \SimpleSAML\XMLSchema\Type\AnyURIValue */ - public static function getXsiTypeNamespaceURI(): string; + public static function getXsiTypeNamespaceURI(): AnyURIValue; /** * Get the namespace-prefix for the element's xsi:type. * - * @return string + * @return \SimpleSAML\XMLSchema\Type\NCNameValue */ - public static function getXsiTypePrefix(): string; + public static function getXsiTypePrefix(): NCNameValue; /** * Return the xsi:type value corresponding this element. * - * @return string + * @return \SimpleSAML\XMLSchema\Type\QNameValue */ - public function getXsiType(): string; + public function getXsiType(): QNameValue; } diff --git a/src/XML/ExtensionPointTrait.php b/src/XML/ExtensionPointTrait.php index 3602fb67d..ac9a5e5b4 100644 --- a/src/XML/ExtensionPointTrait.php +++ b/src/XML/ExtensionPointTrait.php @@ -6,7 +6,12 @@ use RuntimeException; use SimpleSAML\SAML2\Assert\Assert; -use SimpleSAML\XML\Exception\SchemaViolationException; +use SimpleSAML\XMLSchema\Type\AnyURIValue; +use SimpleSAML\XMLSchema\Type\NCNameValue; + +use function constant; +use function defined; +use function sprintf; /** * Trait for several extension points objects. @@ -18,9 +23,9 @@ trait ExtensionPointTrait /** * Get the local name for the element's xsi:type. * - * @return string + * @return \SimpleSAML\XMLSchema\Type\NCNameValue */ - public static function getXsiTypeName(): string + public static function getXsiTypeName(): NCNameValue { Assert::true( defined('static::XSI_TYPE_NAME'), @@ -29,17 +34,16 @@ public static function getXsiTypeName(): string RuntimeException::class, ); - Assert::validNCName(static::XSI_TYPE_NAME, SchemaViolationException::class); - return static::XSI_TYPE_NAME; + return NCNameValue::fromString(constant('static::XSI_TYPE_NAME')); } /** * Get the namespace for the element's xsi:type. * - * @return string + * @return \SimpleSAML\XMLSchema\Type\AnyURIValue */ - public static function getXsiTypeNamespaceURI(): string + public static function getXsiTypeNamespaceURI(): AnyURIValue { Assert::true( defined('static::XSI_TYPE_NAMESPACE'), @@ -48,17 +52,16 @@ public static function getXsiTypeNamespaceURI(): string RuntimeException::class, ); - Assert::validURI(static::XSI_TYPE_NAMESPACE, SchemaViolationException::class); - return static::XSI_TYPE_NAMESPACE; + return AnyURIValue::fromString(constant('static::XSI_TYPE_NAMESPACE')); } /** * Get the namespace-prefix for the element's xsi:type. * - * @return string + * @return \SimpleSAML\XMLSchema\Type\NCNameValue */ - public static function getXsiTypePrefix(): string + public static function getXsiTypePrefix(): NCNameValue { Assert::true( defined('static::XSI_TYPE_PREFIX'), @@ -69,7 +72,6 @@ public static function getXsiTypePrefix(): string RuntimeException::class, ); - Assert::validNCName(static::XSI_TYPE_PREFIX, SchemaViolationException::class); - return static::XSI_TYPE_PREFIX; + return NCNameValue::fromString(constant('static::XSI_TYPE_PREFIX')); } } diff --git a/src/XML/ExtensionsTrait.php b/src/XML/ExtensionsTrait.php index 5e9d31a74..42c07ab99 100644 --- a/src/XML/ExtensionsTrait.php +++ b/src/XML/ExtensionsTrait.php @@ -5,7 +5,7 @@ namespace SimpleSAML\SAML2\XML; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Exception\ProtocolViolationException; use SimpleSAML\XML\ElementInterface; @@ -72,11 +72,11 @@ public function getList(): array */ public function isEmptyElement(): bool { - if (empty($this->extensions)) { + if (empty($this->getList())) { return true; } - foreach ($this->extensions as $extension) { + foreach ($this->getList() as $extension) { if ($extension->isEmptyElement() === false) { return false; } @@ -96,9 +96,11 @@ public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - foreach ($this->extensions as $extension) { - if (!$extension->isEmptyElement()) { - $extension->toXML($e); + if (!$this->isEmptyElement()) { + foreach ($this->getList() as $extension) { + if (!$extension->isEmptyElement()) { + $extension->toXML($e); + } } } diff --git a/src/XML/IdentifierTrait.php b/src/XML/IdentifierTrait.php index 3a227a70c..51f6a90b6 100644 --- a/src/XML/IdentifierTrait.php +++ b/src/XML/IdentifierTrait.php @@ -5,12 +5,12 @@ namespace SimpleSAML\SAML2\XML; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\XML\saml\AbstractBaseID; use SimpleSAML\SAML2\XML\saml\EncryptedID; use SimpleSAML\SAML2\XML\saml\IdentifierInterface; use SimpleSAML\SAML2\XML\saml\NameID; -use SimpleSAML\XML\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; use function array_pop; @@ -56,7 +56,8 @@ protected function setIdentifier(?IdentifierInterface $identifier): void * * @param \DOMElement $xml * @return \SimpleSAML\SAML2\XML\saml\IdentifierInterface|null - * @throws \SimpleSAML\XML\Exception\TooManyElementsException if too many child-elements of a type are specified + * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException + * if too many child-elements of a type are specified */ protected static function getIdentifierFromXML(DOMElement $xml): ?IdentifierInterface { diff --git a/src/XML/SignableElementTrait.php b/src/XML/SignableElementTrait.php index 00fda83f0..0d52cac2c 100644 --- a/src/XML/SignableElementTrait.php +++ b/src/XML/SignableElementTrait.php @@ -5,9 +5,11 @@ namespace SimpleSAML\SAML2\XML; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Compat\ContainerSingleton; use SimpleSAML\XML\DOMDocumentFactory; +use SimpleSAML\XMLSchema\Type\AnyURIValue; +use SimpleSAML\XMLSchema\Type\Base64BinaryValue; use SimpleSAML\XMLSecurity\Alg\Signature\SignatureAlgorithmInterface; use SimpleSAML\XMLSecurity\Constants as C; use SimpleSAML\XMLSecurity\Exception\RuntimeException; @@ -105,22 +107,29 @@ protected function doSign(DOMElement $xml): DOMElement * 5.4.1: SAML assertions and protocols MUST use enveloped signatures when * signing assertions and protocol messages */ - new Transform(C::XMLDSIG_ENVELOPED), - new Transform($this->c14nAlg), + new Transform(AnyURIValue::fromString(C::XMLDSIG_ENVELOPED)), + new Transform(AnyURIValue::fromString($this->c14nAlg)), ]); $canonicalDocument = XML::processTransforms($transforms, $xml); $signedInfo = new SignedInfo( - new CanonicalizationMethod($this->c14nAlg), - new SignatureMethod($algorithm), + new CanonicalizationMethod(AnyURIValue::fromString($this->c14nAlg)), + new SignatureMethod(AnyURIValue::fromString($algorithm)), [$this->getReference($digest, $transforms, $xml, $canonicalDocument)], ); $signingData = $signedInfo->canonicalize($this->c14nAlg); $signedData = base64_encode($this->signer->sign($signingData)); - $this->signature = new Signature($signedInfo, new SignatureValue($signedData), $this->keyInfo); + $this->signature = new Signature( + $signedInfo, + new SignatureValue( + Base64BinaryValue::fromString($signedData), + ), + $this->keyInfo, + ); + return DOMDocumentFactory::fromString($canonicalDocument)->documentElement; } diff --git a/src/XML/SignedElementTrait.php b/src/XML/SignedElementTrait.php index dd8cdc045..ed80fbe3f 100644 --- a/src/XML/SignedElementTrait.php +++ b/src/XML/SignedElementTrait.php @@ -4,7 +4,7 @@ namespace SimpleSAML\SAML2\XML; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Compat\ContainerSingleton; use SimpleSAML\SAML2\Exception\ProtocolViolationException; use SimpleSAML\XMLSecurity\Exception\ReferenceValidationFailedException; @@ -39,9 +39,8 @@ protected function setSignature(Signature $signature): void $reference = array_pop($references); Assert::notNull($reference->getURI(), "URI attribute not found.", ReferenceValidationFailedException::class); - Assert::validURI($reference->getURI(), ReferenceValidationFailedException::class); Assert::startsWith( - $reference->getURI(), + $reference->getURI()->getValue(), '#', "Reference must contain a same-document reference to the ID-attribute of the root element.", ReferenceValidationFailedException::class, diff --git a/src/XML/StringElementTrait.php b/src/XML/StringElementTrait.php deleted file mode 100644 index 9d764b9dc..000000000 --- a/src/XML/StringElementTrait.php +++ /dev/null @@ -1,40 +0,0 @@ -setElements($elements); } @@ -47,9 +46,9 @@ public function __construct( /** * Collect the value of the algorithm-property * - * @return string + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue */ - public function getAlgorithm(): string + public function getAlgorithm(): SAMLAnyURIValue { return $this->algorithm; } @@ -61,9 +60,9 @@ public function getAlgorithm(): string * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the mandatory Algorithm-attribute is missing */ public static function fromXML(DOMElement $xml): static @@ -72,7 +71,7 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->namespaceURI, DigestMethod::NS, InvalidDOMElementException::class); return new static( - self::getAttribute($xml, 'Algorithm'), + self::getAttribute($xml, 'Algorithm', SAMLAnyURIValue::class), self::getChildElementsFromXML($xml), ); } @@ -87,7 +86,7 @@ public static function fromXML(DOMElement $xml): static public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - $e->setAttribute('Algorithm', $this->getAlgorithm()); + $e->setAttribute('Algorithm', $this->getAlgorithm()->getValue()); foreach ($this->getElements() as $element) { /** @var \SimpleSAML\XML\SerializableElementInterface $element */ diff --git a/src/XML/alg/SigningMethod.php b/src/XML/alg/SigningMethod.php index f454ac308..84fa126ca 100644 --- a/src/XML/alg/SigningMethod.php +++ b/src/XML/alg/SigningMethod.php @@ -5,15 +5,14 @@ namespace SimpleSAML\SAML2\XML\alg; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; -use SimpleSAML\XML\Exception\InvalidDOMElementException; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\XML\ExtendableElementTrait; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; -use SimpleSAML\XML\XsNamespace as NS; - -use function strval; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Type\PositiveIntegerValue; +use SimpleSAML\XMLSchema\XML\Constants\NS; /** * Class for handling the alg:SigningMethod element. @@ -34,21 +33,17 @@ final class SigningMethod extends AbstractAlgElement implements SchemaValidatabl /** * Create/parse an alg:SigningMethod element. * - * @param string $algorithm - * @param int|null $minKeySize - * @param int|null $maxKeySize + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $algorithm + * @param \SimpleSAML\XMLSchema\Type\PositiveIntegerValue|null $minKeySize + * @param \SimpleSAML\XMLSchema\Type\PositiveIntegerValue|null $maxKeySize * @param \SimpleSAML\XML\Chunk[] $elements */ public function __construct( - protected string $algorithm, - protected ?int $minKeySize = null, - protected ?int $maxKeySize = null, + protected SAMLAnyURIValue $algorithm, + protected ?PositiveIntegerValue $minKeySize = null, + protected ?PositiveIntegerValue $maxKeySize = null, array $elements = [], ) { - SAMLAssert::validURI($algorithm); - Assert::nullOrPositiveInteger($minKeySize); - Assert::nullOrPositiveInteger($maxKeySize); - $this->setElements($elements); } @@ -56,9 +51,9 @@ public function __construct( /** * Collect the value of the Algorithm-property * - * @return string + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue */ - public function getAlgorithm(): string + public function getAlgorithm(): SAMLAnyURIValue { return $this->algorithm; } @@ -67,9 +62,9 @@ public function getAlgorithm(): string /** * Collect the value of the MinKeySize-property * - * @return int|null + * @return \SimpleSAML\XMLSchema\Type\PositiveIntegerValue|null */ - public function getMinKeySize(): ?int + public function getMinKeySize(): ?PositiveIntegerValue { return $this->minKeySize; } @@ -78,9 +73,9 @@ public function getMinKeySize(): ?int /** * Collect the value of the MaxKeySize-property * - * @return int|null + * @return \SimpleSAML\XMLSchema\Type\PositiveIntegerValue|null */ - public function getMaxKeySize(): ?int + public function getMaxKeySize(): ?PositiveIntegerValue { return $this->maxKeySize; } @@ -92,9 +87,9 @@ public function getMaxKeySize(): ?int * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied argument is missing the Algorithm attribute */ public static function fromXML(DOMElement $xml): static @@ -103,9 +98,9 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->namespaceURI, SigningMethod::NS, InvalidDOMElementException::class); return new static( - self::getAttribute($xml, 'Algorithm'), - self::getOptionalIntegerAttribute($xml, 'MinKeySize', null), - self::getOptionalIntegerAttribute($xml, 'MaxKeySize', null), + self::getAttribute($xml, 'Algorithm', SAMLAnyURIValue::class), + self::getOptionalAttribute($xml, 'MinKeySize', PositiveIntegerValue::class, null), + self::getOptionalAttribute($xml, 'MaxKeySize', PositiveIntegerValue::class, null), self::getChildElementsFromXML($xml), ); } @@ -121,14 +116,14 @@ public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - $e->setAttribute('Algorithm', $this->getAlgorithm()); + $e->setAttribute('Algorithm', $this->getAlgorithm()->getValue()); if ($this->getMinKeySize() !== null) { - $e->setAttribute('MinKeySize', strval($this->getMinKeySize())); + $e->setAttribute('MinKeySize', $this->getMinKeySize()->getValue()); } if ($this->getMaxKeySize() !== null) { - $e->setAttribute('MaxKeySize', strval($this->getMaxKeySize())); + $e->setAttribute('MaxKeySize', $this->getMaxKeySize()->getValue()); } /** @var \SimpleSAML\XML\SerializableElementInterface $element */ diff --git a/src/XML/ecp/RelayState.php b/src/XML/ecp/RelayState.php index 0f0f518ee..7f04c5894 100644 --- a/src/XML/ecp/RelayState.php +++ b/src/XML/ecp/RelayState.php @@ -5,14 +5,16 @@ namespace SimpleSAML\SAML2\XML\ecp; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\StringElementTrait; -use SimpleSAML\SOAP\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingAttributeException; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\SOAP11\Constants as C; +use SimpleSAML\SOAP11\Type\MustUnderstandValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; /** * Class representing the ECP RelayState element. @@ -22,19 +24,11 @@ final class RelayState extends AbstractEcpElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use StringElementTrait; + use TypedTextContentTrait; - /** - * Create a ECP RelayState element. - * - * @param string $relayState - */ - public function __construct( - string $relayState, - ) { - $this->setContent($relayState); - } + /** @var string */ + public const TEXTCONTENT_TYPE = SAMLStringValue::class; /** @@ -43,9 +37,9 @@ public function __construct( * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing any of the mandatory attributes */ public static function fromXML(DOMElement $xml): static @@ -55,33 +49,28 @@ public static function fromXML(DOMElement $xml): static // Assert required attributes Assert::true( - $xml->hasAttributeNS(C::NS_SOAP_ENV_11, 'actor'), + $xml->hasAttributeNS(C::NS_SOAP_ENV, 'actor'), 'Missing env:actor attribute in .', MissingAttributeException::class, ); Assert::true( - $xml->hasAttributeNS(C::NS_SOAP_ENV_11, 'mustUnderstand'), + $xml->hasAttributeNS(C::NS_SOAP_ENV, 'mustUnderstand'), 'Missing env:mustUnderstand attribute in .', MissingAttributeException::class, ); - $mustUnderstand = $xml->getAttributeNS(C::NS_SOAP_ENV_11, 'mustUnderstand'); - Assert::same( - $mustUnderstand, - '1', - 'Invalid value of env:mustUnderstand attribute in .', - ProtocolViolationException::class, - ); + MustUnderstandValue::fromString($xml->getAttributeNS(C::NS_SOAP_ENV, 'mustUnderstand')); - $actor = $xml->getAttributeNS(C::NS_SOAP_ENV_11, 'actor'); Assert::same( - $actor, + $xml->getAttributeNS(C::NS_SOAP_ENV, 'actor'), C::SOAP_ACTOR_NEXT, 'Invalid value of env:actor attribute in .', ProtocolViolationException::class, ); - return new static($xml->textContent); + return new static( + SAMLStringValue::fromString($xml->textContent), + ); } @@ -94,9 +83,10 @@ public static function fromXML(DOMElement $xml): static public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - $e->setAttributeNS(C::NS_SOAP_ENV_11, 'env:mustUnderstand', '1'); - $e->setAttributeNS(C::NS_SOAP_ENV_11, 'env:actor', C::SOAP_ACTOR_NEXT); - $e->textContent = $this->getContent(); + + $e->setAttributeNS(C::NS_SOAP_ENV, 'SOAP-ENV:mustUnderstand', '1'); + $e->setAttributeNS(C::NS_SOAP_ENV, 'SOAP-ENV:actor', C::SOAP_ACTOR_NEXT); + $e->textContent = $this->getContent()->getValue(); return $e; } diff --git a/src/XML/ecp/Request.php b/src/XML/ecp/Request.php index f73566819..e43130243 100644 --- a/src/XML/ecp/Request.php +++ b/src/XML/ecp/Request.php @@ -5,16 +5,19 @@ namespace SimpleSAML\SAML2\XML\ecp; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\samlp\IDPList; -use SimpleSAML\SOAP\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingAttributeException; -use SimpleSAML\XML\Exception\TooManyElementsException; +use SimpleSAML\SOAP11\Constants as C; +use SimpleSAML\SOAP11\Type\MustUnderstandValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\BooleanValue; use function intval; use function strval; @@ -34,14 +37,14 @@ final class Request extends AbstractEcpElement implements SchemaValidatableEleme * * @param \SimpleSAML\SAML2\XML\saml\Issuer $issuer * @param \SimpleSAML\SAML2\XML\samlp\IDPList|null $idpList - * @param string|null $providerName - * @param bool|null $isPassive + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $providerName + * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $isPassive */ public function __construct( protected Issuer $issuer, protected ?IDPList $idpList = null, - protected ?string $providerName = null, - protected ?bool $isPassive = null, + protected ?SAMLStringValue $providerName = null, + protected ?BooleanValue $isPassive = null, ) { } @@ -49,9 +52,9 @@ public function __construct( /** * Collect the value of the isPassive-property * - * @return bool|null + * @return \SimpleSAML\XMLSchema\Type\BooleanValue|null */ - public function getIsPassive(): ?bool + public function getIsPassive(): ?BooleanValue { return $this->isPassive; } @@ -60,9 +63,9 @@ public function getIsPassive(): ?bool /** * Collect the value of the providerName-property * - * @return string|null + * @return \SimpleSAML\SAML2\Type\SAMLStringValue|null */ - public function getProviderName(): ?string + public function getProviderName(): ?SAMLStringValue { return $this->providerName; } @@ -96,9 +99,9 @@ public function getIDPList(): ?IDPList * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing any of the mandatory attributes */ public static function fromXML(DOMElement $xml): static @@ -108,27 +111,20 @@ public static function fromXML(DOMElement $xml): static // Assert required attributes Assert::true( - $xml->hasAttributeNS(C::NS_SOAP_ENV_11, 'actor'), + $xml->hasAttributeNS(C::NS_SOAP_ENV, 'actor'), 'Missing env:actor attribute in .', MissingAttributeException::class, ); Assert::true( - $xml->hasAttributeNS(C::NS_SOAP_ENV_11, 'mustUnderstand'), + $xml->hasAttributeNS(C::NS_SOAP_ENV, 'mustUnderstand'), 'Missing env:mustUnderstand attribute in .', MissingAttributeException::class, ); - $mustUnderstand = $xml->getAttributeNS(C::NS_SOAP_ENV_11, 'mustUnderstand'); - Assert::same( - $mustUnderstand, - '1', - 'Invalid value of env:mustUnderstand attribute in .', - ProtocolViolationException::class, - ); + MustUnderstandValue::fromString($xml->getAttributeNS(C::NS_SOAP_ENV, 'mustUnderstand')); - $actor = $xml->getAttributeNS(C::NS_SOAP_ENV_11, 'actor'); Assert::same( - $actor, + $xml->getAttributeNS(C::NS_SOAP_ENV, 'actor'), C::SOAP_ACTOR_NEXT, 'Invalid value of env:actor attribute in .', ProtocolViolationException::class, @@ -147,8 +143,8 @@ public static function fromXML(DOMElement $xml): static return new static( array_pop($issuer), array_pop($idpList), - self::getOptionalAttribute($xml, 'ProviderName', null), - self::getOptionalBooleanAttribute($xml, 'IsPassive', null), + self::getOptionalAttribute($xml, 'ProviderName', SAMLStringValue::class, null), + self::getOptionalAttribute($xml, 'IsPassive', BooleanValue::class, null), ); } @@ -162,15 +158,15 @@ public static function fromXML(DOMElement $xml): static public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - $e->setAttributeNS(C::NS_SOAP_ENV_11, 'env:mustUnderstand', '1'); - $e->setAttributeNS(C::NS_SOAP_ENV_11, 'env:actor', C::SOAP_ACTOR_NEXT); + $e->setAttributeNS(C::NS_SOAP_ENV, 'SOAP-ENV:mustUnderstand', '1'); + $e->setAttributeNS(C::NS_SOAP_ENV, 'SOAP-ENV:actor', C::SOAP_ACTOR_NEXT); if ($this->getProviderName() !== null) { - $e->setAttribute('ProviderName', $this->getProviderName()); + $e->setAttribute('ProviderName', $this->getProviderName()->getValue()); } if ($this->getIsPassive() !== null) { - $e->setAttribute('IsPassive', strval(intval($this->getIsPassive()))); + $e->setAttribute('IsPassive', strval(intval($this->getIsPassive()->toBoolean()))); } $this->getIssuer()->toXML($e); diff --git a/src/XML/ecp/RequestAuthenticated.php b/src/XML/ecp/RequestAuthenticated.php index 7e8cc682a..a066dc89a 100644 --- a/src/XML/ecp/RequestAuthenticated.php +++ b/src/XML/ecp/RequestAuthenticated.php @@ -5,16 +5,14 @@ namespace SimpleSAML\SAML2\XML\ecp; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SOAP\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingAttributeException; +use SimpleSAML\SOAP11\Constants as C; +use SimpleSAML\SOAP11\Type\MustUnderstandValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; - -use function boolval; -use function strval; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; /** * Class representing the ECP RequestAuthenticated element. @@ -29,10 +27,10 @@ final class RequestAuthenticated extends AbstractEcpElement implements SchemaVal /** * Create a ECP RequestAuthenticated element. * - * @param bool|null $mustUnderstand + * @param \SimpleSAML\SOAP11\Type\MustUnderstandValue|null $mustUnderstand */ public function __construct( - protected ?bool $mustUnderstand = false, + protected ?MustUnderstandValue $mustUnderstand, ) { } @@ -40,9 +38,9 @@ public function __construct( /** * Collect the value of the mustUnderstand-property * - * @return bool|null + * @return \SimpleSAML\SOAP11\Type\MustUnderstandValue|null */ - public function getMustUnderstand(): ?bool + public function getMustUnderstand(): ?MustUnderstandValue { return $this->mustUnderstand; } @@ -54,9 +52,9 @@ public function getMustUnderstand(): ?bool * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing any of the mandatory attributes */ public static function fromXML(DOMElement $xml): static @@ -66,29 +64,19 @@ public static function fromXML(DOMElement $xml): static // Assert required attributes Assert::true( - $xml->hasAttributeNS(C::NS_SOAP_ENV_11, 'actor'), + $xml->hasAttributeNS(C::NS_SOAP_ENV, 'actor'), 'Missing env:actor attribute in .', MissingAttributeException::class, ); $mustUnderstand = null; - if ($xml->hasAttributeNS(C::NS_SOAP_ENV_11, 'mustUnderstand')) { - $mustUnderstand = $xml->getAttributeNS(C::NS_SOAP_ENV_11, 'mustUnderstand'); - - Assert::nullOrOneOf( - $mustUnderstand, - ['0', '1'], - 'Invalid value of env:mustUnderstand attribute in .', - ProtocolViolationException::class, - ); - - $mustUnderstand = boolval($mustUnderstand); + if ($xml->hasAttributeNS(C::NS_SOAP_ENV, 'mustUnderstand')) { + $mustUnderstand = MustUnderstandValue::fromString($xml->getAttributeNS(C::NS_SOAP_ENV, 'mustUnderstand')); } - $actor = $xml->getAttributeNS(C::NS_SOAP_ENV_11, 'actor'); Assert::same( - $actor, - 'http://schemas.xmlsoap.org/soap/actor/next', + $xml->getAttributeNS(C::NS_SOAP_ENV, 'actor'), + C::SOAP_ACTOR_NEXT, 'Invalid value of env:actor attribute in .', ProtocolViolationException::class, ); @@ -108,10 +96,10 @@ public function toXML(?DOMElement $parent = null): DOMElement $e = $this->instantiateParentElement($parent); if ($this->getMustUnderstand() !== null) { - $e->setAttributeNS(C::NS_SOAP_ENV_11, 'env:mustUnderstand', strval(intval($this->getMustUnderstand()))); + $this->getMustUnderstand()->toAttribute()->toXML($e); } - $e->setAttributeNS(C::NS_SOAP_ENV_11, 'env:actor', C::SOAP_ACTOR_NEXT); + $e->setAttributeNS(C::NS_SOAP_ENV, 'SOAP-ENV:actor', C::SOAP_ACTOR_NEXT); return $e; } diff --git a/src/XML/ecp/Response.php b/src/XML/ecp/Response.php index 49f16d719..1e272697b 100644 --- a/src/XML/ecp/Response.php +++ b/src/XML/ecp/Response.php @@ -5,14 +5,15 @@ namespace SimpleSAML\SAML2\XML\ecp; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SOAP\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingAttributeException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SOAP11\Constants as C; +use SimpleSAML\SOAP11\Type\MustUnderstandValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; /** * Class representing the ECP Response element. @@ -27,21 +28,20 @@ final class Response extends AbstractEcpElement implements SchemaValidatableElem /** * Create a ECP Response element. * - * @param string $assertionConsumerServiceURL + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $assertionConsumerServiceURL */ public function __construct( - protected string $assertionConsumerServiceURL, + protected SAMLAnyURIValue $assertionConsumerServiceURL, ) { - SAMLAssert::validURI($assertionConsumerServiceURL); } /** * Collect the value of the AssertionConsumerServiceURL-property * - * @return string + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue */ - public function getAssertionConsumerServiceURL(): string + public function getAssertionConsumerServiceURL(): SAMLAnyURIValue { return $this->assertionConsumerServiceURL; } @@ -53,9 +53,9 @@ public function getAssertionConsumerServiceURL(): string * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing any of the mandatory attributes */ public static function fromXML(DOMElement $xml): static @@ -65,12 +65,12 @@ public static function fromXML(DOMElement $xml): static // Assert required attributes Assert::true( - $xml->hasAttributeNS(C::NS_SOAP_ENV_11, 'mustUnderstand'), + $xml->hasAttributeNS(C::NS_SOAP_ENV, 'mustUnderstand'), 'Missing env:mustUnderstand attribute in .', MissingAttributeException::class, ); Assert::true( - $xml->hasAttributeNS(C::NS_SOAP_ENV_11, 'actor'), + $xml->hasAttributeNS(C::NS_SOAP_ENV, 'actor'), 'Missing env:actor attribute in .', MissingAttributeException::class, ); @@ -80,23 +80,16 @@ public static function fromXML(DOMElement $xml): static MissingAttributeException::class, ); - $mustUnderstand = $xml->getAttributeNS(C::NS_SOAP_ENV_11, 'mustUnderstand'); - $actor = $xml->getAttributeNS(C::NS_SOAP_ENV_11, 'actor'); + MustUnderstandValue::fromString($xml->getAttributeNS(C::NS_SOAP_ENV, 'mustUnderstand')); Assert::same( - $mustUnderstand, - '1', - 'Invalid value of env:mustUnderstand attribute in .', - ProtocolViolationException::class, - ); - Assert::same( - $actor, - 'http://schemas.xmlsoap.org/soap/actor/next', + $xml->getAttributeNS(C::NS_SOAP_ENV, 'actor'), + C::SOAP_ACTOR_NEXT, 'Invalid value of env:actor attribute in .', ProtocolViolationException::class, ); - return new static(self::getAttribute($xml, 'AssertionConsumerServiceURL')); + return new static(self::getAttribute($xml, 'AssertionConsumerServiceURL', SAMLAnyURIValue::class)); } @@ -110,9 +103,9 @@ public function toXML(?DOMElement $parent = null): DOMElement { $response = $this->instantiateParentElement($parent); - $response->setAttributeNS(C::NS_SOAP_ENV_11, 'env:mustUnderstand', '1'); - $response->setAttributeNS(C::NS_SOAP_ENV_11, 'env:actor', 'http://schemas.xmlsoap.org/soap/actor/next'); - $response->setAttribute('AssertionConsumerServiceURL', $this->getAssertionConsumerServiceURL()); + $response->setAttributeNS(C::NS_SOAP_ENV, 'SOAP-ENV:mustUnderstand', '1'); + $response->setAttributeNS(C::NS_SOAP_ENV, 'SOAP-ENV:actor', C::SOAP_ACTOR_NEXT); + $response->setAttribute('AssertionConsumerServiceURL', $this->getAssertionConsumerServiceURL()->getValue()); return $response; } diff --git a/src/XML/ecp/SubjectConfirmation.php b/src/XML/ecp/SubjectConfirmation.php index 5d1ae6e33..32ab09f9f 100644 --- a/src/XML/ecp/SubjectConfirmation.php +++ b/src/XML/ecp/SubjectConfirmation.php @@ -5,16 +5,17 @@ namespace SimpleSAML\SAML2\XML\ecp; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\saml\SubjectConfirmationData; -use SimpleSAML\SOAP\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingAttributeException; -use SimpleSAML\XML\Exception\TooManyElementsException; +use SimpleSAML\SOAP11\Constants as C; +use SimpleSAML\SOAP11\Type\MustUnderstandValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; /** * Class representing the ECP SubjectConfirmation element. @@ -29,23 +30,22 @@ final class SubjectConfirmation extends AbstractEcpElement implements SchemaVali /** * Create a ECP SubjectConfirmation element. * - * @param string $method + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $method * @param \SimpleSAML\SAML2\XML\saml\SubjectConfirmationData|null $subjectConfirmationData */ public function __construct( - protected string $method, + protected SAMLAnyURIValue $method, protected ?SubjectConfirmationData $subjectConfirmationData = null, ) { - SAMLAssert::validURI($method); } /** * Collect the value of the method-property * - * @return string + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue */ - public function getMethod(): string + public function getMethod(): SAMLAnyURIValue { return $this->method; } @@ -68,9 +68,9 @@ public function getSubjectConfirmationData(): ?SubjectConfirmationData * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing any of the mandatory attributes */ public static function fromXML(DOMElement $xml): static @@ -80,27 +80,25 @@ public static function fromXML(DOMElement $xml): static // Assert required attributes Assert::true( - $xml->hasAttributeNS(C::NS_SOAP_ENV_11, 'actor'), + $xml->hasAttributeNS(C::NS_SOAP_ENV, 'actor'), 'Missing env:actor attribute in .', MissingAttributeException::class, ); Assert::true( - $xml->hasAttributeNS(C::NS_SOAP_ENV_11, 'mustUnderstand'), + $xml->hasAttributeNS(C::NS_SOAP_ENV, 'mustUnderstand'), 'Missing env:mustUnderstand attribute in .', MissingAttributeException::class, ); - $mustUnderstand = $xml->getAttributeNS(C::NS_SOAP_ENV_11, 'mustUnderstand'); - Assert::same( - $mustUnderstand, - '1', + $mustUnderstand = MustUnderstandValue::fromString($xml->getAttributeNS(C::NS_SOAP_ENV, 'mustUnderstand')); + Assert::true( + $mustUnderstand->toBoolean(), 'Invalid value of env:mustUnderstand attribute in .', ProtocolViolationException::class, ); - $actor = $xml->getAttributeNS(C::NS_SOAP_ENV_11, 'actor'); Assert::same( - $actor, + $xml->getAttributeNS(C::NS_SOAP_ENV, 'actor'), C::SOAP_ACTOR_NEXT, 'Invalid value of env:actor attribute in .', ProtocolViolationException::class, @@ -115,7 +113,7 @@ public static function fromXML(DOMElement $xml): static ); return new static( - self::getAttribute($xml, 'Method'), + self::getAttribute($xml, 'Method', SAMLAnyURIValue::class), array_pop($subjectConfirmationData), ); } @@ -130,9 +128,9 @@ public static function fromXML(DOMElement $xml): static public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - $e->setAttributeNS(C::NS_SOAP_ENV_11, 'env:mustUnderstand', '1'); - $e->setAttributeNS(C::NS_SOAP_ENV_11, 'env:actor', C::SOAP_ACTOR_NEXT); - $e->setAttribute('Method', $this->getMethod()); + $e->setAttributeNS(C::NS_SOAP_ENV, 'SOAP-ENV:mustUnderstand', '1'); + $e->setAttributeNS(C::NS_SOAP_ENV, 'SOAP-ENV:actor', C::SOAP_ACTOR_NEXT); + $e->setAttribute('Method', $this->getMethod()->getValue()); $this->getSubjectConfirmationData()?->toXML($e); diff --git a/src/XML/emd/RepublishRequest.php b/src/XML/emd/RepublishRequest.php index 365b01358..10cfbf8dd 100644 --- a/src/XML/emd/RepublishRequest.php +++ b/src/XML/emd/RepublishRequest.php @@ -5,13 +5,14 @@ namespace SimpleSAML\SAML2\XML\emd; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ArrayValidationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\XML\ArrayizableElementInterface; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\SchemaViolationException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\SchemaViolationException; use function array_pop; @@ -53,9 +54,9 @@ public function getRepublishTarget(): RepublishTarget * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes */ public static function fromXML(DOMElement $xml): static @@ -102,7 +103,11 @@ public static function fromArray(array $data): static Assert::keyExists($data, 'RepublishTarget', ArrayValidationException::class); Assert::string($data['RepublishTarget'], ArrayValidationException::class); - return new static(new RepublishTarget($data['RepublishTarget'])); + return new static( + new RepublishTarget( + SAMLAnyURIValue::fromString($data['RepublishTarget']), + ), + ); } @@ -113,6 +118,6 @@ public static function fromArray(array $data): static */ public function toArray(): array { - return ['RepublishTarget' => $this->getRepublishTarget()->getContent()]; + return ['RepublishTarget' => $this->getRepublishTarget()->getContent()->getValue()]; } } diff --git a/src/XML/emd/RepublishTarget.php b/src/XML/emd/RepublishTarget.php index fb40885c2..2e1483d8b 100644 --- a/src/XML/emd/RepublishTarget.php +++ b/src/XML/emd/RepublishTarget.php @@ -4,8 +4,9 @@ namespace SimpleSAML\SAML2\XML\emd; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\XML\URIElementTrait; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class implementing RepublishTarget. @@ -14,30 +15,20 @@ */ final class RepublishTarget extends AbstractEmdElement { - use URIElementTrait { - URIElementTrait::validateContent as baseValidateContent; - } + use TypedTextContentTrait; - /** - * @param string $content - */ - public function __construct(string $content) - { - $this->setContent($content); - } + /** @var string */ + public const TEXTCONTENT_TYPE = SAMLAnyURIValue::class; /** - * Validate the content of the element. - * - * @param string $content The value to go in the XML textContent - * @throws \Exception on failure - * @return void + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $content */ - protected function validateContent(string $content): void - { - $this->baseValidateContent($content); - Assert::same($content, 'http://edugain.org/'); + public function __construct( + SAMLAnyURIValue $content, + ) { + $this->setContent($content); + Assert::same($content->getValue(), 'http://edugain.org/'); } } diff --git a/src/XML/idpdisc/DiscoveryResponse.php b/src/XML/idpdisc/DiscoveryResponse.php index f23e0bd1c..75dc661d5 100644 --- a/src/XML/idpdisc/DiscoveryResponse.php +++ b/src/XML/idpdisc/DiscoveryResponse.php @@ -4,12 +4,15 @@ namespace SimpleSAML\SAML2\XML\idpdisc; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\md\AbstractIndexedEndpointType; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Type\BooleanValue; +use SimpleSAML\XMLSchema\Type\UnsignedShortValue; /** * Abstract class to be implemented by all the classes in this namespace @@ -38,30 +41,30 @@ final class DiscoveryResponse extends AbstractIndexedEndpointType implements Sch * * This is an endpoint with one restriction: it cannot contain a ResponseLocation. * - * @param int $index - * @param string $binding - * @param string $location - * @param bool|null $isDefault - * @param string|null $unused + * @param \SimpleSAML\XMLSchema\Type\UnsignedShortValue $index + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $binding + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $location + * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $isDefault + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $responseLocation * @param array<\SimpleSAML\XML\SerializableElementInterface> $children * @param array<\SimpleSAML\XML\Attribute> $attributes * * @throws \SimpleSAML\Assert\AssertionFailedException */ public function __construct( - int $index, - string $binding, - string $location, - ?bool $isDefault = null, - ?string $unused = null, + UnsignedShortValue $index, + SAMLAnyURIValue $binding, + SAMLAnyURIValue $location, + ?BooleanValue $isDefault = null, + ?SAMLAnyURIValue $responseLocation = null, // unused array $children = [], array $attributes = [], ) { - Assert::same($binding, C::BINDING_IDPDISC, ProtocolViolationException::class); + Assert::same($binding->getValue(), C::BINDING_IDPDISC, ProtocolViolationException::class); Assert::null( - $unused, + $responseLocation, 'The \'ResponseLocation\' attribute must be omitted for idpdisc:DiscoveryResponse.', ); - parent::__construct($index, C::BINDING_IDPDISC, $location, $isDefault, null, $children, $attributes); + parent::__construct($index, $binding, $location, $isDefault, null, $children, $attributes); } } diff --git a/src/XML/init/RequestInitiator.php b/src/XML/init/RequestInitiator.php index 5f33ebec8..005414b8e 100644 --- a/src/XML/init/RequestInitiator.php +++ b/src/XML/init/RequestInitiator.php @@ -5,12 +5,13 @@ namespace SimpleSAML\SAML2\XML\init; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\md\AbstractEndpointType; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; /** * Class for handling the init:RequestInitiator element. @@ -37,20 +38,26 @@ final class RequestInitiator extends AbstractEndpointType implements SchemaValid /** * EndpointType constructor. * - * @param string $location - * @param string|null $responseLocation - * @param array $children + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $location + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $responseLocation + * @param array<\SimpleSAML\XML\SerializableElementInterface> $children * @param array<\SimpleSAML\XML\Attribute> $attributes * * @throws \InvalidArgumentException */ public function __construct( - string $location, - ?string $responseLocation = null, + SAMLAnyURIValue $location, + ?SAMLAnyURIValue $responseLocation = null, array $children = [], array $attributes = [], ) { - parent::__construct(self::NS, $location, $responseLocation, $children, $attributes); + parent::__construct( + SAMLAnyURIValue::fromString(self::NS), + $location, + $responseLocation, + $children, + $attributes, + ); } @@ -81,8 +88,8 @@ public static function fromXML(DOMElement $xml): static ); return new static( - self::getAttribute($xml, 'Location'), - self::getOptionalAttribute($xml, 'ResponseLocation', null), + self::getAttribute($xml, 'Location', SAMLAnyURIValue::class), + self::getOptionalAttribute($xml, 'ResponseLocation', SAMLAnyURIValue::class, null), self::getChildElementsFromXML($xml), self::getAttributesNSFromXML($xml), ); diff --git a/src/XML/md/AbstractEndpointType.php b/src/XML/md/AbstractEndpointType.php index ed3c6e7f9..25fe5d477 100644 --- a/src/XML/md/AbstractEndpointType.php +++ b/src/XML/md/AbstractEndpointType.php @@ -5,16 +5,16 @@ namespace SimpleSAML\SAML2\XML\md; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ArrayValidationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\XML\ArrayizableElementInterface; use SimpleSAML\XML\Attribute as XMLAttribute; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\ExtendableAttributesTrait; use SimpleSAML\XML\ExtendableElementTrait; use SimpleSAML\XML\SerializableElementInterface; -use SimpleSAML\XML\XsNamespace as NS; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\XML\Constants\NS; use function array_change_key_case; use function array_key_exists; @@ -52,25 +52,21 @@ abstract class AbstractEndpointType extends AbstractMdElement implements Arrayiz /** * EndpointType constructor. * - * @param string $binding - * @param string $location - * @param string|null $responseLocation + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $binding + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $location + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $responseLocation * @param \SimpleSAML\XML\ElementInterface[] $children * @param array<\SimpleSAML\XML\Attribute> $attributes * * @throws \SimpleSAML\Assert\AssertionFailedException */ public function __construct( - protected string $binding, - protected string $location, - protected ?string $responseLocation = null, + protected SAMLAnyURIValue $binding, + protected SAMLAnyURIValue $location, + protected ?SAMLAnyURIValue $responseLocation = null, array $children = [], array $attributes = [], ) { - SAMLAssert::validURI($binding); - SAMLAssert::validURI($location); - SAMLAssert::nullOrValidURI($responseLocation); - $this->setElements($children); $this->setAttributesNS($attributes); } @@ -79,9 +75,9 @@ public function __construct( /** * Collect the value of the Binding property. * - * @return string + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue */ - public function getBinding(): string + public function getBinding(): SAMLAnyURIValue { return $this->binding; } @@ -90,9 +86,9 @@ public function getBinding(): string /** * Collect the value of the Location property. * - * @return string + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue */ - public function getLocation(): string + public function getLocation(): SAMLAnyURIValue { return $this->location; } @@ -101,9 +97,9 @@ public function getLocation(): string /** * Collect the value of the ResponseLocation property. * - * @return string|null + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null */ - public function getResponseLocation(): ?string + public function getResponseLocation(): ?SAMLAnyURIValue { return $this->responseLocation; } @@ -117,9 +113,9 @@ public function getResponseLocation(): ?string * @param \DOMElement $xml The XML element we should load. * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing any of the mandatory attributes */ public static function fromXML(DOMElement $xml): static @@ -133,9 +129,9 @@ public static function fromXML(DOMElement $xml): static ); return new static( - self::getAttribute($xml, 'Binding'), - self::getAttribute($xml, 'Location'), - self::getOptionalAttribute($xml, 'ResponseLocation', null), + self::getAttribute($xml, 'Binding', SAMLAnyURIValue::class), + self::getAttribute($xml, 'Location', SAMLAnyURIValue::class), + self::getOptionalAttribute($xml, 'ResponseLocation', SAMLAnyURIValue::class, null), self::getChildElementsFromXML($xml), self::getAttributesNSFromXML($xml), ); @@ -152,11 +148,11 @@ public function toXML(?DOMElement $parent = null): DOMElement { $e = parent::instantiateParentElement($parent); - $e->setAttribute('Binding', $this->getBinding()); - $e->setAttribute('Location', $this->getLocation()); + $e->setAttribute('Binding', $this->getBinding()->getValue()); + $e->setAttribute('Location', $this->getLocation()->getValue()); if ($this->getResponseLocation() !== null) { - $e->setAttribute('ResponseLocation', $this->getResponseLocation()); + $e->setAttribute('ResponseLocation', $this->getResponseLocation()->getValue()); } foreach ($this->getAttributesNS() as $attr) { @@ -185,9 +181,9 @@ public static function fromArray(array $data): static $data = self::processArrayContents($data); return new static( - $data['Binding'], - $data['Location'], - $data['ResponseLocation'] ?? null, + SAMLAnyURIValue::fromString($data['Binding']), + SAMLAnyURIValue::fromString($data['Location']), + $data['ResponseLocation'] !== null ? SAMLAnyURIValue::fromString($data['ResponseLocation']) : null, $data['children'] ?? [], $data['attributes'] ?? [], ); @@ -260,9 +256,9 @@ private static function processArrayContents(array $data): array public function toArray(): array { $data = [ - 'Binding' => $this->getBinding(), - 'Location' => $this->getLocation(), - 'ResponseLocation' => $this->getResponseLocation(), + 'Binding' => $this->getBinding()->getValue(), + 'Location' => $this->getLocation()->getValue(), + 'ResponseLocation' => $this->getResponseLocation()?->getValue(), 'children' => $this->getElements(), ]; diff --git a/src/XML/md/AbstractIndexedEndpointType.php b/src/XML/md/AbstractIndexedEndpointType.php index 6a66a6ada..8a55c2b88 100644 --- a/src/XML/md/AbstractIndexedEndpointType.php +++ b/src/XML/md/AbstractIndexedEndpointType.php @@ -5,18 +5,19 @@ namespace SimpleSAML\SAML2\XML\md; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ArrayValidationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\XML\ArrayizableElementInterface; use SimpleSAML\XML\Attribute as XMLAttribute; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\SerializableElementInterface; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Type\BooleanValue; +use SimpleSAML\XMLSchema\Type\UnsignedShortValue; use function array_filter; use function array_key_exists; use function array_keys; -use function is_bool; -use function strval; /** * Class representing a SAML2 IndexedEndpointType. @@ -36,20 +37,20 @@ abstract class AbstractIndexedEndpointType extends AbstractEndpointType implemen * static methods to get its properties from a given \DOMElement for your convenience. Look at the implementation * of fromXML() to know how to use them. * - * @param int $index - * @param string $binding - * @param string $location - * @param bool|null $isDefault - * @param string|null $responseLocation + * @param \SimpleSAML\XMLSchema\Type\UnsignedShortValue $index + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $binding + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $location + * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $isDefault + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $responseLocation * @param array $children * @param list<\SimpleSAML\XML\Attribute> $attributes */ public function __construct( - int $index, - string $binding, - string $location, - ?bool $isDefault = null, - ?string $responseLocation = null, + UnsignedShortValue $index, + SAMLAnyURIValue $binding, + SAMLAnyURIValue $location, + ?BooleanValue $isDefault = null, + ?SAMLAnyURIValue $responseLocation = null, array $children = [], array $attributes = [], ) { @@ -66,9 +67,9 @@ public function __construct( * @param \DOMElement $xml The XML element we should load. * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing any of the mandatory attributes */ public static function fromXML(DOMElement $xml): static @@ -82,11 +83,11 @@ public static function fromXML(DOMElement $xml): static ); return new static( - self::getIntegerAttribute($xml, 'index'), - self::getAttribute($xml, 'Binding'), - self::getAttribute($xml, 'Location'), - self::getOptionalBooleanAttribute($xml, 'isDefault', null), - self::getOptionalAttribute($xml, 'ResponseLocation', null), + self::getAttribute($xml, 'index', UnsignedShortValue::class), + self::getAttribute($xml, 'Binding', SAMLAnyURIValue::class), + self::getAttribute($xml, 'Location', SAMLAnyURIValue::class), + self::getOptionalAttribute($xml, 'isDefault', BooleanValue::class, null), + self::getOptionalAttribute($xml, 'ResponseLocation', SAMLAnyURIValue::class, null), self::getChildElementsFromXML($xml), self::getAttributesNSFromXML($xml), ); @@ -102,17 +103,17 @@ public static function fromXML(DOMElement $xml): static public function toXML(?DOMElement $parent = null): DOMElement { $e = parent::instantiateParentElement($parent); + $e->setAttribute('Binding', $this->getBinding()->getValue()); + $e->setAttribute('Location', $this->getLocation()->getValue()); - $e->setAttribute('Binding', $this->getBinding()); - $e->setAttribute('Location', $this->getLocation()); if ($this->getResponseLocation() !== null) { - $e->setAttribute('ResponseLocation', $this->getResponseLocation()); + $e->setAttribute('ResponseLocation', $this->getResponseLocation()->getValue()); } - $e->setAttribute('index', strval($this->getIndex())); + $e->setAttribute('index', $this->getIndex()->getValue()); - if (is_bool($this->getIsDefault())) { - $e->setAttribute('isDefault', $this->getIsDefault() ? 'true' : 'false'); + if ($this->getIsDefault() !== null) { + $e->setAttribute('isDefault', $this->getIsDefault()->getValue()); } foreach ($this->getAttributesNS() as $attr) { @@ -141,11 +142,11 @@ public static function fromArray(array $data): static $data = self::processArrayContents($data); return new static( - $data['index'], - $data['Binding'], - $data['Location'], - $data['isDefault'] ?? null, - $data['ResponseLocation'] ?? null, + UnsignedShortValue::fromInteger($data['index']), + SAMLAnyURIValue::fromString($data['Binding']), + SAMLAnyURIValue::fromString($data['Location']), + $data['isDefault'] !== null ? BooleanValue::fromBoolean($data['isDefault']) : null, + ($data['ResponseLocation'] ?? null) ? SAMLAnyURIValue::fromString($data['ResponseLocation']) : null, $data['children'] ?? [], $data['attributes'] ?? [], ); @@ -226,8 +227,8 @@ private static function processArrayContents(array $data): array public function toArray(): array { $data = parent::toArray(); - $data['index'] = $this->getIndex(); - $data['isDefault'] = $this->getIsDefault(); + $data['index'] = $this->getIndex()->toInteger(); + $data['isDefault'] = $this->getIsDefault()?->toBoolean(); return array_filter($data); } diff --git a/src/XML/md/AbstractLocalizedName.php b/src/XML/md/AbstractLocalizedName.php index 91cad4395..ae6aed9f5 100644 --- a/src/XML/md/AbstractLocalizedName.php +++ b/src/XML/md/AbstractLocalizedName.php @@ -5,14 +5,15 @@ namespace SimpleSAML\SAML2\XML\md; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ArrayValidationException; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\StringElementTrait; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\XML\ArrayizableElementInterface; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingAttributeException; +use SimpleSAML\XML\TypedTextContentTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Type\LanguageValue; use function array_key_first; @@ -23,31 +24,33 @@ */ abstract class AbstractLocalizedName extends AbstractMdElement implements ArrayizableElementInterface { - use StringElementTrait; + use TypedTextContentTrait; + + + /** @var string */ + public const TEXTCONTENT_TYPE = SAMLStringValue::class; /** * LocalizedNameType constructor. * - * @param string $language The language this string is localized in. - * @param string $value The localized string. + * @param \SimpleSAML\XMLSchema\Type\LanguageValue $language The language this string is localized in. + * @param \SimpleSAML\SAML2\Type\SAMLStringValue $content The localized string. */ - final public function __construct( - protected string $language, - string $value, + public function __construct( + protected LanguageValue $language, + SAMLStringValue $content, ) { - Assert::notWhitespaceOnly($language, ProtocolViolationException::class); - - $this->setContent($value); + $this->setContent($content); } /** * Get the language this string is localized in. * - * @return string + * @return \SimpleSAML\XMLSchema\Type\LanguageValue */ - public function getLanguage(): string + public function getLanguage(): LanguageValue { return $this->language; } @@ -59,7 +62,7 @@ public function getLanguage(): string * @param \DOMElement $xml * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -72,7 +75,10 @@ public static function fromXML(DOMElement $xml): static MissingAttributeException::class, ); - return new static($xml->getAttributeNS(C::NS_XML, 'lang'), $xml->textContent); + return new static( + LanguageValue::fromString($xml->getAttributeNS(C::NS_XML, 'lang')), + SAMLStringValue::fromString($xml->textContent), + ); } @@ -83,8 +89,8 @@ public static function fromXML(DOMElement $xml): static final public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - $e->setAttributeNS(C::NS_XML, 'xml:lang', $this->getLanguage()); - $e->textContent = $this->getContent(); + $e->setAttributeNS(C::NS_XML, 'xml:lang', $this->getLanguage()->getValue()); + $e->textContent = $this->getContent()->getValue(); return $e; } @@ -100,11 +106,8 @@ public static function fromArray(array $data): static { Assert::count($data, 1, ArrayValidationException::class); - $lang = array_key_first($data); - Assert::stringNotEmpty($lang, ArrayValidationException::class); - - $value = $data[$lang]; - Assert::stringNotEmpty($value, ArrayValidationException::class); + $lang = LanguageValue::fromString(array_key_first($data)); + $value = SAMLStringValue::fromString($data[$lang->getValue()]); return new static($lang, $value); } @@ -117,6 +120,6 @@ public static function fromArray(array $data): static */ public function toArray(): array { - return [$this->language => $this->getContent()]; + return [$this->getLanguage()->getValue() => $this->getContent()->getValue()]; } } diff --git a/src/XML/md/AbstractLocalizedURI.php b/src/XML/md/AbstractLocalizedURI.php index 826e04782..88331a5dc 100644 --- a/src/XML/md/AbstractLocalizedURI.php +++ b/src/XML/md/AbstractLocalizedURI.php @@ -4,8 +4,16 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use DOMElement; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Type\LanguageValue; + +use function array_key_first; /** * Abstract class implementing LocalizedURIType. @@ -14,64 +22,49 @@ */ abstract class AbstractLocalizedURI extends AbstractLocalizedName { - /** - * Set the content of the element. - * - * @param string $content The value to go in the XML textContent - */ - protected function setContent(string $content): void - { - $this->validateContent($content); - $this->content = $content; - } + /** @var string */ + public const TEXTCONTENT_TYPE = SAMLAnyURIValue::class; /** - * Get the content of the element. + * LocalizedNameType constructor. * - * @return string + * @param \SimpleSAML\XMLSchema\Type\LanguageValue $language The language this string is localized in. + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $content The localized string. */ - public function getContent(): string - { - return $this->sanitizeContent($this->getRawContent()); - } - + final public function __construct( + protected LanguageValue $language, + SAMLAnyURIValue $content, + ) { + $content = SAMLStringValue::fromString($content->getValue()); - /** - * Get the raw and unsanitized content of the element. - * - * @return string - */ - public function getRawContent(): string - { - return $this->content; + parent::__construct($language, $content); } /** - * Sanitize the content of the element. + * Create an instance of this object from its XML representation. * - * @param string $content The unsanitized textContent - * @throws \Exception on failure - * @return string - */ - protected function sanitizeContent(string $content): string - { - // We've seen metadata in the wild that had stray whitespace around URIs, causing assertions to fail - return trim($content); - } - - - /** - * Validate the content of the element. + * @param \DOMElement $xml + * @return static * - * @param string $content The value to go in the XML textContent - * @throws \Exception on failure - * @return void + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException + * if the qualified name of the supplied element is wrong */ - protected function validateContent(string $content): void + public static function fromXML(DOMElement $xml): static { - SAMLAssert::validURI($this->sanitizeContent($content)); + Assert::same($xml->localName, static::getLocalName(), InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + Assert::true( + $xml->hasAttributeNS(C::NS_XML, 'lang'), + 'Missing xml:lang from ' . static::getLocalName(), + MissingAttributeException::class, + ); + + return new static( + LanguageValue::fromString($xml->getAttributeNS(C::NS_XML, 'lang')), + SAMLAnyURIValue::fromString($xml->textContent), + ); } @@ -85,12 +78,10 @@ public static function fromArray(array $data): static { Assert::count($data, 1); - $lang = array_key_first($data); - Assert::stringNotEmpty($lang); - - $value = $data[$lang]; - Assert::stringNotEmpty($value); - SAMLAssert::validURI($value); + $lang = LanguageValue::fromString(array_key_first($data)); + $value = SAMLAnyURIValue::fromString( + $data[$lang->getValue()], + ); return new static($lang, $value); } diff --git a/src/XML/md/AbstractMetadataDocument.php b/src/XML/md/AbstractMetadataDocument.php index 845e91090..5beadee15 100644 --- a/src/XML/md/AbstractMetadataDocument.php +++ b/src/XML/md/AbstractMetadataDocument.php @@ -4,12 +4,18 @@ namespace SimpleSAML\SAML2\XML\md; -use DateTimeImmutable; use DOMElement; use SimpleSAML\SAML2\Assert\Assert; -use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\SAML2\XML\ExtendableElementTrait; -use SimpleSAML\XML\Exception\SchemaViolationException; +use SimpleSAML\SAML2\XML\mdrpi\PublicationInfo; +use SimpleSAML\SAML2\XML\mdrpi\PublicationPath; +use SimpleSAML\SAML2\XML\mdrpi\RegistrationInfo; +use SimpleSAML\SAML2\XML\mdui\DiscoHints; +use SimpleSAML\SAML2\XML\mdui\UIInfo; +use SimpleSAML\XMLSchema\Type\DurationValue; +use SimpleSAML\XMLSchema\Type\IDValue; /** * Class to represent a metadata document @@ -24,20 +30,63 @@ abstract class AbstractMetadataDocument extends AbstractSignedMdElement /** * Generic constructor for SAML metadata documents. * - * @param string|null $id The ID for this document. Defaults to null. - * @param \DateTimeImmutable|null $validUntil Unix time of validity for this document. Defaults to null. - * @param string|null $cacheDuration Maximum time this document can be cached. Defaults to null. + * @param \SimpleSAML\XMLSchema\Type\IDValue|null $id The ID for this document. Defaults to null. + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil Unix time of validity for this document. + * Defaults to null. + * @param \SimpleSAML\XMLSchema\Type\DurationValue|null $cacheDuration Maximum time this document can be cached. + * Defaults to null. * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions An array of extensions. Defaults to null. */ public function __construct( - protected ?string $id = null, - protected ?DateTimeImmutable $validUntil = null, - protected ?string $cacheDuration = null, + protected ?IDValue $id = null, + protected ?SAMLDateTimeValue $validUntil = null, + protected ?DurationValue $cacheDuration = null, ?Extensions $extensions = null, ) { - Assert::nullOrValidNCName($id, SchemaViolationException::class); - Assert::nullOrSame($validUntil?->getTimeZone()->getName(), 'Z'); - Assert::nullOrValidDuration($cacheDuration, SchemaViolationException::class); + if ($extensions !== null) { + $exts = $extensions->getList(); + + /** + * MDUI 2.1: this element MUST NOT appear more than once within a given element. + */ + $uiInfo = array_values(array_filter($exts, function ($ext) { + return $ext instanceof UIInfo; + })); + Assert::maxCount($uiInfo, 1, ProtocolViolationException::class); + + /** + * MDUI 2.2: this element MUST NOT appear more than once within a given element. + */ + $discoHints = array_values(array_filter($exts, function ($ext) { + return $ext instanceof DiscoHints; + })); + Assert::maxCount($discoHints, 1, ProtocolViolationException::class); + + /** + * MDRPI 2.1: this element MUST NOT appear more than once within a given element. + */ + $regInfo = array_values(array_filter($exts, function ($ext) { + return $ext instanceof RegistrationInfo; + })); + Assert::maxCount($regInfo, 1, ProtocolViolationException::class); + + /** + * MDRPI 2.2: this element MUST NOT appear more than once within a given element. + */ + $pubInfo = array_values(array_filter($exts, function ($ext) { + return $ext instanceof PublicationInfo; + })); + Assert::maxCount($regInfo, 1, ProtocolViolationException::class); + + /** + * MDRPI 2.3: The element MUST NOT appear more than once within the + * element of a given or element. + */ + $pubPath = array_values(array_filter($exts, function ($ext) { + return $ext instanceof PublicationPath; + })); + Assert::maxCount($pubPath, 1, ProtocolViolationException::class); + } $this->setExtensions($extensions); } @@ -46,9 +95,9 @@ public function __construct( /** * Collect the value of the id property. * - * @return string|null + * @return \SimpleSAML\XMLSchema\Type\IDValue|null */ - public function getId(): ?string + public function getId(): ?IDValue { return $this->id; } @@ -57,9 +106,9 @@ public function getId(): ?string /** * Collect the value of the validUntil property. * - * @return \DateTimeImmutable|null + * @return \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null */ - public function getValidUntil(): ?DateTimeImmutable + public function getValidUntil(): ?SAMLDateTimeValue { return $this->validUntil; } @@ -68,9 +117,9 @@ public function getValidUntil(): ?DateTimeImmutable /** * Collect the value of the cacheDuration property. * - * @return string|null + * @return \SimpleSAML\XMLSchema\Type\DurationValue|null */ - public function getCacheDuration(): ?string + public function getCacheDuration(): ?DurationValue { return $this->cacheDuration; } @@ -95,15 +144,15 @@ public function toUnsignedXML(?DOMElement $parent = null): DOMElement $e = $this->instantiateParentElement($parent); if ($this->getId() !== null) { - $e->setAttribute('ID', $this->getId()); + $e->setAttribute('ID', $this->getId()->getValue()); } if ($this->getValidUntil() !== null) { - $e->setAttribute('validUntil', $this->getValidUntil()->format(C::DATETIME_FORMAT)); + $e->setAttribute('validUntil', $this->getValidUntil()->getValue()); } if ($this->getCacheDuration() !== null) { - $e->setAttribute('cacheDuration', $this->getCacheDuration()); + $e->setAttribute('cacheDuration', $this->getCacheDuration()->getValue()); } $extensions = $this->getExtensions(); diff --git a/src/XML/md/AbstractRoleDescriptor.php b/src/XML/md/AbstractRoleDescriptor.php index cbd7c6fa5..3d2975d59 100644 --- a/src/XML/md/AbstractRoleDescriptor.php +++ b/src/XML/md/AbstractRoleDescriptor.php @@ -4,24 +4,27 @@ namespace SimpleSAML\SAML2\XML\md; -use DateTimeImmutable; use DOMElement; use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\AnyURIListValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\XML\ExtensionPointInterface; use SimpleSAML\SAML2\XML\ExtensionPointTrait; -use SimpleSAML\XML\Attribute as XMLAttribute; use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\SchemaViolationException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Constants as C_XSI; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\SchemaViolationException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\DurationValue; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\QNameValue; use function array_pop; -use function count; -use function implode; /** * Class representing a SAML2 RoleDescriptor element. @@ -43,13 +46,17 @@ abstract class AbstractRoleDescriptor extends AbstractRoleDescriptorType impleme /** * Initialize a md:RoleDescriptor from scratch. * - * @param string $type - * @param string[] $protocolSupportEnumeration A set of URI specifying the protocols supported. - * @param string|null $ID The ID for this document. Defaults to null. - * @param \DateTimeImmutable|null $validUntil Unix time of validity for this document. Defaults to null. - * @param string|null $cacheDuration Maximum time this document can be cached. Defaults to null. + * @param \SimpleSAML\XMLSchema\Type\QNameValue $type + * @param \SimpleSAML\SAML2\Type\AnyURIListValue $protocolSupportEnumeration + * A set of URI specifying the protocols supported. + * @param \SimpleSAML\XMLSchema\Type\IDValue|null $ID The ID for this document. Defaults to null. + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil Unix time of validity for this document. + * Defaults to null. + * @param \SimpleSAML\XMLSchema\Type\DurationValue|null $cacheDuration Maximum time this document can be cached. + * Defaults to null. * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions An Extensions object. Defaults to null. - * @param string|null $errorURL An URI where to redirect users for support. Defaults to null. + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $errorURL An URI where to redirect users for support. + * Defaults to null. * @param \SimpleSAML\SAML2\XML\md\KeyDescriptor[] $keyDescriptor * An array of KeyDescriptor elements. Defaults to an empty array. * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization @@ -59,13 +66,13 @@ abstract class AbstractRoleDescriptor extends AbstractRoleDescriptorType impleme * @param list<\SimpleSAML\XML\Attribute> $namespacedAttributes */ public function __construct( - protected string $type, - array $protocolSupportEnumeration, - ?string $ID = null, - ?DateTimeImmutable $validUntil = null, - ?string $cacheDuration = null, + protected QNameValue $type, + AnyURIListValue $protocolSupportEnumeration, + ?IDValue $ID = null, + ?SAMLDateTimeValue $validUntil = null, + ?DurationValue $cacheDuration = null, ?Extensions $extensions = null, - ?string $errorURL = null, + ?SAMLAnyURIValue $errorURL = null, array $keyDescriptor = [], ?Organization $organization = null, array $contactPerson = [], @@ -89,9 +96,9 @@ public function __construct( /** * Return the xsi:type value corresponding this element. * - * @return string + * @return \SimpleSAML\XMLSchema\Type\QNameValue */ - public function getXsiType(): string + public function getXsiType(): QNameValue { return $this->type; } @@ -102,7 +109,7 @@ public function getXsiType(): string * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -110,34 +117,17 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'RoleDescriptor', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, C::NS_MD, InvalidDOMElementException::class); Assert::true( - $xml->hasAttributeNS(C::NS_XSI, 'type'), - 'Missing required xsi:type in element.', + $xml->hasAttributeNS(C_XSI::NS_XSI, 'type'), + 'Missing required xsi:type in element.', SchemaViolationException::class, ); - $type = $xml->getAttributeNS(C::NS_XSI, 'type'); - Assert::validQName($type, SchemaViolationException::class); - - // first, try to resolve the type to a full namespaced version - $qname = explode(':', $type, 2); - if (count($qname) === 2) { - list($prefix, $element) = $qname; - } else { - $prefix = null; - list($element) = $qname; - } - $ns = $xml->lookupNamespaceUri($prefix); - $type = ($ns === null) ? $element : implode(':', [$ns, $element]); + $type = QNameValue::fromDocument($xml->getAttributeNS(C_XSI::NS_XSI, 'type'), $xml); // now check if we have a handler registered for it $handler = Utils::getContainer()->getExtensionHandler($type); if ($handler === null) { // we don't have a handler, proceed with unknown RoleDescriptor - $protocols = self::getAttribute($xml, 'protocolSupportEnumeration'); - - $validUntil = self::getOptionalAttribute($xml, 'validUntil', null); - Assert::nullOrValidDateTime($validUntil); - $orgs = Organization::getChildrenOfClass($xml); Assert::maxCount( $orgs, @@ -157,12 +147,12 @@ public static function fromXML(DOMElement $xml): static return new UnknownRoleDescriptor( new Chunk($xml), $type, - preg_split('/[\s]+/', trim($protocols)), - self::getOptionalAttribute($xml, 'ID', null), - $validUntil !== null ? new DateTimeImmutable($validUntil) : null, - self::getOptionalAttribute($xml, 'cacheDuration', null), + self::getAttribute($xml, 'protocolSupportEnumeration', AnyURIListValue::class), + self::getOptionalAttribute($xml, 'ID', IDValue::class, null), + self::getOptionalAttribute($xml, 'validUntil', SAMLDateTimeValue::class, null), + self::getOptionalAttribute($xml, 'cacheDuration', DurationValue::class, null), array_pop($extensions), - self::getOptionalAttribute($xml, 'errorURL', null), + self::getOptionalAttribute($xml, 'errorURL', SAMLAnyURIValue::class, null), KeyDescriptor::getChildrenOfClass($xml), array_pop($orgs), ContactPerson::getChildrenOfClass($xml), @@ -178,21 +168,4 @@ public static function fromXML(DOMElement $xml): static return $handler::fromXML($xml); } - - - /** - * Convert this RoleDescriptor to XML. - * - * @param \DOMElement|null $parent The element we are converting to XML. - * @return \DOMElement The XML element after adding the data corresponding to this RoleDescriptor. - */ - public function toUnsignedXML(?DOMElement $parent = null): DOMElement - { - $e = parent::toUnsignedXML($parent); - - $type = new XMLAttribute(C::NS_XSI, 'xsi', 'type', $this->getXsiType()); - $type->toXML($e); - - return $e; - } } diff --git a/src/XML/md/AbstractRoleDescriptorType.php b/src/XML/md/AbstractRoleDescriptorType.php index d54c88cb0..a72b87dca 100644 --- a/src/XML/md/AbstractRoleDescriptorType.php +++ b/src/XML/md/AbstractRoleDescriptorType.php @@ -4,16 +4,18 @@ namespace SimpleSAML\SAML2\XML\md; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\XML\Exception\SchemaViolationException; +use SimpleSAML\SAML2\Type\AnyURIListValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\XML\ExtendableAttributesTrait; -use SimpleSAML\XML\XsNamespace as NS; +use SimpleSAML\XMLSchema\Type\DurationValue; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\XML\Constants\NS; -use function implode; +use function strval; /** * Class representing SAML2 RoleDescriptorType. @@ -32,12 +34,16 @@ abstract class AbstractRoleDescriptorType extends AbstractMetadataDocument /** * Initialize a RoleDescriptor. * - * @param string[] $protocolSupportEnumeration A set of URI specifying the protocols supported. - * @param string|null $ID The ID for this document. Defaults to null. - * @param \DateTimeImmutable|null $validUntil Unix time of validity for this document. Defaults to null. - * @param string|null $cacheDuration Maximum time this document can be cached. Defaults to null. + * @param \SimpleSAML\SAML2\Type\AnyURIListValue $protocolSupportEnumeration + * A set of URI specifying the protocols supported. + * @param \SimpleSAML\XMLSchema\Type\IDValue|null $ID The ID for this document. Defaults to null. + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil Unix time of validity for this document. + * Defaults to null. + * @param \SimpleSAML\XMLSchema\Type\DurationValue|null $cacheDuration Maximum time this document can be cached. + * Defaults to null. * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions An Extensions object. Defaults to null. - * @param string|null $errorURL An URI where to redirect users for support. Defaults to null. + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $errorURL An URI where to redirect users for support. + * Defaults to null. * @param \SimpleSAML\SAML2\XML\md\KeyDescriptor[] $keyDescriptor An array of KeyDescriptor elements. * Defaults to an empty array. * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization @@ -47,25 +53,17 @@ abstract class AbstractRoleDescriptorType extends AbstractMetadataDocument * @param list<\SimpleSAML\XML\Attribute> $namespacedAttributes */ public function __construct( - protected array $protocolSupportEnumeration, - ?string $ID = null, - ?DateTimeImmutable $validUntil = null, - ?string $cacheDuration = null, + protected AnyURIListValue $protocolSupportEnumeration, + ?IDValue $ID = null, + ?SAMLDateTimeValue $validUntil = null, + ?DurationValue $cacheDuration = null, ?Extensions $extensions = null, - protected ?string $errorURL = null, + protected ?SAMLAnyURIValue $errorURL = null, protected array $keyDescriptor = [], protected ?Organization $organization = null, protected array $contact = [], array $namespacedAttributes = [], ) { - Assert::maxCount($protocolSupportEnumeration, C::UNBOUNDED_LIMIT); - Assert::minCount( - $protocolSupportEnumeration, - 1, - 'At least one protocol must be supported by this ' . static::NS_PREFIX . ':' . static::getLocalName() . '.', - ); - SAMLAssert::allValidURI($protocolSupportEnumeration, SchemaViolationException::class); - SAMLAssert::nullOrValidURI($errorURL, SchemaViolationException::class); Assert::maxCount($contact, C::UNBOUNDED_LIMIT); Assert::allIsInstanceOf( $contact, @@ -88,9 +86,9 @@ public function __construct( /** * Collect the value of the errorURL property. * - * @return string|null + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null */ - public function getErrorURL(): ?string + public function getErrorURL(): ?SAMLAnyURIValue { return $this->errorURL; } @@ -99,9 +97,9 @@ public function getErrorURL(): ?string /** * Collect the value of the protocolSupportEnumeration property. * - * @return string[] + * @return \SimpleSAML\SAML2\Type\AnyURIListValue */ - public function getProtocolSupportEnumeration(): array + public function getProtocolSupportEnumeration(): AnyURIListValue { return $this->protocolSupportEnumeration; } @@ -149,10 +147,10 @@ public function getKeyDescriptor(): array public function toUnsignedXML(?DOMElement $parent = null): DOMElement { $e = parent::toUnsignedXML($parent); - $e->setAttribute('protocolSupportEnumeration', implode(' ', $this->getProtocolSupportEnumeration())); + $e->setAttribute('protocolSupportEnumeration', strval($this->getProtocolSupportEnumeration())); if ($this->getErrorURL() !== null) { - $e->setAttribute('errorURL', $this->getErrorURL()); + $e->setAttribute('errorURL', strval($this->getErrorURL())); } foreach ($this->getKeyDescriptor() as $kd) { diff --git a/src/XML/md/AbstractSSODescriptor.php b/src/XML/md/AbstractSSODescriptor.php index 19196fdfb..2e01d84b8 100644 --- a/src/XML/md/AbstractSSODescriptor.php +++ b/src/XML/md/AbstractSSODescriptor.php @@ -4,11 +4,15 @@ namespace SimpleSAML\SAML2\XML\md; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\AnyURIListValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\XML\Constants as C; +use SimpleSAML\XMLSchema\Type\DurationValue; +use SimpleSAML\XMLSchema\Type\IDValue; /** * Class representing SAML 2 SSODescriptorType. @@ -20,12 +24,16 @@ abstract class AbstractSSODescriptor extends AbstractRoleDescriptorType /** * Initialize a RoleDescriptor. * - * @param string[] $protocolSupportEnumeration A set of URI specifying the protocols supported. - * @param string|null $ID The ID for this document. Defaults to null. - * @param \DateTimeImmutable|null $validUntil Unix time of validity for this document. Defaults to null. - * @param string|null $cacheDuration Maximum time this document can be cached. Defaults to null. + * @param \SimpleSAML\SAML2\Type\AnyURIListValue $protocolSupportEnumeration + * A set of URI specifying the protocols supported. + * @param \SimpleSAML\XMLSchema\Type\IDValue|null $ID The ID for this document. Defaults to null. + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil Unix time of validity for this document. + * Defaults to null. + * @param \SimpleSAML\XMLSchema\Type\DurationValue|null $cacheDuration Maximum time this document can be cached. + * Defaults to null. * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions An array of extensions. Defaults to an empty array. - * @param string|null $errorURL An URI where to redirect users for support. Defaults to null. + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $errorURL An URI where to redirect users for support. + * Defaults to null. * @param \SimpleSAML\SAML2\XML\md\KeyDescriptor[] $keyDescriptors An array of KeyDescriptor elements. * Defaults to an empty array. * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization @@ -42,12 +50,12 @@ abstract class AbstractSSODescriptor extends AbstractRoleDescriptorType * Defaults to an empty array. */ public function __construct( - array $protocolSupportEnumeration, - ?string $ID = null, - ?DateTimeImmutable $validUntil = null, - ?string $cacheDuration = null, + AnyURIListValue $protocolSupportEnumeration, + ?IDValue $ID = null, + ?SAMLDateTimeValue $validUntil = null, + ?DurationValue $cacheDuration = null, ?Extensions $extensions = null, - ?string $errorURL = null, + ?SAMLAnyURIValue $errorURL = null, array $keyDescriptors = [], ?Organization $organization = null, array $contacts = [], diff --git a/src/XML/md/AbstractSignedMdElement.php b/src/XML/md/AbstractSignedMdElement.php index 428c37786..17e699f4f 100644 --- a/src/XML/md/AbstractSignedMdElement.php +++ b/src/XML/md/AbstractSignedMdElement.php @@ -76,6 +76,7 @@ public function toXML(?DOMElement $parent = null): DOMElement } $e = $this->toUnsignedXML($parent); + // This is a dirty hack, but if we add the xsi-type on AbstractRoleDescriptor we cannot // get the tests to pass because the attribute-order is messed up. This has something // to do with the fact that toUnsignedXML's recursive nature. @@ -83,7 +84,7 @@ public function toXML(?DOMElement $parent = null): DOMElement $e->setAttributeNS( 'http://www.w3.org/2000/xmlns/', 'xmlns:' . static::getXsiTypePrefix(), - static::getXsiTypeNamespaceURI(), + static::getXsiTypeNamespaceURI()->getValue(), ); } diff --git a/src/XML/md/AdditionalMetadataLocation.php b/src/XML/md/AdditionalMetadataLocation.php index 7b7c50393..502600809 100644 --- a/src/XML/md/AdditionalMetadataLocation.php +++ b/src/XML/md/AdditionalMetadataLocation.php @@ -5,14 +5,11 @@ namespace SimpleSAML\SAML2\XML\md; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; -use SimpleSAML\SAML2\XML\URIElementTrait; -use SimpleSAML\XML\Exception\InvalidDOMElementException; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; - -use function trim; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; /** * Class representing SAML 2 metadata AdditionalMetadataLocation element. @@ -22,44 +19,52 @@ final class AdditionalMetadataLocation extends AbstractMdElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use URIElementTrait; /** * Create a new instance of AdditionalMetadataLocation * - * @param string $namespace - * @param string $location + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $namespace + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $location */ public function __construct( - protected string $namespace, - string $location, + protected SAMLAnyURIValue $namespace, + protected SAMLAnyURIValue $location, ) { - SAMLAssert::validURI($namespace); - $this->setContent($location); } /** * Collect the value of the namespace-property * - * @return string + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue */ - public function getNamespace(): string + public function getNamespace(): SAMLAnyURIValue { return $this->namespace; } + /** + * Collect the value of the location-property + * + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue + */ + public function getLocation(): SAMLAnyURIValue + { + return $this->location; + } + + /** * Initialize an AdditionalMetadataLocation element. * * @param \DOMElement $xml The XML element we should load. * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing any of the mandatory attributes */ public static function fromXML(DOMElement $xml): static @@ -67,9 +72,10 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'AdditionalMetadataLocation', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, AdditionalMetadataLocation::NS, InvalidDOMElementException::class); - $namespace = self::getAttribute($xml, 'namespace'); - - return new static($namespace, trim($xml->textContent)); + return new static( + self::getAttribute($xml, 'namespace', SAMLAnyURIValue::class), + SAMLAnyURIValue::fromString($xml->textContent), + ); } @@ -82,8 +88,8 @@ public static function fromXML(DOMElement $xml): static public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - $e->textContent = $this->getContent(); - $e->setAttribute('namespace', $this->getNamespace()); + $e->textContent = $this->getLocation()->getValue(); + $e->setAttribute('namespace', $this->getNamespace()->getValue()); return $e; } diff --git a/src/XML/md/AffiliateMember.php b/src/XML/md/AffiliateMember.php index b1d1f8485..e8e6be83f 100644 --- a/src/XML/md/AffiliateMember.php +++ b/src/XML/md/AffiliateMember.php @@ -4,10 +4,10 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; -use SimpleSAML\SAML2\XML\StringElementTrait; +use SimpleSAML\SAML2\Type\EntityIDValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class implementing AffiliateMember. @@ -17,27 +17,9 @@ final class AffiliateMember extends AbstractMdElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use StringElementTrait; + use TypedTextContentTrait; - /** - * @param string $content - */ - public function __construct(string $content) - { - $this->setContent($content); - } - - - /** - * Validate the content of the element. - * - * @param string $content The value to go in the XML textContent - * @throws \Exception on failure - * @return void - */ - protected function validateContent(string $content): void - { - SAMLAssert::validEntityID($content); - } + /** @var string */ + public const TEXTCONTENT_TYPE = EntityIDValue::class; } diff --git a/src/XML/md/AffiliationDescriptor.php b/src/XML/md/AffiliationDescriptor.php index 5502dd074..9ab7f5eb1 100644 --- a/src/XML/md/AffiliationDescriptor.php +++ b/src/XML/md/AffiliationDescriptor.php @@ -4,17 +4,19 @@ namespace SimpleSAML\SAML2\XML\md; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\XML\ExtendableAttributesTrait; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; -use SimpleSAML\XML\XsNamespace as NS; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\DurationValue; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\XML\Constants\NS; use SimpleSAML\XMLSecurity\XML\ds\Signature; /** @@ -35,28 +37,29 @@ final class AffiliationDescriptor extends AbstractMetadataDocument implements Sc /** * Generic constructor for SAML metadata documents. * - * @param string $affiliationOwnerId The ID of the owner of this affiliation. + * @param \SimpleSAML\SAML2\Type\EntityIDValue $affiliationOwnerId The ID of the owner of this affiliation. * @param \SimpleSAML\SAML2\XML\md\AffiliateMember[] $affiliateMember * A non-empty array of members of this affiliation. - * @param string|null $ID The ID for this document. Defaults to null. - * @param \DateTimeImmutable|null $validUntil Unix time of validity for this document. Defaults to null. - * @param string|null $cacheDuration Maximum time this document can be cached. Defaults to null. + * @param \SimpleSAML\XMLSchema\Type\IDValue|null $ID The ID for this document. Defaults to null. + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil Unix time of validity for this document. + * Defaults to null. + * @param \SimpleSAML\XMLSchema\Type\DurationValue|null $cacheDuration Maximum time this document can be cached. + * Defaults to null. * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions An array of extensions. Defaults to an empty array. * @param \SimpleSAML\SAML2\XML\md\KeyDescriptor[] $keyDescriptor * An optional array of KeyDescriptors. Defaults to an empty array. * @param list<\SimpleSAML\XML\Attribute> $namespacedAttribute */ public function __construct( - protected string $affiliationOwnerId, + protected EntityIDValue $affiliationOwnerId, protected array $affiliateMember, - ?string $ID = null, - ?DateTimeImmutable $validUntil = null, - ?string $cacheDuration = null, + ?IDValue $ID = null, + ?SAMLDateTimeValue $validUntil = null, + ?DurationValue $cacheDuration = null, ?Extensions $extensions = null, protected array $keyDescriptor = [], array $namespacedAttribute = [], ) { - SAMLAssert::validEntityID($affiliationOwnerId); Assert::notEmpty($affiliateMember, 'List of affiliated members must not be empty.'); Assert::maxCount($affiliateMember, C::UNBOUNDED_LIMIT); Assert::allIsInstanceOf($affiliateMember, AffiliateMember::class); @@ -72,9 +75,9 @@ public function __construct( /** * Collect the value of the affiliationOwnerId-property * - * @return string + * @return \SimpleSAML\SAML2\Type\EntityIDValue */ - public function getAffiliationOwnerId(): string + public function getAffiliationOwnerId(): EntityIDValue { return $this->affiliationOwnerId; } @@ -108,11 +111,11 @@ public function getKeyDescriptor(): array * @param \DOMElement $xml The XML element we should load. * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes - * @throws \SimpleSAML\XML\Exception\TooManyElementsException + * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException * if too many child-elements of a type are specified */ public static function fromXML(DOMElement $xml): static @@ -120,13 +123,10 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'AffiliationDescriptor', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, AffiliationDescriptor::NS, InvalidDOMElementException::class); - $owner = self::getAttribute($xml, 'affiliationOwnerID'); + $owner = self::getAttribute($xml, 'affiliationOwnerID', EntityIDValue::class); $members = AffiliateMember::getChildrenOfClass($xml); $keyDescriptors = KeyDescriptor::getChildrenOfClass($xml); - $validUntil = self::getOptionalAttribute($xml, 'validUntil', null); - SAMLAssert::nullOrValidDateTime($validUntil); - $orgs = Organization::getChildrenOfClass($xml); Assert::maxCount( $orgs, @@ -154,9 +154,9 @@ public static function fromXML(DOMElement $xml): static $afd = new static( $owner, $members, - self::getOptionalAttribute($xml, 'ID', null), - $validUntil !== null ? new DateTimeImmutable($validUntil) : null, - self::getOptionalAttribute($xml, 'cacheDuration', null), + self::getOptionalAttribute($xml, 'ID', IDValue::class, null), + self::getOptionalAttribute($xml, 'validUntil', SAMLDateTimeValue::class, null), + self::getOptionalAttribute($xml, 'cacheDuration', DurationValue::class, null), !empty($extensions) ? $extensions[0] : null, $keyDescriptors, self::getAttributesNSFromXML($xml), @@ -180,7 +180,7 @@ public static function fromXML(DOMElement $xml): static public function toUnsignedXML(?DOMElement $parent = null): DOMElement { $e = parent::toUnsignedXML($parent); - $e->setAttribute('affiliationOwnerID', $this->getAffiliationOwnerId()); + $e->setAttribute('affiliationOwnerID', $this->getAffiliationOwnerId()->getValue()); foreach ($this->getAttributesNS() as $attr) { $attr->toXML($e); diff --git a/src/XML/md/ArtifactResolutionService.php b/src/XML/md/ArtifactResolutionService.php index 64d80e9b9..a4417d0d8 100644 --- a/src/XML/md/ArtifactResolutionService.php +++ b/src/XML/md/ArtifactResolutionService.php @@ -4,9 +4,12 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Type\BooleanValue; +use SimpleSAML\XMLSchema\Type\UnsignedShortValue; /** * A class implementing the md:ArtifactResolutionService element. @@ -23,22 +26,22 @@ final class ArtifactResolutionService extends AbstractIndexedEndpointType implem * * This is an endpoint with one restriction: it cannot contain a ResponseLocation. * - * @param int $index - * @param string $binding - * @param string $location - * @param bool|null $isDefault - * @param string|null $unused + * @param \SimpleSAML\XMLSchema\Type\UnsignedShortValue $index + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $binding + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $location + * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $isDefault + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $unused * @param list<\SimpleSAML\XML\Attribute> $attributes * @param array $children * * @throws \SimpleSAML\Assert\AssertionFailedException */ public function __construct( - int $index, - string $binding, - string $location, - ?bool $isDefault = null, - ?string $unused = null, + UnsignedShortValue $index, + SAMLAnyURIValue $binding, + SAMLAnyURIValue $location, + ?BooleanValue $isDefault = null, + ?SAMLAnyURIValue $unused = null, array $children = [], array $attributes = [], ) { diff --git a/src/XML/md/AttributeAuthorityDescriptor.php b/src/XML/md/AttributeAuthorityDescriptor.php index 694b1a694..6658a88bc 100644 --- a/src/XML/md/AttributeAuthorityDescriptor.php +++ b/src/XML/md/AttributeAuthorityDescriptor.php @@ -4,21 +4,22 @@ namespace SimpleSAML\SAML2\XML\md; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\AnyURIListValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\SAML2\XML\saml\Attribute; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\DurationValue; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\XML\ds\Signature; -use function preg_split; - /** * Class representing SAML 2 metadata AttributeAuthorityDescriptor. * @@ -34,16 +35,16 @@ final class AttributeAuthorityDescriptor extends AbstractRoleDescriptorType impl * AttributeAuthorityDescriptor constructor. * * @param \SimpleSAML\SAML2\XML\md\AttributeService[] $attributeService - * @param string[] $protocolSupportEnumeration + * @param \SimpleSAML\SAML2\Type\AnyURIListValue $protocolSupportEnumeration * @param \SimpleSAML\SAML2\XML\md\AssertionIDRequestService[] $assertionIDRequestService * @param \SimpleSAML\SAML2\XML\md\NameIDFormat[] $nameIDFormat * @param \SimpleSAML\SAML2\XML\md\AttributeProfile[] $attributeProfile * @param \SimpleSAML\SAML2\XML\saml\Attribute[] $attribute - * @param string|null $ID - * @param \DateTimeImmutable|null $validUntil - * @param string|null $cacheDuration + * @param \SimpleSAML\XMLSchema\Type\IDValue|null $ID + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil + * @param \SimpleSAML\XMLSchema\Type\DurationValue|null $cacheDuration * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions - * @param string|null $errorURL + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $errorURL * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization * @param \SimpleSAML\SAML2\XML\md\KeyDescriptor[] $keyDescriptor * @param \SimpleSAML\SAML2\XML\md\ContactPerson[] $contact @@ -51,16 +52,16 @@ final class AttributeAuthorityDescriptor extends AbstractRoleDescriptorType impl */ public function __construct( protected array $attributeService, - array $protocolSupportEnumeration, + AnyURIListValue $protocolSupportEnumeration, protected array $assertionIDRequestService = [], protected array $nameIDFormat = [], protected array $attributeProfile = [], protected array $attribute = [], - ?string $ID = null, - ?DateTimeImmutable $validUntil = null, - ?string $cacheDuration = null, + ?IDValue $ID = null, + ?SAMLDateTimeValue $validUntil = null, + ?DurationValue $cacheDuration = null, ?Extensions $extensions = null, - ?string $errorURL = null, + ?SAMLAnyURIValue $errorURL = null, ?Organization $organization = null, array $keyDescriptor = [], array $contact = [], @@ -164,13 +165,13 @@ public function getAttributes(): array * @param \DOMElement $xml The XML element we should load. * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes - * @throws \SimpleSAML\XML\Exception\MissingElementException + * @throws \SimpleSAML\XMLSchema\Exception\MissingElementException * if one of the mandatory child-elements is missing - * @throws \SimpleSAML\XML\Exception\TooManyElementsException + * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException * if too many child-elements of a type are specified */ public static function fromXML(DOMElement $xml): static @@ -178,10 +179,6 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'AttributeAuthorityDescriptor', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, AttributeAuthorityDescriptor::NS, InvalidDOMElementException::class); - $protocols = self::getAttribute($xml, 'protocolSupportEnumeration'); - $validUntil = self::getOptionalAttribute($xml, 'validUntil', null); - SAMLAssert::nullOrValidDateTime($validUntil); - $attrServices = AttributeService::getChildrenOfClass($xml); Assert::notEmpty( $attrServices, @@ -220,16 +217,16 @@ public static function fromXML(DOMElement $xml): static $authority = new static( $attrServices, - preg_split('/[\s]+/', trim($protocols)), + self::getAttribute($xml, 'protocolSupportEnumeration', AnyURIListValue::class), $assertIDReqServices, $nameIDFormats, $attrProfiles, $attributes, - self::getOptionalAttribute($xml, 'ID', null), - $validUntil !== null ? new DateTimeImmutable($validUntil) : null, - self::getOptionalAttribute($xml, 'cacheDuration', null), + self::getOptionalAttribute($xml, 'ID', IDValue::class, null), + self::getOptionalAttribute($xml, 'validUntil', SAMLDateTimeValue::class, null), + self::getOptionalAttribute($xml, 'cacheDuration', DurationValue::class, null), !empty($extensions) ? $extensions[0] : null, - self::getOptionalAttribute($xml, 'errorURL', null), + self::getOptionalAttribute($xml, 'errorURL', SAMLAnyURIValue::class, null), !empty($orgs) ? $orgs[0] : null, KeyDescriptor::getChildrenOfClass($xml), ContactPerson::getChildrenOfClass($xml), diff --git a/src/XML/md/AttributeConsumingService.php b/src/XML/md/AttributeConsumingService.php index 44bd1535b..549da9f17 100644 --- a/src/XML/md/AttributeConsumingService.php +++ b/src/XML/md/AttributeConsumingService.php @@ -5,14 +5,16 @@ namespace SimpleSAML\SAML2\XML\md; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingElementException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Type\BooleanValue; +use SimpleSAML\XMLSchema\Type\UnsignedShortValue; -use function strval; +use function var_export; /** * Class representing SAML 2 Metadata AttributeConsumingService element. @@ -28,17 +30,17 @@ final class AttributeConsumingService extends AbstractMdElement implements Schem /** * AttributeConsumingService constructor. * - * @param int $index + * @param \SimpleSAML\XMLSchema\Type\UnsignedShortValue $index * @param \SimpleSAML\SAML2\XML\md\ServiceName[] $serviceName * @param \SimpleSAML\SAML2\XML\md\RequestedAttribute[] $requestedAttribute - * @param bool|null $isDefault + * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $isDefault * @param \SimpleSAML\SAML2\XML\md\ServiceDescription[] $serviceDescription */ public function __construct( - int $index, + UnsignedShortValue $index, protected array $serviceName, protected array $requestedAttribute, - ?bool $isDefault = null, + ?BooleanValue $isDefault = null, protected array $serviceDescription = [], ) { Assert::maxCount($serviceName, C::UNBOUNDED_LIMIT); @@ -83,9 +85,9 @@ public function __construct( * @param \DOMElement $xml The XML element we should load. * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingElementException + * @throws \SimpleSAML\XMLSchema\Exception\MissingElementException * if one of the mandatory child-elements is missing */ public static function fromXML(DOMElement $xml): static @@ -93,7 +95,6 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'AttributeConsumingService', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, AttributeConsumingService::NS, InvalidDOMElementException::class); - $index = self::getIntegerAttribute($xml, 'index'); $names = ServiceName::getChildrenOfClass($xml); Assert::minCount( $names, @@ -107,10 +108,10 @@ public static function fromXML(DOMElement $xml): static $requestedAttrs = RequestedAttribute::getChildrenOfClass($xml); return new static( - $index, + self::getAttribute($xml, 'index', UnsignedShortValue::class), $names, $requestedAttrs, - self::getOptionalBooleanAttribute($xml, 'isDefault', null), + self::getOptionalAttribute($xml, 'isDefault', BooleanValue::class, null), $descriptions, ); } @@ -158,12 +159,10 @@ public function getRequestedAttribute(): array public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - $e->setAttribute('index', strval($this->getIndex())); + $e->setAttribute('index', $this->getIndex()->getValue()); - if ($this->getIsDefault() === true) { - $e->setAttribute('isDefault', 'true'); - } elseif ($this->getIsDefault() === false) { - $e->setAttribute('isDefault', 'false'); + if ($this->getIsDefault() !== null) { + $e->setAttribute('isDefault', var_export($this->getIsDefault()->toBoolean(), true)); } foreach ($this->getServiceName() as $name) { diff --git a/src/XML/md/AttributeProfile.php b/src/XML/md/AttributeProfile.php index 71043af2f..d78326cc4 100644 --- a/src/XML/md/AttributeProfile.php +++ b/src/XML/md/AttributeProfile.php @@ -4,9 +4,10 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\SAML2\XML\StringElementTrait; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class implementing AttributeProfile. @@ -16,14 +17,9 @@ final class AttributeProfile extends AbstractMdElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use StringElementTrait; + use TypedTextContentTrait; - /** - * @param string $content - */ - public function __construct(string $content) - { - $this->setContent($content); - } + /** @var string */ + public const TEXTCONTENT_TYPE = SAMLAnyURIValue::class; } diff --git a/src/XML/md/AuthnAuthorityDescriptor.php b/src/XML/md/AuthnAuthorityDescriptor.php index 77cd1bfe3..4bae53661 100644 --- a/src/XML/md/AuthnAuthorityDescriptor.php +++ b/src/XML/md/AuthnAuthorityDescriptor.php @@ -4,19 +4,20 @@ namespace SimpleSAML\SAML2\XML\md; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\AnyURIListValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\DurationValue; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\XML\ds\Signature; -use function preg_split; - /** * Class representing SAML 2 metadata AuthnAuthorityDescriptor. * @@ -31,14 +32,14 @@ final class AuthnAuthorityDescriptor extends AbstractRoleDescriptorType implemen * AuthnAuthorityDescriptor constructor. * * @param array $authnQueryService - * @param array $protocolSupportEnumeration + * @param \SimpleSAML\SAML2\Type\AnyURIListValue $protocolSupportEnumeration * @param array $assertionIDRequestService * @param array $nameIDFormat - * @param string|null $ID - * @param \DateTimeImmutable|null $validUntil - * @param string|null $cacheDuration + * @param \SimpleSAML\XMLSchema\Type\IDValue|null $ID + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil + * @param \SimpleSAML\XMLSchema\Type\DurationValue|null $cacheDuration * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions - * @param string|null $errorURL + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $errorURL * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization * @param array $keyDescriptor * @param array $contact @@ -46,14 +47,14 @@ final class AuthnAuthorityDescriptor extends AbstractRoleDescriptorType implemen */ public function __construct( protected array $authnQueryService, - array $protocolSupportEnumeration, + AnyURIListValue $protocolSupportEnumeration, protected array $assertionIDRequestService = [], protected array $nameIDFormat = [], - ?string $ID = null, - ?DateTimeImmutable $validUntil = null, - ?string $cacheDuration = null, + ?IDValue $ID = null, + ?SAMLDateTimeValue $validUntil = null, + ?DurationValue $cacheDuration = null, ?Extensions $extensions = null, - ?string $errorURL = null, + ?SAMLAnyURIValue $errorURL = null, ?Organization $organization = null, array $keyDescriptor = [], array $contact = [], @@ -129,11 +130,11 @@ public function getNameIDFormat(): array * @param \DOMElement $xml The XML element we should load. * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes - * @throws \SimpleSAML\XML\Exception\TooManyElementsException + * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException * if too many child-elements of a type are specified */ public static function fromXML(DOMElement $xml): static @@ -141,15 +142,10 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'AuthnAuthorityDescriptor', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, AuthnAuthorityDescriptor::NS, InvalidDOMElementException::class); - $protocols = self::getAttribute($xml, 'protocolSupportEnumeration'); - $authnQueryServices = AuthnQueryService::getChildrenOfClass($xml); $assertionIDRequestServices = AssertionIDRequestService::getChildrenOfClass($xml); $nameIDFormats = NameIDFormat::getChildrenOfClass($xml); - $validUntil = self::getOptionalAttribute($xml, 'validUntil', null); - SAMLAssert::nullOrValidDateTime($validUntil); - $orgs = Organization::getChildrenOfClass($xml); Assert::maxCount( $orgs, @@ -176,14 +172,14 @@ public static function fromXML(DOMElement $xml): static $authority = new static( $authnQueryServices, - preg_split('/[\s]+/', trim($protocols)), + self::getAttribute($xml, 'protocolSupportEnumeration', AnyURIListValue::class), $assertionIDRequestServices, $nameIDFormats, - self::getOptionalAttribute($xml, 'ID', null), - $validUntil !== null ? new DateTimeImmutable($validUntil) : null, - self::getOptionalAttribute($xml, 'cacheDuration', null), + self::getOptionalAttribute($xml, 'ID', IDValue::class, null), + self::getOptionalAttribute($xml, 'validUntil', SAMLDateTimeValue::class, null), + self::getOptionalAttribute($xml, 'cacheDuration', DurationValue::class, null), !empty($extensions) ? $extensions[0] : null, - self::getOptionalAttribute($xml, 'errorURL', null), + self::getOptionalAttribute($xml, 'errorURL', SAMLAnyURIValue::class, null), !empty($orgs) ? $orgs[0] : null, KeyDescriptor::getChildrenOfClass($xml), ContactPerson::getChildrenOfClass($xml), diff --git a/src/XML/md/Company.php b/src/XML/md/Company.php index 0800fdd7d..45cad9ad3 100644 --- a/src/XML/md/Company.php +++ b/src/XML/md/Company.php @@ -4,9 +4,10 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\SAML2\XML\StringElementTrait; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class implementing Company. @@ -16,14 +17,9 @@ final class Company extends AbstractMdElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use StringElementTrait; + use TypedTextContentTrait; - /** - * @param string $content - */ - public function __construct(string $content) - { - $this->setContent($content); - } + /** @var string */ + public const TEXTCONTENT_TYPE = SAMLStringValue::class; } diff --git a/src/XML/md/ContactPerson.php b/src/XML/md/ContactPerson.php index a1b340a85..94abc5ba4 100644 --- a/src/XML/md/ContactPerson.php +++ b/src/XML/md/ContactPerson.php @@ -5,23 +5,25 @@ namespace SimpleSAML\SAML2\XML\md; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ArrayValidationException; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\ExtendableElementTrait; use SimpleSAML\XML\ArrayizableElementInterface; use SimpleSAML\XML\Attribute as XMLAttribute; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\ExtendableAttributesTrait; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; -use SimpleSAML\XML\XsNamespace as NS; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\XML\Constants\NS; use function array_change_key_case; use function array_filter; use function array_key_exists; use function array_keys; +use function array_map; use function array_pop; use function count; @@ -57,7 +59,7 @@ final class ContactPerson extends AbstractMdElement implements /** * ContactPerson constructor. * - * @param string $contactType + * @param \SimpleSAML\SAML2\Type\SAMLStringValue $contactType * @param \SimpleSAML\SAML2\XML\md\Company|null $company * @param \SimpleSAML\SAML2\XML\md\GivenName|null $givenName * @param \SimpleSAML\SAML2\XML\md\SurName|null $surName @@ -67,7 +69,7 @@ final class ContactPerson extends AbstractMdElement implements * @param list<\SimpleSAML\XML\Attribute> $namespacedAttribute */ public function __construct( - protected string $contactType, + protected SAMLStringValue $contactType, protected ?Company $company = null, protected ?GivenName $givenName = null, protected ?SurName $surName = null, @@ -76,7 +78,7 @@ public function __construct( protected array $telephoneNumber = [], array $namespacedAttribute = [], ) { - Assert::oneOf($contactType, self::CONTACT_TYPES); + Assert::oneOf($contactType->getValue(), self::CONTACT_TYPES); Assert::maxCount($emailAddress, C::UNBOUNDED_LIMIT); Assert::allIsInstanceOf($emailAddress, EmailAddress::class); Assert::maxCount($telephoneNumber, C::UNBOUNDED_LIMIT); @@ -90,9 +92,9 @@ public function __construct( /** * Collect the value of the contactType-property * - * @return string + * @return \SimpleSAML\SAML2\Type\SAMLStringValue */ - public function getContactType(): string + public function getContactType(): SAMLStringValue { return $this->contactType; } @@ -159,11 +161,11 @@ public function getTelephoneNumber(): array * @param \DOMElement $xml The XML element we should load. * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes - * @throws \SimpleSAML\XML\Exception\TooManyElementsException + * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException * if too many child-elements of a type are specified */ public static function fromXML(DOMElement $xml): static @@ -171,7 +173,7 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'ContactPerson', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, ContactPerson::NS, InvalidDOMElementException::class); - $contactType = self::getAttribute($xml, 'contactType'); + $contactType = self::getAttribute($xml, 'contactType', SAMLStringValue::class); $company = Company::getChildrenOfClass($xml); Assert::maxCount($company, 1, 'More than one Company in md:ContactPerson'); @@ -212,7 +214,7 @@ public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - $e->setAttribute('contactType', $this->getContactType()); + $e->setAttribute('contactType', $this->getContactType()->getValue()); foreach ($this->getAttributesNS() as $attr) { $attr->toXML($e); @@ -246,13 +248,17 @@ public static function fromArray(array $data): static $data = self::processArrayContents($data); return new static( - $data['contactType'], - $data['Company'] ?? null, - $data['GivenName'] ?? null, - $data['SurName'] ?? null, + SAMLStringValue::fromString($data['contactType']), + $data['Company'] !== null ? new Company(SAMLStringValue::fromString($data['Company'])) : null, + $data['GivenName'] !== null ? new GivenName(SAMLStringValue::fromString($data['GivenName'])) : null, + $data['SurName'] !== null ? new SurName(SAMLStringValue::fromString($data['SurName'])) : null, $data['Extensions'] ?? null, - $data['EmailAddress'] ?? [], - $data['TelephoneNumber'] ?? [], + $data['EmailAddress'] !== null + ? array_map([EmailAddress::class, 'fromArray'], [$data['EmailAddress']]) + : [], + $data['TelephoneNumber'] !== null + ? array_map([TelephoneNumber::class, 'fromArray'], [$data['TelephoneNumber']]) + : [], $data['attributes'] ?? [], ); } @@ -292,24 +298,24 @@ private static function processArrayContents(array $data): array if (array_key_exists('company', $data)) { Assert::string($data['company'], ArrayValidationException::class); - $retval['Company'] = new Company($data['company']); + $retval['Company'] = $data['company']; } if (array_key_exists('givenname', $data)) { Assert::string($data['givenname'], ArrayValidationException::class); - $retval['GivenName'] = new GivenName($data['givenname']); + $retval['GivenName'] = $data['givenname']; } if (array_key_exists('surname', $data)) { Assert::string($data['surname'], ArrayValidationException::class); - $retval['SurName'] = new SurName($data['surname']); + $retval['SurName'] = $data['surname']; } if (array_key_exists('emailaddress', $data)) { Assert::isArray($data['emailaddress'], ArrayValidationException::class); Assert::allString($data['emailaddress'], ArrayValidationException::class); foreach ($data['emailaddress'] as $email) { - $retval['EmailAddress'][] = new EmailAddress($email); + $retval['EmailAddress'][] = $email; } } @@ -317,7 +323,7 @@ private static function processArrayContents(array $data): array Assert::isArray($data['telephonenumber'], ArrayValidationException::class); Assert::allString($data['telephonenumber'], ArrayValidationException::class); foreach ($data['telephonenumber'] as $telephone) { - $retval['TelephoneNumber'][] = new TelephoneNumber($telephone); + $retval['TelephoneNumber'][] = $telephone; } } @@ -346,10 +352,10 @@ private static function processArrayContents(array $data): array public function toArray(): array { $data = [ - 'ContactType' => $this->getContactType(), - 'Company' => $this->getCompany()?->getContent(), - 'GivenName' => $this->getGivenName()?->getContent(), - 'SurName' => $this->getSurName()?->getContent(), + 'ContactType' => $this->getContactType()->getValue(), + 'Company' => $this->getCompany()?->getContent()->getValue(), + 'GivenName' => $this->getGivenName()?->getContent()->getValue(), + 'SurName' => $this->getSurName()?->getContent()->getValue(), 'EmailAddress' => [], 'TelephoneNumber' => [], 'Extensions' => $this->Extensions?->getList(), diff --git a/src/XML/md/EmailAddress.php b/src/XML/md/EmailAddress.php index c342fa5e3..c09cda195 100644 --- a/src/XML/md/EmailAddress.php +++ b/src/XML/md/EmailAddress.php @@ -4,17 +4,16 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ArrayValidationException; -use SimpleSAML\SAML2\XML\StringElementTrait; +use SimpleSAML\SAML2\Type\EmailAddressValue; use SimpleSAML\XML\ArrayizableElementInterface; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; use function array_key_first; use function preg_filter; -use function preg_replace; -use function trim; /** * Class implementing EmailAddress. @@ -26,60 +25,11 @@ final class EmailAddress extends AbstractMdElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use StringElementTrait { - StringElementTrait::validateContent as baseValidateContent; - } - - - /** - * @param string $content - */ - public function __construct(string $content) - { - $this->setContent($content); - } - - - /** - * Validate the content of the element. - * - * @param string $content The value to go in the XML textContent - * @throws \Exception on failure - * @return void - */ - protected function validateContent(string $content): void - { - $this->baseValidateContent($content); - Assert::email($content); - } + use TypedTextContentTrait; - /** - * Sanitize the content of the element. - * - * @param string $content The unsanitized textContent - * @throws \Exception on failure - * @return string - */ - protected function sanitizeContent(string $content): string - { - return trim(preg_replace('/^(mailto:)+/i', '', $content)); - } - - - /** - * Set the content of the element. - * - * @param string $content The value to go in the XML textContent - */ - protected function setContent(string $content): void - { - $sanitized = $this->sanitizeContent($content); - $this->validateContent($sanitized); - - // Store the email address without mailto: URI - $this->content = $sanitized; - } + /** @var string */ + public const TEXTCONTENT_TYPE = EmailAddressValue::class; /** @@ -89,7 +39,7 @@ protected function setContent(string $content): void */ public function getContent(): string { - return preg_filter('/^/', 'mailto:', $this->content); + return preg_filter('/^/', 'mailto:', $this->content->getValue()); } @@ -104,7 +54,9 @@ public static function fromArray(array $data): static Assert::allString($data, ArrayValidationException::class); $index = array_key_first($data); - return new static($data[$index]); + return new static( + EmailAddressValue::fromString($data[$index]), + ); } diff --git a/src/XML/md/EntitiesDescriptor.php b/src/XML/md/EntitiesDescriptor.php index 62ad6fea2..415927093 100644 --- a/src/XML/md/EntitiesDescriptor.php +++ b/src/XML/md/EntitiesDescriptor.php @@ -4,18 +4,28 @@ namespace SimpleSAML\SAML2\XML\md; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\SAML2\XML\mdrpi\PublicationInfo; +use SimpleSAML\SAML2\XML\mdrpi\PublicationPath; +use SimpleSAML\SAML2\XML\mdrpi\RegistrationInfo; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\DurationValue; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\XML\ds\Signature; +use function array_filter; +use function array_merge; +use function array_values; +use function count; + /** * Class representing SAML 2 EntitiesDescriptor element. * @@ -31,19 +41,19 @@ final class EntitiesDescriptor extends AbstractMetadataDocument implements Schem * * @param \SimpleSAML\SAML2\XML\md\EntityDescriptor[] $entityDescriptors * @param \SimpleSAML\SAML2\XML\md\EntitiesDescriptor[] $entitiesDescriptors - * @param string|null $Name - * @param string|null $ID - * @param \DateTimeImmutable|null $validUntil - * @param string|null $cacheDuration + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $Name + * @param \SimpleSAML\XMLSchema\Type\IDValue|null $ID + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil + * @param \SimpleSAML\XMLSchema\Type\DurationValue|null $cacheDuration * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions */ public function __construct( protected array $entityDescriptors = [], protected array $entitiesDescriptors = [], - protected ?string $Name = null, - ?string $ID = null, - ?DateTimeImmutable $validUntil = null, - ?string $cacheDuration = null, + protected ?SAMLStringValue $Name = null, + ?IDValue $ID = null, + ?SAMLDateTimeValue $validUntil = null, + ?DurationValue $cacheDuration = null, ?Extensions $extensions = null, ) { Assert::true( @@ -56,10 +66,110 @@ public function __construct( Assert::allIsInstanceOf($entitiesDescriptors, EntitiesDescriptor::class); Assert::allIsInstanceOf($entityDescriptors, EntityDescriptor::class); + if ($extensions !== null) { + /** + * When a element appears in the element of a + * element it applies to all descendant and + * elements. That is to say, this is equivalent to putting an identical + * on every descendant . When used in this + * manner, descendant and elements MUST + * NOT contain a element in their element. + */ + $toplevel_regInfo = array_values(array_filter($extensions->getList(), function ($ext) { + return $ext instanceof RegistrationInfo; + })); + + /** + * The element SHOULD only be used on the root element of a metadata document. + */ + $toplevel_pubInfo = array_values(array_filter($extensions->getList(), function ($ext) { + return $ext instanceof PublicationInfo; + })); + + /** + * When a element appears in the element of a + * element it applies to all descendant and + * elements. That is to say, this is equivalent to putting an identical + * on every descendant and . + * When used in this manner, descendant and + * elements MUST NOT contain a element in their element. + */ + $toplevel_pubPath = array_values(array_filter($extensions->getList(), function ($ext) { + return $ext instanceof PublicationPath; + })); + + if (count($toplevel_regInfo) > 0 || count($toplevel_pubInfo) > 0 || count($toplevel_pubPath)) { + $nestedExtensions = []; + foreach (array_merge($entityDescriptors, $entitiesDescriptors) as $ed) { + $nestedExtensions = array_merge($nestedExtensions, $this->getRecursiveExtensions($ed)); + } + + if (count($toplevel_regInfo) > 0) { + $nested_regInfo = array_values(array_filter($nestedExtensions, function ($ext) { + return $ext instanceof RegistrationInfo; + })); + + Assert::count( + $nested_regInfo, + 0, + " already set at top-level.", + ProtocolViolationException::class, + ); + } + + if (count($toplevel_pubInfo) > 0) { + $nested_pubInfo = array_values(array_filter($nestedExtensions, function ($ext) { + return $ext instanceof PublicationInfo; + })); + + Assert::count( + $nested_pubInfo, + 0, + " already set at top-level.", + ProtocolViolationException::class, + ); + } + + if (count($toplevel_pubPath) > 0) { + $nested_pubPath = array_values(array_filter($nestedExtensions, function ($ext) { + return $ext instanceof PublicationPath; + })); + + Assert::count( + $nested_pubPath, + 0, + " already set at top-level.", + ProtocolViolationException::class, + ); + } + } + } + parent::__construct($ID, $validUntil, $cacheDuration, $extensions); } + /** + * Get all extensions from all nested entity/entities descriptors + */ + private function getRecursiveExtensions(EntityDescriptor|EntitiesDescriptor $descriptor): array + { + $extensions = []; + if ($descriptor->getExtensions() !== null) { + $extensions = $descriptor->getExtensions()->getList(); + + if ($descriptor instanceof EntitiesDescriptor) { + $eds = array_merge($descriptor->getEntitiesDescriptors(), $descriptor->getEntityDescriptors()); + foreach ($eds as $ed) { + $extensions = array_merge($extensions, $descriptor->getRecursiveExtensions($ed)); + } + } + } + + return $extensions; + } + + /** * Get the EntitiesDescriptor children objects * @@ -85,9 +195,9 @@ public function getEntityDescriptors(): array /** * Collect the value of the Name property. * - * @return string|null + * @return \SimpleSAML\SAML2\Type\SAMLStringValue|null */ - public function getName(): ?string + public function getName(): ?SAMLStringValue { return $this->Name; } @@ -99,9 +209,9 @@ public function getName(): ?string * @param \DOMElement $xml The XML element we should load. * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\TooManyElementsException + * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException * if too many child-elements of a type are specified */ public static function fromXML(DOMElement $xml): static @@ -109,9 +219,6 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'EntitiesDescriptor', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, EntitiesDescriptor::NS, InvalidDOMElementException::class); - $validUntil = self::getOptionalAttribute($xml, 'validUntil', null); - SAMLAssert::nullOrValidDateTime($validUntil); - $orgs = Organization::getChildrenOfClass($xml); Assert::maxCount( $orgs, @@ -139,10 +246,10 @@ public static function fromXML(DOMElement $xml): static $entities = new static( EntityDescriptor::getChildrenOfClass($xml), EntitiesDescriptor::getChildrenOfClass($xml), - self::getOptionalAttribute($xml, 'Name', null), - self::getOptionalAttribute($xml, 'ID', null), - $validUntil !== null ? new DateTimeImmutable($validUntil) : null, - self::getOptionalAttribute($xml, 'cacheDuration', null), + self::getOptionalAttribute($xml, 'Name', SAMLStringValue::class, null), + self::getOptionalAttribute($xml, 'ID', IDValue::class, null), + self::getOptionalAttribute($xml, 'validUntil', SAMLDateTimeValue::class, null), + self::getOptionalAttribute($xml, 'cacheDuration', DurationValue::class, null), !empty($extensions) ? $extensions[0] : null, ); @@ -165,8 +272,8 @@ public function toUnsignedXML(?DOMElement $parent = null): DOMElement { $e = parent::toUnsignedXML($parent); - if ($this->Name !== null) { - $e->setAttribute('Name', $this->Name); + if ($this->getName() !== null) { + $e->setAttribute('Name', $this->getName()->getValue()); } foreach ($this->getEntitiesDescriptors() as $entitiesDescriptor) { diff --git a/src/XML/md/EntityDescriptor.php b/src/XML/md/EntityDescriptor.php index fcf5122a7..5f9a982c1 100644 --- a/src/XML/md/EntityDescriptor.php +++ b/src/XML/md/EntityDescriptor.php @@ -4,18 +4,20 @@ namespace SimpleSAML\SAML2\XML\md; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\XML\ExtendableAttributesTrait; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; -use SimpleSAML\XML\XsNamespace as NS; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\DurationValue; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\XML\Constants\NS; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function is_null; @@ -38,10 +40,12 @@ final class EntityDescriptor extends AbstractMetadataDocument implements SchemaV /** * Initialize an EntitiyDescriptor. * - * @param string $entityId The entityID of the entity described by this descriptor. - * @param string|null $id The ID for this document. Defaults to null. - * @param \DateTimeImmutable|null $validUntil Unix time of validify for this document. Defaults to null. - * @param string|null $cacheDuration Maximum time this document can be cached. Defaults to null. + * @param \SimpleSAML\SAML2\Type\EntityIDValue $entityId The entityID of the entity described by this descriptor. + * @param \SimpleSAML\XMLSchema\Type\IDValue|null $id The ID for this document. Defaults to null. + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil Unix time of validify for this document. + * Defaults to null. + * @param \SimpleSAML\XMLSchema\Type\DurationValue|null $cacheDuration Maximum time this document can be cached. + * Defaults to null. * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions An array of extensions. * @param \SimpleSAML\SAML2\XML\md\AbstractRoleDescriptorType[] $roleDescriptor An array of role descriptors. * @param \SimpleSAML\SAML2\XML\md\AffiliationDescriptor|null $affiliationDescriptor An affiliation descriptor to @@ -55,10 +59,10 @@ final class EntityDescriptor extends AbstractMetadataDocument implements SchemaV * @throws \Exception */ public function __construct( - protected string $entityId, - ?string $id = null, - ?DateTimeImmutable $validUntil = null, - ?string $cacheDuration = null, + protected EntityIDValue $entityId, + ?IDValue $id = null, + ?SAMLDateTimeValue $validUntil = null, + ?DurationValue $cacheDuration = null, ?Extensions $extensions = null, protected array $roleDescriptor = [], protected ?AffiliationDescriptor $affiliationDescriptor = null, @@ -72,7 +76,6 @@ public function __construct( 'Must have either one of the RoleDescriptors or an AffiliationDescriptor in EntityDescriptor.', ProtocolViolationException::class, ); - SAMLAssert::validEntityID($entityId); Assert::maxCount($roleDescriptor, C::UNBOUNDED_LIMIT); Assert::allIsInstanceOf( $roleDescriptor, @@ -104,11 +107,11 @@ public function __construct( * @param \DOMElement $xml An existing EntityDescriptor XML document. * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes - * @throws \SimpleSAML\XML\Exception\TooManyElementsException + * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException * if too many child-elements of a type are specified */ public static function fromXML(DOMElement $xml): static @@ -116,16 +119,12 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'EntityDescriptor', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, EntityDescriptor::NS, InvalidDOMElementException::class); - $validUntil = self::getOptionalAttribute($xml, 'validUntil', null); - SAMLAssert::nullOrValidDateTime($validUntil); - $extensions = Extensions::getChildrenOfClass($xml); Assert::maxCount($extensions, 1, 'Only one md:Extensions element is allowed.', TooManyElementsException::class); $signature = Signature::getChildrenOfClass($xml); Assert::maxCount($signature, 1, 'Only one ds:Signature element is allowed.', TooManyElementsException::class); - $entityID = self::getAttribute($xml, 'entityID'); $roleDescriptors = []; $affiliationDescriptor = null; $organization = null; @@ -192,10 +191,10 @@ public static function fromXML(DOMElement $xml): static ); $entity = new static( - $entityID, - self::getOptionalAttribute($xml, 'ID', null), - $validUntil !== null ? new DateTimeImmutable($validUntil) : null, - self::getOptionalAttribute($xml, 'cacheDuration', null), + self::getAttribute($xml, 'entityID', EntityIDValue::class), + self::getOptionalAttribute($xml, 'ID', IDValue::class, null), + self::getOptionalAttribute($xml, 'validUntil', SAMLDateTimeValue::class, null), + self::getOptionalAttribute($xml, 'cacheDuration', DurationValue::class, null), !empty($extensions) ? $extensions[0] : null, $roleDescriptors, $affiliationDescriptor, @@ -217,10 +216,9 @@ public static function fromXML(DOMElement $xml): static /** * Collect the value of the entityID property. * - * @return string - * @throws \SimpleSAML\Assert\AssertionFailedException + * @return \SimpleSAML\SAML2\Type\EntityIDValue */ - public function getEntityId(): string + public function getEntityId(): EntityIDValue { return $this->entityId; } @@ -290,7 +288,7 @@ public function getAdditionalMetadataLocation(): array public function toUnsignedXML(?DOMElement $parent = null): DOMElement { $e = parent::toUnsignedXML($parent); - $e->setAttribute('entityID', $this->getEntityId()); + $e->setAttribute('entityID', $this->getEntityId()->getValue()); foreach ($this->getAttributesNS() as $attr) { $attr->toXML($e); diff --git a/src/XML/md/Extensions.php b/src/XML/md/Extensions.php index 26af56fe4..01481d80e 100644 --- a/src/XML/md/Extensions.php +++ b/src/XML/md/Extensions.php @@ -5,7 +5,7 @@ namespace SimpleSAML\SAML2\XML\md; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\alg\AbstractAlgElement as ALG; use SimpleSAML\SAML2\XML\alg\DigestMethod; @@ -24,9 +24,9 @@ use SimpleSAML\SAML2\XML\mdui\UIInfo; use SimpleSAML\SAML2\XML\shibmd\Scope; use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; use function array_key_exists; @@ -50,7 +50,7 @@ final class Extensions extends AbstractMdElement implements SchemaValidatableEle * @param \DOMElement $xml * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static diff --git a/src/XML/md/GivenName.php b/src/XML/md/GivenName.php index 8d9e606ef..83b7a52aa 100644 --- a/src/XML/md/GivenName.php +++ b/src/XML/md/GivenName.php @@ -4,9 +4,10 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\SAML2\XML\StringElementTrait; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class implementing GivenName. @@ -16,14 +17,9 @@ final class GivenName extends AbstractMdElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use StringElementTrait; + use TypedTextContentTrait; - /** - * @param string $content - */ - public function __construct(string $content) - { - $this->setContent($content); - } + /** @var string */ + public const TEXTCONTENT_TYPE = SAMLStringValue::class; } diff --git a/src/XML/md/IDPSSODescriptor.php b/src/XML/md/IDPSSODescriptor.php index 265b37ab9..18068a995 100644 --- a/src/XML/md/IDPSSODescriptor.php +++ b/src/XML/md/IDPSSODescriptor.php @@ -4,19 +4,23 @@ namespace SimpleSAML\SAML2\XML\md; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\AnyURIListValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\SAML2\XML\saml\Attribute; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\BooleanValue; +use SimpleSAML\XMLSchema\Type\DurationValue; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\XML\ds\Signature; -use function preg_split; +use function var_export; /** * Class representing SAML 2 IDPSSODescriptor. @@ -32,17 +36,17 @@ final class IDPSSODescriptor extends AbstractSSODescriptor implements SchemaVali * IDPSSODescriptor constructor. * * @param \SimpleSAML\SAML2\XML\md\SingleSignOnService[] $singleSignOnService - * @param string[] $protocolSupportEnumeration - * @param bool|null $wantAuthnRequestsSigned + * @param \SimpleSAML\SAML2\Type\AnyURIListValue $protocolSupportEnumeration + * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $wantAuthnRequestsSigned * @param \SimpleSAML\SAML2\XML\md\NameIDMappingService[] $nameIDMappingService * @param \SimpleSAML\SAML2\XML\md\AssertionIDRequestService[] $assertionIDRequestService * @param \SimpleSAML\SAML2\XML\md\AttributeProfile[] $attributeProfile * @param \SimpleSAML\SAML2\XML\saml\Attribute[] $attribute - * @param string|null $ID - * @param \DateTimeImmutable|null $validUntil - * @param string|null $cacheDuration + * @param \SimpleSAML\XMLSchema\Type\IDValue|null $ID + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil + * @param \SimpleSAML\XMLSchema\Type\DurationValue|null $cacheDuration * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions - * @param string|null $errorURL + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $errorURL * @param \SimpleSAML\SAML2\XML\md\KeyDescriptor[] $keyDescriptor * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization * @param \SimpleSAML\SAML2\XML\md\ContactPerson[] $contact @@ -53,17 +57,17 @@ final class IDPSSODescriptor extends AbstractSSODescriptor implements SchemaVali */ public function __construct( protected array $singleSignOnService, - array $protocolSupportEnumeration, - protected ?bool $wantAuthnRequestsSigned = null, + AnyURIListValue $protocolSupportEnumeration, + protected ?BooleanValue $wantAuthnRequestsSigned = null, protected array $nameIDMappingService = [], protected array $assertionIDRequestService = [], protected array $attributeProfile = [], protected array $attribute = [], - ?string $ID = null, - ?DateTimeImmutable $validUntil = null, - ?string $cacheDuration = null, + ?IDValue $ID = null, + ?SAMLDateTimeValue $validUntil = null, + ?DurationValue $cacheDuration = null, ?Extensions $extensions = null, - ?string $errorURL = null, + ?SAMLAnyURIValue $errorURL = null, array $keyDescriptor = [], ?Organization $organization = null, array $contact = [], @@ -121,9 +125,9 @@ public function __construct( /** * Collect the value of the WantAuthnRequestsSigned-property * - * @return bool|null + * @return \SimpleSAML\XMLSchema\Type\BooleanValue|null */ - public function wantAuthnRequestsSigned(): ?bool + public function wantAuthnRequestsSigned(): ?BooleanValue { return $this->wantAuthnRequestsSigned; } @@ -190,11 +194,11 @@ public function getSupportedAttribute(): array * @param \DOMElement $xml The XML element we should load. * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingElementException + * @throws \SimpleSAML\XMLSchema\Exception\MissingElementException * if one of the mandatory child-elements is missing - * @throws \SimpleSAML\XML\Exception\TooManyElementsException + * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException * if too many child-elements of a type are specified */ public static function fromXML(DOMElement $xml): static @@ -202,10 +206,6 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'IDPSSODescriptor', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, IDPSSODescriptor::NS, InvalidDOMElementException::class); - $protocols = self::getAttribute($xml, 'protocolSupportEnumeration'); - $validUntil = self::getOptionalAttribute($xml, 'validUntil', null); - SAMLAssert::nullOrValidDateTime($validUntil); - $orgs = Organization::getChildrenOfClass($xml); Assert::maxCount( $orgs, @@ -232,17 +232,17 @@ public static function fromXML(DOMElement $xml): static $idpssod = new static( SingleSignOnService::getChildrenOfClass($xml), - preg_split('/[\s]+/', trim($protocols)), - self::getOptionalBooleanAttribute($xml, 'WantAuthnRequestsSigned', null), + self::getAttribute($xml, 'protocolSupportEnumeration', AnyURIListValue::class), + self::getOptionalAttribute($xml, 'WantAuthnRequestsSigned', BooleanValue::class, null), NameIDMappingService::getChildrenOfClass($xml), AssertionIDRequestService::getChildrenOfClass($xml), AttributeProfile::getChildrenOfClass($xml), Attribute::getChildrenOfClass($xml), - self::getOptionalAttribute($xml, 'ID', null), - $validUntil !== null ? new DateTimeImmutable($validUntil) : null, - self::getOptionalAttribute($xml, 'cacheDuration', null), + self::getOptionalAttribute($xml, 'ID', IDValue::class, null), + self::getOptionalAttribute($xml, 'validUntil', SAMLDateTimeValue::class, null), + self::getOptionalAttribute($xml, 'cacheDuration', DurationValue::class, null), !empty($extensions) ? $extensions[0] : null, - self::getOptionalAttribute($xml, 'errorURL', null), + self::getOptionalAttribute($xml, 'errorURL', SAMLAnyURIValue::class, null), KeyDescriptor::getChildrenOfClass($xml), !empty($orgs) ? $orgs[0] : null, ContactPerson::getChildrenOfClass($xml), @@ -270,8 +270,11 @@ public function toUnsignedXML(?DOMElement $parent = null): DOMElement { $e = parent::toUnsignedXML($parent); - if (is_bool($this->wantAuthnRequestsSigned)) { - $e->setAttribute('WantAuthnRequestsSigned', $this->wantAuthnRequestsSigned ? 'true' : 'false'); + if ($this->wantAuthnRequestsSigned() !== null) { + $e->setAttribute( + 'WantAuthnRequestsSigned', + var_export($this->wantAuthnRequestsSigned()->toBoolean(), true), + ); } foreach ($this->getSingleSignOnService() as $ep) { diff --git a/src/XML/md/IndexedElementTrait.php b/src/XML/md/IndexedElementTrait.php index 9caca8650..d89f1426c 100644 --- a/src/XML/md/IndexedElementTrait.php +++ b/src/XML/md/IndexedElementTrait.php @@ -4,7 +4,8 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\Assert\Assert; +use SimpleSAML\XMLSchema\Type\BooleanValue; +use SimpleSAML\XMLSchema\Type\UnsignedShortValue; /** * Trait adding methods to handle elements that can be indexed. @@ -16,24 +17,24 @@ trait IndexedElementTrait /** * The index for this endpoint. * - * @var int + * @var \SimpleSAML\XMLSchema\Type\UnsignedShortValue */ - protected int $index; + protected UnsignedShortValue $index; /** * Whether this endpoint is the default. * - * @var bool|null + * @var \SimpleSAML\XMLSchema\Type\BooleanValue|null */ - protected ?bool $isDefault = null; + protected ?BooleanValue $isDefault = null; /** * Collect the value of the index property. * - * @return int + * @return \SimpleSAML\XMLSchema\Type\UnsignedShortValue */ - public function getIndex(): int + public function getIndex(): UnsignedShortValue { return $this->index; } @@ -42,12 +43,10 @@ public function getIndex(): int /** * Set the value of the index property. * - * @param int $index - * @throws \SimpleSAML\Assert\AssertionFailedException + * @param \SimpleSAML\XMLSchema\Type\UnsignedShortValue $index */ - protected function setIndex(int $index): void + protected function setIndex(UnsignedShortValue $index): void { - Assert::range($index, 0, 65535); $this->index = $index; } @@ -55,9 +54,9 @@ protected function setIndex(int $index): void /** * Collect the value of the isDefault property. * - * @return bool|null + * @return \SimpleSAML\XMLSchema\Type\BooleanValue|null */ - public function getIsDefault(): ?bool + public function getIsDefault(): ?BooleanValue { return $this->isDefault; } @@ -66,9 +65,9 @@ public function getIsDefault(): ?bool /** * Set the value of the isDefault property. * - * @param bool|null $flag + * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $flag */ - protected function setIsDefault(?bool $flag): void + protected function setIsDefault(?BooleanValue $flag): void { $this->isDefault = $flag; } diff --git a/src/XML/md/KeyDescriptor.php b/src/XML/md/KeyDescriptor.php index e3d80c086..d5f68060d 100644 --- a/src/XML/md/KeyDescriptor.php +++ b/src/XML/md/KeyDescriptor.php @@ -5,15 +5,18 @@ namespace SimpleSAML\SAML2\XML\md; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\KeyTypesValue; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; +use function array_pop; + /** * Class representing a KeyDescriptor element. * @@ -28,19 +31,14 @@ final class KeyDescriptor extends AbstractMdElement implements SchemaValidatable * KeyDescriptor constructor. * * @param \SimpleSAML\XMLSecurity\XML\ds\KeyInfo $keyInfo - * @param string|null $use + * @param \SimpleSAML\SAML2\Type\KeyTypesValue|null $use * @param \SimpleSAML\SAML2\XML\md\EncryptionMethod[] $encryptionMethod */ public function __construct( protected KeyInfo $keyInfo, - protected ?string $use = null, + protected ?KeyTypesValue $use = null, protected array $encryptionMethod = [], ) { - Assert::nullOrOneOf( - $use, - ['encryption', 'signing'], - 'The "use" attribute of a KeyDescriptor can only be "encryption" or "signing".', - ); Assert::maxCount($encryptionMethod, C::UNBOUNDED_LIMIT); Assert::allIsInstanceOf($encryptionMethod, EncryptionMethod::class); } @@ -49,9 +47,9 @@ public function __construct( /** * Collect the value of the use property. * - * @return string|null + * @return \SimpleSAML\SAML2\Type\KeyTypesValue|null */ - public function getUse(): ?string + public function getUse(): ?KeyTypesValue { return $this->use; } @@ -85,11 +83,11 @@ public function getEncryptionMethod(): array * @param \DOMElement $xml The XML element we should load. * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingElementException + * @throws \SimpleSAML\XMLSchema\Exception\MissingElementException * if one of the mandatory child-elements is missing - * @throws \SimpleSAML\XML\Exception\TooManyElementsException + * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException * if too many child-elements of a type are specified */ public static function fromXML(DOMElement $xml): static @@ -97,23 +95,13 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'KeyDescriptor', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, KeyDescriptor::NS, InvalidDOMElementException::class); - $keyInfoElements = KeyInfo::getChildrenOfClass($xml); - Assert::minCount( - $keyInfoElements, - 1, - 'No ds:KeyInfo in the KeyDescriptor.', - MissingElementException::class, - ); - Assert::maxCount( - $keyInfoElements, - 1, - 'More than one ds:KeyInfo in the KeyDescriptor.', - TooManyElementsException::class, - ); + $keyInfo = KeyInfo::getChildrenOfClass($xml); + Assert::minCount($keyInfo, 1, 'No ds:KeyInfo in the KeyDescriptor.', MissingElementException::class); + Assert::maxCount($keyInfo, 1, 'Too many ds:KeyInfo in the KeyDescriptor.', TooManyElementsException::class); return new static( - $keyInfoElements[0], - self::getOptionalAttribute($xml, 'use', null), + array_pop($keyInfo), + self::getOptionalAttribute($xml, 'use', KeyTypesValue::class, null), EncryptionMethod::getChildrenOfClass($xml), ); } @@ -130,7 +118,7 @@ public function toXML(?DOMElement $parent = null): DOMElement $e = $this->instantiateParentElement($parent); if ($this->getUse() !== null) { - $e->setAttribute('use', $this->getUse()); + $e->setAttribute('use', $this->getUse()->getValue()); } $this->getKeyInfo()->toXML($e); diff --git a/src/XML/md/KeyTypesEnum.php b/src/XML/md/KeyTypesEnum.php new file mode 100644 index 000000000..a00f67314 --- /dev/null +++ b/src/XML/md/KeyTypesEnum.php @@ -0,0 +1,11 @@ +setContent($content); - } + /** @var string */ + public const TEXTCONTENT_TYPE = SAMLAnyURIValue::class; } diff --git a/src/XML/md/NameIDMappingService.php b/src/XML/md/NameIDMappingService.php index 58b75fa5c..0b7d6c034 100644 --- a/src/XML/md/NameIDMappingService.php +++ b/src/XML/md/NameIDMappingService.php @@ -4,7 +4,8 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; @@ -23,22 +24,23 @@ final class NameIDMappingService extends AbstractEndpointType implements SchemaV * * This is an endpoint with one restriction: it cannot contain a ResponseLocation. * - * @param string $binding - * @param string $location - * @param string|null $unused + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $binding + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $location + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $unused * @param array $attributes * @throws \SimpleSAML\Assert\AssertionFailedException */ public function __construct( - string $binding, - string $location, - ?string $unused = null, + SAMLAnyURIValue $binding, + SAMLAnyURIValue $location, + ?SAMLAnyURIValue $unused = null, array $attributes = [], ) { Assert::null( $unused, 'The \'ResponseLocation\' attribute must be omitted for md:NameIDMappingService.', ); + parent::__construct($binding, $location, null, $attributes); } } diff --git a/src/XML/md/Organization.php b/src/XML/md/Organization.php index dbf9ade17..a72195e95 100644 --- a/src/XML/md/Organization.php +++ b/src/XML/md/Organization.php @@ -5,20 +5,20 @@ namespace SimpleSAML\SAML2\XML\md; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ArrayValidationException; use SimpleSAML\SAML2\Exception\ProtocolViolationException; use SimpleSAML\SAML2\XML\ExtendableElementTrait; use SimpleSAML\XML\ArrayizableElementInterface; use SimpleSAML\XML\Attribute as XMLAttribute; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\ExtendableAttributesTrait; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; -use SimpleSAML\XML\XsNamespace as NS; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\XML\Constants\NS; use function array_change_key_case; use function array_filter; @@ -117,9 +117,9 @@ public function getOrganizationURL(): array * @param \DOMElement $xml The XML element we should load. * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingElementException + * @throws \SimpleSAML\XMLSchema\Exception\MissingElementException * if one of the mandatory child-elements is missing */ public static function fromXML(DOMElement $xml): static diff --git a/src/XML/md/PDPDescriptor.php b/src/XML/md/PDPDescriptor.php index 52d537e03..983e421cc 100644 --- a/src/XML/md/PDPDescriptor.php +++ b/src/XML/md/PDPDescriptor.php @@ -4,19 +4,20 @@ namespace SimpleSAML\SAML2\XML\md; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\AnyURIListValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\DurationValue; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\XML\ds\Signature; -use function preg_split; - /** * Class representing SAML 2 metadata PDPDescriptor. * @@ -31,14 +32,14 @@ final class PDPDescriptor extends AbstractRoleDescriptorType implements SchemaVa * PDPDescriptor constructor. * * @param \SimpleSAML\SAML2\XML\md\AuthzService[] $authzService - * @param string[] $protocolSupportEnumeration + * @param \SimpleSAML\SAML2\Type\AnyURIListValue $protocolSupportEnumeration * @param \SimpleSAML\SAML2\XML\md\AssertionIDRequestService[] $assertionIDRequestService * @param \SimpleSAML\SAML2\XML\md\NameIDFormat[] $nameIDFormat - * @param string|null $ID - * @param \DateTimeImmutable|null $validUntil - * @param string|null $cacheDuration + * @param \SimpleSAML\XMLSchema\Type\IDValue|null $ID + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil + * @param \SimpleSAML\XMLSchema\Type\DurationValue|null $cacheDuration * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions - * @param string|null $errorURL + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $errorURL * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization * @param \SimpleSAML\SAML2\XML\md\KeyDescriptor[] $keyDescriptors * @param \SimpleSAML\SAML2\XML\md\ContactPerson[] $contacts @@ -46,14 +47,14 @@ final class PDPDescriptor extends AbstractRoleDescriptorType implements SchemaVa */ public function __construct( protected array $authzService, - array $protocolSupportEnumeration, + AnyURIListValue $protocolSupportEnumeration, protected array $assertionIDRequestService = [], protected array $nameIDFormat = [], - ?string $ID = null, - ?DateTimeImmutable $validUntil = null, - ?string $cacheDuration = null, + ?IDValue $ID = null, + ?SAMLDateTimeValue $validUntil = null, + ?DurationValue $cacheDuration = null, ?Extensions $extensions = null, - ?string $errorURL = null, + ?SAMLAnyURIValue $errorURL = null, ?Organization $organization = null, array $keyDescriptors = [], array $contacts = [], @@ -129,11 +130,11 @@ public function getNameIDFormat(): array * @param \DOMElement $xml The XML element we should load. * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes - * @throws \SimpleSAML\XML\Exception\TooManyElementsException + * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException * if too many child-elements of a type are specified */ public static function fromXML(DOMElement $xml): static @@ -141,10 +142,6 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'PDPDescriptor', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, PDPDescriptor::NS, InvalidDOMElementException::class); - $protocols = self::getAttribute($xml, 'protocolSupportEnumeration'); - $validUntil = self::getOptionalAttribute($xml, 'validUntil', null); - SAMLAssert::nullOrValidDateTime($validUntil); - $orgs = Organization::getChildrenOfClass($xml); Assert::maxCount( $orgs, @@ -166,14 +163,14 @@ public static function fromXML(DOMElement $xml): static $pdp = new static( AuthzService::getChildrenOfClass($xml), - preg_split('/[\s]+/', trim($protocols)), + self::getAttribute($xml, 'protocolSupportEnumeration', AnyURIListValue::class), AssertionIDRequestService::getChildrenOfClass($xml), NameIDFormat::getChildrenOfClass($xml), - self::getOptionalAttribute($xml, 'ID', null), - $validUntil !== null ? new DateTimeImmutable($validUntil) : null, - self::getOptionalAttribute($xml, 'cacheDuration', null), + self::getOptionalAttribute($xml, 'ID', IDValue::class, null), + self::getOptionalAttribute($xml, 'validUntil', SAMLDateTimeValue::class, null), + self::getOptionalAttribute($xml, 'cacheDuration', DurationValue::class, null), !empty($extensions) ? $extensions[0] : null, - self::getOptionalAttribute($xml, 'errorURL', null), + self::getOptionalAttribute($xml, 'errorURL', SAMLAnyURIValue::class, null), !empty($orgs) ? $orgs[0] : null, KeyDescriptor::getChildrenOfClass($xml), ContactPerson::getChildrenOfClass($xml), diff --git a/src/XML/md/RequestedAttribute.php b/src/XML/md/RequestedAttribute.php index 3d106a647..d8a715b3c 100644 --- a/src/XML/md/RequestedAttribute.php +++ b/src/XML/md/RequestedAttribute.php @@ -5,12 +5,13 @@ namespace SimpleSAML\SAML2\XML\md; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\Attribute; use SimpleSAML\SAML2\XML\saml\AttributeValue; -use SimpleSAML\XML\Exception\InvalidDOMElementException; - -use function is_bool; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Type\BooleanValue; /** * Class representing SAML 2 metadata RequestedAttribute. @@ -32,17 +33,17 @@ final class RequestedAttribute extends Attribute /** * RequestedAttribute constructor. * - * @param string $Name - * @param bool|null $isRequired - * @param string|null $NameFormat - * @param string|null $FriendlyName + * @param \SimpleSAML\SAML2\Type\SAMLStringValue $Name + * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $isRequired + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $NameFormat + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $FriendlyName * @param \SimpleSAML\SAML2\XML\saml\AttributeValue[] $AttributeValues */ public function __construct( - string $Name, - protected ?bool $isRequired = null, - ?string $NameFormat = null, - ?string $FriendlyName = null, + SAMLStringValue $Name, + protected ?BooleanValue $isRequired = null, + ?SAMLAnyURIValue $NameFormat = null, + ?SAMLStringValue $FriendlyName = null, array $AttributeValues = [], ) { parent::__construct($Name, $NameFormat, $FriendlyName, $AttributeValues); @@ -52,9 +53,9 @@ public function __construct( /** * Collect the value of the isRequired-property * - * @return bool|null + * @return \SimpleSAML\XMLSchema\Type\BooleanValue|null */ - public function getIsRequired(): ?bool + public function getIsRequired(): ?BooleanValue { return $this->isRequired; } @@ -66,9 +67,9 @@ public function getIsRequired(): ?bool * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes */ public static function fromXML(DOMElement $xml): static @@ -77,10 +78,10 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->namespaceURI, RequestedAttribute::NS, InvalidDOMElementException::class); return new static( - self::getAttribute($xml, 'Name'), - self::getOptionalBooleanAttribute($xml, 'isRequired', null), - self::getOptionalAttribute($xml, 'NameFormat', null), - self::getOptionalAttribute($xml, 'FriendlyName', null), + self::getAttribute($xml, 'Name', SAMLStringValue::class), + self::getOptionalAttribute($xml, 'isRequired', BooleanValue::class, null), + self::getOptionalAttribute($xml, 'NameFormat', SAMLAnyURIValue::class, null), + self::getOptionalAttribute($xml, 'FriendlyName', SAMLStringValue::class, null), AttributeValue::getChildrenOfClass($xml), ); } @@ -96,8 +97,8 @@ public function toXML(?DOMElement $parent = null): DOMElement { $e = parent::toXML($parent); - if (is_bool($this->getIsRequired())) { - $e->setAttribute('isRequired', $this->getIsRequired() ? 'true' : 'false'); + if ($this->getIsRequired()?->toBoolean() !== null) { + $e->setAttribute('isRequired', $this->getIsRequired()->toBoolean() ? 'true' : 'false'); } return $e; diff --git a/src/XML/md/SPSSODescriptor.php b/src/XML/md/SPSSODescriptor.php index cf53aa004..9dc6f0e8f 100644 --- a/src/XML/md/SPSSODescriptor.php +++ b/src/XML/md/SPSSODescriptor.php @@ -4,20 +4,23 @@ namespace SimpleSAML\SAML2\XML\md; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\AnyURIListValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\BooleanValue; +use SimpleSAML\XMLSchema\Type\DurationValue; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function array_filter; -use function is_bool; -use function preg_split; +use function var_export; /** * Class representing SAML 2 SPSSODescriptor. @@ -33,15 +36,15 @@ final class SPSSODescriptor extends AbstractSSODescriptor implements SchemaValid * SPSSODescriptor constructor. * * @param array<\SimpleSAML\SAML2\XML\md\AssertionConsumerService> $assertionConsumerService - * @param string[] $protocolSupportEnumeration - * @param bool|null $authnRequestsSigned - * @param bool|null $wantAssertionsSigned + * @param \SimpleSAML\SAML2\Type\AnyURIListValue $protocolSupportEnumeration + * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $authnRequestsSigned + * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $wantAssertionsSigned * @param array<\SimpleSAML\SAML2\XML\md\AttributeConsumingService> $attributeConsumingService - * @param string|null $ID - * @param \DateTimeImmutable|null $validUntil - * @param string|null $cacheDuration + * @param \SimpleSAML\XMLSchema\Type\IDValue|null $ID + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil + * @param \SimpleSAML\XMLSchema\Type\DurationValue|null $cacheDuration * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions - * @param string|null $errorURL + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $errorURL * @param array<\SimpleSAML\SAML2\XML\md\KeyDescriptor> $keyDescriptors * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization * @param array<\SimpleSAML\SAML2\XML\md\ContactPerson> $contacts @@ -52,15 +55,15 @@ final class SPSSODescriptor extends AbstractSSODescriptor implements SchemaValid */ public function __construct( protected array $assertionConsumerService, - array $protocolSupportEnumeration, - protected ?bool $authnRequestsSigned = null, - protected ?bool $wantAssertionsSigned = null, + AnyURIListValue $protocolSupportEnumeration, + protected ?BooleanValue $authnRequestsSigned = null, + protected ?BooleanValue $wantAssertionsSigned = null, protected array $attributeConsumingService = [], - ?string $ID = null, - ?DateTimeImmutable $validUntil = null, - ?string $cacheDuration = null, + ?IDValue $ID = null, + ?SAMLDateTimeValue $validUntil = null, + ?DurationValue $cacheDuration = null, ?Extensions $extensions = null, - ?string $errorURL = null, + ?SAMLAnyURIValue $errorURL = null, array $keyDescriptors = [], ?Organization $organization = null, array $contacts = [], @@ -106,7 +109,7 @@ public function __construct( array_filter( $attributeConsumingService, function (AttributeConsumingService $acs) { - return $acs->getIsDefault() === true; + return $acs->getIsDefault()?->toBoolean() === true; }, ), 1, @@ -118,9 +121,9 @@ function (AttributeConsumingService $acs) { /** * Collect the value of the AuthnRequestsSigned-property * - * @return bool|null + * @return \SimpleSAML\XMLSchema\Type\BooleanValue|null */ - public function getAuthnRequestsSigned(): ?bool + public function getAuthnRequestsSigned(): ?BooleanValue { return $this->authnRequestsSigned; } @@ -129,9 +132,9 @@ public function getAuthnRequestsSigned(): ?bool /** * Collect the value of the WantAssertionsSigned-property * - * @return bool|null + * @return \SimpleSAML\XMLSchema\Type\BooleanValue|null */ - public function getWantAssertionsSigned(): ?bool + public function getWantAssertionsSigned(): ?BooleanValue { return $this->wantAssertionsSigned; } @@ -165,11 +168,11 @@ public function getAttributeConsumingService(): array * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes - * @throws \SimpleSAML\XML\Exception\TooManyElementsException + * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException * if too many child-elements of a type are specified */ public static function fromXML(DOMElement $xml): static @@ -177,10 +180,6 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'SPSSODescriptor', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, SPSSODescriptor::NS, InvalidDOMElementException::class); - $protocols = self::getAttribute($xml, 'protocolSupportEnumeration'); - $validUntil = self::getOptionalAttribute($xml, 'validUntil', null); - SAMLAssert::nullOrValidDateTime($validUntil); - $orgs = Organization::getChildrenOfClass($xml); Assert::maxCount( $orgs, @@ -207,15 +206,15 @@ public static function fromXML(DOMElement $xml): static $spssod = new static( AssertionConsumerService::getChildrenOfClass($xml), - preg_split('/[\s]+/', trim($protocols)), - self::getOptionalBooleanAttribute($xml, 'AuthnRequestsSigned', null), - self::getOptionalBooleanAttribute($xml, 'WantAssertionsSigned', null), + self::getAttribute($xml, 'protocolSupportEnumeration', AnyURIListValue::class), + self::getOptionalAttribute($xml, 'AuthnRequestsSigned', BooleanValue::class, null), + self::getOptionalAttribute($xml, 'WantAssertionsSigned', BooleanValue::class, null), AttributeConsumingService::getChildrenOfClass($xml), - self::getOptionalAttribute($xml, 'ID', null), - $validUntil !== null ? new DateTimeImmutable($validUntil) : null, - self::getOptionalAttribute($xml, 'cacheDuration', null), + self::getOptionalAttribute($xml, 'ID', IDValue::class, null), + self::getOptionalAttribute($xml, 'validUntil', SAMLDateTimeValue::class, null), + self::getOptionalAttribute($xml, 'cacheDuration', DurationValue::class, null), !empty($extensions) ? $extensions[0] : null, - self::getOptionalAttribute($xml, 'errorURL', null), + self::getOptionalAttribute($xml, 'errorURL', SAMLAnyURIValue::class, null), KeyDescriptor::getChildrenOfClass($xml), !empty($orgs) ? $orgs[0] : null, ContactPerson::getChildrenOfClass($xml), @@ -244,12 +243,12 @@ public function toUnsignedXML(?DOMElement $parent = null): DOMElement { $e = parent::toUnsignedXML($parent); - if (is_bool($this->getAuthnRequestsSigned())) { - $e->setAttribute('AuthnRequestsSigned', $this->getAuthnRequestsSigned() ? 'true' : 'false'); + if ($this->getAuthnRequestsSigned() !== null) { + $e->setAttribute('AuthnRequestsSigned', var_export($this->getAuthnRequestsSigned()->toBoolean(), true)); } - if (is_bool($this->getWantAssertionsSigned())) { - $e->setAttribute('WantAssertionsSigned', $this->getWantAssertionsSigned() ? 'true' : 'false'); + if ($this->getWantAssertionsSigned() !== null) { + $e->setAttribute('WantAssertionsSigned', var_export($this->getWantAssertionsSigned()->toBoolean(), true)); } foreach ($this->getAssertionConsumerService() as $ep) { diff --git a/src/XML/md/SingleSignOnService.php b/src/XML/md/SingleSignOnService.php index ad4b8d951..10f6538f2 100644 --- a/src/XML/md/SingleSignOnService.php +++ b/src/XML/md/SingleSignOnService.php @@ -4,7 +4,9 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; @@ -23,21 +25,22 @@ final class SingleSignOnService extends AbstractEndpointType implements SchemaVa * * This is an endpoint with one restriction: it cannot contain a ResponseLocation. * - * @param string $binding - * @param string $location - * @param string|null $unused + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $binding + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $location + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $unused * @param array $attributes * @throws \SimpleSAML\Assert\AssertionFailedException */ public function __construct( - string $binding, - string $location, - ?string $unused = null, + SAMLAnyURIValue $binding, + SAMLAnyURIValue $location, + ?SAMLAnyURIValue $unused = null, array $attributes = [], ) { Assert::null( $unused, 'The \'ResponseLocation\' attribute must be omitted for md:SingleSignOnService.', + ProtocolViolationException::class, ); parent::__construct($binding, $location, null, $attributes); } diff --git a/src/XML/md/SurName.php b/src/XML/md/SurName.php index d1ec826cc..6b57a2df7 100644 --- a/src/XML/md/SurName.php +++ b/src/XML/md/SurName.php @@ -4,9 +4,10 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\SAML2\XML\StringElementTrait; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class implementing SurName. @@ -16,14 +17,9 @@ final class SurName extends AbstractMdElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use StringElementTrait; + use TypedTextContentTrait; - /** - * @param string $content - */ - public function __construct(string $content) - { - $this->setContent($content); - } + /** @var string */ + public const TEXTCONTENT_TYPE = SAMLStringValue::class; } diff --git a/src/XML/md/TelephoneNumber.php b/src/XML/md/TelephoneNumber.php index 2eca6e176..ca19021cb 100644 --- a/src/XML/md/TelephoneNumber.php +++ b/src/XML/md/TelephoneNumber.php @@ -4,12 +4,13 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ArrayValidationException; -use SimpleSAML\SAML2\XML\StringElementTrait; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\XML\ArrayizableElementInterface; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; use function array_key_first; @@ -23,16 +24,11 @@ final class TelephoneNumber extends AbstractMdElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use StringElementTrait; + use TypedTextContentTrait; - /** - * @param string $content - */ - public function __construct(string $content) - { - $this->setContent($content); - } + /** @var string */ + public const TEXTCONTENT_TYPE = SAMLStringValue::class; /** @@ -46,7 +42,9 @@ public static function fromArray(array $data): static Assert::allString($data, ArrayValidationException::class); $index = array_key_first($data); - return new static($data[$index]); + return new static( + SAMLStringValue::fromString($data[$index]), + ); } @@ -57,6 +55,6 @@ public static function fromArray(array $data): static */ public function toArray(): array { - return [$this->getContent()]; + return [$this->getContent()->getValue()]; } } diff --git a/src/XML/md/UnknownRoleDescriptor.php b/src/XML/md/UnknownRoleDescriptor.php index ce55c7b6e..604b9df8d 100644 --- a/src/XML/md/UnknownRoleDescriptor.php +++ b/src/XML/md/UnknownRoleDescriptor.php @@ -4,9 +4,14 @@ namespace SimpleSAML\SAML2\XML\md; -use DateTimeImmutable; use DOMElement; +use SimpleSAML\SAML2\Type\AnyURIListValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\XML\Chunk; +use SimpleSAML\XMLSchema\Type\DurationValue; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\QNameValue; /** * Class representing unknown RoleDescriptors. @@ -19,13 +24,17 @@ final class UnknownRoleDescriptor extends AbstractRoleDescriptor * Initialize an unknown RoleDescriptor. * * @param \SimpleSAML\XML\Chunk $chunk The whole RoleDescriptor element as a chunk object. - * @param string $type - * @param string[] $protocolSupportEnumeration A set of URI specifying the protocols supported. - * @param string|null $ID The ID for this document. Defaults to null. - * @param \DateTimeImmutable|null $validUntil Unix time of validity for this document. Defaults to null. - * @param string|null $cacheDuration Maximum time this document can be cached. Defaults to null. + * @param \SimpleSAML\XMLSchema\Type\QNameValue $type + * @param \SimpleSAML\SAML2\Type\AnyURIListValue $protocolSupportEnumeration + * A set of URI specifying the protocols supported. + * @param \SimpleSAML\XMLSchema\Type\IDValue|null $ID The ID for this document. Defaults to null. + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil Unix time of validity for this document. + * Defaults to null. + * @param \SimpleSAML\XMLSchema\Type\DurationValue|null $cacheDuration Maximum time this document can be cached. + * Defaults to null. * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions An Extensions object. Defaults to null. - * @param string|null $errorURL An URI where to redirect users for support. Defaults to null. + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $errorURL An URI where to redirect users for support. + * Defaults to null. * @param \SimpleSAML\SAML2\XML\md\KeyDescriptor[] $keyDescriptors An array of KeyDescriptor elements. * Defaults to an empty array. * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization @@ -36,13 +45,13 @@ final class UnknownRoleDescriptor extends AbstractRoleDescriptor */ protected function __construct( protected Chunk $chunk, - string $type, - array $protocolSupportEnumeration, - ?string $ID = null, - ?DateTimeImmutable $validUntil = null, - ?string $cacheDuration = null, + QNameValue $type, + AnyURIListValue $protocolSupportEnumeration, + ?IDValue $ID = null, + ?SAMLDateTimeValue $validUntil = null, + ?DurationValue $cacheDuration = null, ?Extensions $extensions = null, - ?string $errorURL = null, + ?SAMLAnyURIValue $errorURL = null, array $keyDescriptors = [], ?Organization $organization = null, array $contacts = [], diff --git a/src/XML/mdattr/EntityAttributes.php b/src/XML/mdattr/EntityAttributes.php index d486a04b3..c7fa26c58 100644 --- a/src/XML/mdattr/EntityAttributes.php +++ b/src/XML/mdattr/EntityAttributes.php @@ -5,16 +5,16 @@ namespace SimpleSAML\SAML2\XML\mdattr; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Exception\ProtocolViolationException; use SimpleSAML\SAML2\XML\saml\Assertion; use SimpleSAML\SAML2\XML\saml\Attribute; use SimpleSAML\SAML2\XML\saml\AttributeStatement; use SimpleSAML\SAML2\XML\saml\NameID; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; use function array_filter; use function array_merge; @@ -80,7 +80,7 @@ public function __construct( ); Assert::isEmpty( - $subject?->getSubjectConfirmation(), + $subject->getSubjectConfirmation(), 'Every inside a must NOT contain any SubjectConfirmation', ProtocolViolationException::class, ); @@ -94,7 +94,7 @@ public function __construct( ProtocolViolationException::class, ); Assert::same( - $nameId?->getFormat(), + $nameId?->getFormat()->getValue(), C::NAMEID_ENTITY, sprintf('The NameID format must be %s', C::NAMEID_ENTITY), ProtocolViolationException::class, @@ -133,7 +133,7 @@ public function addChild($child): void * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static diff --git a/src/XML/mdrpi/Publication.php b/src/XML/mdrpi/Publication.php index cacff1963..c5aeff245 100644 --- a/src/XML/mdrpi/Publication.php +++ b/src/XML/mdrpi/Publication.php @@ -4,19 +4,15 @@ namespace SimpleSAML\SAML2\XML\mdrpi; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; -use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ArrayValidationException; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\XML\ArrayizableElementInterface; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; - -use function preg_replace; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; /** * Class for handling the mdrpi:Publication element. @@ -34,25 +30,24 @@ final class Publication extends AbstractMdrpiElement implements /** * Create/parse a mdrpi:PublicationInfo element. * - * @param string $publisher - * @param \DateTimeImmutable|null $creationInstant - * @param string|null $publicationId + * @param \SimpleSAML\SAML2\Type\SAMLStringValue $publisher + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $creationInstant + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $publicationId */ public function __construct( - protected string $publisher, - protected ?DateTimeImmutable $creationInstant = null, - protected ?string $publicationId = null, + protected SAMLStringValue $publisher, + protected ?SAMLDateTimeValue $creationInstant = null, + protected ?SAMLStringValue $publicationId = null, ) { - Assert::nullOrSame($creationInstant?->getTimeZone()->getName(), 'Z', ProtocolViolationException::class); } /** * Collect the value of the publisher-property * - * @return string + * @return \SimpleSAML\SAML2\Type\SAMLStringValue */ - public function getPublisher(): string + public function getPublisher(): SAMLStringValue { return $this->publisher; } @@ -61,9 +56,9 @@ public function getPublisher(): string /** * Collect the value of the creationInstant-property * - * @return \DateTimeImmutable|null + * @return \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null */ - public function getCreationInstant(): ?DateTimeImmutable + public function getCreationInstant(): ?SAMLDateTimeValue { return $this->creationInstant; } @@ -72,9 +67,9 @@ public function getCreationInstant(): ?DateTimeImmutable /** * Collect the value of the publicationId-property * - * @return string|null + * @return \SimpleSAML\SAML2\Type\SAMLStringValue|null */ - public function getPublicationId(): ?string + public function getPublicationId(): ?SAMLStringValue { return $this->publicationId; } @@ -86,9 +81,9 @@ public function getPublicationId(): ?string * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes */ public static function fromXML(DOMElement $xml): static @@ -96,19 +91,9 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'Publication', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, Publication::NS, InvalidDOMElementException::class); - $publisher = self::getAttribute($xml, 'publisher'); - $creationInstant = self::getOptionalAttribute($xml, 'creationInstant', null); - - // 2.2.1: Time values MUST be expressed in the UTC timezone using the 'Z' timezone identifier - if ($creationInstant !== null) { - // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications - $creationInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $creationInstant, 1); - - SAMLAssert::validDateTime($creationInstant, ProtocolViolationException::class); - $creationInstant = new DateTimeImmutable($creationInstant); - } - - $publicationId = self::getOptionalAttribute($xml, 'publicationId', null); + $publisher = self::getAttribute($xml, 'publisher', SAMLStringValue::class); + $creationInstant = self::getOptionalAttribute($xml, 'creationInstant', SAMLDateTimeValue::class, null); + $publicationId = self::getOptionalAttribute($xml, 'publicationId', SAMLStringValue::class, null); return new static($publisher, $creationInstant, $publicationId); } @@ -123,14 +108,14 @@ public static function fromXML(DOMElement $xml): static public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - $e->setAttribute('publisher', $this->getPublisher()); + $e->setAttribute('publisher', $this->getPublisher()->getValue()); if ($this->getCreationInstant() !== null) { - $e->setAttribute('creationInstant', $this->getCreationInstant()->format(C::DATETIME_FORMAT)); + $e->setAttribute('creationInstant', $this->getCreationInstant()->getValue()); } if ($this->getPublicationId() !== null) { - $e->setAttribute('publicationId', $this->getPublicationId()); + $e->setAttribute('publicationId', $this->getPublicationId()->getValue()); } return $e; @@ -148,9 +133,9 @@ public static function fromArray(array $data): static $data = self::processArrayContents($data); return new static( - $data['publisher'], - $data['creationInstant'] ?? null, - $data['publicationId'] ?? null, + SAMLStringValue::fromString($data['publisher']), + $data['creationInstant'] !== null ? SAMLDateTimeValue::fromString($data['creationInstant']) : null, + $data['publicationId'] !== null ? SAMLStringValue::fromString($data['publicationId']) : null, ); } @@ -178,8 +163,8 @@ private static function processArrayContents(array $data): array if (array_key_exists('creationinstant', $data)) { Assert::string($data['creationinstant'], ArrayValidationException::class); - SAMLAssert::validDateTime($data['creationinstant'], ArrayValidationException::class); - $retval['creationInstant'] = new DateTimeImmutable($data['creationinstant']); + Assert::validSAMLDateTime($data['creationinstant'], ArrayValidationException::class); + $retval['creationInstant'] = $data['creationinstant']; } if (array_key_exists('publicationid', $data)) { @@ -199,14 +184,14 @@ private static function processArrayContents(array $data): array public function toArray(): array { $data = []; - $data['publisher'] = $this->getPublisher(); + $data['publisher'] = $this->getPublisher()->getValue(); if ($this->getCreationInstant() !== null) { - $data['creationInstant'] = $this->getCreationInstant()->format(C::DATETIME_FORMAT); + $data['creationInstant'] = $this->getCreationInstant()->getValue(); } if ($this->getPublicationId() !== null) { - $data['publicationId'] = $this->getPublicationId(); + $data['publicationId'] = $this->getPublicationId()->getValue(); } return $data; diff --git a/src/XML/mdrpi/PublicationInfo.php b/src/XML/mdrpi/PublicationInfo.php index f3656103f..dc85068ec 100644 --- a/src/XML/mdrpi/PublicationInfo.php +++ b/src/XML/mdrpi/PublicationInfo.php @@ -4,21 +4,20 @@ namespace SimpleSAML\SAML2\XML\mdrpi; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Exception\ArrayValidationException; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\XML\ArrayizableElementInterface; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; use function array_change_key_case; use function array_keys; -use function preg_replace; /** * Class for handling the mdrpi:PublicationInfo element. @@ -36,18 +35,17 @@ final class PublicationInfo extends AbstractMdrpiElement implements /** * Create/parse a mdrpi:PublicationInfo element. * - * @param string $publisher - * @param \DateTimeImmutable|null $creationInstant - * @param string|null $publicationId + * @param \SimpleSAML\SAML2\Type\SAMLStringValue $publisher + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $creationInstant + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $publicationId * @param \SimpleSAML\SAML2\XML\mdrpi\UsagePolicy[] $usagePolicy */ public function __construct( - protected string $publisher, - protected ?DateTimeImmutable $creationInstant = null, - protected ?string $publicationId = null, + protected SAMLStringValue $publisher, + protected ?SAMLDateTimeValue $creationInstant = null, + protected ?SAMLStringValue $publicationId = null, protected array $usagePolicy = [], ) { - Assert::nullOrSame($creationInstant?->getTimeZone()->getName(), 'Z', ProtocolViolationException::class); Assert::maxCount($usagePolicy, C::UNBOUNDED_LIMIT); Assert::allIsInstanceOf($usagePolicy, UsagePolicy::class); @@ -73,9 +71,9 @@ function ($up) { /** * Collect the value of the publisher-property * - * @return string + * @return \SimpleSAML\SAML2\Type\SAMLStringValue */ - public function getPublisher(): string + public function getPublisher(): SAMLStringValue { return $this->publisher; } @@ -84,9 +82,9 @@ public function getPublisher(): string /** * Collect the value of the creationInstant-property * - * @return \DateTimeImmutable|null + * @return \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null */ - public function getCreationInstant(): ?DateTimeImmutable + public function getCreationInstant(): ?SAMLDateTimeValue { return $this->creationInstant; } @@ -95,9 +93,9 @@ public function getCreationInstant(): ?DateTimeImmutable /** * Collect the value of the publicationId-property * - * @return string|null + * @return \SimpleSAML\SAML2\Type\SAMLStringValue|null */ - public function getPublicationId(): ?string + public function getPublicationId(): ?SAMLStringValue { return $this->publicationId; } @@ -120,9 +118,9 @@ public function getUsagePolicy(): array * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes */ public static function fromXML(DOMElement $xml): static @@ -130,19 +128,9 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'PublicationInfo', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, PublicationInfo::NS, InvalidDOMElementException::class); - $publisher = self::getAttribute($xml, 'publisher'); - $creationInstant = self::getOptionalAttribute($xml, 'creationInstant', null); - - // 2.2.1: Time values MUST be expressed in the UTC timezone using the 'Z' timezone identifier - if ($creationInstant !== null) { - // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications - $creationInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $creationInstant, 1); - - SAMLAssert::validDateTime($creationInstant, ProtocolViolationException::class); - $creationInstant = new DateTimeImmutable($creationInstant); - } - - $publicationId = self::getOptionalAttribute($xml, 'publicationId', null); + $publisher = self::getAttribute($xml, 'publisher', SAMLStringValue::class); + $creationInstant = self::getOptionalAttribute($xml, 'creationInstant', SAMLDateTimeValue::class, null); + $publicationId = self::getOptionalAttribute($xml, 'publicationId', SAMLStringValue::class, null); $UsagePolicy = UsagePolicy::getChildrenOfClass($xml); return new static($publisher, $creationInstant, $publicationId, $UsagePolicy); @@ -158,14 +146,14 @@ public static function fromXML(DOMElement $xml): static public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - $e->setAttribute('publisher', $this->getPublisher()); + $e->setAttribute('publisher', $this->getPublisher()->getValue()); if ($this->getCreationInstant() !== null) { - $e->setAttribute('creationInstant', $this->getCreationInstant()->format(C::DATETIME_FORMAT)); + $e->setAttribute('creationInstant', $this->getCreationInstant()->getValue()); } if ($this->getPublicationId() !== null) { - $e->setAttribute('publicationId', $this->getPublicationId()); + $e->setAttribute('publicationId', $this->getPublicationId()->getValue()); } foreach ($this->getUsagePolicy() as $up) { @@ -187,9 +175,9 @@ public static function fromArray(array $data): static $data = self::processArrayContents($data); return new static( - $data['publisher'], - $data['creationInstant'] ?? null, - $data['publicationId'] ?? null, + SAMLStringValue::fromString($data['publisher']), + $data['creationInstant'] !== null ? SAMLDateTimeValue::fromString($data['creationInstant']) : null, + $data['publicationId'] !== null ? SAMLStringValue::fromString($data['publicationId']) : null, $data['UsagePolicy'] ?? [], ); } @@ -218,8 +206,8 @@ private static function processArrayContents(array $data): array if (array_key_exists('creationinstant', $data)) { Assert::string($data['creationinstant'], ArrayValidationException::class); - SAMLAssert::validDateTime($data['creationinstant'], ArrayValidationException::class); - $retval['creationInstant'] = new DateTimeImmutable($data['creationinstant']); + Assert::validSAMLDateTime($data['creationinstant'], ArrayValidationException::class); + $retval['creationInstant'] = $data['creationinstant']; } if (array_key_exists('publicationid', $data)) { @@ -246,14 +234,14 @@ private static function processArrayContents(array $data): array public function toArray(): array { $data = []; - $data['publisher'] = $this->getPublisher(); + $data['publisher'] = $this->getPublisher()->getValue(); if ($this->getCreationInstant() !== null) { - $data['creationInstant'] = $this->getCreationInstant()->format(C::DATETIME_FORMAT); + $data['creationInstant'] = $this->getCreationInstant()->getValue(); } if ($this->getPublicationId() !== null) { - $data['publicationId'] = $this->getPublicationId(); + $data['publicationId'] = $this->getPublicationId()->getValue(); } if (!empty($this->getUsagePolicy())) { diff --git a/src/XML/mdrpi/PublicationPath.php b/src/XML/mdrpi/PublicationPath.php index 756109c1b..96eccda8e 100644 --- a/src/XML/mdrpi/PublicationPath.php +++ b/src/XML/mdrpi/PublicationPath.php @@ -5,13 +5,13 @@ namespace SimpleSAML\SAML2\XML\mdrpi; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ArrayValidationException; use SimpleSAML\XML\ArrayizableElementInterface; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; /** * Class for handling the mdrpi:PublicationPath element. @@ -67,9 +67,9 @@ public function isEmptyElement(): bool * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes */ public static function fromXML(DOMElement $xml): static diff --git a/src/XML/mdrpi/RegistrationInfo.php b/src/XML/mdrpi/RegistrationInfo.php index 24fe1d700..6b6e44433 100644 --- a/src/XML/mdrpi/RegistrationInfo.php +++ b/src/XML/mdrpi/RegistrationInfo.php @@ -4,19 +4,17 @@ namespace SimpleSAML\SAML2\XML\mdrpi; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Exception\ArrayValidationException; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\XML\ArrayizableElementInterface; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; - -use function preg_replace; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; /** * Class for handling the mdrpi:RegistrationInfo element. @@ -34,16 +32,15 @@ final class RegistrationInfo extends AbstractMdrpiElement implements /** * Create/parse a mdrpi:RegistrationInfo element. * - * @param string $registrationAuthority - * @param \DateTimeImmutable|null $registrationInstant + * @param \SimpleSAML\SAML2\Type\SAMLStringValue $registrationAuthority + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $registrationInstant * @param \SimpleSAML\SAML2\XML\mdrpi\RegistrationPolicy[] $registrationPolicy */ public function __construct( - protected string $registrationAuthority, - protected ?DateTimeImmutable $registrationInstant = null, + protected SAMLStringValue $registrationAuthority, + protected ?SAMLDateTimeValue $registrationInstant = null, protected array $registrationPolicy = [], ) { - Assert::nullOrSame($registrationInstant?->getTimeZone()->getName(), 'Z', ProtocolViolationException::class); Assert::maxCount($registrationPolicy, C::UNBOUNDED_LIMIT); Assert::allIsInstanceOf($registrationPolicy, RegistrationPolicy::class); @@ -69,9 +66,9 @@ function ($rp) { /** * Collect the value of the RegistrationAuthority property * - * @return string + * @return \SimpleSAML\SAML2\Type\SAMLStringValue */ - public function getRegistrationAuthority(): string + public function getRegistrationAuthority(): SAMLStringValue { return $this->registrationAuthority; } @@ -80,9 +77,9 @@ public function getRegistrationAuthority(): string /** * Collect the value of the registrationInstant property * - * @return \DateTimeImmutable|null + * @return \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null */ - public function getRegistrationInstant(): ?DateTimeImmutable + public function getRegistrationInstant(): ?SAMLDateTimeValue { return $this->registrationInstant; } @@ -105,9 +102,9 @@ public function getRegistrationPolicy(): array * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes */ public static function fromXML(DOMElement $xml): static @@ -115,17 +112,8 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'RegistrationInfo', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, RegistrationInfo::NS, InvalidDOMElementException::class); - $registrationAuthority = self::getAttribute($xml, 'registrationAuthority'); - $registrationInstant = self::getOptionalAttribute($xml, 'registrationInstant', null); - - // 2.1.1: Time values MUST be expressed in the UTC timezone using the 'Z' timezone identifier - if ($registrationInstant !== null) { - // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications - $registrationInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $registrationInstant, 1); - - SAMLAssert::validDateTime($registrationInstant, ProtocolViolationException::class); - $registrationInstant = new DateTimeImmutable($registrationInstant); - } + $registrationAuthority = self::getAttribute($xml, 'registrationAuthority', SAMLStringValue::class); + $registrationInstant = self::getOptionalAttribute($xml, 'registrationInstant', SAMLDateTimeValue::class, null); $RegistrationPolicy = RegistrationPolicy::getChildrenOfClass($xml); return new static($registrationAuthority, $registrationInstant, $RegistrationPolicy); @@ -141,10 +129,10 @@ public static function fromXML(DOMElement $xml): static public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - $e->setAttribute('registrationAuthority', $this->getRegistrationAuthority()); + $e->setAttribute('registrationAuthority', $this->getRegistrationAuthority()->getValue()); if ($this->getRegistrationInstant() !== null) { - $e->setAttribute('registrationInstant', $this->getRegistrationInstant()->format(C::DATETIME_FORMAT)); + $e->setAttribute('registrationInstant', $this->getRegistrationInstant()->getValue()); } foreach ($this->getRegistrationPolicy() as $rp) { @@ -166,8 +154,8 @@ public static function fromArray(array $data): static $data = self::processArrayContents($data); return new static( - $data['registrationAuthority'], - $data['registrationInstant'] ?? null, + SAMLStringValue::fromString($data['registrationAuthority']), + $data['registrationInstant'] !== null ? SAMLDateTimeValue::fromString($data['registrationInstant']) : null, $data['RegistrationPolicy'] ?? [], ); } @@ -196,8 +184,8 @@ private static function processArrayContents(array $data): array if (array_key_exists('registrationinstant', $data)) { Assert::string($data['registrationinstant'], ArrayValidationException::class); - SAMLAssert::validDateTime($data['registrationinstant'], ArrayValidationException::class); - $retval['registrationInstant'] = new DateTimeImmutable($data['registrationinstant']); + Assert::validSAMLDateTime($data['registrationinstant'], ArrayValidationException::class); + $retval['registrationInstant'] = $data['registrationinstant']; } if (array_key_exists('registrationpolicy', $data)) { @@ -219,10 +207,10 @@ private static function processArrayContents(array $data): array public function toArray(): array { $data = []; - $data['registrationAuthority'] = $this->getRegistrationAuthority(); + $data['registrationAuthority'] = $this->getRegistrationAuthority()->getValue(); if ($this->getRegistrationInstant() !== null) { - $data['registrationInstant'] = $this->getRegistrationInstant()->format(C::DATETIME_FORMAT); + $data['registrationInstant'] = $this->getRegistrationInstant()->getValue(); } if (!empty($this->getRegistrationPolicy())) { diff --git a/src/XML/mdui/DiscoHints.php b/src/XML/mdui/DiscoHints.php index e33097ced..f644bc8b1 100644 --- a/src/XML/mdui/DiscoHints.php +++ b/src/XML/mdui/DiscoHints.php @@ -5,18 +5,20 @@ namespace SimpleSAML\SAML2\XML\mdui; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ArrayValidationException; -use SimpleSAML\SAML2\Utils\XPath; +use SimpleSAML\SAML2\Type\CIDRValue; +use SimpleSAML\SAML2\Type\DomainValue; +use SimpleSAML\SAML2\Type\GeolocationValue; use SimpleSAML\XML\ArrayizableElementInterface; use SimpleSAML\XML\Chunk; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\ExtendableElementTrait; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; use SimpleSAML\XML\SerializableElementInterface; -use SimpleSAML\XML\XsNamespace as NS; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\XML\Constants\NS; use function array_filter; use function array_key_exists; @@ -116,10 +118,10 @@ public function addChild(Chunk $child): void */ public function isEmptyElement(): bool { - return empty($this->elements) - && empty($this->ipHint) - && empty($this->domainHint) - && empty($this->geolocationHint); + return empty($this->getElements()) + && empty($this->getIPHint()) + && empty($this->getDomainHint()) + && empty($this->getGeolocationHint()); } @@ -129,7 +131,7 @@ public function isEmptyElement(): bool * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -140,13 +142,7 @@ public static function fromXML(DOMElement $xml): static $IPHint = IPHint::getChildrenOfClass($xml); $DomainHint = DomainHint::getChildrenOfClass($xml); $GeolocationHint = GeolocationHint::getChildrenOfClass($xml); - $children = []; - - /** @var \DOMElement[] $nodes */ - $nodes = XPath::xpQuery($xml, "./*[namespace-uri()!='" . DiscoHints::NS . "']", XPath::getXPath($xml)); - foreach ($nodes as $node) { - $children[] = new Chunk($node); - } + $children = self::getChildElementsFromXML($xml); return new static($children, $IPHint, $DomainHint, $GeolocationHint); } @@ -231,7 +227,9 @@ private static function processArrayContents(array $data): array Assert::isArray($data['iphint'], ArrayValidationException::class); Assert::allString($data['iphint'], ArrayValidationException::class); foreach ($data['iphint'] as $hint) { - $retval['IPHint'][] = new IPHint($hint); + $retval['IPHint'][] = new IPHint( + CIDRValue::fromString($hint), + ); } } @@ -239,7 +237,9 @@ private static function processArrayContents(array $data): array Assert::isArray($data['domainhint'], ArrayValidationException::class); Assert::allString($data['domainhint'], ArrayValidationException::class); foreach ($data['domainhint'] as $hint) { - $retval['DomainHint'][] = new DomainHint($hint); + $retval['DomainHint'][] = new DomainHint( + DomainValue::fromString($hint), + ); } } @@ -247,7 +247,9 @@ private static function processArrayContents(array $data): array Assert::isArray($data['geolocationhint'], ArrayValidationException::class); Assert::allString($data['geolocationhint'], ArrayValidationException::class); foreach ($data['geolocationhint'] as $hint) { - $retval['GeolocationHint'][] = new GeolocationHint($hint); + $retval['GeolocationHint'][] = new GeolocationHint( + GeolocationValue::fromString($hint), + ); } } diff --git a/src/XML/mdui/DomainHint.php b/src/XML/mdui/DomainHint.php index 715f9f2cf..266e2dbc0 100644 --- a/src/XML/mdui/DomainHint.php +++ b/src/XML/mdui/DomainHint.php @@ -4,17 +4,10 @@ namespace SimpleSAML\SAML2\XML\mdui; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Exception\InvalidArgumentException; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\StringElementTrait; +use SimpleSAML\SAML2\Type\DomainValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; - -use function filter_var; -use function preg_replace; -use function rtrim; -use function sprintf; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class implementing DomainHint. @@ -24,46 +17,9 @@ final class DomainHint extends AbstractMduiElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use StringElementTrait; - - - /** - * @param string $content - */ - public function __construct(string $content) - { - $this->setContent($content); - } - - - /** - * Sanitize the content of the element. - * - * @param string $content The unsanitized textContent - * @throws \Exception on failure - * @return string - */ - protected function sanitizeContent(string $content): string - { - // Remove prefixed schema and/or trailing whitespace + forward slashes - return rtrim(preg_replace('#^http[s]?://#i', '', $content), " \n\r\t\v\x00/"); - } - + use TypedTextContentTrait; - /** - * Validate the content of the element. - * - * @param string $content The value to go in the XML textContent - * @throws \Exception on failure - * @return void - */ - protected function validateContent(string $content): void - { - $sanitizedContent = $this->sanitizeContent($content); - Assert::notWhitespaceOnly($sanitizedContent, ProtocolViolationException::class); - if (!filter_var($sanitizedContent, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)) { - throw new InvalidArgumentException(sprintf('DomainHint is not a valid hostname; %s', $sanitizedContent)); - } - } + /** @var string */ + public const TEXTCONTENT_TYPE = DomainValue::class; } diff --git a/src/XML/mdui/GeolocationHint.php b/src/XML/mdui/GeolocationHint.php index c72a5e05e..abf21f978 100644 --- a/src/XML/mdui/GeolocationHint.php +++ b/src/XML/mdui/GeolocationHint.php @@ -4,12 +4,10 @@ namespace SimpleSAML\SAML2\XML\mdui; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\StringElementTrait; +use SimpleSAML\SAML2\Type\GeolocationValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class implementing GeolocationHint. @@ -19,62 +17,9 @@ final class GeolocationHint extends AbstractMduiElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use StringElementTrait; + use TypedTextContentTrait; - /** - * @param string $content - */ - public function __construct(string $content) - { - $this->setContent($content); - } - - - /** - * Set the content of the element. - * - * @param string $content The value to go in the XML textContent - */ - protected function setContent(string $content): void - { - $sanitized = $this->sanitizeContent($content); - $this->validateContent($sanitized); - - // Store the email address with any whitespace removed - $this->content = $sanitized; - } - - - /** - * Sanitize the content of the element. - * - * @param string $content The unsanitized textContent - * @throws \Exception on failure - * @return string - */ - protected function sanitizeContent(string $content): string - { - return preg_replace('/\s+/', '', $content); - } - - - /** - * Validate the content of the element. - * - * @param string $content The value to go in the XML textContent - * @throws \Exception on failure - * @return void - */ - protected function validateContent(string $content): void - { - Assert::notWhitespaceOnly($content, ProtocolViolationException::class); - // Assert::regex( - // $content, - // '/^geo:([-+]?\d+(?:\.\d+)?),([-+]?\d+(?:\.\d+)?)(?:\?z=(\d{1,2}))?$/', - // 'Content is not a valid geolocation: %s' - // ); - // The regex above is incomplete, so for now we only test for a valid URI - SAMLAssert::validURI($content); - } + /** @var string */ + public const TEXTCONTENT_TYPE = GeolocationValue::class; } diff --git a/src/XML/mdui/IPHint.php b/src/XML/mdui/IPHint.php index 18a039813..5e2af9119 100644 --- a/src/XML/mdui/IPHint.php +++ b/src/XML/mdui/IPHint.php @@ -4,9 +4,10 @@ namespace SimpleSAML\SAML2\XML\mdui; -use SimpleSAML\SAML2\XML\StringElementTrait; +use SimpleSAML\SAML2\Type\CIDRValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class implementing IPHint. @@ -16,14 +17,9 @@ final class IPHint extends AbstractMduiElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use StringElementTrait; + use TypedTextContentTrait; - /** - * @param string $content - */ - public function __construct(string $content) - { - $this->setContent($content); - } + /** @var string */ + public const TEXTCONTENT_TYPE = CIDRValue::class; } diff --git a/src/XML/mdui/Keywords.php b/src/XML/mdui/Keywords.php index 7c302bd3d..0e94f3a7e 100644 --- a/src/XML/mdui/Keywords.php +++ b/src/XML/mdui/Keywords.php @@ -5,18 +5,18 @@ namespace SimpleSAML\SAML2\XML\mdui; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ArrayValidationException; +use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\ListOfStringsValue; use SimpleSAML\XML\ArrayizableElementInterface; -use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Type\LanguageValue; use function array_key_first; -use function explode; -use function implode; -use function rtrim; /** * Class for handling the Keywords metadata extensions for login and discovery user interface @@ -29,68 +29,47 @@ final class Keywords extends AbstractMduiElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; + use TypedTextContentTrait; + + + /** @var string */ + public const TEXTCONTENT_TYPE = ListOfStringsValue::class; /** * Initialize a Keywords. * - * @param string $lang - * @param string[] $keywords + * @param \SimpleSAML\XMLSchema\Type\LanguageValue $lang + * @param \SimpleSAML\SAML2\Type\ListOfStringsValue $keywords */ public function __construct( - protected string $lang, - protected array $keywords = [], + protected LanguageValue $lang, + ListOfStringsValue $keywords, ) { - Assert::maxCount($keywords, C::UNBOUNDED_LIMIT); - Assert::allNotContains($keywords, '+', 'Keywords may not contain a "+" character.'); + $this->setContent($keywords); } /** * Collect the value of the lang-property * - * @return string + * @return \SimpleSAML\XMLSchema\Type\LanguageValue */ - public function getLanguage(): string + public function getLanguage(): LanguageValue { return $this->lang; } - /** - * Collect the value of the Keywords-property - * - * @return string[] - */ - public function getKeywords(): array - { - return $this->keywords; - } - - - /** - * Add the value to the Keywords-property - * - * @param string $keyword - * - * @throws \SimpleSAML\Assert\AssertionFailedException if the keyword contains a `+` - */ - public function addKeyword(string $keyword): void - { - Assert::notContains($keyword, '+', 'Keyword may not contain a "+" character.'); - $this->keywords[] = $keyword; - } - - /** * Convert XML into a Keywords * * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes */ public static function fromXML(DOMElement $xml): static @@ -99,8 +78,8 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->namespaceURI, Keywords::NS, InvalidDOMElementException::class); Assert::stringNotEmpty($xml->textContent, 'Missing value for Keywords.'); - $lang = self::getAttribute($xml, 'xml:lang'); - $Keywords = explode('+', $xml->textContent); + $lang = self::getAttribute($xml, 'xml:lang', LanguageValue::class); + $Keywords = ListOfStringsValue::fromString($xml->textContent); return new static($lang, $Keywords); } @@ -115,10 +94,9 @@ public static function fromXML(DOMElement $xml): static */ public function toXML(?DOMElement $parent = null): DOMElement { - /** @psalm-var \DOMDocument $e->ownerDocument */ $e = $this->instantiateParentElement($parent); - $e->setAttribute('xml:lang', $this->getLanguage()); - $e->textContent = rtrim(implode('+', $this->getKeywords())); + $e->setAttribute('xml:lang', $this->getLanguage()->getValue()); + $e->textContent = $this->getContent()->getValue(); return $e; } @@ -135,10 +113,12 @@ public static function fromArray(array $data): static Assert::notEmpty($data, ArrayValidationException::class); Assert::count($data, 1, ArrayValidationException::class); - $lang = array_key_first($data); - $keywords = $data[$lang]; + $lang = LanguageValue::fromString(array_key_first($data)); + $keywords = $data[$lang->getValue()]; - return new static($lang, $keywords); + Assert::allNotContains($keywords, '+', ProtocolViolationException::class); + + return new static($lang, ListOfStringsValue::fromArray($keywords)); } @@ -149,6 +129,9 @@ public static function fromArray(array $data): static */ public function toArray(): array { - return [$this->getLanguage() => $this->getKeywords()]; + /** @var \SimpleSAML\SAML2\Type\ListOfStringsValue $content */ + $content = $this->getContent(); + + return [$this->getLanguage()->getValue() => $content->toArray()]; } } diff --git a/src/XML/mdui/Logo.php b/src/XML/mdui/Logo.php index 2c553d356..7573c5f81 100644 --- a/src/XML/mdui/Logo.php +++ b/src/XML/mdui/Logo.php @@ -5,21 +5,18 @@ namespace SimpleSAML\SAML2\XML\mdui; use DOMElement; -use InvalidArgumentException; -use SimpleSAML\Assert\Assert; -//use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ArrayValidationException; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\StringElementTrait; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\XML\ArrayizableElementInterface; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; - -use function filter_var; -use function strval; -use function substr; -use function trim; +use SimpleSAML\XML\TypedTextContentTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\SchemaViolationException; +use SimpleSAML\XMLSchema\Type\LanguageValue; +use SimpleSAML\XMLSchema\Type\PositiveIntegerValue; /** * Class for handling the Logo metadata extensions for login and discovery user interface @@ -32,22 +29,30 @@ final class Logo extends AbstractMduiElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use StringElementTrait; + use TypedTextContentTrait; + + + /** @var string */ + public const TEXTCONTENT_TYPE = SAMLAnyURIValue::class; + + + /** @var string */ + private static string $scheme_regex = '/^(data|http[s]?[:])/i'; /** * Initialize a Logo. * - * @param string $url - * @param int $height - * @param int $width - * @param string|null $lang + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $url + * @param \SimpleSAML\XMLSchema\Type\PositiveIntegerValue $height + * @param \SimpleSAML\XMLSchema\Type\PositiveIntegerValue $width + * @param \SimpleSAML\XMLSchema\Type\LanguageValue|null $lang */ public function __construct( - protected string $url, - protected int $height, - protected int $width, - protected ?string $lang = null, + SAMLAnyURIValue $url, + protected PositiveIntegerValue $height, + protected PositiveIntegerValue $width, + protected ?LanguageValue $lang = null, ) { $this->setContent($url); } @@ -62,21 +67,17 @@ public function __construct( */ protected function validateContent(string $content): void { - // NOTE: we override the validateContent from the trait to be able to be less restrictive - // SAMLAssert::validURI($content, SchemaViolationException::class); - Assert::notWhitespaceOnly($content, ProtocolViolationException::class); - if (!filter_var(trim($content), FILTER_VALIDATE_URL) && substr(trim($content), 0, 5) !== 'data:') { - throw new InvalidArgumentException('mdui:Logo is not a valid URL.'); - } + Assert::validURI($content, SchemaViolationException::class); + Assert::regex(self::$scheme_regex, $content, ProtocolViolationException::class); } /** * Collect the value of the lang-property * - * @return string|null + * @return \SimpleSAML\XMLSchema\Type\LanguageValue|null */ - public function getLanguage(): ?string + public function getLanguage(): ?LanguageValue { return $this->lang; } @@ -85,9 +86,9 @@ public function getLanguage(): ?string /** * Collect the value of the height-property * - * @return int + * @return \SimpleSAML\XMLSchema\Type\PositiveIntegerValue */ - public function getHeight(): int + public function getHeight(): PositiveIntegerValue { return $this->height; } @@ -96,9 +97,9 @@ public function getHeight(): int /** * Collect the value of the width-property * - * @return int + * @return \SimpleSAML\XMLSchema\Type\PositiveIntegerValue */ - public function getWidth(): int + public function getWidth(): PositiveIntegerValue { return $this->width; } @@ -110,9 +111,9 @@ public function getWidth(): int * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes */ public static function fromXML(DOMElement $xml): static @@ -121,10 +122,10 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->namespaceURI, Logo::NS, InvalidDOMElementException::class); Assert::stringNotEmpty($xml->textContent, 'Missing url value for Logo.'); - $Url = $xml->textContent; - $Width = self::getIntegerAttribute($xml, 'width'); - $Height = self::getIntegerAttribute($xml, 'height'); - $lang = self::getOptionalAttribute($xml, 'xml:lang', null); + $Url = SAMLAnyURIValue::fromString($xml->textContent); + $Width = self::getAttribute($xml, 'width', PositiveIntegerValue::class); + $Height = self::getAttribute($xml, 'height', PositiveIntegerValue::class); + $lang = self::getOptionalAttribute($xml, 'xml:lang', LanguageValue::class, null); return new static($Url, $Height, $Width, $lang); } @@ -139,12 +140,12 @@ public static function fromXML(DOMElement $xml): static public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - $e->textContent = $this->getContent(); - $e->setAttribute('height', strval($this->getHeight())); - $e->setAttribute('width', strval($this->getWidth())); + $e->textContent = $this->getContent()->getValue(); + $e->setAttribute('height', $this->getHeight()->getValue()); + $e->setAttribute('width', $this->getWidth()->getValue()); if ($this->getLanguage() !== null) { - $e->setAttribute('xml:lang', $this->getLanguage()); + $e->setAttribute('xml:lang', $this->getLanguage()->getValue()); } return $e; @@ -161,7 +162,12 @@ public static function fromArray(array $data): static { $data = self::processArrayContents($data); - return new static($data['url'], $data['height'], $data['width'], $data['lang'] ?? null); + return new static( + SAMLAnyURIValue::fromString($data['url']), + PositiveIntegerValue::fromInteger($data['height']), + PositiveIntegerValue::fromInteger($data['width']), + $data['lang'] !== null ? LanguageValue::fromString($data['lang']) : null, + ); } @@ -217,12 +223,12 @@ private static function processArrayContents(array $data): array */ public function toArray(): array { - $lang = $this->getLanguage(); + $lang = $this->getLanguage()?->getValue(); return [ - 'url' => $this->getContent(), - 'width' => $this->getWidth(), - 'height' => $this->getHeight(), + 'url' => $this->getContent()->getValue(), + 'width' => $this->getWidth()->toInteger(), + 'height' => $this->getHeight()->toInteger(), ] + (isset($lang) ? ['lang' => $lang] : []); } } diff --git a/src/XML/mdui/UIInfo.php b/src/XML/mdui/UIInfo.php index 0d1e82c31..0f2e7002f 100644 --- a/src/XML/mdui/UIInfo.php +++ b/src/XML/mdui/UIInfo.php @@ -5,19 +5,18 @@ namespace SimpleSAML\SAML2\XML\mdui; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ArrayValidationException; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\XML\ArrayizableElementInterface; use SimpleSAML\XML\Chunk; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\ExtendableElementTrait; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; use SimpleSAML\XML\SerializableElementInterface; -use SimpleSAML\XML\XsNamespace as NS; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\XML\Constants\NS; use function array_filter; use function array_key_exists; @@ -222,20 +221,20 @@ public function addChild(Chunk $child): void */ public function isEmptyElement(): bool { - return empty($this->displayName) - && empty($this->description) - && empty($this->informationURL) - && empty($this->privacyStatementURL) - && empty($this->keywords) - && empty($this->logo) - && empty($this->elements); + return empty($this->getDisplayName()) + && empty($this->getDescription()) + && empty($this->getInformationURL()) + && empty($this->getPrivacyStatementURL()) + && empty($this->getKeywords()) + && empty($this->getLogo()) + && empty($this->getElements()); } /** * Test localized elements for multiple items with the same language * - * @param (\SimpleSAML\SAML2\XML\md\AbstractLocalizedURL| + * @param (\SimpleSAML\SAML2\XML\md\AbstractLocalizedURI| * \SimpleSAML\SAML2\XML\md\AbstractLocalizedName| * \SimpleSAML\SAML2\XML\mdui\Keywords)[] $elements * @return void @@ -268,7 +267,7 @@ function ($elt) { * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -282,14 +281,7 @@ public static function fromXML(DOMElement $xml): static $PrivacyStatementURL = PrivacyStatementURL::getChildrenOfClass($xml); $Keywords = Keywords::getChildrenOfClass($xml); $Logo = Logo::getChildrenOfClass($xml); - $children = []; - - /** @var \DOMElement $node */ - foreach (XPath::xpQuery($xml, './*', XPath::getXPath($xml)) as $node) { - if ($node->namespaceURI !== UIInfo::NS) { - $children[] = new Chunk($node); - } - } + $children = self::getChildElementsFromXML($xml); return new static( $DisplayName, diff --git a/src/XML/saml/AbstractBaseID.php b/src/XML/saml/AbstractBaseID.php index f32d54c69..96585e77e 100644 --- a/src/XML/saml/AbstractBaseID.php +++ b/src/XML/saml/AbstractBaseID.php @@ -7,22 +7,22 @@ use DOMElement; use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\XML\EncryptableElementTrait; use SimpleSAML\SAML2\XML\ExtensionPointInterface; use SimpleSAML\SAML2\XML\ExtensionPointTrait; use SimpleSAML\XML\Attribute as XMLAttribute; use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\SchemaViolationException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Constants as C_XSI; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\SchemaViolationException; +use SimpleSAML\XMLSchema\Type\QNameValue; use SimpleSAML\XMLSecurity\Backend\EncryptionBackend; use SimpleSAML\XMLSecurity\XML\EncryptableElementInterface; -use function count; -use function explode; - /** * SAML BaseID data type. * @@ -45,23 +45,23 @@ abstract class AbstractBaseID extends AbstractBaseIDType implements /** * Initialize a saml:BaseID from scratch * - * @param string $type - * @param string|null $NameQualifier - * @param string|null $SPNameQualifier + * @param \SimpleSAML\XMLSchema\Type\QNameValue $type + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $NameQualifier + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $SPNameQualifier */ protected function __construct( - protected string $type, - ?string $NameQualifier = null, - ?string $SPNameQualifier = null, + protected QNameValue $type, + ?SAMLStringValue $NameQualifier = null, + ?SAMLStringValue $SPNameQualifier = null, ) { parent::__construct($NameQualifier, $SPNameQualifier); } /** - * @inheritDoc + * @return \SimpleSAML\XMLSchema\Type\QNameValue */ - public function getXsiType(): string + public function getXsiType(): QNameValue { return $this->type; } @@ -73,7 +73,7 @@ public function getXsiType(): string * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -81,24 +81,12 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'BaseID', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, C::NS_SAML, InvalidDOMElementException::class); Assert::true( - $xml->hasAttributeNS(C::NS_XSI, 'type'), + $xml->hasAttributeNS(C_XSI::NS_XSI, 'type'), 'Missing required xsi:type in element.', SchemaViolationException::class, ); - $type = $xml->getAttributeNS(C::NS_XSI, 'type'); - Assert::validQName($type, SchemaViolationException::class); - - // first, try to resolve the type to a full namespaced version - $qname = explode(':', $type, 2); - if (count($qname) === 2) { - list($prefix, $element) = $qname; - } else { - $prefix = null; - list($element) = $qname; - } - $ns = $xml->lookupNamespaceUri($prefix); - $type = ($ns === null) ? $element : implode(':', [$ns, $element]); + $type = QNameValue::fromDocument($xml->getAttributeNS(C_XSI::NS_XSI, 'type'), $xml); // now check if we have a handler registered for it $handler = Utils::getContainer()->getExtensionHandler($type); @@ -107,8 +95,8 @@ public static function fromXML(DOMElement $xml): static return new UnknownID( new Chunk($xml), $type, - self::getOptionalAttribute($xml, 'NameQualifier', null), - self::getOptionalAttribute($xml, 'SPNameQualifier', null), + self::getOptionalAttribute($xml, 'NameQualifier', SAMLStringValue::class, null), + self::getOptionalAttribute($xml, 'SPNameQualifier', SAMLStringValue::class, null), ); } @@ -133,18 +121,18 @@ public function toXML(?DOMElement $parent = null): DOMElement $e->setAttributeNS( 'http://www.w3.org/2000/xmlns/', 'xmlns:' . static::getXsiTypePrefix(), - static::getXsiTypeNamespaceURI(), + static::getXsiTypeNamespaceURI()->getValue(), ); - $type = new XMLAttribute(C::NS_XSI, 'xsi', 'type', $this->getXsiType()); + $type = new XMLAttribute(C_XSI::NS_XSI, 'xsi', 'type', $this->getXsiType()); $type->toXML($e); if ($this->getNameQualifier() !== null) { - $e->setAttribute('NameQualifier', $this->getNameQualifier()); + $e->setAttribute('NameQualifier', $this->getNameQualifier()->getValue()); } if ($this->getSPNameQualifier() !== null) { - $e->setAttribute('SPNameQualifier', $this->getSPNameQualifier()); + $e->setAttribute('SPNameQualifier', $this->getSPNameQualifier()->getValue()); } return $e; diff --git a/src/XML/saml/AbstractBaseIDType.php b/src/XML/saml/AbstractBaseIDType.php index 6e0536c68..d6c11c696 100644 --- a/src/XML/saml/AbstractBaseIDType.php +++ b/src/XML/saml/AbstractBaseIDType.php @@ -5,7 +5,8 @@ namespace SimpleSAML\SAML2\XML\saml; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\SAMLStringValue; /** * SAML BaseID data type. @@ -20,16 +21,16 @@ abstract class AbstractBaseIDType extends AbstractSamlElement implements BaseIde /** * Initialize a saml:BaseIDAbstractType from scratch * - * @param string|null $NameQualifier + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $NameQualifier * The security or administrative domain that qualifies the identifier. * This attribute provides a means to federate identifiers from disparate user stores without collision. - * @param string|null $SPNameQualifier + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $SPNameQualifier * Further qualifies an identifier with the name of a service provider or affiliation of providers. This * attribute provides an additional means to federate identifiers on the basis of the relying party or parties. */ protected function __construct( - protected ?string $NameQualifier = null, - protected ?string $SPNameQualifier = null, + protected ?SAMLStringValue $NameQualifier = null, + protected ?SAMLStringValue $SPNameQualifier = null, ) { Assert::nullOrNotWhitespaceOnly($NameQualifier); Assert::nullOrNotWhitespaceOnly($SPNameQualifier); @@ -47,11 +48,11 @@ public function toXML(?DOMElement $parent = null): DOMElement $e = $this->instantiateParentElement($parent); if ($this->getNameQualifier() !== null) { - $e->setAttribute('NameQualifier', $this->getNameQualifier()); + $e->setAttribute('NameQualifier', $this->getNameQualifier()->getValue()); } if ($this->getSPNameQualifier() !== null) { - $e->setAttribute('SPNameQualifier', $this->getSPNameQualifier()); + $e->setAttribute('SPNameQualifier', $this->getSPNameQualifier()->getValue()); } return $e; diff --git a/src/XML/saml/AbstractCondition.php b/src/XML/saml/AbstractCondition.php index 2bdd80192..a7bc84b89 100644 --- a/src/XML/saml/AbstractCondition.php +++ b/src/XML/saml/AbstractCondition.php @@ -12,13 +12,12 @@ use SimpleSAML\SAML2\XML\ExtensionPointTrait; use SimpleSAML\XML\Attribute as XMLAttribute; use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\SchemaViolationException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; - -use function count; -use function explode; +use SimpleSAML\XMLSchema\Constants as C_XSI; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\SchemaViolationException; +use SimpleSAML\XMLSchema\Type\QNameValue; /** * SAML Condition data type. @@ -40,18 +39,18 @@ abstract class AbstractCondition extends AbstractConditionType implements /** * Initialize a custom saml:Condition element. * - * @param string $type + * @param \SimpleSAML\XMLSchema\Type\QNameValue $type */ protected function __construct( - protected string $type, + protected QNameValue $type, ) { } /** - * @inheritDoc + * @return \SimpleSAML\XMLSchema\Type\QNameValue */ - public function getXsiType(): string + public function getXsiType(): QNameValue { return $this->type; } @@ -63,7 +62,7 @@ public function getXsiType(): string * @param \DOMElement $xml The root XML element * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -71,24 +70,12 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'Condition', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, C::NS_SAML, InvalidDOMElementException::class); Assert::true( - $xml->hasAttributeNS(C::NS_XSI, 'type'), + $xml->hasAttributeNS(C_XSI::NS_XSI, 'type'), 'Missing required xsi:type in element.', SchemaViolationException::class, ); - $type = $xml->getAttributeNS(C::NS_XSI, 'type'); - Assert::validQName($type, SchemaViolationException::class); - - // first, try to resolve the type to a full namespaced version - $qname = explode(':', $type, 2); - if (count($qname) === 2) { - list($prefix, $element) = $qname; - } else { - $prefix = null; - list($element) = $qname; - } - $ns = $xml->lookupNamespaceUri($prefix); - $type = ($ns === null) ? $element : implode(':', [$ns, $element]); + $type = QNameValue::fromDocument($xml->getAttributeNS(C_XSI::NS_XSI, 'type'), $xml); // now check if we have a handler registered for it $handler = Utils::getContainer()->getExtensionHandler($type); @@ -118,10 +105,10 @@ public function toXML(?DOMElement $parent = null): DOMElement $e->setAttributeNS( 'http://www.w3.org/2000/xmlns/', 'xmlns:' . static::getXsiTypePrefix(), - static::getXsiTypeNamespaceURI(), + static::getXsiTypeNamespaceURI()->getValue(), ); - $type = new XMLAttribute(C::NS_XSI, 'xsi', 'type', $this->getXsiType()); + $type = new XMLAttribute(C_XSI::NS_XSI, 'xsi', 'type', $this->getXsiType()); $type->toXML($e); return $e; diff --git a/src/XML/saml/AbstractStatement.php b/src/XML/saml/AbstractStatement.php index 4883e7c32..683a8444c 100644 --- a/src/XML/saml/AbstractStatement.php +++ b/src/XML/saml/AbstractStatement.php @@ -12,13 +12,12 @@ use SimpleSAML\SAML2\XML\ExtensionPointTrait; use SimpleSAML\XML\Attribute as XMLAttribute; use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\SchemaViolationException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; - -use function count; -use function explode; +use SimpleSAML\XMLSchema\Constants as C_XSI; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\SchemaViolationException; +use SimpleSAML\XMLSchema\Type\QNameValue; /** * Class implementing the extension point. @@ -40,18 +39,18 @@ abstract class AbstractStatement extends AbstractStatementType implements /** * Initialize a custom saml:Statement element. * - * @param string $type + * @param \SimpleSAML\XMLSchema\Type\QNameValue $type */ protected function __construct( - protected string $type, + protected QNameValue $type, ) { } /** - * @inheritDoc + * @return \SimpleSAML\XMLSchema\Type\QNameValue */ - public function getXsiType(): string + public function getXsiType(): QNameValue { return $this->type; } @@ -63,7 +62,7 @@ public function getXsiType(): string * @param \DOMElement $xml The root XML element * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -71,24 +70,12 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'Statement', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, C::NS_SAML, InvalidDOMElementException::class); Assert::true( - $xml->hasAttributeNS(C::NS_XSI, 'type'), + $xml->hasAttributeNS(C_XSI::NS_XSI, 'type'), 'Missing required xsi:type in element.', SchemaViolationException::class, ); - $type = $xml->getAttributeNS(C::NS_XSI, 'type'); - Assert::validQName($type, SchemaViolationException::class); - - // first, try to resolve the type to a full namespaced version - $qname = explode(':', $type, 2); - if (count($qname) === 2) { - list($prefix, $element) = $qname; - } else { - $prefix = null; - list($element) = $qname; - } - $ns = $xml->lookupNamespaceUri($prefix); - $type = ($ns === null) ? $element : implode(':', [$ns, $element]); + $type = QNameValue::fromDocument($xml->getAttributeNS(C_XSI::NS_XSI, 'type'), $xml); // now check if we have a handler registered for it $handler = Utils::getContainer()->getExtensionHandler($type); @@ -118,10 +105,10 @@ public function toXML(?DOMElement $parent = null): DOMElement $e->setAttributeNS( 'http://www.w3.org/2000/xmlns/', 'xmlns:' . static::getXsiTypePrefix(), - static::getXsiTypeNamespaceURI(), + static::getXsiTypeNamespaceURI()->getValue(), ); - $type = new XMLAttribute(C::NS_XSI, 'xsi', 'type', $this->getXsiType()); + $type = new XMLAttribute(C_XSI::NS_XSI, 'xsi', 'type', $this->getXsiType()); $type->toXML($e); return $e; diff --git a/src/XML/saml/Action.php b/src/XML/saml/Action.php index 7621ad65a..1c8275d3c 100644 --- a/src/XML/saml/Action.php +++ b/src/XML/saml/Action.php @@ -5,10 +5,13 @@ namespace SimpleSAML\SAML2\XML\saml; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; -use SimpleSAML\SAML2\XML\StringElementTrait; -use SimpleSAML\XML\Exception\InvalidDOMElementException; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\XML\TypedTextContentTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; + +use function strval; /** * Class representing SAML2 Action @@ -17,21 +20,24 @@ */ final class Action extends AbstractSamlElement { - use StringElementTrait; + use TypedTextContentTrait; + + + /** @var string */ + public const TEXTCONTENT_TYPE = SAMLStringValue::class; /** * Initialize an Action. * - * @param string $namespace This attribute was marked REQUIRED in the 2012 SAML errata (E36) - * @param string $content + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $namespace + * NOTE: The namespace-attribute was marked REQUIRED in the 2012 SAML errata (E36) + * @param \SimpleSAML\SAML2\Type\SAMLStringValue $content */ public function __construct( - protected string $namespace, - string $content, + protected SAMLAnyURIValue $namespace, + SAMLStringValue $content, ) { - SAMLAssert::validURI($namespace); - $this->setContent($content); } @@ -39,9 +45,9 @@ public function __construct( /** * Collect the value of the namespace-property * - * @return string + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue */ - public function getNamespace(): string + public function getNamespace(): SAMLAnyURIValue { return $this->namespace; } @@ -53,7 +59,7 @@ public function getNamespace(): string * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -62,8 +68,8 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->namespaceURI, Action::NS, InvalidDOMElementException::class); return new self( - self::getAttribute($xml, 'Namespace'), - $xml->textContent, + self::getAttribute($xml, 'Namespace', SAMLAnyURIValue::class), + SAMLStringValue::fromString($xml->textContent), ); } @@ -78,8 +84,8 @@ public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - $e->setAttribute('Namespace', $this->getNamespace()); - $e->textContent = $this->getContent(); + $e->setAttribute('Namespace', strval($this->getNamespace())); + $e->textContent = strval($this->getContent()); return $e; } diff --git a/src/XML/saml/Advice.php b/src/XML/saml/Advice.php index 28f221f8a..192176337 100644 --- a/src/XML/saml/Advice.php +++ b/src/XML/saml/Advice.php @@ -5,14 +5,14 @@ namespace SimpleSAML\SAML2\XML\saml; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\SchemaViolationException; use SimpleSAML\XML\ExtendableElementTrait; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; -use SimpleSAML\XML\XsNamespace as NS; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\SchemaViolationException; +use SimpleSAML\XMLSchema\XML\Constants\NS; /** * Class representing a saml:Advice element. @@ -113,7 +113,7 @@ public function getEncryptedAssertion(): array * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * If the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static diff --git a/src/XML/saml/Assertion.php b/src/XML/saml/Assertion.php index 224a27b5f..64af86bab 100644 --- a/src/XML/saml/Assertion.php +++ b/src/XML/saml/Assertion.php @@ -4,21 +4,23 @@ namespace SimpleSAML\SAML2\XML\saml; -use DateTimeImmutable; use DOMElement; use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooHighException; +use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\EncryptableElementTrait; use SimpleSAML\SAML2\XML\SignableElementTrait; use SimpleSAML\SAML2\XML\SignedElementTrait; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; -use SimpleSAML\XML\Utils\Random as RandomUtils; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\Backend\EncryptionBackend; use SimpleSAML\XMLSecurity\XML\ds\Signature; use SimpleSAML\XMLSecurity\XML\EncryptableElementInterface; @@ -29,6 +31,7 @@ use function array_merge; use function array_pop; use function array_values; +use function strval; /** * Class representing a SAML 2 assertion. @@ -45,6 +48,8 @@ final class Assertion extends AbstractSamlElement implements EncryptableElementTrait::getBlacklistedAlgorithms insteadof SignedElementTrait; EncryptableElementTrait::getBlacklistedAlgorithms insteadof SignableElementTrait; } + + use SchemaValidatableElementTrait; use SignableElementTrait; use SignedElementTrait; @@ -67,29 +72,26 @@ final class Assertion extends AbstractSamlElement implements * Assertion constructor. * * @param \SimpleSAML\SAML2\XML\saml\Issuer $issuer - * @param string|null $id - * @param \DateTimeImmutable $issueInstant + * @param \SimpleSAML\XMLSchema\Type\IDValue $id + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue $issueInstant * @param \SimpleSAML\SAML2\XML\saml\Subject|null $subject * @param \SimpleSAML\SAML2\XML\saml\Conditions|null $conditions * @param \SimpleSAML\SAML2\XML\saml\AbstractStatementType[] $statements */ public function __construct( protected Issuer $issuer, - protected DateTimeImmutable $issueInstant, - protected ?string $id = null, + protected SAMLDateTimeValue $issueInstant, + protected IDValue $id, protected ?Subject $subject = null, protected ?Conditions $conditions = null, protected array $statements = [], ) { - Assert::same($issueInstant->getTimeZone()->getName(), 'Z', ProtocolViolationException::class); - Assert::nullOrValidNCName($id); // Covers the empty string Assert::true( $subject || !empty($statements), "Either a or some statement must be present in a ", ); Assert::maxCount($statements, C::UNBOUNDED_LIMIT); Assert::allIsInstanceOf($statements, AbstractStatementType::class); - Assert::nullOrNotWhitespaceOnly($id); } @@ -151,14 +153,10 @@ public function getStatements(): array /** * Retrieve the identifier of this assertion. * - * @return string The identifier of this assertion. + * @return \SimpleSAML\XMLSchema\Type\IDValue The identifier of this assertion. */ - public function getId(): string + public function getId(): IDValue { - if ($this->id === null) { - return (new RandomUtils())->generateId(); - } - return $this->id; } @@ -166,9 +164,9 @@ public function getId(): string /** * Retrieve the issue timestamp of this assertion. * - * @return \DateTimeImmutable The issue timestamp of this assertion, as an UNIX timestamp. + * @return \SimpleSAML\SAML2\Type\SAMLDateTimeValue The issue timestamp of this assertion, as an UNIX timestamp. */ - public function getIssueInstant(): DateTimeImmutable + public function getIssueInstant(): SAMLDateTimeValue { return $this->issueInstant; } @@ -240,29 +238,24 @@ public function getEncryptionBackend(): ?EncryptionBackend * @return static * * @throws \SimpleSAML\Assert\AssertionFailedException if assertions are false - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes - * @throws \SimpleSAML\XML\Exception\MissingElementException if one of the mandatory child-elements is missing - * @throws \SimpleSAML\XML\Exception\TooManyElementsException if too many child-elements of a type are specified + * @throws \SimpleSAML\XMLSchema\Exception\MissingElementException + * if one of the mandatory child-elements is missing + * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException + * if too many child-elements of a type are specified * @throws \Exception */ public static function fromXML(DOMElement $xml): static { Assert::same($xml->localName, 'Assertion', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, Assertion::NS, InvalidDOMElementException::class); - Assert::same(self::getAttribute($xml, 'Version'), '2.0', 'Unsupported version: %s'); - - $id = self::getAttribute($xml, 'ID'); - Assert::validNCName($id); // Covers the empty string - - $issueInstant = self::getAttribute($xml, 'IssueInstant'); - // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications - $issueInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $issueInstant, 1); - Assert::validDateTime($issueInstant, ProtocolViolationException::class); - $issueInstant = new DateTimeImmutable($issueInstant); + $version = self::getAttribute($xml, 'Version', SAMLStringValue::class); + Assert::true(version_compare('2.0', strval($version), '<='), RequestVersionTooLowException::class); + Assert::true(version_compare('2.0', strval($version), '>='), RequestVersionTooHighException::class); $issuer = Issuer::getChildrenOfClass($xml); Assert::minCount($issuer, 1, 'Missing in assertion.', MissingElementException::class); @@ -293,8 +286,8 @@ public static function fromXML(DOMElement $xml): static $assertion = new static( array_pop($issuer), - $issueInstant, - $id, + self::getAttribute($xml, 'IssueInstant', SAMLDateTimeValue::class), + self::getAttribute($xml, 'ID', IDValue::class), array_pop($subject), array_pop($conditions), array_merge($authnStatement, $attrStatement, $statements), @@ -321,8 +314,8 @@ protected function toUnsignedXML(?DOMElement $parent = null): DOMElement $e = $this->instantiateParentElement($parent); $e->setAttribute('Version', '2.0'); - $e->setAttribute('ID', $this->getId()); - $e->setAttribute('IssueInstant', $this->getIssueInstant()->format(C::DATETIME_FORMAT)); + $e->setAttribute('ID', strval($this->getId())); + $e->setAttribute('IssueInstant', strval($this->getIssueInstant())); $this->getIssuer()->toXML($e); $this->getSubject()?->toXML($e); diff --git a/src/XML/saml/AssertionIDRef.php b/src/XML/saml/AssertionIDRef.php index 514f8b13e..71d09e9bd 100644 --- a/src/XML/saml/AssertionIDRef.php +++ b/src/XML/saml/AssertionIDRef.php @@ -4,11 +4,10 @@ namespace SimpleSAML\SAML2\XML\saml; -use SimpleSAML\SAML2\Assert\Assert; -use SimpleSAML\SAML2\XML\StringElementTrait; -use SimpleSAML\XML\Exception\SchemaViolationException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; +use SimpleSAML\XMLSchema\Type\NCNameValue; /** * Class representing a saml:AssertionIDRef element. @@ -18,30 +17,9 @@ final class AssertionIDRef extends AbstractSamlElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use StringElementTrait { - StringElementTrait::validateContent as baseValidateContent; - } + use TypedTextContentTrait; - /** - * @param string $content - */ - public function __construct(string $content) - { - $this->setContent($content); - } - - - /** - * Validate the content of the element. - * - * @param string $content The value to go in the XML textContent - * @throws \Exception on failure - * @return void - */ - protected function validateContent(string $content): void - { - $this->baseValidateContent($content); - Assert::validNCName($content, SchemaViolationException::class); - } + /** @var string */ + public const TEXTCONTENT_TYPE = NCNameValue::class; } diff --git a/src/XML/saml/AssertionURIRef.php b/src/XML/saml/AssertionURIRef.php index 16634123f..b4d4e8a95 100644 --- a/src/XML/saml/AssertionURIRef.php +++ b/src/XML/saml/AssertionURIRef.php @@ -4,9 +4,10 @@ namespace SimpleSAML\SAML2\XML\saml; -use SimpleSAML\SAML2\XML\URIElementTrait; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class representing a saml:AssertionURIRef element. @@ -16,14 +17,9 @@ final class AssertionURIRef extends AbstractSamlElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use URIElementTrait; + use TypedTextContentTrait; - /** - * @param string $content - */ - public function __construct(string $content) - { - $this->setContent($content); - } + /** @var string */ + public const TEXTCONTENT_TYPE = SAMLAnyURIValue::class; } diff --git a/src/XML/saml/Attribute.php b/src/XML/saml/Attribute.php index 969fdb52a..a0900bc7d 100644 --- a/src/XML/saml/Attribute.php +++ b/src/XML/saml/Attribute.php @@ -7,15 +7,19 @@ use DOMElement; use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\EncryptableElementTrait; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\ExtendableAttributesTrait; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; -use SimpleSAML\XML\XsNamespace as NS; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\XML\Constants\NS; use SimpleSAML\XMLSecurity\Backend\EncryptionBackend; use SimpleSAML\XMLSecurity\XML\EncryptableElementInterface; +use function strval; + /** * Class representing SAML 2 Attribute. * @@ -37,35 +41,35 @@ class Attribute extends AbstractSamlElement implements /** * Initialize an Attribute. * - * @param string $name - * @param string|null $nameFormat - * @param string|null $friendlyName + * @param \SimpleSAML\SAML2\Type\SAMLStringValue $name + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $nameFormat + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $friendlyName * @param \SimpleSAML\SAML2\XML\saml\AttributeValue[] $attributeValue * @param list<\SimpleSAML\XML\Attribute> $namespacedAttribute */ public function __construct( - protected string $name, - protected ?string $nameFormat = null, - protected ?string $friendlyName = null, + protected SAMLStringValue $name, + protected ?SAMLAnyURIValue $nameFormat = null, + protected ?SAMLStringValue $friendlyName = null, protected array $attributeValue = [], array $namespacedAttribute = [], ) { - Assert::notWhitespaceOnly($name, 'Cannot specify an empty name for an Attribute.'); - Assert::nullOrValidURI($nameFormat); - Assert::nullOrNotWhitespaceOnly($friendlyName, 'FriendlyName cannot be an empty string.'); Assert::maxCount($attributeValue, C::UNBOUNDED_LIMIT); Assert::allIsInstanceOf($attributeValue, AttributeValue::class, 'Invalid AttributeValue.'); - if ($nameFormat === C::NAMEFORMAT_URI) { - Assert::validURI( - $name, - sprintf("Attribute name `%s` does not match its declared format `%s`", $name, $nameFormat), - ); - } elseif ($nameFormat === C::NAMEFORMAT_BASIC) { - Assert::validNCName( - $name, - sprintf("Attribute name `%s` does not match its declared format `%s`", $name, $nameFormat), - ); + switch (strval($nameFormat)) { + case C::NAMEFORMAT_URI: + Assert::validURI( + strval($name), + sprintf("Attribute name `%s` does not match its declared format `%s`", $name, $nameFormat), + ); + break; + case C::NAMEFORMAT_BASIC: + Assert::validNCName( + strval($name), + sprintf("Attribute name `%s` does not match its declared format `%s`", $name, $nameFormat), + ); + break; } $this->setAttributesNS($namespacedAttribute); @@ -75,9 +79,9 @@ public function __construct( /** * Collect the value of the Name-property * - * @return string + * @return \SimpleSAML\SAML2\Type\SAMLStringValue */ - public function getName(): string + public function getName(): SAMLStringValue { return $this->name; } @@ -86,9 +90,9 @@ public function getName(): string /** * Collect the value of the NameFormat-property * - * @return string|null + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null */ - public function getNameFormat(): ?string + public function getNameFormat(): ?SAMLAnyURIValue { return $this->nameFormat; } @@ -97,9 +101,9 @@ public function getNameFormat(): ?string /** * Collect the value of the FriendlyName-property * - * @return string|null + * @return \SimpleSAML\SAML2\Type\SAMLStringValue|null */ - public function getFriendlyName(): ?string + public function getFriendlyName(): ?SAMLStringValue { return $this->friendlyName; } @@ -130,9 +134,9 @@ public function getEncryptionBackend(): ?EncryptionBackend * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes */ public static function fromXML(DOMElement $xml): static @@ -141,9 +145,9 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->namespaceURI, Attribute::NS, InvalidDOMElementException::class); return new static( - self::getAttribute($xml, 'Name'), - self::getOptionalAttribute($xml, 'NameFormat', null), - self::getOptionalAttribute($xml, 'FriendlyName', null), + self::getAttribute($xml, 'Name', SAMLStringValue::class), + self::getOptionalAttribute($xml, 'NameFormat', SAMLAnyURIValue::class, null), + self::getOptionalAttribute($xml, 'FriendlyName', SAMLStringValue::class, null), AttributeValue::getChildrenOfClass($xml), self::getAttributesNSFromXML($xml), ); @@ -159,14 +163,14 @@ public static function fromXML(DOMElement $xml): static public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - $e->setAttribute('Name', $this->getName()); + $e->setAttribute('Name', strval($this->getName())); if ($this->getNameFormat() !== null) { - $e->setAttribute('NameFormat', $this->getNameFormat()); + $e->setAttribute('NameFormat', strval($this->getNameFormat())); } if ($this->getFriendlyName() !== null) { - $e->setAttribute('FriendlyName', $this->getFriendlyName()); + $e->setAttribute('FriendlyName', strval($this->getFriendlyName())); } foreach ($this->getAttributesNS() as $attr) { diff --git a/src/XML/saml/AttributeStatement.php b/src/XML/saml/AttributeStatement.php index 070d51637..c1161fd5a 100644 --- a/src/XML/saml/AttributeStatement.php +++ b/src/XML/saml/AttributeStatement.php @@ -5,11 +5,11 @@ namespace SimpleSAML\SAML2\XML\saml; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; /** * Class representing a SAML2 AttributeStatement @@ -70,7 +70,7 @@ public function hasEncryptedAttributes(): bool * @param \DOMElement $xml * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static diff --git a/src/XML/saml/AttributeValue.php b/src/XML/saml/AttributeValue.php index 1bded8dd4..480c9fbe4 100644 --- a/src/XML/saml/AttributeValue.php +++ b/src/XML/saml/AttributeValue.php @@ -11,9 +11,10 @@ use SimpleSAML\SAML2\Constants as C; use SimpleSAML\XML\AbstractElement; use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Constants as C_XSI; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; use function class_exists; use function explode; @@ -98,7 +99,7 @@ public function getValue() * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -122,16 +123,16 @@ public static function fromXML(DOMElement $xml): static $value = Chunk::fromXML($node); } } elseif ( - $xml->hasAttributeNS(C::NS_XSI, "type") && - $xml->getAttributeNS(C::NS_XSI, "type") === "xs:integer" + $xml->hasAttributeNS(C_XSI::NS_XSI, "type") && + $xml->getAttributeNS(C_XSI::NS_XSI, "type") === "xs:integer" ) { Assert::numeric($xml->textContent); // we have an integer as value $value = intval($xml->textContent); } elseif ( - $xml->hasAttributeNS(C::NS_XSI, "type") && - $xml->getAttributeNS(C::NS_XSI, "type") === "xs:dateTime" + $xml->hasAttributeNS(C_XSI::NS_XSI, "type") && + $xml->getAttributeNS(C_XSI::NS_XSI, "type") === "xs:dateTime" ) { Assert::validDateTime($xml->textContent); @@ -139,9 +140,9 @@ public static function fromXML(DOMElement $xml): static $value = new DateTimeImmutable($xml->textContent); } elseif ( // null value - $xml->hasAttributeNS(C::NS_XSI, "nil") && - ($xml->getAttributeNS(C::NS_XSI, "nil") === "1" || - $xml->getAttributeNS(C::NS_XSI, "nil") === "true") + $xml->hasAttributeNS(C_XSI::NS_XSI, "nil") && + ($xml->getAttributeNS(C_XSI::NS_XSI, "nil") === "1" || + $xml->getAttributeNS(C_XSI::NS_XSI, "nil") === "true") ) { Assert::isEmpty($xml->nodeValue); Assert::isEmpty($xml->textContent); @@ -172,20 +173,20 @@ public function toXML(?DOMElement $parent = null): DOMElement switch ($type) { case "integer": // make sure that the xs namespace is available in the AttributeValue - $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xsi', C::NS_XSI); - $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xs', C::NS_XS); - $e->setAttributeNS(C::NS_XSI, 'xsi:type', 'xs:integer'); + $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xsi', C_XSI::NS_XSI); + $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xs', C_XSI::NS_XS); + $e->setAttributeNS(C_XSI::NS_XSI, 'xsi:type', 'xs:integer'); $e->textContent = strval($value); break; case "NULL": - $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xsi', C::NS_XSI); - $e->setAttributeNS(C::NS_XSI, 'xsi:nil', '1'); + $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xsi', C_XSI::NS_XSI); + $e->setAttributeNS(C_XSI::NS_XSI, 'xsi:nil', '1'); break; case "object": if ($value instanceof DateTimeInterface) { - $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xsi', C::NS_XSI); - $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xs', C::NS_XS); - $e->setAttributeNS(C::NS_XSI, 'xsi:type', 'xs:dateTime'); + $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xsi', C_XSI::NS_XSI); + $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xs', C_XSI::NS_XS); + $e->setAttributeNS(C_XSI::NS_XSI, 'xsi:type', 'xs:dateTime'); $e->textContent = $value->format(C::DATETIME_FORMAT); } else { $value->toXML($e); diff --git a/src/XML/saml/Audience.php b/src/XML/saml/Audience.php index 30b56494f..b7d8f5176 100644 --- a/src/XML/saml/Audience.php +++ b/src/XML/saml/Audience.php @@ -4,10 +4,10 @@ namespace SimpleSAML\SAML2\XML\saml; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; -use SimpleSAML\SAML2\XML\URIElementTrait; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class representing a saml:Audience element. @@ -17,27 +17,9 @@ final class Audience extends AbstractSamlElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use URIElementTrait; + use TypedTextContentTrait; - /** - * @param string $content - */ - public function __construct(string $content) - { - $this->setContent($content); - } - - - /** - * Validate the content of the element. - * - * @param string $content The value to go in the XML textContent - * @throws \Exception on failure - * @return void - */ - protected function validateContent(string $content): void - { - SAMLAssert::validEntityID($content); - } + /** @var string */ + public const TEXTCONTENT_TYPE = SAMLAnyURIValue::class; } diff --git a/src/XML/saml/AudienceRestriction.php b/src/XML/saml/AudienceRestriction.php index ba2f3bd76..b3be527ee 100644 --- a/src/XML/saml/AudienceRestriction.php +++ b/src/XML/saml/AudienceRestriction.php @@ -5,12 +5,12 @@ namespace SimpleSAML\SAML2\XML\saml; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\SchemaViolationException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\SchemaViolationException; /** * SAML AudienceRestriction data type. @@ -53,7 +53,7 @@ public function getAudience(): array * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static diff --git a/src/XML/saml/AuthenticatingAuthority.php b/src/XML/saml/AuthenticatingAuthority.php index 2fabef427..5b970104b 100644 --- a/src/XML/saml/AuthenticatingAuthority.php +++ b/src/XML/saml/AuthenticatingAuthority.php @@ -4,10 +4,10 @@ namespace SimpleSAML\SAML2\XML\saml; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; -use SimpleSAML\SAML2\XML\URIElementTrait; +use SimpleSAML\SAML2\Type\EntityIDValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class representing a saml:AuthenticatingAuthority element. @@ -17,27 +17,9 @@ final class AuthenticatingAuthority extends AbstractSamlElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use URIElementTrait; + use TypedTextContentTrait; - /** - * @param string $content - */ - public function __construct(string $content) - { - $this->setContent($content); - } - - - /** - * Validate the content of the element. - * - * @param string $content The value to go in the XML textContent - * @throws \Exception on failure - * @return void - */ - protected function validateContent(string $content): void - { - SAMLAssert::validEntityID($content); - } + /** @var string */ + public const TEXTCONTENT_TYPE = EntityIDValue::class; } diff --git a/src/XML/saml/AuthnContext.php b/src/XML/saml/AuthnContext.php index 4591db1ca..c99d90182 100644 --- a/src/XML/saml/AuthnContext.php +++ b/src/XML/saml/AuthnContext.php @@ -5,15 +5,15 @@ namespace SimpleSAML\SAML2\XML\saml; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\XML\saml\AuthnContextClassRef; use SimpleSAML\SAML2\XML\saml\AuthnContextDecl; use SimpleSAML\SAML2\XML\saml\AuthnContextDeclRef; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; use function array_pop; use function is_null; @@ -110,7 +110,7 @@ public function getAuthenticatingAuthorities(): array * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static diff --git a/src/XML/saml/AuthnContextClassRef.php b/src/XML/saml/AuthnContextClassRef.php index 7f8720756..a43118b47 100644 --- a/src/XML/saml/AuthnContextClassRef.php +++ b/src/XML/saml/AuthnContextClassRef.php @@ -4,9 +4,10 @@ namespace SimpleSAML\SAML2\XML\saml; -use SimpleSAML\SAML2\XML\URIElementTrait; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class representing SAML2 AuthnContextClassRef @@ -16,14 +17,9 @@ final class AuthnContextClassRef extends AbstractSamlElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use URIElementTrait; + use TypedTextContentTrait; - /** - * @param string $content - */ - public function __construct(string $content) - { - $this->setContent($content); - } + /** @var string */ + public const TEXTCONTENT_TYPE = SAMLAnyURIValue::class; } diff --git a/src/XML/saml/AuthnContextDecl.php b/src/XML/saml/AuthnContextDecl.php index ca8adfdf0..5dc0a1654 100644 --- a/src/XML/saml/AuthnContextDecl.php +++ b/src/XML/saml/AuthnContextDecl.php @@ -5,13 +5,13 @@ namespace SimpleSAML\SAML2\XML\saml; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\XML\Exception\InvalidDOMElementException; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\XML\ExtendableAttributesTrait; use SimpleSAML\XML\ExtendableElementTrait; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; -use SimpleSAML\XML\XsNamespace as NS; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\XML\Constants\NS; /** * Class representing SAML2 AuthnContextDecl @@ -63,7 +63,7 @@ public function isEmptyElement(): bool * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static diff --git a/src/XML/saml/AuthnContextDeclRef.php b/src/XML/saml/AuthnContextDeclRef.php index a8983b35b..2d1d748fe 100644 --- a/src/XML/saml/AuthnContextDeclRef.php +++ b/src/XML/saml/AuthnContextDeclRef.php @@ -4,9 +4,10 @@ namespace SimpleSAML\SAML2\XML\saml; -use SimpleSAML\SAML2\XML\URIElementTrait; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class representing SAML2 AuthnContextDeclRef @@ -16,14 +17,9 @@ final class AuthnContextDeclRef extends AbstractSamlElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use URIElementTrait; + use TypedTextContentTrait; - /** - * @param string $content - */ - public function __construct(string $content) - { - $this->setContent($content); - } + /** @var string */ + public const TEXTCONTENT_TYPE = SAMLAnyURIValue::class; } diff --git a/src/XML/saml/AuthnStatement.php b/src/XML/saml/AuthnStatement.php index fb5bf8460..fc4b4b39a 100644 --- a/src/XML/saml/AuthnStatement.php +++ b/src/XML/saml/AuthnStatement.php @@ -4,20 +4,17 @@ namespace SimpleSAML\SAML2\XML\saml; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; -use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; use function array_pop; -use function preg_replace; /** * Class representing a SAML2 AuthnStatement @@ -33,20 +30,18 @@ final class AuthnStatement extends AbstractStatementType implements SchemaValida * Initialize an AuthnStatement. * * @param \SimpleSAML\SAML2\XML\saml\AuthnContext $authnContext - * @param \DateTimeImmutable $authnInstant - * @param \DateTimeImmutable|null $sessionNotOnOrAfter - * @param string|null $sessionIndex + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue $authnInstant + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $sessionNotOnOrAfter + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $sessionIndex * @param \SimpleSAML\SAML2\XML\saml\SubjectLocality|null $subjectLocality */ public function __construct( protected AuthnContext $authnContext, - protected DateTimeImmutable $authnInstant, - protected ?DateTimeImmutable $sessionNotOnOrAfter = null, - protected ?string $sessionIndex = null, + protected SAMLDateTimeValue $authnInstant, + protected ?SAMLDateTimeValue $sessionNotOnOrAfter = null, + protected ?SAMLStringValue $sessionIndex = null, protected ?SubjectLocality $subjectLocality = null, ) { - Assert::same($authnInstant->getTimeZone()->getName(), 'Z', ProtocolViolationException::class); - Assert::nullOrSame($sessionNotOnOrAfter?->getTimeZone()->getName(), 'Z', ProtocolViolationException::class); Assert::nullOrNotWhitespaceOnly($sessionIndex); } @@ -65,9 +60,9 @@ public function getAuthnContext(): AuthnContext /** * Collect the value of the AuthnInstant-property * - * @return \DateTimeImmutable + * @return \SimpleSAML\SAML2\Type\SAMLDateTimeValue */ - public function getAuthnInstant(): DateTimeImmutable + public function getAuthnInstant(): SAMLDateTimeValue { return $this->authnInstant; } @@ -76,9 +71,9 @@ public function getAuthnInstant(): DateTimeImmutable /** * Collect the value of the sessionNotOnOrAfter-property * - * @return \DateTimeImmutable|null + * @return \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null */ - public function getSessionNotOnOrAfter(): ?DateTimeImmutable + public function getSessionNotOnOrAfter(): ?SAMLDateTimeValue { return $this->sessionNotOnOrAfter; } @@ -87,9 +82,9 @@ public function getSessionNotOnOrAfter(): ?DateTimeImmutable /** * Collect the value of the sessionIndex-property * - * @return ?string + * @return \SimpleSAML\SAML2\Type\SAMLStringValue|null */ - public function getSessionIndex(): ?string + public function getSessionIndex(): ?SAMLStringValue { return $this->sessionIndex; } @@ -112,9 +107,9 @@ public function getSubjectLocality(): ?SubjectLocality * @param \DOMElement $xml The XML element we should load * * @return static - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingElementException + * @throws \SimpleSAML\XMLSchema\Exception\MissingElementException * if one of the mandatory child-elements is missing * @throws \Exception if the authentication instant is not a valid timestamp. */ @@ -137,29 +132,13 @@ public static function fromXML(DOMElement $xml): static TooManyElementsException::class, ); - $authnInstant = self::getAttribute($xml, 'AuthnInstant'); - // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications - $authnInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $authnInstant, 1); - - SAMLAssert::validDateTime($authnInstant, ProtocolViolationException::class); - $authnInstant = new DateTimeImmutable($authnInstant); - - $sessionNotOnOrAfter = self::getOptionalAttribute($xml, 'SessionNotOnOrAfter', null); - if ($sessionNotOnOrAfter !== null) { - // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications - $sessionNotOnOrAfter = preg_replace('/([.][0-9]+Z)$/', 'Z', $sessionNotOnOrAfter, 1); - - SAMLAssert::validDateTime($sessionNotOnOrAfter, ProtocolViolationException::class); - $sessionNotOnOrAfter = new DateTimeImmutable($sessionNotOnOrAfter); - } - $subjectLocality = SubjectLocality::getChildrenOfClass($xml); return new static( array_pop($authnContext), - $authnInstant, - $sessionNotOnOrAfter, - self::getOptionalAttribute($xml, 'SessionIndex', null), + self::getAttribute($xml, 'AuthnInstant', SAMLDateTimeValue::class), + self::getOptionalAttribute($xml, 'SessionNotOnOrAfter', SAMLDateTimeValue::class, null), + self::getOptionalAttribute($xml, 'SessionIndex', SAMLStringValue::class, null), array_pop($subjectLocality), ); } @@ -181,14 +160,14 @@ public function toXML(?DOMElement $parent = null): DOMElement $this->getAuthnContext()->toXML($e); - $e->setAttribute('AuthnInstant', $this->getAuthnInstant()->format(C::DATETIME_FORMAT)); + $e->setAttribute('AuthnInstant', $this->getAuthnInstant()->getValue()); if ($this->getSessionIndex() !== null) { - $e->setAttribute('SessionIndex', $this->getSessionIndex()); + $e->setAttribute('SessionIndex', $this->getSessionIndex()->getValue()); } if ($this->getSessionNotOnOrAfter() !== null) { - $e->setAttribute('SessionNotOnOrAfter', $this->getSessionNotOnOrAfter()->format(C::DATETIME_FORMAT)); + $e->setAttribute('SessionNotOnOrAfter', $this->getSessionNotOnOrAfter()->getValue()); } return $e; diff --git a/src/XML/saml/AuthzDecisionStatement.php b/src/XML/saml/AuthzDecisionStatement.php index edd130a50..3d8a1cfcc 100644 --- a/src/XML/saml/AuthzDecisionStatement.php +++ b/src/XML/saml/AuthzDecisionStatement.php @@ -5,21 +5,19 @@ namespace SimpleSAML\SAML2\XML\saml; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\Decision; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingElementException; -use SimpleSAML\XML\Exception\SchemaViolationException; -use SimpleSAML\XML\Exception\TooManyElementsException; +use SimpleSAML\SAML2\Type\DecisionTypeValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; -use ValueError; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Exception\SchemaViolationException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\AnyURIValue; use function array_pop; -use function sprintf; +use function strval; /** * Class representing a SAML2 AuthzDecisionStatement @@ -34,18 +32,18 @@ final class AuthzDecisionStatement extends AbstractStatementType implements Sche /** * Initialize an AuthzDecisionStatement. * - * @param string $resource - * @param \SimpleSAML\SAML2\XML\Decision $decision + * @param \SimpleSAML\XMLSchema\Type\AnyURIValue $resource + * @param \SimpleSAML\SAML2\Type\DecisionTypeValue $decision * @param \SimpleSAML\SAML2\XML\saml\Action[] $action * @param \SimpleSAML\SAML2\XML\saml\Evidence|null $evidence */ public function __construct( - protected string $resource, - protected Decision $decision, + // Uses the base AnyURIValue because the SAML-specification allows this attribute to be an empty string + protected AnyURIValue $resource, + protected DecisionTypeValue $decision, protected array $action, protected ?Evidence $evidence = null, ) { - SAMLAssert::validURI($resource); Assert::maxCount($action, C::UNBOUNDED_LIMIT); Assert::allIsInstanceOf($action, Action::class, SchemaViolationException::class); } @@ -54,9 +52,9 @@ public function __construct( /** * Collect the value of the resource-property * - * @return string + * @return \SimpleSAML\XMLSchema\Type\AnyURIValue */ - public function getResource(): string + public function getResource(): AnyURIValue { return $this->resource; } @@ -65,9 +63,9 @@ public function getResource(): string /** * Collect the value of the decision-property * - * @return \SimpleSAML\SAML2\XML\Decision + * @return \SimpleSAML\SAML2\Type\DecisionTypeValue */ - public function getDecision(): Decision + public function getDecision(): DecisionTypeValue { return $this->decision; } @@ -76,7 +74,7 @@ public function getDecision(): Decision /** * Collect the value of the action-property * - * @return array + * @return \SimpleSAML\SAML2\XML\saml\Action[] */ public function getAction(): array { @@ -101,9 +99,9 @@ public function getEvidence(): ?Evidence * @param \DOMElement $xml The XML element we should load * * @return static - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingElementException + * @throws \SimpleSAML\XMLSchema\Exception\MissingElementException * if one of the mandatory child-elements is missing * @throws \Exception if the authentication instant is not a valid timestamp. */ @@ -128,16 +126,10 @@ public static function fromXML(DOMElement $xml): static TooManyElementsException::class, ); - $decision = self::getAttribute($xml, 'Decision'); - try { - $decision = Decision::from($decision); - } catch (ValueError) { - throw new ProtocolViolationException(sprintf('Unknown value \'%s\' for Decision attribute.', $decision)); - } return new static( - self::getAttribute($xml, 'Resource'), - $decision, + self::getAttribute($xml, 'Resource', AnyURIValue::class), + self::getAttribute($xml, 'Decision', DecisionTypeValue::class), $action, array_pop($evidence), ); @@ -154,8 +146,8 @@ public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - $e->setAttribute('Resource', $this->getResource()); - $e->setAttribute('Decision', $this->getDecision()->value); + $e->setAttribute('Resource', strval($this->getResource())); + $e->setAttribute('Decision', strval($this->getDecision())); foreach ($this->getAction() as $action) { $action->toXML($e); diff --git a/src/XML/saml/BaseIdentifierInterface.php b/src/XML/saml/BaseIdentifierInterface.php index d054270fd..c577c660b 100644 --- a/src/XML/saml/BaseIdentifierInterface.php +++ b/src/XML/saml/BaseIdentifierInterface.php @@ -4,6 +4,8 @@ namespace SimpleSAML\SAML2\XML\saml; +use SimpleSAML\SAML2\Type\SAMLStringValue; + /** * Interface for BaseID objects. * @@ -14,15 +16,15 @@ interface BaseIdentifierInterface extends IdentifierInterface /** * Get the value of the NameQualifier attribute of an identifier. * - * @return string|null + * @return \SimpleSAML\SAML2\Type\SAMLStringValue|null */ - public function getNameQualifier(): ?string; + public function getNameQualifier(): ?SAMLStringValue; /** * Get the value of the SPNameQualifier attribute of an identifier. * - * @return string|null + * @return \SimpleSAML\SAML2\Type\SAMLStringValue|null */ - public function getSPNameQualifier(): ?string; + public function getSPNameQualifier(): ?SAMLStringValue; } diff --git a/src/XML/saml/Conditions.php b/src/XML/saml/Conditions.php index 5e6b9c18b..5592de7ab 100644 --- a/src/XML/saml/Conditions.php +++ b/src/XML/saml/Conditions.php @@ -4,15 +4,14 @@ namespace SimpleSAML\SAML2\XML\saml; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\XML\Exception\InvalidDOMElementException; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; use function array_pop; @@ -29,23 +28,21 @@ final class Conditions extends AbstractSamlElement implements SchemaValidatableE /** * Initialize a Conditions element. * - * @param \DateTimeImmutable|null $notBefore - * @param \DateTimeImmutable|null $notOnOrAfter + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $notBefore + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $notOnOrAfter * @param \SimpleSAML\SAML2\XML\saml\AbstractCondition[] $condition * @param \SimpleSAML\SAML2\XML\saml\AudienceRestriction[] $audienceRestriction * @param \SimpleSAML\SAML2\XML\saml\OneTimeUse|null $oneTimeUse * @param \SimpleSAML\SAML2\XML\saml\ProxyRestriction|null $proxyRestriction */ public function __construct( - protected ?DateTimeImmutable $notBefore = null, - protected ?DateTimeImmutable $notOnOrAfter = null, + protected ?SAMLDateTimeValue $notBefore = null, + protected ?SAMLDateTimeValue $notOnOrAfter = null, protected array $condition = [], protected array $audienceRestriction = [], protected ?OneTimeUse $oneTimeUse = null, protected ?ProxyRestriction $proxyRestriction = null, ) { - Assert::nullOrSame($notBefore?->getTimeZone()->getName(), 'Z', ProtocolViolationException::class); - Assert::nullOrSame($notOnOrAfter?->getTimeZone()->getName(), 'Z', ProtocolViolationException::class); Assert::maxCount($condition, C::UNBOUNDED_LIMIT); Assert::allIsInstanceOf($condition, AbstractCondition::class); Assert::maxCount($audienceRestriction, C::UNBOUNDED_LIMIT); @@ -56,9 +53,9 @@ public function __construct( /** * Collect the value of the notBefore-property * - * @return \DateTimeImmutable|null + * @return \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null */ - public function getNotBefore(): ?DateTimeImmutable + public function getNotBefore(): ?SAMLDateTimeValue { return $this->notBefore; } @@ -67,9 +64,9 @@ public function getNotBefore(): ?DateTimeImmutable /** * Collect the value of the notOnOrAfter-property * - * @return \DateTimeImmutable|null + * @return \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null */ - public function getNotOnOrAfter(): ?DateTimeImmutable + public function getNotOnOrAfter(): ?SAMLDateTimeValue { return $this->notOnOrAfter; } @@ -126,12 +123,12 @@ public function getProxyRestriction(): ?ProxyRestriction */ public function isEmptyElement(): bool { - return empty($this->notBefore) - && empty($this->notOnOrAfter) - && empty($this->condition) - && empty($this->audienceRestriction) - && empty($this->oneTimeUse) - && empty($this->proxyRestriction); + return empty($this->getNotBefore()) + && empty($this->getNotOnOrAfter()) + && empty($this->getCondition()) + && empty($this->getAudienceRestriction()) + && empty($this->getOneTimeUse()) + && empty($this->getProxyRestriction()); } @@ -141,7 +138,7 @@ public function isEmptyElement(): bool * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -149,22 +146,6 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'Conditions', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, Conditions::NS, InvalidDOMElementException::class); - $notBefore = self::getOptionalAttribute($xml, 'NotBefore', null); - if ($notBefore !== null) { - // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications - $notBefore = preg_replace('/([.][0-9]+Z)$/', 'Z', $notBefore, 1); - - SAMLAssert::validDateTime($notBefore, ProtocolViolationException::class); - } - - $notOnOrAfter = self::getOptionalAttribute($xml, 'NotOnOrAfter', null); - if ($notOnOrAfter !== null) { - // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications - $notOnOrAfter = preg_replace('/([.][0-9]+Z)$/', 'Z', $notOnOrAfter, 1); - - SAMLAssert::validDateTime($notOnOrAfter, ProtocolViolationException::class); - } - $condition = AbstractCondition::getChildrenOfClass($xml); $audienceRestriction = AudienceRestriction::getChildrenOfClass($xml); $oneTimeUse = OneTimeUse::getChildrenOfClass($xml); @@ -184,8 +165,8 @@ public static function fromXML(DOMElement $xml): static ); return new static( - $notBefore !== null ? new DateTimeImmutable($notBefore) : null, - $notOnOrAfter !== null ? new DateTimeImmutable($notOnOrAfter) : null, + self::getOptionalAttribute($xml, 'NotBefore', SAMLDateTimeValue::class, null), + self::getOptionalAttribute($xml, 'NotOnOrAfter', SAMLDateTimeValue::class, null), $condition, $audienceRestriction, array_pop($oneTimeUse), @@ -205,11 +186,11 @@ public function toXML(?DOMElement $parent = null): DOMElement $e = $this->instantiateParentElement($parent); if ($this->getNotBefore() !== null) { - $e->setAttribute('NotBefore', $this->getNotBefore()->format(C::DATETIME_FORMAT)); + $e->setAttribute('NotBefore', $this->getNotBefore()->getValue()); } if ($this->getNotOnOrAfter() !== null) { - $e->setAttribute('NotOnOrAfter', $this->getNotOnOrAfter()->format(C::DATETIME_FORMAT)); + $e->setAttribute('NotOnOrAfter', $this->getNotOnOrAfter()->getValue()); } foreach ($this->getCondition() as $condition) { diff --git a/src/XML/saml/DecisionTypeEnum.php b/src/XML/saml/DecisionTypeEnum.php new file mode 100644 index 000000000..0784232b8 --- /dev/null +++ b/src/XML/saml/DecisionTypeEnum.php @@ -0,0 +1,12 @@ +decryptData($decryptor))->documentElement, ); } - - - /** - * @return bool - */ - public function wasSignedAtConstruction(): bool - { - return $this->wasSignedAtConstruction; - } } diff --git a/src/XML/saml/Evidence.php b/src/XML/saml/Evidence.php index 37915d504..446b08191 100644 --- a/src/XML/saml/Evidence.php +++ b/src/XML/saml/Evidence.php @@ -5,12 +5,12 @@ namespace SimpleSAML\SAML2\XML\saml; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\SchemaViolationException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\SchemaViolationException; /** * Class representing a saml:Evidence element. @@ -101,7 +101,7 @@ public function getEncryptedAssertion(): array * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * If the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static diff --git a/src/XML/saml/IDNameQualifiersTrait.php b/src/XML/saml/IDNameQualifiersTrait.php index c321a2370..4bb945f65 100644 --- a/src/XML/saml/IDNameQualifiersTrait.php +++ b/src/XML/saml/IDNameQualifiersTrait.php @@ -4,6 +4,8 @@ namespace SimpleSAML\SAML2\XML\saml; +use SimpleSAML\SAML2\Type\SAMLStringValue; + /** * SAML IDNameQualifier attribute group. * @@ -14,9 +16,9 @@ trait IDNameQualifiersTrait /** * Collect the value of the NameQualifier-property * - * @return string|null + * @return \SimpleSAML\SAML2\Type\SAMLStringValue|null */ - public function getNameQualifier(): ?string + public function getNameQualifier(): ?SAMLStringValue { return $this->NameQualifier; } @@ -25,9 +27,9 @@ public function getNameQualifier(): ?string /** * Collect the value of the SPNameQualifier-property * - * @return string|null + * @return \SimpleSAML\SAML2\Type\SAMLStringValue|null */ - public function getSPNameQualifier(): ?string + public function getSPNameQualifier(): ?SAMLStringValue { return $this->SPNameQualifier; } diff --git a/src/XML/saml/Issuer.php b/src/XML/saml/Issuer.php index 56472f0b4..c7fa75472 100644 --- a/src/XML/saml/Issuer.php +++ b/src/XML/saml/Issuer.php @@ -4,9 +4,11 @@ namespace SimpleSAML\SAML2\XML\saml; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; @@ -23,18 +25,18 @@ final class Issuer extends NameIDType implements SchemaValidatableElementInterfa /** * Initialize a saml:Issuer * - * @param string $value - * @param string|null $NameQualifier - * @param string|null $SPNameQualifier - * @param string|null $Format - * @param string|null $SPProvidedID + * @param \SimpleSAML\SAML2\Type\SAMLStringValue $value + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $NameQualifier + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $SPNameQualifier + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $Format + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $SPProvidedID */ public function __construct( - string $value, - ?string $NameQualifier = null, - ?string $SPNameQualifier = null, - ?string $Format = null, - ?string $SPProvidedID = null, + SAMLStringValue $value, + ?SAMLStringValue $NameQualifier = null, + ?SAMLStringValue $SPNameQualifier = null, + ?SAMLAnyURIValue $Format = null, + ?SAMLStringValue $SPProvidedID = null, ) { /** * The format of this NameIDType. @@ -57,13 +59,13 @@ public function __construct( * From saml-core-2.0-os 8.3.6, when the entity Format is used: "The NameQualifier, SPNameQualifier, and * SPProvidedID attributes MUST be omitted." */ - if ($Format === C::NAMEID_ENTITY || $Format === null) { + if ($Format === null || $Format->getValue() === C::NAMEID_ENTITY) { Assert::allNull( [$NameQualifier, $SPNameQualifier, $SPProvidedID], 'Illegal combination of attributes being used', ); - SamlAssert::validEntityID($value); + Assert::validEntityID($value->getValue(), ProtocolViolationException::class); } parent::__construct($value, $NameQualifier, $SPNameQualifier, $Format, $SPProvidedID); diff --git a/src/XML/saml/NameID.php b/src/XML/saml/NameID.php index 18b55b7db..8338cc269 100644 --- a/src/XML/saml/NameID.php +++ b/src/XML/saml/NameID.php @@ -4,9 +4,11 @@ namespace SimpleSAML\SAML2\XML\saml; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Exception\ArrayValidationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\EncryptableElementTrait; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; @@ -34,48 +36,53 @@ final class NameID extends NameIDType implements /** * Initialize a saml:NameID * - * @param string $value - * @param string|null $NameQualifier - * @param string|null $SPNameQualifier - * @param string|null $Format - * @param string|null $SPProvidedID + * @param \SimpleSAML\SAML2\Type\SAMLStringValue $value + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $NameQualifier + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $SPNameQualifier + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $Format + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $SPProvidedID */ public function __construct( - string $value, - ?string $NameQualifier = null, - ?string $SPNameQualifier = null, - ?string $Format = null, - ?string $SPProvidedID = null, + SAMLStringValue $value, + ?SAMLStringValue $NameQualifier = null, + ?SAMLStringValue $SPNameQualifier = null, + ?SAMLAnyURIValue $Format = null, + ?SAMLStringValue $SPProvidedID = null, ) { - switch ($Format) { - case C::NAMEID_EMAIL_ADDRESS: - Assert::email( - $value, - "The content %s of the NameID was not in the format specified by the Format attribute", - ); - break; - case C::NAMEID_ENTITY: - /* 8.3.6: he NameQualifier, SPNameQualifier, and SPProvidedID attributes MUST be omitted. */ - Assert::null($NameQualifier, "Entity Identifier included a disallowed NameQualifier attribute."); - Assert::null($SPNameQualifier, "Entity Identifier included a disallowed SPNameQualifier attribute."); - Assert::null($SPProvidedID, "Entity Identifier included a disallowed SPProvidedID attribute."); - break; - case C::NAMEID_PERSISTENT: - /* 8.3.7: Persistent name identifier values MUST NOT exceed a length of 256 characters. */ - Assert::maxLength( - $value, - 256, - "Persistent name identifier values MUST NOT exceed a length of 256 characters.", - ); - break; - case C::NAMEID_TRANSIENT: - /* 8.3.8: Transient name identifier values MUST NOT exceed a length of 256 characters. */ - Assert::maxLength( - $value, - 256, - "Transient name identifier values MUST NOT exceed a length of 256 characters.", - ); - break; + if ($Format !== null) { + switch ($Format->getValue()) { + case C::NAMEID_EMAIL_ADDRESS: + Assert::email( + $value->getValue(), + "The content %s of the NameID was not in the format specified by the Format attribute", + ); + break; + case C::NAMEID_ENTITY: + /* 8.3.6: the NameQualifier, SPNameQualifier, and SPProvidedID attributes MUST be omitted. */ + Assert::null($NameQualifier, "Entity Identifier included a disallowed NameQualifier attribute."); + Assert::null( + $SPNameQualifier, + "Entity Identifier included a disallowed SPNameQualifier attribute.", + ); + Assert::null($SPProvidedID, "Entity Identifier included a disallowed SPProvidedID attribute."); + break; + case C::NAMEID_PERSISTENT: + /* 8.3.7: Persistent name identifier values MUST NOT exceed a length of 256 characters. */ + Assert::maxLength( + $value->getValue(), + 256, + "Persistent name identifier values MUST NOT exceed a length of 256 characters.", + ); + break; + case C::NAMEID_TRANSIENT: + /* 8.3.8: Transient name identifier values MUST NOT exceed a length of 256 characters. */ + Assert::maxLength( + $value->getValue(), + 256, + "Transient name identifier values MUST NOT exceed a length of 256 characters.", + ); + break; + } } parent::__construct($value, $NameQualifier, $SPNameQualifier, $Format, $SPProvidedID); @@ -101,11 +108,11 @@ public static function fromArray(array $data): static $data = self::processArrayContents($data); return new static( - $data['value'], - $data['NameQualifier'] ?? null, - $data['SPNameQualifier'] ?? null, - $data['Format'] ?? null, - $data['SPProvidedID'] ?? null, + SAMLStringValue::fromString($data['value']), + $data['NameQualifier'] ? SAMLStringValue::fromString($data['NameQualifier']) : null, + $data['SPNameQualifier'] ? SAMLStringValue::fromString($data['SPNameQualifier']) : null, + $data['Format'] ? SAMLAnyURIValue::fromString($data['Format']) : null, + $data['SPProvidedID'] ? SAMLStringValue::fromString($data['SPProvidedID']) : null, ); } @@ -170,11 +177,11 @@ private static function processArrayContents(array $data): array public function toArray(): array { $data = [ - 'value' => $this->getContent(), - 'Format' => $this->getFormat(), - 'NameQualifier' => $this->getNameQualifier(), - 'SPNameQualifier' => $this->getSPNameQualifier(), - 'SPProvidedID' => $this->getSPProvidedID(), + 'value' => $this->getContent()->getValue(), + 'Format' => $this->getFormat()?->getValue(), + 'NameQualifier' => $this->getNameQualifier()?->getValue(), + 'SPNameQualifier' => $this->getSPNameQualifier()?->getValue(), + 'SPProvidedID' => $this->getSPProvidedID()?->getValue(), ]; return array_filter($data); diff --git a/src/XML/saml/NameIDType.php b/src/XML/saml/NameIDType.php index 825b118d5..4f232ad96 100644 --- a/src/XML/saml/NameIDType.php +++ b/src/XML/saml/NameIDType.php @@ -5,10 +5,13 @@ namespace SimpleSAML\SAML2\XML\saml; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; -use SimpleSAML\SAML2\XML\StringElementTrait; -use SimpleSAML\XML\Exception\InvalidDOMElementException; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\XML\TypedTextContentTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; + +use function strval; /** * SAML NameIDType abstract data type. @@ -19,30 +22,29 @@ abstract class NameIDType extends AbstractSamlElement implements IdentifierInterface { use IDNameQualifiersTrait; - use StringElementTrait; + use TypedTextContentTrait; + + + /** @var string */ + public const TEXTCONTENT_TYPE = SAMLStringValue::class; /** * Initialize a saml:NameIDType from scratch * - * @param string $value - * @param string|null $Format - * @param string|null $SPProvidedID - * @param string|null $NameQualifier - * @param string|null $SPNameQualifier + * @param \SimpleSAML\SAML2\Type\SAMLStringValue $value + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $Format + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $SPProvidedID + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $NameQualifier + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $SPNameQualifier */ protected function __construct( - string $value, - protected ?string $NameQualifier = null, - protected ?string $SPNameQualifier = null, - protected ?string $Format = null, - protected ?string $SPProvidedID = null, + SAMLStringValue|SAMLAnyURIValue $value, + protected ?SAMLStringValue $NameQualifier = null, + protected ?SAMLStringValue $SPNameQualifier = null, + protected ?SAMLAnyURIValue $Format = null, + protected ?SAMLStringValue $SPProvidedID = null, ) { - SAMLAssert::nullOrValidEntityID($NameQualifier); - SAMLAssert::nullOrValidEntityID($SPNameQualifier); - SAMLAssert::nullOrValidURI($Format); - Assert::nullOrNotWhitespaceOnly($SPProvidedID); - $this->setContent($value); } @@ -50,9 +52,9 @@ protected function __construct( /** * Collect the value of the Format-property * - * @return string|null + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null */ - public function getFormat(): ?string + public function getFormat(): ?SAMLAnyURIValue { return $this->Format; } @@ -61,34 +63,21 @@ public function getFormat(): ?string /** * Collect the value of the SPProvidedID-property * - * @return string|null + * @return \SimpleSAML\SAML2\Type\SAMLStringValue|null */ - public function getSPProvidedID(): ?string + public function getSPProvidedID(): ?SAMLStringValue { return $this->SPProvidedID; } - /** - * Validate the content of the element. - * - * @param string $content The value to go in the XML textContent - * @throws \Exception on failure - * @return void - */ - protected function validateContent(string $content): void - { - Assert::notWhitespaceOnly($content); - } - - /** * Convert XML into an NameID * * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -96,12 +85,13 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, static::getLocalName(), InvalidDOMElementException::class); Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); - $NameQualifier = self::getOptionalAttribute($xml, 'NameQualifier', null); - $SPNameQualifier = self::getOptionalAttribute($xml, 'SPNameQualifier', null); - $Format = self::getOptionalAttribute($xml, 'Format', null); - $SPProvidedID = self::getOptionalAttribute($xml, 'SPProvidedID', null); - - return new static($xml->textContent, $NameQualifier, $SPNameQualifier, $Format, $SPProvidedID); + return new static( + SAMLStringValue::fromString($xml->textContent), + self::getOptionalAttribute($xml, 'NameQualifier', SAMLStringValue::class, null), + self::getOptionalAttribute($xml, 'SPNameQualifier', SAMLStringValue::class, null), + self::getOptionalAttribute($xml, 'Format', SAMLAnyURIValue::class, null), + self::getOptionalAttribute($xml, 'SPProvidedID', SAMLStringValue::class, null), + ); } @@ -114,24 +104,24 @@ public static function fromXML(DOMElement $xml): static public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); + $e->textContent = strval($this->getContent()); if ($this->getNameQualifier() !== null) { - $e->setAttribute('NameQualifier', $this->getNameQualifier()); + $e->setAttribute('NameQualifier', $this->getNameQualifier()->getValue()); } if ($this->getSPNameQualifier() !== null) { - $e->setAttribute('SPNameQualifier', $this->getSPNameQualifier()); + $e->setAttribute('SPNameQualifier', $this->getSPNameQualifier()->getValue()); } if ($this->getFormat() !== null) { - $e->setAttribute('Format', $this->getFormat()); + $e->setAttribute('Format', $this->getFormat()->getValue()); } if ($this->getSPProvidedID() !== null) { - $e->setAttribute('SPProvidedID', $this->getSPProvidedID()); + $e->setAttribute('SPProvidedID', $this->getSPProvidedID()->getValue()); } - $e->textContent = $this->getContent(); return $e; } } diff --git a/src/XML/saml/OneTimeUse.php b/src/XML/saml/OneTimeUse.php index 79c59feda..269fb283f 100644 --- a/src/XML/saml/OneTimeUse.php +++ b/src/XML/saml/OneTimeUse.php @@ -5,10 +5,10 @@ namespace SimpleSAML\SAML2\XML\saml; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\XML\Exception\InvalidDOMElementException; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; /** * Class representing a saml:OneTimeUse element. @@ -26,7 +26,7 @@ final class OneTimeUse extends AbstractConditionType implements SchemaValidatabl * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * If the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static diff --git a/src/XML/saml/ProxyRestriction.php b/src/XML/saml/ProxyRestriction.php index 13aa8c256..5e3931e1a 100644 --- a/src/XML/saml/ProxyRestriction.php +++ b/src/XML/saml/ProxyRestriction.php @@ -5,13 +5,12 @@ namespace SimpleSAML\SAML2\XML\saml; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; - -use function strval; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Type\NonNegativeIntegerValue; /** * @package simplesamlphp/saml2 @@ -25,13 +24,12 @@ final class ProxyRestriction extends AbstractConditionType implements SchemaVali * ProxyRestriction constructor. * * @param \SimpleSAML\SAML2\XML\saml\Audience[] $audience - * @param int|null $count + * @param \SimpleSAML\XMLSchema\Type\NonNegativeIntegerValue|null $count */ public function __construct( protected array $audience = [], - protected ?int $count = null, + protected ?NonNegativeIntegerValue $count = null, ) { - Assert::nullOrNatural($count, 'Count must be a non-negative integer.'); Assert::maxCount($audience, C::UNBOUNDED_LIMIT); Assert::allIsInstanceOf($audience, Audience::class); } @@ -40,9 +38,9 @@ public function __construct( /** * Get the value of the count-attribute. * - * @return int|null + * @return \SimpleSAML\XMLSchema\Type\NonNegativeIntegerValue|null */ - public function getCount(): ?int + public function getCount(): ?NonNegativeIntegerValue { return $this->count; } @@ -63,7 +61,7 @@ public function getAudience(): array * @param \DOMElement $xml * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -71,7 +69,7 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'ProxyRestriction', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, ProxyRestriction::NS, InvalidDOMElementException::class); - $count = self::getOptionalIntegerAttribute($xml, 'Count', null); + $count = self::getOptionalAttribute($xml, 'Count', NonNegativeIntegerValue::class, null); $audience = Audience::getChildrenOfClass($xml); return new static($audience, $count); @@ -89,7 +87,7 @@ public function toXML(?DOMElement $parent = null): DOMElement $e = $this->instantiateParentElement($parent); if ($this->getCount() !== null) { - $e->setAttribute('Count', strval($this->getCount())); + $e->setAttribute('Count', $this->getCount()->getValue()); } foreach ($this->getAudience() as $audience) { diff --git a/src/XML/saml/Subject.php b/src/XML/saml/Subject.php index 47a0d2230..cc07d13a0 100644 --- a/src/XML/saml/Subject.php +++ b/src/XML/saml/Subject.php @@ -5,13 +5,13 @@ namespace SimpleSAML\SAML2\XML\saml; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\XML\IdentifierTrait; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; /** * Class representing SAML 2 Subject element. @@ -65,7 +65,7 @@ public function getSubjectConfirmation(): array * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -102,7 +102,7 @@ public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - /** @var \SimpleSAML\XML\SerializableElementInterface|null $identifier */ + /** @var \SimpleSAML\XML\SerializableElementInterface&\SimpleSAML\SAML2\XML\saml\IdentifierInterface $identifier */ $identifier = $this->getIdentifier(); $identifier?->toXML($e); diff --git a/src/XML/saml/SubjectConfirmation.php b/src/XML/saml/SubjectConfirmation.php index 1bfeb53bc..0e8066037 100644 --- a/src/XML/saml/SubjectConfirmation.php +++ b/src/XML/saml/SubjectConfirmation.php @@ -5,13 +5,13 @@ namespace SimpleSAML\SAML2\XML\saml; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\IdentifierTrait; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; use function array_pop; @@ -29,16 +29,15 @@ final class SubjectConfirmation extends AbstractSamlElement implements SchemaVal /** * Initialize (and parse) a SubjectConfirmation element. * - * @param string $method + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $method * @param \SimpleSAML\SAML2\XML\saml\IdentifierInterface|null $identifier * @param \SimpleSAML\SAML2\XML\saml\SubjectConfirmationData|null $subjectConfirmationData */ public function __construct( - protected string $method, + protected SAMLAnyURIValue $method, ?IdentifierInterface $identifier = null, protected ?SubjectConfirmationData $subjectConfirmationData = null, ) { - SAMLAssert::validURI($method); $this->setIdentifier($identifier); } @@ -46,9 +45,9 @@ public function __construct( /** * Collect the value of the Method-property * - * @return string + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue */ - public function getMethod(): string + public function getMethod(): SAMLAnyURIValue { return $this->method; } @@ -71,11 +70,11 @@ public function getSubjectConfirmationData(): ?SubjectConfirmationData * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes - * @throws \SimpleSAML\XML\Exception\TooManyElementsException + * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException * if too many child-elements of a type are specified */ public static function fromXML(DOMElement $xml): static @@ -83,10 +82,7 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'SubjectConfirmation', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, SubjectConfirmation::NS, InvalidDOMElementException::class); - $Method = self::getAttribute($xml, 'Method'); - $identifier = self::getIdentifierFromXML($xml); $subjectConfirmationData = SubjectConfirmationData::getChildrenOfClass($xml); - Assert::maxCount( $subjectConfirmationData, 1, @@ -95,8 +91,8 @@ public static function fromXML(DOMElement $xml): static ); return new static( - $Method, - $identifier, + self::getAttribute($xml, 'Method', SAMLAnyURIValue::class), + self::getIdentifierFromXML($xml), array_pop($subjectConfirmationData), ); } @@ -111,9 +107,9 @@ public static function fromXML(DOMElement $xml): static public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - $e->setAttribute('Method', $this->getMethod()); + $e->setAttribute('Method', $this->getMethod()->getValue()); - /** @var \SimpleSAML\XML\SerializableElementInterface|null $identifier */ + /** @var \SimpleSAML\XML\SerializableElementInterface&\SimpleSAML\SAML2\XML\saml\IdentifierInterface $identifier */ $identifier = $this->getIdentifier(); $identifier?->toXML($e); diff --git a/src/XML/saml/SubjectConfirmationData.php b/src/XML/saml/SubjectConfirmationData.php index 2260cf60a..591aef707 100644 --- a/src/XML/saml/SubjectConfirmationData.php +++ b/src/XML/saml/SubjectConfirmationData.php @@ -4,22 +4,22 @@ namespace SimpleSAML\SAML2\XML\saml; -use DateTimeImmutable; use DOMElement; +use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; -use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\ExtendableAttributesTrait; use SimpleSAML\XML\ExtendableElementTrait; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; -use SimpleSAML\XML\XsNamespace as NS; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Type\NCNameValue; +use SimpleSAML\XMLSchema\XML\Constants\NS; -use function filter_var; -use function is_null; +use function strval; /** * Class representing SAML 2 SubjectConfirmationData element. @@ -43,32 +43,36 @@ final class SubjectConfirmationData extends AbstractSamlElement implements Schem /** * Initialize (and parse) a SubjectConfirmationData element. * - * @param \DateTimeImmutable|null $notBefore - * @param \DateTimeImmutable|null $notOnOrAfter - * @param string|null $recipient - * @param string|null $inResponseTo - * @param string|null $address + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $notBefore + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $notOnOrAfter + * @param \SimpleSAML\SAML2\Type\EntityIDValue|null $recipient + * @param \SimpleSAML\XMLSchema\Type\NCNameValue|null $inResponseTo + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $address * @param \SimpleSAML\XML\SerializableElementInterface[] $children * @param list<\SimpleSAML\XML\Attribute> $namespacedAttributes */ public function __construct( - protected ?DateTimeImmutable $notBefore = null, - protected ?DateTimeImmutable $notOnOrAfter = null, - protected ?string $recipient = null, - protected ?string $inResponseTo = null, - protected ?string $address = null, + protected ?SAMLDateTimeValue $notBefore = null, + protected ?SAMLDateTimeValue $notOnOrAfter = null, + protected ?EntityIDValue $recipient = null, + protected ?NCNameValue $inResponseTo = null, + protected ?SAMLStringValue $address = null, array $children = [], array $namespacedAttributes = [], ) { - Assert::nullOrSame($notBefore?->getTimeZone()->getName(), 'Z', ProtocolViolationException::class); - Assert::nullOrSame($notOnOrAfter?->getTimeZone()->getName(), 'Z', ProtocolViolationException::class); - Assert::nullOrNotWhitespaceOnly($recipient); - Assert::nullOrValidNCName($inResponseTo); // Covers the empty string - - if (!is_null($address) && !filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) { - Utils::getContainer()->getLogger()->warning( - sprintf('Provided argument (%s) is not a valid IP address.', $address), - ); + if ($address !== null) { + try { + /** + * IPv4 addresses SHOULD be represented in the usual dotted-decimal format (e.g., "1.2.3.4"). + * IPv6 addresses SHOULD be represented as defined by Section 2.2 of IETF RFC 3513 [RFC 3513] + * (e.g., "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210"). + */ + Assert::ip($address->getValue()); + } catch (AssertionFailedException) { + Utils::getContainer()->getLogger()->warning( + sprintf('Provided address (%s) is not a valid IPv4 or IPv6 address.', $address->getValue()), + ); + } } $this->setElements($children); @@ -79,9 +83,9 @@ public function __construct( /** * Collect the value of the NotBefore-property * - * @return \DateTimeImmutable|null + * @return \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null */ - public function getNotBefore(): ?DateTimeImmutable + public function getNotBefore(): ?SAMLDateTimeValue { return $this->notBefore; } @@ -90,9 +94,9 @@ public function getNotBefore(): ?DateTimeImmutable /** * Collect the value of the NotOnOrAfter-property * - * @return \DateTimeImmutable|null + * @return \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null */ - public function getNotOnOrAfter(): ?DateTimeImmutable + public function getNotOnOrAfter(): ?SAMLDateTimeValue { return $this->notOnOrAfter; } @@ -101,9 +105,9 @@ public function getNotOnOrAfter(): ?DateTimeImmutable /** * Collect the value of the Recipient-property * - * @return string|null + * @return \SimpleSAML\SAML2\Type\EntityIDValue|null */ - public function getRecipient(): ?string + public function getRecipient(): ?EntityIDValue { return $this->recipient; } @@ -112,9 +116,9 @@ public function getRecipient(): ?string /** * Collect the value of the InResponseTo-property * - * @return string|null + * @return \SimpleSAML\XMLSchema\Type\NCNameValue|null */ - public function getInResponseTo(): ?string + public function getInResponseTo(): ?NCNameValue { return $this->inResponseTo; } @@ -123,9 +127,9 @@ public function getInResponseTo(): ?string /** * Collect the value of the Address-property * - * @return string|null + * @return \SimpleSAML\SAML2\Type\SAMLStringValue|null */ - public function getAddress(): ?string + public function getAddress(): ?SAMLStringValue { return $this->address; } @@ -138,13 +142,13 @@ public function getAddress(): ?string */ public function isEmptyElement(): bool { - return empty($this->notBefore) - && empty($this->notOnOrAfter) - && empty($this->recipient) - && empty($this->inResponseTo) - && empty($this->address) - && empty($this->elements) - && empty($this->namespacedAttributes); + return empty($this->getNotBefore()) + && empty($this->getNotOnOrAfter()) + && empty($this->getRecipient()) + && empty($this->getInResponseTo()) + && empty($this->getAddress()) + && empty($this->getElements()) + && empty($this->getAttributesNS()); } @@ -154,9 +158,9 @@ public function isEmptyElement(): bool * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing any of the mandatory attributes * @throws \SimpleSAML\Assert\AssertionFailedException * if NotBefore or NotOnOrAfter contain an invalid date. @@ -166,34 +170,12 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'SubjectConfirmationData', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, SubjectConfirmationData::NS, InvalidDOMElementException::class); - $NotBefore = self::getOptionalAttribute($xml, 'NotBefore', null); - if ($NotBefore !== null) { - // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications - $NotBefore = preg_replace('/([.][0-9]+Z)$/', 'Z', $NotBefore, 1); - - SAMLAssert::validDateTime($NotBefore, ProtocolViolationException::class); - $NotBefore = new DateTimeImmutable($NotBefore); - } - - $NotOnOrAfter = self::getOptionalAttribute($xml, 'NotOnOrAfter', null); - if ($NotOnOrAfter !== null) { - // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications - $NotOnOrAfter = preg_replace('/([.][0-9]+Z)$/', 'Z', $NotOnOrAfter, 1); - - SAMLAssert::validDateTime($NotOnOrAfter, ProtocolViolationException::class); - $NotOnOrAfter = new DateTimeImmutable($NotOnOrAfter); - } - - $Recipient = self::getOptionalAttribute($xml, 'Recipient', null); - $InResponseTo = self::getOptionalAttribute($xml, 'InResponseTo', null); - $Address = self::getOptionalAttribute($xml, 'Address', null); - return new static( - $NotBefore, - $NotOnOrAfter, - $Recipient, - $InResponseTo, - $Address, + self::getOptionalAttribute($xml, 'NotBefore', SAMLDateTimeValue::class, null), + self::getOptionalAttribute($xml, 'NotOnOrAfter', SAMLDateTimeValue::class, null), + self::getOptionalAttribute($xml, 'Recipient', EntityIDValue::class, null), + self::getOptionalAttribute($xml, 'InResponseTo', NCNameValue::class, null), + self::getOptionalAttribute($xml, 'Address', SAMLStringValue::class, null), self::getChildElementsFromXML($xml), self::getAttributesNSFromXML($xml), ); @@ -211,19 +193,19 @@ public function toXML(?DOMElement $parent = null): DOMElement $e = $this->instantiateParentElement($parent); if ($this->getNotBefore() !== null) { - $e->setAttribute('NotBefore', $this->getNotBefore()->format(C::DATETIME_FORMAT)); + $e->setAttribute('NotBefore', strval($this->getNotBefore())); } if ($this->getNotOnOrAfter() !== null) { - $e->setAttribute('NotOnOrAfter', $this->getNotOnOrAfter()->format(C::DATETIME_FORMAT)); + $e->setAttribute('NotOnOrAfter', strval($this->getNotOnOrAfter())); } if ($this->getRecipient() !== null) { - $e->setAttribute('Recipient', $this->getRecipient()); + $e->setAttribute('Recipient', strval($this->getRecipient())); } if ($this->getInResponseTo() !== null) { - $e->setAttribute('InResponseTo', $this->getInResponseTo()); + $e->setAttribute('InResponseTo', strval($this->getInResponseTo())); } if ($this->getAddress() !== null) { - $e->setAttribute('Address', $this->getAddress()); + $e->setAttribute('Address', strval($this->getAddress())); } foreach ($this->getAttributesNS() as $attr) { diff --git a/src/XML/saml/SubjectLocality.php b/src/XML/saml/SubjectLocality.php index 680f0434d..269513353 100644 --- a/src/XML/saml/SubjectLocality.php +++ b/src/XML/saml/SubjectLocality.php @@ -5,10 +5,12 @@ namespace SimpleSAML\SAML2\XML\saml; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\XML\Exception\InvalidDOMElementException; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\DomainValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; /** * Class representing SAML2 SubjectLocality @@ -23,24 +25,23 @@ final class SubjectLocality extends AbstractSamlElement implements SchemaValidat /** * Initialize an SubjectLocality. * - * @param string|null $address - * @param string|null $dnsName + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $address + * @param \SimpleSAML\SAML2\Type\DomainValue|null $dnsName */ public function __construct( - protected ?string $address = null, - protected ?string $dnsName = null, + protected ?SAMLStringValue $address = null, + protected ?DomainValue $dnsName = null, ) { - Assert::nullOrIp($address, 'Invalid IP address'); - Assert::nullOrNotWhitespaceOnly($dnsName, 'Invalid DNS name'); + Assert::nullOrIp($address?->getValue(), 'Invalid IP address'); } /** * Collect the value of the address-property * - * @return string|null + * @return \SimpleSAML\SAML2\Type\SAMLStringValue|null */ - public function getAddress(): ?string + public function getAddress(): ?SAMLStringValue { return $this->address; } @@ -49,9 +50,9 @@ public function getAddress(): ?string /** * Collect the value of the dnsName-property * - * @return string|null + * @return \SimpleSAML\SAML2\Type\DomainValue|null */ - public function getDnsName(): ?string + public function getDnsName(): ?DomainValue { return $this->dnsName; } @@ -64,8 +65,8 @@ public function getDnsName(): ?string */ public function isEmptyElement(): bool { - return empty($this->address) - && empty($this->dnsName); + return empty($this->getAddress()) + && empty($this->getDnsName()); } @@ -75,7 +76,7 @@ public function isEmptyElement(): bool * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -84,8 +85,8 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->namespaceURI, SubjectLocality::NS, InvalidDOMElementException::class); return new static( - self::getOptionalAttribute($xml, 'Address', null), - self::getOptionalAttribute($xml, 'DNSName', null), + self::getOptionalAttribute($xml, 'Address', SAMLStringValue::class, null), + self::getOptionalAttribute($xml, 'DNSName', DomainValue::class, null), ); } @@ -101,11 +102,11 @@ public function toXML(?DOMElement $parent = null): DOMElement $e = $this->instantiateParentElement($parent); if ($this->getAddress() !== null) { - $e->setAttribute('Address', $this->getAddress()); + $e->setAttribute('Address', $this->getAddress()->getValue()); } if ($this->getDnsName() !== null) { - $e->setAttribute('DNSName', $this->getDnsName()); + $e->setAttribute('DNSName', $this->getDnsName()->getValue()); } return $e; diff --git a/src/XML/saml/UnknownCondition.php b/src/XML/saml/UnknownCondition.php index e2999da94..cfa38df61 100644 --- a/src/XML/saml/UnknownCondition.php +++ b/src/XML/saml/UnknownCondition.php @@ -6,6 +6,7 @@ use DOMElement; use SimpleSAML\XML\Chunk; +use SimpleSAML\XMLSchema\Type\QNameValue; /** * Class for unknown conditions. @@ -16,11 +17,11 @@ final class UnknownCondition extends AbstractCondition { /** * @param \SimpleSAML\XML\Chunk $chunk The whole Condition element as a chunk object. - * @param string $type The xsi:type of this condition. + * @param \SimpleSAML\XMLSchema\Type\QNameValue $type The xsi:type of this condition. */ public function __construct( protected Chunk $chunk, - string $type, + QNameValue $type, ) { parent::__construct($type); } diff --git a/src/XML/saml/UnknownID.php b/src/XML/saml/UnknownID.php index 122d84c25..9b4414661 100644 --- a/src/XML/saml/UnknownID.php +++ b/src/XML/saml/UnknownID.php @@ -5,7 +5,9 @@ namespace SimpleSAML\SAML2\XML\saml; use DOMElement; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\XML\Chunk; +use SimpleSAML\XMLSchema\Type\QNameValue; /** * Class for unknown identifiers. @@ -16,15 +18,15 @@ final class UnknownID extends AbstractBaseID { /** * @param \SimpleSAML\XML\Chunk $chunk The whole BaseID element as a chunk object. - * @param string $type The xsi:type of this identifier. - * @param string|null $NameQualifier - * @param string|null $SPNameQualifier + * @param \SimpleSAML\XMLSchema\Type\QNameValue $type The xsi:type of this identifier. + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $NameQualifier + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $SPNameQualifier */ public function __construct( protected Chunk $chunk, - string $type, - ?string $NameQualifier = null, - ?string $SPNameQualifier = null, + QNameValue $type, + ?SAMLStringValue $NameQualifier = null, + ?SAMLStringValue $SPNameQualifier = null, ) { parent::__construct($type, $NameQualifier, $SPNameQualifier); } diff --git a/src/XML/saml/UnknownStatement.php b/src/XML/saml/UnknownStatement.php index 0008fa1bc..1cd4ccd18 100644 --- a/src/XML/saml/UnknownStatement.php +++ b/src/XML/saml/UnknownStatement.php @@ -6,6 +6,7 @@ use DOMElement; use SimpleSAML\XML\Chunk; +use SimpleSAML\XMLSchema\Type\QNameValue; /** * Class for unknown statements. @@ -16,11 +17,11 @@ final class UnknownStatement extends AbstractStatement { /** * @param \SimpleSAML\XML\Chunk $chunk The whole Statement element as a chunk object. - * @param string $type The xsi:type of this statement + * @param \SimpleSAML\XMLSchema\Type\QNameValue $type The xsi:type of this statement */ public function __construct( protected Chunk $chunk, - string $type, + QNameValue $type, ) { parent::__construct($type); } diff --git a/src/XML/samlp/AbstractMessage.php b/src/XML/samlp/AbstractMessage.php index b31fc3533..c00f21e30 100644 --- a/src/XML/samlp/AbstractMessage.php +++ b/src/XML/samlp/AbstractMessage.php @@ -4,18 +4,16 @@ namespace SimpleSAML\SAML2\XML\samlp; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\Utils; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\ExtendableElementTrait; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\SignableElementTrait; use SimpleSAML\SAML2\XML\SignedElementTrait; -use SimpleSAML\XML\Utils\Random as RandomUtils; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\XML\SignableElementInterface; use SimpleSAML\XMLSecurity\XML\SignedElementInterface; @@ -54,29 +52,22 @@ abstract class AbstractMessage extends AbstractSamlpElement implements SignableE * Initialize a message. * * @param \SimpleSAML\SAML2\XML\saml\Issuer|null $issuer - * @param string|null $id - * @param string $version - * @param \DateTimeImmutable|null $issueInstant - * @param string|null $destination - * @param string|null $consent + * @param \SimpleSAML\XMLSchema\Type\IDValue $id + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $issueInstant + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $destination + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $consent * @param \SimpleSAML\SAML2\XML\samlp\Extensions $extensions * * @throws \Exception */ protected function __construct( + protected IDValue $id, protected ?Issuer $issuer = null, - protected ?string $id = null, - protected string $version = '2.0', - protected ?DateTimeImmutable $issueInstant = null, - protected ?string $destination = null, - protected ?string $consent = null, + protected ?SAMLDateTimeValue $issueInstant = null, + protected ?SAMLAnyURIValue $destination = null, + protected ?SAMLAnyURIValue $consent = null, ?Extensions $extensions = null, ) { - Assert::nullOrSame($issueInstant?->getTimeZone()->getName(), 'Z', ProtocolViolationException::class); - Assert::nullOrValidNCName($id); // Covers the empty string - Assert::nullOrValidURI($destination); - Assert::nullOrValidURI($consent); - $this->setExtensions($extensions); } @@ -84,40 +75,21 @@ protected function __construct( /** * Retrieve the identifier of this message. * - * @return string The identifier of this message + * @return \SimpleSAML\XMLSchema\Type\IDValue The identifier of this message */ - public function getId(): string + public function getId(): IDValue { - if ($this->id === null) { - return (new RandomUtils())->generateId(); - } - return $this->id; } - /** - * Retrieve the version of this message. - * - * @return string The version of this message - */ - public function getVersion(): string - { - return $this->version; - } - - /** * Retrieve the issue timestamp of this message. * - * @return \DateTimeImmutable The issue timestamp of this message, as an UNIX timestamp + * @return \SimpleSAML\SAML2\Type\SAMLDateTimeValue The issue timestamp of this message, as an UNIX timestamp */ - public function getIssueInstant(): DateTimeImmutable + public function getIssueInstant(): SAMLDateTimeValue { - if ($this->issueInstant === null) { - return Utils::getContainer()->getClock()->now(); - } - return $this->issueInstant; } @@ -125,9 +97,10 @@ public function getIssueInstant(): DateTimeImmutable /** * Retrieve the destination of this message. * - * @return string|null The destination of this message, or NULL if no destination is given + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null The destination of this message, + * or NULL if no destination is given */ - public function getDestination(): ?string + public function getDestination(): ?SAMLAnyURIValue { return $this->destination; } @@ -138,9 +111,9 @@ public function getDestination(): ?string * Most likely (though not required) a value of urn:oasis:names:tc:SAML:2.0:consent. * * @see \SimpleSAML\SAML2\Constants - * @return string|null Consent + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null Consent */ - public function getConsent(): ?string + public function getConsent(): ?SAMLAnyURIValue { return $this->consent; } @@ -210,19 +183,19 @@ protected function toUnsignedXML(?DOMElement $parent = null): DOMElement $root = $this->instantiateParentElement($parent); /* Ugly hack to add another namespace declaration to the root element. */ - $root->setAttributeNS(C::NS_SAML, 'saml:tmp', 'tmp'); - $root->removeAttributeNS(C::NS_SAML, 'tmp'); +// $root->setAttributeNS(C::NS_SAML, 'saml:tmp', 'tmp'); +// $root->removeAttributeNS(C::NS_SAML, 'tmp'); - $root->setAttribute('Version', $this->getVersion()); - $root->setAttribute('ID', $this->getId()); - $root->setAttribute('IssueInstant', $this->getIssueInstant()->format(C::DATETIME_FORMAT)); + $root->setAttribute('Version', '2.0'); + $root->setAttribute('ID', $this->getId()->getValue()); + $root->setAttribute('IssueInstant', $this->getIssueInstant()->getValue()); if ($this->getDestination() !== null) { - $root->setAttribute('Destination', $this->getDestination()); + $root->setAttribute('Destination', $this->getDestination()->getValue()); } - if ($this->getConsent() !== null && $this->getConsent() !== C::CONSENT_UNSPECIFIED) { - $root->setAttribute('Consent', $this->getConsent()); + if ($this->getConsent() !== null && $this->getConsent()->getValue() !== C::CONSENT_UNSPECIFIED) { + $root->setAttribute('Consent', $this->getConsent()->getValue()); } $this->getIssuer()?->toXML($root); diff --git a/src/XML/samlp/AbstractStatusResponse.php b/src/XML/samlp/AbstractStatusResponse.php index 8ff880c91..e4e05d324 100644 --- a/src/XML/samlp/AbstractStatusResponse.php +++ b/src/XML/samlp/AbstractStatusResponse.php @@ -4,17 +4,19 @@ namespace SimpleSAML\SAML2\XML\samlp; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\SAML2\XML\saml\Issuer; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\NCNameValue; /** * Base class for all SAML 2 response messages. * - * Implements samlp:StatusResponseType. All of the elements in that type is - * stored in the \SimpleSAML\SAML2\Message class, and this class is therefore more + * Implements samlp:StatusResponseType. All of the elements in that type are + * stored in the \SimpleSAML\SAML2\XML\AbstractMessage class, and this class is therefore more * or less empty. It is included mainly to make it easy to separate requests from * responses. * @@ -25,32 +27,28 @@ abstract class AbstractStatusResponse extends AbstractMessage /** * Constructor for SAML 2 response messages. * + * @param \SimpleSAML\XMLSchema\Type\IDValue $id * @param \SimpleSAML\SAML2\XML\samlp\Status $status - * @param \DateTimeImmutable $issueInstant + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue $issueInstant * @param \SimpleSAML\SAML2\XML\saml\Issuer|null $issuer - * @param string|null $id - * @param string $version - * @param string|null $inResponseTo - * @param string|null $destination - * @param string|null $consent + * @param \SimpleSAML\XMLSchema\Type\NCNameValue|null $inResponseTo + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $destination + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $consent * @param \SimpleSAML\SAML2\XML\samlp\Extensions|null $extensions * * @throws \Exception */ protected function __construct( + IDValue $id, protected Status $status, - DateTimeImmutable $issueInstant, + SAMLDateTimeValue $issueInstant, ?Issuer $issuer = null, - ?string $id = null, - string $version = '2.0', - protected ?string $inResponseTo = null, - ?string $destination = null, - ?string $consent = null, + protected ?NCNameValue $inResponseTo = null, + ?SAMLAnyURIValue $destination = null, + ?SAMLAnyURIValue $consent = null, ?Extensions $extensions = null, ) { - Assert::nullOrValidNCName($inResponseTo); // Covers the empty string - - parent::__construct($issuer, $id, $version, $issueInstant, $destination, $consent, $extensions); + parent::__construct($id, $issuer, $issueInstant, $destination, $consent, $extensions); } @@ -61,16 +59,16 @@ protected function __construct( */ public function isSuccess(): bool { - return $this->status->getStatusCode()->getValue() === C::STATUS_SUCCESS; + return strval($this->status->getStatusCode()->getValue()) === C::STATUS_SUCCESS; } /** * Retrieve the ID of the request this is a response to. * - * @return string|null The ID of the request. + * @return \SimpleSAML\XMLSchema\Type\NCNameValue|null The ID of the request. */ - public function getInResponseTo(): ?string + public function getInResponseTo(): ?NCNameValue { return $this->inResponseTo; } @@ -98,7 +96,7 @@ protected function toUnsignedXML(?DOMElement $parent = null): DOMElement $e = parent::toUnsignedXML($parent); if ($this->getInResponseTo() !== null) { - $e->setAttribute('InResponseTo', $this->getInResponseTo()); + $e->setAttribute('InResponseTo', $this->getInResponseTo()->getValue()); } $this->getStatus()->toXML($e); diff --git a/src/XML/samlp/AbstractSubjectQuery.php b/src/XML/samlp/AbstractSubjectQuery.php index a7bf87bf9..ff0bfbba3 100644 --- a/src/XML/samlp/AbstractSubjectQuery.php +++ b/src/XML/samlp/AbstractSubjectQuery.php @@ -4,11 +4,13 @@ namespace SimpleSAML\SAML2\XML\samlp; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\saml\Subject; +use SimpleSAML\XMLSchema\Type\IDValue; /** * Base class for SAML 2 subject query messages. @@ -26,26 +28,24 @@ abstract class AbstractSubjectQuery extends AbstractRequest /** * Constructor for SAML 2 response messages. * + * @param \SimpleSAML\XMLSchema\Type\IDValue $id * @param \SimpleSAML\SAML2\XML\saml\Subject $subject * @param \SimpleSAML\SAML2\XML\saml\Issuer $issuer - * @param string|null $id - * @param string $version - * @param \DateTimeImmutable $issueInstant - * @param string|null $destination - * @param string|null $consent + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue $issueInstant + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $destination + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $consent * @param \SimpleSAML\SAML2\XML\samlp\Extensions $extensions */ protected function __construct( + IDValue $id, protected Subject $subject, ?Issuer $issuer = null, - ?string $id = null, - string $version = '2.0', - ?DateTimeImmutable $issueInstant = null, - ?string $destination = null, - ?string $consent = null, + ?SAMLDateTimeValue $issueInstant = null, + ?SAMLAnyURIValue $destination = null, + ?SAMLAnyURIValue $consent = null, ?Extensions $extensions = null, ) { - parent::__construct($issuer, $id, $version, $issueInstant, $destination, $consent, $extensions); + parent::__construct($id, $issuer, $issueInstant, $destination, $consent, $extensions); } diff --git a/src/XML/samlp/Artifact.php b/src/XML/samlp/Artifact.php index 423383ec7..4d5a7cb71 100644 --- a/src/XML/samlp/Artifact.php +++ b/src/XML/samlp/Artifact.php @@ -4,12 +4,10 @@ namespace SimpleSAML\SAML2\XML\samlp; -use DOMElement; -use SimpleSAML\SAML2\Assert\Assert; -use SimpleSAML\XML\Base64ElementTrait; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; +use SimpleSAML\XMLSchema\Type\Base64BinaryValue; /** * Class for SAML artifacts. @@ -18,36 +16,10 @@ */ final class Artifact extends AbstractSamlpElement implements SchemaValidatableElementInterface { - use Base64ElementTrait; use SchemaValidatableElementTrait; + use TypedTextContentTrait; - /** - * Initialize an artifact. - * - * @param string $content - */ - public function __construct( - string $content, - ) { - $this->setContent($content); - } - - - /** - * Convert XML into an Artifact - * - * @param \DOMElement $xml The XML element we should load - * @return static - * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException - * If the qualified name of the supplied element is wrong - */ - public static function fromXML(DOMElement $xml): static - { - Assert::same($xml->localName, 'Artifact', InvalidDOMElementException::class); - Assert::same($xml->namespaceURI, Artifact::NS, InvalidDOMElementException::class); - - return new static($xml->textContent); - } + /** @var string */ + public const TEXTCONTENT_TYPE = Base64BinaryValue::class; } diff --git a/src/XML/samlp/ArtifactResolve.php b/src/XML/samlp/ArtifactResolve.php index 5090893e2..5106e0d5c 100644 --- a/src/XML/samlp/ArtifactResolve.php +++ b/src/XML/samlp/ArtifactResolve.php @@ -4,22 +4,23 @@ namespace SimpleSAML\SAML2\XML\samlp; -use DateTimeImmutable; use DOMElement; use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooHighException; use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\Issuer; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function array_pop; -use function preg_replace; /** * The Artifact is part of the SAML 2.0 IdP code, and it builds an artifact object. @@ -36,28 +37,26 @@ class ArtifactResolve extends AbstractRequest implements SchemaValidatableElemen /** * Initialize an ArtifactResolve. * + * @param \SimpleSAML\XMLSchema\Type\IDValue $id * @param \SimpleSAML\SAML2\XML\samlp\Artifact $artifact - * @param \DateTimeImmutable $issueInstant + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue $issueInstant * @param \SimpleSAML\SAML2\XML\saml\Issuer|null $issuer - * @param string|null $id - * @param string $version - * @param string|null $destination - * @param string|null $consent + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $destination + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $consent * @param \SimpleSAML\SAML2\XML\samlp\Extensions $extensions * * @throws \Exception */ final public function __construct( + IDValue $id, protected Artifact $artifact, - DateTimeImmutable $issueInstant, + SAMLDateTimeValue $issueInstant, ?Issuer $issuer = null, - ?string $id = null, - string $version = '2.0', - ?string $destination = null, - ?string $consent = null, + ?SAMLAnyURIValue $destination = null, + ?SAMLAnyURIValue $consent = null, ?Extensions $extensions = null, ) { - parent::__construct($issuer, $id, $version, $issueInstant, $destination, $consent, $extensions); + parent::__construct($id, $issuer, $issueInstant, $destination, $consent, $extensions); } @@ -76,11 +75,11 @@ public function getArtifact(): Artifact * @param \DOMElement $xml * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes - * @throws \SimpleSAML\XML\Exception\TooManyElementsException + * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException * if too many child-elements of a type are specified */ public static function fromXML(DOMElement $xml): static @@ -88,19 +87,9 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'ArtifactResolve', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, ArtifactResolve::NS, InvalidDOMElementException::class); - $version = self::getAttribute($xml, 'Version'); - Assert::true(version_compare('2.0', $version, '<='), RequestVersionTooLowException::class); - Assert::true(version_compare('2.0', $version, '>='), RequestVersionTooHighException::class); - - $id = self::getAttribute($xml, 'ID'); - Assert::validNCName($id); // Covers the empty string - - $issueInstant = self::getAttribute($xml, 'IssueInstant'); - // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications - $issueInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $issueInstant, 1); - - Assert::validDateTime($issueInstant, ProtocolViolationException::class); - $issueInstant = new DateTimeImmutable($issueInstant); + $version = self::getAttribute($xml, 'Version', SAMLStringValue::class); + Assert::true(version_compare('2.0', $version->getValue(), '<='), RequestVersionTooLowException::class); + Assert::true(version_compare('2.0', $version->getValue(), '>='), RequestVersionTooHighException::class); $issuer = Issuer::getChildrenOfClass($xml); Assert::maxCount($issuer, 1); @@ -121,13 +110,12 @@ public static function fromXML(DOMElement $xml): static Assert::maxCount($artifact, 1, 'Only one samlp:Artifact is allowed.', TooManyElementsException::class); $resolve = new static( + self::getAttribute($xml, 'ID', IDValue::class), $artifact[0], - $issueInstant, + self::getAttribute($xml, 'IssueInstant', SAMLDateTimeValue::class), array_pop($issuer), - $id, - $version, - self::getOptionalAttribute($xml, 'Destination', null), - self::getOptionalAttribute($xml, 'Consent', null), + self::getOptionalAttribute($xml, 'Destination', SAMLAnyURIValue::class, null), + self::getOptionalAttribute($xml, 'Consent', SAMLAnyURIValue::class, null), array_pop($extensions), ); diff --git a/src/XML/samlp/ArtifactResponse.php b/src/XML/samlp/ArtifactResponse.php index cc242c0e3..af3b9eca4 100644 --- a/src/XML/samlp/ArtifactResponse.php +++ b/src/XML/samlp/ArtifactResponse.php @@ -4,22 +4,24 @@ namespace SimpleSAML\SAML2\XML\samlp; -use DateTimeImmutable; use DOMElement; use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooHighException; use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\saml\Issuer; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\NCNameValue; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function array_pop; -use function preg_replace; use function version_compare; /** @@ -36,35 +38,32 @@ class ArtifactResponse extends AbstractStatusResponse implements SchemaValidatab /** * Constructor for SAML 2 ArtifactResponse. * + * @param \SimpleSAML\XMLSchema\Type\IDValue $id * @param \SimpleSAML\SAML2\XML\samlp\Status $status - * @param \DateTimeImmutable $issueInstant + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue $issueInstant * @param \SimpleSAML\SAML2\XML\saml\Issuer|null $issuer - * @param string|null $id - * @param string $version - * @param string|null $inResponseTo - * @param string|null $destination - * @param string|null $consent + * @param \SimpleSAML\XMLSchema\Type\NCNameValue|null $inResponseTo + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $destination + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $consent * @param \SimpleSAML\SAML2\XML\samlp\Extensions|null $extensions * @param \SimpleSAML\SAML2\XML\samlp\AbstractMessage|null $message */ final public function __construct( + IDValue $id, Status $status, - DateTimeImmutable $issueInstant, + SAMLDateTimeValue $issueInstant, ?Issuer $issuer = null, - ?string $id = null, - string $version = '2.0', - ?string $inResponseTo = null, - ?string $destination = null, - ?string $consent = null, + ?NCNameValue $inResponseTo = null, + ?SAMLAnyURIValue $destination = null, + ?SAMLAnyURIValue $consent = null, ?Extensions $extensions = null, protected ?AbstractMessage $message = null, ) { parent::__construct( + $id, $status, $issueInstant, $issuer, - $id, - $version, $inResponseTo, $destination, $consent, @@ -90,9 +89,9 @@ public function getMessage(): ?AbstractMessage * @param \DOMElement $xml * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes */ public static function fromXML(DOMElement $xml): static @@ -100,23 +99,9 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'ArtifactResponse', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, ArtifactResponse::NS, InvalidDOMElementException::class); - $version = self::getAttribute($xml, 'Version'); - Assert::true(version_compare('2.0', $version, '<='), RequestVersionTooLowException::class); - Assert::true(version_compare('2.0', $version, '>='), RequestVersionTooHighException::class); - - $id = self::getAttribute($xml, 'ID'); - Assert::validNCName($id); // Covers the empty string - - $inResponseTo = self::getOptionalAttribute($xml, 'InResponseTo', null); - $destination = self::getOptionalAttribute($xml, 'Destination', null); - $consent = self::getOptionalAttribute($xml, 'Consent', null); - - $issueInstant = self::getAttribute($xml, 'IssueInstant'); - // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications - $issueInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $issueInstant, 1); - - Assert::validDateTime($issueInstant, ProtocolViolationException::class); - $issueInstant = new DateTimeImmutable($issueInstant); + $version = self::getAttribute($xml, 'Version', SAMLStringValue::class); + Assert::true(version_compare('2.0', $version->getValue(), '<='), RequestVersionTooLowException::class); + Assert::true(version_compare('2.0', $version->getValue(), '>='), RequestVersionTooHighException::class); $issuer = Issuer::getChildrenOfClass($xml); Assert::countBetween($issuer, 0, 1); @@ -155,14 +140,13 @@ public static function fromXML(DOMElement $xml): static ); $response = new static( + self::getAttribute($xml, 'ID', IDValue::class), array_pop($status), - $issueInstant, + self::getAttribute($xml, 'IssueInstant', SAMLDateTimeValue::class), empty($issuer) ? null : array_pop($issuer), - $id, - $version, - $inResponseTo, - $destination, - $consent, + self::getOptionalAttribute($xml, 'InResponseTo', NCNameValue::class, null), + self::getOptionalAttribute($xml, 'Destination', SAMLAnyURIValue::class, null), + self::getOptionalAttribute($xml, 'Consent', SAMLAnyURIValue::class, null), empty($extensions) ? null : array_pop($extensions), $message, ); diff --git a/src/XML/samlp/AssertionIDRequest.php b/src/XML/samlp/AssertionIDRequest.php index 01c4a2642..e1bae46c6 100644 --- a/src/XML/samlp/AssertionIDRequest.php +++ b/src/XML/samlp/AssertionIDRequest.php @@ -4,23 +4,24 @@ namespace SimpleSAML\SAML2\XML\samlp; -use DateTimeImmutable; use DOMElement; use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooHighException; use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\AssertionIDRef; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function array_pop; -use function preg_replace; use function version_compare; /** @@ -34,34 +35,31 @@ final class AssertionIDRequest extends AbstractRequest implements SchemaValidata /** * Initialize an AssertionIDRequest. * + * @param \SimpleSAML\XMLSchema\Type\IDValue $id * @param \SimpleSAML\SAML2\XML\saml\AssertionIDRef[] $assertionIDRef * @param \SimpleSAML\SAML2\XML\saml\Issuer|null $issuer - * @param string|null $id - * @param string $version - * @param \DateTimeImmutable|null $issueInstant - * @param string|null $destination - * @param string|null $consent + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $issueInstant + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $destination + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $consent * @param \SimpleSAML\SAML2\XML\samlp\Extensions $extensions * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException */ public function __construct( + IDValue $id, protected array $assertionIDRef, ?Issuer $issuer = null, - ?string $id = null, - string $version = '2.0', - ?DateTimeImmutable $issueInstant = null, - ?string $destination = null, - ?string $consent = null, + ?SAMLDateTimeValue $issueInstant = null, + ?SAMLAnyURIValue $destination = null, + ?SAMLAnyURIValue $consent = null, ?Extensions $extensions = null, ) { Assert::maxCount($assertionIDRef, C::UNBOUNDED_LIMIT); Assert::allIsInstanceOf($assertionIDRef, AssertionIDRef::class, InvalidDOMElementException::class); parent::__construct( - $issuer, $id, - $version, + $issuer, $issueInstant, $destination, $consent, @@ -85,7 +83,7 @@ public function getAssertionIDRef(): array * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * If the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -104,19 +102,9 @@ public static function fromXML(DOMElement $xml): static $issuer = Issuer::getChildrenOfClass($xml); Assert::maxCount($issuer, 1, 'Only one element is allowed.', TooManyElementsException::class); - $version = self::getAttribute($xml, 'Version'); - Assert::true(version_compare('2.0', $version, '<='), RequestVersionTooLowException::class); - Assert::true(version_compare('2.0', $version, '>='), RequestVersionTooHighException::class); - - $id = self::getAttribute($xml, 'ID'); - Assert::validNCName($id); // Covers the empty string - - $issueInstant = self::getAttribute($xml, 'IssueInstant'); - // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications - $issueInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $issueInstant, 1); - - Assert::validDateTime($issueInstant, ProtocolViolationException::class); - $issueInstant = new DateTimeImmutable($issueInstant); + $version = self::getAttribute($xml, 'Version', SAMLStringValue::class); + Assert::true(version_compare('2.0', strval($version), '<='), RequestVersionTooLowException::class); + Assert::true(version_compare('2.0', strval($version), '>='), RequestVersionTooHighException::class); $extensions = Extensions::getChildrenOfClass($xml); Assert::maxCount( @@ -135,13 +123,12 @@ public static function fromXML(DOMElement $xml): static ); $request = new static( + self::getAttribute($xml, 'ID', IDValue::class), $assertionIDRef, array_pop($issuer), - $id, - $version, - $issueInstant, - self::getOptionalAttribute($xml, 'Destination', null), - self::getOptionalAttribute($xml, 'Consent', null), + self::getAttribute($xml, 'IssueInstant', SAMLDateTimeValue::class), + self::getOptionalAttribute($xml, 'Destination', SAMLAnyURIValue::class, null), + self::getOptionalAttribute($xml, 'Consent', SAMLAnyURIValue::class, null), array_pop($extensions), ); diff --git a/src/XML/samlp/AttributeQuery.php b/src/XML/samlp/AttributeQuery.php index d2d1c72ff..d4681a05f 100644 --- a/src/XML/samlp/AttributeQuery.php +++ b/src/XML/samlp/AttributeQuery.php @@ -4,21 +4,24 @@ namespace SimpleSAML\SAML2\XML\samlp; -use DateTimeImmutable; use DOMElement; use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooHighException; use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\Attribute; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\saml\Subject; -use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function array_pop; @@ -47,25 +50,23 @@ class AttributeQuery extends AbstractSubjectQuery implements SchemaValidatableEl /** * Constructor for SAML 2 AttributeQuery. * + * @param \SimpleSAML\XMLSchema\Type\IDValue $id * @param \SimpleSAML\SAML2\XML\saml\Subject $subject - * @param \DateTimeImmutable $issueInstant + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue $issueInstant * @param \SimpleSAML\SAML2\XML\saml\Attribute[] $attributes * @param \SimpleSAML\SAML2\XML\saml\Issuer $issuer - * @param string|null $id - * @param string $version - * @param string|null $destination - * @param string|null $consent + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $destination + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $consent * @param \SimpleSAML\SAML2\XML\samlp\Extensions $extensions */ final public function __construct( + IDValue $id, Subject $subject, - DateTimeImmutable $issueInstant, + SAMLDateTimeValue $issueInstant, protected array $attributes = [], ?Issuer $issuer = null, - ?string $id = null, - string $version = '2.0', - ?string $destination = null, - ?string $consent = null, + ?SAMLAnyURIValue $destination = null, + ?SAMLAnyURIValue $consent = null, ?Extensions $extensions = null, ) { Assert::maxCount($attributes, C::UNBOUNDED_LIMIT); @@ -74,7 +75,7 @@ final public function __construct( $cache = []; foreach ($attributes as $attribute) { $name = $attribute->getName(); - $nameFormat = $attribute->getNameFormat(); + $nameFormat = $attribute->getNameFormat()?->getValue() ?? C::NAMEFORMAT_UNSPECIFIED; if (isset($cache[$nameFormat])) { Assert::true( @@ -87,7 +88,7 @@ final public function __construct( } unset($cache); - parent::__construct($subject, $issuer, $id, $version, $issueInstant, $destination, $consent, $extensions); + parent::__construct($id, $subject, $issuer, $issueInstant, $destination, $consent, $extensions); } @@ -108,13 +109,13 @@ public function getAttributes(): array * @param \DOMElement $xml * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes - * @throws \SimpleSAML\XML\Exception\MissingElementException + * @throws \SimpleSAML\XMLSchema\Exception\MissingElementException * if one of the mandatory child-elements is missing - * @throws \SimpleSAML\XML\Exception\TooManyElementsException + * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException * if too many child-elements of a type are specified */ public static function fromXML(DOMElement $xml): static @@ -122,22 +123,9 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'AttributeQuery', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, AttributeQuery::NS, InvalidDOMElementException::class); - $version = self::getAttribute($xml, 'Version'); - Assert::true(version_compare('2.0', $version, '<='), RequestVersionTooLowException::class); - Assert::true(version_compare('2.0', $version, '>='), RequestVersionTooHighException::class); - - $id = self::getAttribute($xml, 'ID'); - Assert::validNCName($id); // Covers the empty string - - $destination = self::getOptionalAttribute($xml, 'Destination', null); - $consent = self::getOptionalAttribute($xml, 'Consent', null); - - $issueInstant = self::getAttribute($xml, 'IssueInstant'); - // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications - $issueInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $issueInstant, 1); - - Assert::validDateTime($issueInstant, ProtocolViolationException::class); - $issueInstant = new DateTimeImmutable($issueInstant); + $version = self::getAttribute($xml, 'Version', SAMLStringValue::class); + Assert::true(version_compare('2.0', strval($version), '<='), RequestVersionTooLowException::class); + Assert::true(version_compare('2.0', strval($version), '>='), RequestVersionTooHighException::class); $issuer = Issuer::getChildrenOfClass($xml); Assert::countBetween($issuer, 0, 1); @@ -163,14 +151,13 @@ public static function fromXML(DOMElement $xml): static Assert::maxCount($signature, 1, 'Only one ds:Signature element is allowed.', TooManyElementsException::class); $request = new static( + self::getAttribute($xml, 'ID', IDValue::class), array_pop($subject), - $issueInstant, + self::getAttribute($xml, 'IssueInstant', SAMLDateTimeValue::class), Attribute::getChildrenOfClass($xml), array_pop($issuer), - $id, - $version, - $destination, - $consent, + self::getOptionalAttribute($xml, 'Destination', SAMLAnyURIValue::class, null), + self::getOptionalAttribute($xml, 'Consent', SAMLAnyURIValue::class, null), array_pop($extensions), ); diff --git a/src/XML/Comparison.php b/src/XML/samlp/AuthnContextComparisonTypeEnum.php similarity index 85% rename from src/XML/Comparison.php rename to src/XML/samlp/AuthnContextComparisonTypeEnum.php index d27176ad1..f44b9eaeb 100644 --- a/src/XML/Comparison.php +++ b/src/XML/samlp/AuthnContextComparisonTypeEnum.php @@ -2,34 +2,34 @@ declare(strict_types=1); -namespace SimpleSAML\SAML2\XML; +namespace SimpleSAML\SAML2\XML\samlp; -enum Comparison: string +enum AuthnContextComparisonTypeEnum: string { /** * Request Authentication Context Comparison indicating that the resulting authentication context in the * authentication statement MUST be stronger (as deemed by the responder) than any one of the authentication * contexts specified */ - case BETTER = 'better'; + case Better = 'better'; /** * Request Authentication Context Comparison indicating that the resulting authentication context in the * authentication statement MUST be the exact match of at least one of the authentication contexts specified */ - case EXACT = 'exact'; + case Exact = 'exact'; /** * Request Authentication Context Comparison indicating that the resulting authentication context in the * authentication statement MUST be as strong as possible (as deemed by the responder) without exceeding the * strength of at least one of the authentication contexts specified. */ - case MAXIMUM = 'maximum'; + case Maxmimum = 'maximum'; /** * Request Authentication Context Comparison indicating that he resulting authentication context in the * authentication statement MUST be at least as strong (as deemed by the responder) as one of the authentication * contexts specified. */ - case MINIMUM = 'minimum'; + case Minimum = 'minimum'; } diff --git a/src/XML/samlp/AuthnQuery.php b/src/XML/samlp/AuthnQuery.php index 429403362..57a77fc0a 100644 --- a/src/XML/samlp/AuthnQuery.php +++ b/src/XML/samlp/AuthnQuery.php @@ -4,24 +4,25 @@ namespace SimpleSAML\SAML2\XML\samlp; -use DateTimeImmutable; use DOMElement; use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooHighException; use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\saml\Subject; use SimpleSAML\SAML2\XML\samlp\RequestedAuthnContext; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function array_pop; -use function preg_replace; use function version_compare; /** @@ -37,30 +38,28 @@ final class AuthnQuery extends AbstractSubjectQuery implements SchemaValidatable /** * Constructor for SAML 2 AuthnQuery. * + * @param \SimpleSAML\XMLSchema\Type\IDValue $id * @param \SimpleSAML\SAML2\XML\saml\Subject $subject * @param \SimpleSAML\SAML2\XML\samlp\RequestedAuthnContext|null $requestedAuthnContext - * @param string|null $sessionIndex + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $sessionIndex * @param \SimpleSAML\SAML2\XML\saml\Issuer $issuer - * @param string|null $id - * @param string $version - * @param \DateTimeImmutable $issueInstant - * @param string|null $destination - * @param string|null $consent + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue $issueInstant + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $destination + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $consent * @param \SimpleSAML\SAML2\XML\samlp\Extensions $extensions */ public function __construct( + IDValue $id, Subject $subject, - DateTimeImmutable $issueInstant, + SAMLDateTimeValue $issueInstant, protected ?RequestedAuthnContext $requestedAuthnContext = null, - protected ?string $sessionIndex = null, + protected ?SAMLStringValue $sessionIndex = null, ?Issuer $issuer = null, - ?string $id = null, - string $version = '2.0', - ?string $destination = null, - ?string $consent = null, + ?SAMLAnyURIValue $destination = null, + ?SAMLAnyURIValue $consent = null, ?Extensions $extensions = null, ) { - parent::__construct($subject, $issuer, $id, $version, $issueInstant, $destination, $consent, $extensions); + parent::__construct($id, $subject, $issuer, $issueInstant, $destination, $consent, $extensions); } @@ -78,9 +77,9 @@ public function getRequestedAuthnContext(): ?RequestedAuthnContext /** * Retrieve session index. * - * @return string|null + * @return \SimpleSAML\SAML2\Type\SAMLStringValue|null */ - public function getSessionIndex(): ?string + public function getSessionIndex(): ?SAMLStringValue { return $this->sessionIndex; } @@ -92,13 +91,13 @@ public function getSessionIndex(): ?string * @param \DOMElement $xml * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes - * @throws \SimpleSAML\XML\Exception\MissingElementException + * @throws \SimpleSAML\XMLSchema\Exception\MissingElementException * if one of the mandatory child-elements is missing - * @throws \SimpleSAML\XML\Exception\TooManyElementsException + * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException * if too many child-elements of a type are specified */ public static function fromXML(DOMElement $xml): static @@ -107,22 +106,8 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->namespaceURI, AuthnQuery::NS, InvalidDOMElementException::class); $version = self::getAttribute($xml, 'Version'); - Assert::true(version_compare('2.0', $version, '<='), RequestVersionTooLowException::class); - Assert::true(version_compare('2.0', $version, '>='), RequestVersionTooHighException::class); - - $id = self::getAttribute($xml, 'ID'); - Assert::validNCName($id); // Covers the empty string - - $destination = self::getOptionalAttribute($xml, 'Destination', null); - $consent = self::getOptionalAttribute($xml, 'Consent', null); - $sessionIndex = self::getOptionalAttribute($xml, 'SessionIndex', null); - - $issueInstant = self::getAttribute($xml, 'IssueInstant'); - // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications - $issueInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $issueInstant, 1); - - Assert::validDateTime($issueInstant, ProtocolViolationException::class); - $issueInstant = new DateTimeImmutable($issueInstant); + Assert::true(version_compare('2.0', $version->getValue(), '<='), RequestVersionTooLowException::class); + Assert::true(version_compare('2.0', $version->getValue(), '>='), RequestVersionTooHighException::class); $requestedAuthnContext = RequestedAuthnContext::getChildrenOfClass($xml); @@ -150,15 +135,14 @@ public static function fromXML(DOMElement $xml): static Assert::maxCount($signature, 1, 'Only one ds:Signature element is allowed.', TooManyElementsException::class); $request = new static( + self::getAttribute($xml, 'ID', IDValue::class), array_pop($subject), - $issueInstant, + self::getAttribute($xml, 'IssueInstant', SAMLDateTimeValue::class), array_pop($requestedAuthnContext), - $sessionIndex, + self::getOptionalAttribute($xml, 'SessionIndex', SAMLStringValue::class, null), array_pop($issuer), - $id, - $version, - $destination, - $consent, + self::getOptionalAttribute($xml, 'Destination', SAMLAnyURIValue::class, null), + self::getOptionalAttribute($xml, 'Consent', SAMLAnyURIValue::class, null), array_pop($extensions), ); @@ -183,7 +167,7 @@ protected function toUnsignedXML(?DOMElement $parent = null): DOMElement $sessionIndex = $this->getSessionIndex(); if ($sessionIndex !== null) { - $e->setAttribute('SessionIndex', $sessionIndex); + $e->setAttribute('SessionIndex', $sessionIndex->getValue()); } $this->getRequestedAuthnContext()?->toXML($e); diff --git a/src/XML/samlp/AuthnRequest.php b/src/XML/samlp/AuthnRequest.php index 86476ec42..28d97f158 100644 --- a/src/XML/samlp/AuthnRequest.php +++ b/src/XML/samlp/AuthnRequest.php @@ -4,19 +4,24 @@ namespace SimpleSAML\SAML2\XML\samlp; -use DateTimeImmutable; use DOMElement; use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooHighException; use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\Conditions; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\saml\Subject; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\BooleanValue; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\UnsignedShortValue; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function array_pop; @@ -35,49 +40,46 @@ class AuthnRequest extends AbstractRequest implements SchemaValidatableElementIn /** * Constructor for SAML 2 AuthnRequest * - * @param \DateTimeImmutable $issueInstant + * @param \SimpleSAML\XMLSchema\Type\IDValue $id + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue $issueInstant * @param \SimpleSAML\SAML2\XML\samlp\RequestedAuthnContext|null $requestedAuthnContext * @param \SimpleSAML\SAML2\XML\saml\Subject|null $subject * @param \SimpleSAML\SAML2\XML\samlp\NameIDPolicy|null $nameIdPolicy * @param \SimpleSAML\SAML2\XML\saml\Conditions|null $conditions - * @param bool|null $forceAuthn - * @param bool|null $isPassive - * @param string|null $assertionConsumerServiceURL - * @param int|null $assertionConsumerServiceIndex - * @param string|null $protocolBinding - * @param int|null $attributeConsumingServiceIndex - * @param string|null $providerName + * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $forceAuthn + * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $isPassive + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $assertionConsumerServiceURL + * @param \SimpleSAML\XMLSchema\Type\UnsignedShortValue|null $assertionConsumerServiceIndex + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $protocolBinding + * @param \SimpleSAML\XMLSchema\Type\UnsignedShortValue|null $attributeConsumingServiceIndex + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $providerName * @param \SimpleSAML\SAML2\XML\saml\Issuer|null $issuer - * @param string|null $id - * @param string $version - * @param string|null $destination - * @param string|null $consent + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $destination + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $consent * @param \SimpleSAML\SAML2\XML\samlp\Extensions|null $extensions * @param \SimpleSAML\SAML2\XML\samlp\Scoping|null $scoping * @throws \Exception */ final public function __construct( - DateTimeImmutable $issueInstant, + IDValue $id, + SAMLDateTimeValue $issueInstant, protected ?RequestedAuthnContext $requestedAuthnContext = null, protected ?Subject $subject = null, protected ?NameIDPolicy $nameIdPolicy = null, protected ?Conditions $conditions = null, - protected ?bool $forceAuthn = null, - protected ?bool $isPassive = null, - protected ?string $assertionConsumerServiceURL = null, - protected ?int $assertionConsumerServiceIndex = null, - protected ?string $protocolBinding = null, - protected ?int $attributeConsumingServiceIndex = null, - protected ?string $providerName = null, + protected ?BooleanValue $forceAuthn = null, + protected ?BooleanValue $isPassive = null, + protected ?SAMLAnyURIValue $assertionConsumerServiceURL = null, + protected ?UnsignedShortValue $assertionConsumerServiceIndex = null, + protected ?SAMLAnyURIValue $protocolBinding = null, + protected ?UnsignedShortValue $attributeConsumingServiceIndex = null, + protected ?SAMLStringValue $providerName = null, ?Issuer $issuer = null, - ?string $id = null, - string $version = '2.0', - ?string $destination = null, - ?string $consent = null, + ?SAMLAnyURIValue $destination = null, + ?SAMLAnyURIValue $consent = null, ?Extensions $extensions = null, protected ?Scoping $scoping = null, ) { - Assert::nullOrNotWhitespaceOnly($providerName); Assert::oneOf( null, [$assertionConsumerServiceURL, $assertionConsumerServiceIndex], @@ -92,12 +94,8 @@ final public function __construct( . ' please specify one or the other.', ProtocolViolationException::class, ); - Assert::nullOrValidURL($assertionConsumerServiceURL); - Assert::nullOrValidURI($protocolBinding); - Assert::nullOrRange($attributeConsumingServiceIndex, 0, 65535); - Assert::nullOrRange($assertionConsumerServiceIndex, 0, 65535); - parent::__construct($issuer, $id, $version, $issueInstant, $destination, $consent, $extensions); + parent::__construct($id, $issuer, $issueInstant, $destination, $consent, $extensions); } @@ -131,7 +129,6 @@ public function getConditions(): ?Conditions /** * Retrieve the NameIdPolicy. * - * @see \SimpleSAML\SAML2\AuthnRequest::setNameIdPolicy() * @return \SimpleSAML\SAML2\XML\samlp\NameIDPolicy|null The NameIdPolicy. */ public function getNameIdPolicy(): ?NameIDPolicy @@ -143,9 +140,9 @@ public function getNameIdPolicy(): ?NameIDPolicy /** * Retrieve the value of the ForceAuthn attribute. * - * @return bool|null The ForceAuthn attribute. + * @return \SimpleSAML\XMLSchema\Type\BooleanValue|null The ForceAuthn attribute. */ - public function getForceAuthn(): ?bool + public function getForceAuthn(): ?BooleanValue { return $this->forceAuthn; } @@ -154,9 +151,9 @@ public function getForceAuthn(): ?bool /** * Retrieve the value of the ProviderName attribute. * - * @return string|null The ProviderName attribute. + * @return \SimpleSAML\SAML2\Type\SAMLStringValue|null The ProviderName attribute. */ - public function getProviderName(): ?string + public function getProviderName(): ?SAMLStringValue { return $this->providerName; } @@ -165,9 +162,9 @@ public function getProviderName(): ?string /** * Retrieve the value of the IsPassive attribute. * - * @return bool|null The IsPassive attribute. + * @return \SimpleSAML\XMLSchema\Type\BooleanValue|null The IsPassive attribute. */ - public function getIsPassive(): ?bool + public function getIsPassive(): ?BooleanValue { return $this->isPassive; } @@ -176,9 +173,9 @@ public function getIsPassive(): ?bool /** * Retrieve the value of the AssertionConsumerServiceURL attribute. * - * @return string|null The AssertionConsumerServiceURL attribute. + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null The AssertionConsumerServiceURL attribute. */ - public function getAssertionConsumerServiceURL(): ?string + public function getAssertionConsumerServiceURL(): ?SAMLAnyURIValue { return $this->assertionConsumerServiceURL; } @@ -187,9 +184,9 @@ public function getAssertionConsumerServiceURL(): ?string /** * Retrieve the value of the ProtocolBinding attribute. * - * @return string|null The ProtocolBinding attribute. + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null The ProtocolBinding attribute. */ - public function getProtocolBinding(): ?string + public function getProtocolBinding(): ?SAMLAnyURIValue { return $this->protocolBinding; } @@ -198,9 +195,9 @@ public function getProtocolBinding(): ?string /** * Retrieve the value of the AttributeConsumingServiceIndex attribute. * - * @return int|null The AttributeConsumingServiceIndex attribute. + * @return \SimpleSAML\XMLSchema\Type\UnsignedShortValue|null The AttributeConsumingServiceIndex attribute. */ - public function getAttributeConsumingServiceIndex(): ?int + public function getAttributeConsumingServiceIndex(): ?UnsignedShortValue { return $this->attributeConsumingServiceIndex; } @@ -209,9 +206,9 @@ public function getAttributeConsumingServiceIndex(): ?int /** * Retrieve the value of the AssertionConsumerServiceIndex attribute. * - * @return int|null The AssertionConsumerServiceIndex attribute. + * @return \SimpleSAML\XMLSchema\Type\UnsignedShortValue|null The AssertionConsumerServiceIndex attribute. */ - public function getAssertionConsumerServiceIndex(): ?int + public function getAssertionConsumerServiceIndex(): ?UnsignedShortValue { return $this->assertionConsumerServiceIndex; } @@ -234,11 +231,11 @@ public function getRequestedAuthnContext(): ?RequestedAuthnContext * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes - * @throws \SimpleSAML\XML\Exception\TooManyElementsException + * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException * if too many child-elements of a type are specified */ public static function fromXML(DOMElement $xml): static @@ -246,30 +243,9 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'AuthnRequest', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, AuthnRequest::NS, InvalidDOMElementException::class); - $version = self::getAttribute($xml, 'Version'); - Assert::true(version_compare('2.0', $version, '<='), RequestVersionTooLowException::class); - Assert::true(version_compare('2.0', $version, '>='), RequestVersionTooHighException::class); - - $id = self::getAttribute($xml, 'ID'); - Assert::validNCName($id); // Covers the empty string - - $issueInstant = self::getAttribute($xml, 'IssueInstant'); - // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications - $issueInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $issueInstant, 1); - - Assert::validDateTime($issueInstant, ProtocolViolationException::class); - $issueInstant = new DateTimeImmutable($issueInstant); - - $attributeConsumingServiceIndex = self::getOptionalIntegerAttribute( - $xml, - 'AttributeConsumingServiceIndex', - null, - ); - $assertionConsumerServiceIndex = self::getOptionalIntegerAttribute( - $xml, - 'AssertionConsumerServiceIndex', - null, - ); + $version = self::getAttribute($xml, 'Version', SAMLStringValue::class); + Assert::true(version_compare('2.0', strval($version), '<='), RequestVersionTooLowException::class); + Assert::true(version_compare('2.0', strval($version), '>='), RequestVersionTooHighException::class); $conditions = Conditions::getChildrenOfClass($xml); Assert::maxCount( @@ -321,23 +297,22 @@ public static function fromXML(DOMElement $xml): static Assert::maxCount($scoping, 1, 'Only one element is allowed.', TooManyElementsException::class); $request = new static( - $issueInstant, + self::getAttribute($xml, 'ID', IDValue::class), + self::getAttribute($xml, 'IssueInstant', SAMLDateTimeValue::class), array_pop($requestedAuthnContext), array_pop($subject), array_pop($nameIdPolicy), array_pop($conditions), - self::getOptionalBooleanAttribute($xml, 'ForceAuthn', null), - self::getOptionalBooleanAttribute($xml, 'IsPassive', null), - self::getOptionalAttribute($xml, 'AssertionConsumerServiceURL', null), - $assertionConsumerServiceIndex, - self::getOptionalAttribute($xml, 'ProtocolBinding', null), - $attributeConsumingServiceIndex, - self::getOptionalAttribute($xml, 'ProviderName', null), + self::getOptionalAttribute($xml, 'ForceAuthn', BooleanValue::class, null), + self::getOptionalAttribute($xml, 'IsPassive', BooleanValue::class, null), + self::getOptionalAttribute($xml, 'AssertionConsumerServiceURL', SAMLAnyURIValue::class, null), + self::getOptionalAttribute($xml, 'AssertionConsumerServiceIndex', UnsignedShortValue::class, null), + self::getOptionalAttribute($xml, 'ProtocolBinding', SAMLAnyURIValue::class, null), + self::getOptionalAttribute($xml, 'AttributeConsumingServiceIndex', UnsignedShortValue::class, null), + self::getOptionalAttribute($xml, 'ProviderName', SAMLStringValue::class, null), array_pop($issuer), - $id, - $version, - self::getOptionalAttribute($xml, 'Destination', null), - self::getOptionalAttribute($xml, 'Consent', null), + self::getOptionalAttribute($xml, 'Destination', SAMLAnyURIValue::class, null), + self::getOptionalAttribute($xml, 'Consent', SAMLAnyURIValue::class, null), array_pop($extensions), array_pop($scoping), ); @@ -363,25 +338,25 @@ protected function toUnsignedXML(?DOMElement $parent = null): DOMElement $e = parent::toUnsignedXML($parent); if ($this->getForceAuthn() === true) { - $e->setAttribute('ForceAuthn', 'true'); + $e->setAttribute('ForceAuthn', strval($this->getForceAuthn())); } if ($this->getProviderName() !== null) { - $e->setAttribute('ProviderName', $this->getProviderName()); + $e->setAttribute('ProviderName', strval($this->getProviderName())); } if ($this->getIsPassive() === true) { - $e->setAttribute('IsPassive', 'true'); + $e->setAttribute('IsPassive', strval($this->getIsPassive())); } if ($this->getAssertionConsumerServiceIndex() !== null) { $e->setAttribute('AssertionConsumerServiceIndex', strval($this->getAssertionConsumerServiceIndex())); } else { if ($this->getAssertionConsumerServiceURL() !== null) { - $e->setAttribute('AssertionConsumerServiceURL', $this->getAssertionConsumerServiceURL()); + $e->setAttribute('AssertionConsumerServiceURL', strval($this->getAssertionConsumerServiceURL())); } if ($this->getProtocolBinding() !== null) { - $e->setAttribute('ProtocolBinding', $this->getProtocolBinding()); + $e->setAttribute('ProtocolBinding', strval($this->getProtocolBinding())); } } diff --git a/src/XML/samlp/AuthzDecisionQuery.php b/src/XML/samlp/AuthzDecisionQuery.php index c76e2bb7d..b4e3da51c 100644 --- a/src/XML/samlp/AuthzDecisionQuery.php +++ b/src/XML/samlp/AuthzDecisionQuery.php @@ -4,23 +4,25 @@ namespace SimpleSAML\SAML2\XML\samlp; -use DateTimeImmutable; use DOMElement; use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooHighException; use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\Action; use SimpleSAML\SAML2\XML\saml\Evidence; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\saml\Subject; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingElementException; -use SimpleSAML\XML\Exception\SchemaViolationException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Exception\SchemaViolationException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function version_compare; @@ -38,45 +40,42 @@ final class AuthzDecisionQuery extends AbstractSubjectQuery implements SchemaVal /** * Constructor for SAML 2 AuthzDecisionQuery. * + * @param \SimpleSAML\XMLSchema\Type\IDValue $id * @param \SimpleSAML\SAML2\XML\saml\Subject $subject - * @param string $resource + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $resource * @param \SimpleSAML\SAML2\XML\saml\Action[] $action * @param \SimpleSAML\SAML2\XML\saml\Evidence $evidence * @param \SimpleSAML\SAML2\XML\saml\Issuer $issuer - * @param string|null $id - * @param string $version - * @param \DateTimeImmutable $issueInstant - * @param string|null $destination - * @param string|null $consent + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue $issueInstant + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $destination + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $consent * @param \SimpleSAML\SAML2\XML\samlp\Extensions $extensions */ public function __construct( + IDVaLue $id, Subject $subject, - DateTimeImmutable $issueInstant, - protected string $resource, + SAMLDateTimeValue $issueInstant, + protected SAMLAnyURIValue $resource, protected array $action, protected ?Evidence $evidence = null, ?Issuer $issuer = null, - ?string $id = null, - string $version = '2.0', - ?string $destination = null, - ?string $consent = null, + ?SAMLAnyURIValue $destination = null, + ?SAMLAnyURIValue $consent = null, ?Extensions $extensions = null, ) { - Assert::validURI($resource); Assert::maxCount($action, C::UNBOUNDED_LIMIT); Assert::allIsInstanceOf($action, Action::class, SchemaViolationException::class); - parent::__construct($subject, $issuer, $id, $version, $issueInstant, $destination, $consent, $extensions); + parent::__construct($id, $subject, $issuer, $issueInstant, $destination, $consent, $extensions); } /** * Collect the value of the resource-property * - * @return string + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue */ - public function getResource(): string + public function getResource(): SAMLAnyURIValue { return $this->resource; } @@ -110,9 +109,9 @@ public function getEvidence(): ?Evidence * @param \DOMElement $xml The XML element we should load * * @return static - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingElementException + * @throws \SimpleSAML\XMLSchema\Exception\MissingElementException * if one of the mandatory child-elements is missing * @throws \Exception if the authentication instant is not a valid timestamp. */ @@ -121,22 +120,9 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'AuthzDecisionQuery', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, AuthzDecisionQuery::NS, InvalidDOMElementException::class); - $version = self::getAttribute($xml, 'Version'); - Assert::true(version_compare('2.0', $version, '<='), RequestVersionTooLowException::class); - Assert::true(version_compare('2.0', $version, '>='), RequestVersionTooHighException::class); - - $id = self::getAttribute($xml, 'ID'); - Assert::validNCName($id); // Covers the empty string - - $destination = self::getOptionalAttribute($xml, 'Destination', null); - $consent = self::getOptionalAttribute($xml, 'Consent', null); - - $issueInstant = self::getAttribute($xml, 'IssueInstant'); - // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications - $issueInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $issueInstant, 1); - - Assert::validDateTime($issueInstant, ProtocolViolationException::class); - $issueInstant = new DateTimeImmutable($issueInstant); + $version = self::getAttribute($xml, 'Version', SAMLStringValue::class); + Assert::true(version_compare('2.0', $version->getValue(), '<='), RequestVersionTooLowException::class); + Assert::true(version_compare('2.0', $version->getValue(), '>='), RequestVersionTooHighException::class); $issuer = Issuer::getChildrenOfClass($xml); Assert::countBetween($issuer, 0, 1); @@ -178,16 +164,15 @@ public static function fromXML(DOMElement $xml): static Assert::maxCount($signature, 1, 'Only one ds:Signature element is allowed.', TooManyElementsException::class); $request = new static( + self::getAttribute($xml, 'ID', IDValue::class), array_pop($subject), - $issueInstant, - self::getAttribute($xml, 'Resource'), + self::getAttribute($xml, 'IssueInstant', SAMLDateTimeValue::class), + self::getAttribute($xml, 'Resource', SAMLAnyURIValue::class), $action, array_pop($evidence), array_pop($issuer), - $id, - $version, - $destination, - $consent, + self::getOptionalAttribute($xml, 'Destination', SAMLAnyURIValue::class, null), + self::getOptionalAttribute($xml, 'Consent', SAMLAnyURIValue::class, null), array_pop($extensions), ); @@ -209,7 +194,7 @@ public static function fromXML(DOMElement $xml): static protected function toUnsignedXML(?DOMElement $parent = null): DOMElement { $e = parent::toUnsignedXML($parent); - $e->setAttribute('Resource', $this->getResource()); + $e->setAttribute('Resource', $this->getResource()->getValue()); foreach ($this->getAction() as $action) { $action->toXML($e); diff --git a/src/XML/samlp/Extensions.php b/src/XML/samlp/Extensions.php index 5808ab4aa..69692479e 100644 --- a/src/XML/samlp/Extensions.php +++ b/src/XML/samlp/Extensions.php @@ -5,13 +5,13 @@ namespace SimpleSAML\SAML2\XML\samlp; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\ExtensionsTrait; use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; /** * Class for handling SAML2 extensions. @@ -33,7 +33,7 @@ final class Extensions extends AbstractSamlpElement implements SchemaValidatable * @param \DOMElement $xml * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static diff --git a/src/XML/samlp/GetComplete.php b/src/XML/samlp/GetComplete.php index 4e7ea7514..ba9946c85 100644 --- a/src/XML/samlp/GetComplete.php +++ b/src/XML/samlp/GetComplete.php @@ -4,13 +4,15 @@ namespace SimpleSAML\SAML2\XML\samlp; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ArrayValidationException; -use SimpleSAML\SAML2\XML\URIElementTrait; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; use function array_key_first; +use function strval; /** * Class representing a samlp:GetComplete element. @@ -20,16 +22,11 @@ final class GetComplete extends AbstractSamlpElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use URIElementTrait; + use TypedTextContentTrait; - /** - * @param string $content - */ - public function __construct(string $content) - { - $this->setContent($content); - } + /** @var string */ + public const TEXTCONTENT_TYPE = SAMLAnyURIValue::class; /** @@ -43,7 +40,9 @@ public static function fromArray(array $data): static Assert::allString($data, ArrayValidationException::class); $index = array_key_first($data); - return new static($data[$index]); + return new static( + SAMLAnyURIValue::fromString($data[$index]), + ); } @@ -54,6 +53,6 @@ public static function fromArray(array $data): static */ public function toArray(): array { - return [$this->getContent()]; + return [strval($this->getContent())]; } } diff --git a/src/XML/samlp/IDPEntry.php b/src/XML/samlp/IDPEntry.php index d835de03c..5a3ea9cec 100644 --- a/src/XML/samlp/IDPEntry.php +++ b/src/XML/samlp/IDPEntry.php @@ -5,12 +5,14 @@ namespace SimpleSAML\SAML2\XML\samlp; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ArrayValidationException; -use SimpleSAML\XML\Exception\InvalidDOMElementException; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; use function array_change_key_case; use function array_filter; @@ -30,43 +32,40 @@ final class IDPEntry extends AbstractSamlpElement implements SchemaValidatableEl /** * Initialize an IDPEntry element. * - * @param string $providerId - * @param string|null $name - * @param string|null $loc + * @param \SimpleSAML\SAML2\Type\EntityIDValue $providerId + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $name + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $loc */ public function __construct( - protected string $providerId, - protected ?string $name = null, - protected ?string $loc = null, + protected EntityIDValue $providerId, + protected ?SAMLStringValue $name = null, + protected ?SAMLAnyURIValue $loc = null, ) { - SAMLAssert::validEntityID($providerId); - Assert::nullOrNotWhitespaceOnly($name); - SAMLAssert::nullOrValidURI($loc); } /** - * @return string + * @return \SimpleSAML\SAML2\Type\EntityIDValue */ - public function getProviderId(): string + public function getProviderId(): EntityIDValue { return $this->providerId; } /** - * @return string|null + * @return \SimpleSAML\SAML2\Type\SAMLStringValue|null */ - public function getName(): ?string + public function getName(): ?SAMLStringValue { return $this->name; } /** - * @return string|null + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null */ - public function getLoc(): ?string + public function getLoc(): ?SAMLAnyURIValue { return $this->loc; } @@ -78,9 +77,9 @@ public function getLoc(): ?string * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes */ public static function fromXML(DOMElement $xml): static @@ -88,11 +87,11 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'IDPEntry', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, IDPEntry::NS, InvalidDOMElementException::class); - $providerId = self::getAttribute($xml, 'ProviderID'); - $name = self::getOptionalAttribute($xml, 'Name', null); - $loc = self::getOptionalAttribute($xml, 'Loc', null); - - return new static($providerId, $name, $loc); + return new static( + self::getAttribute($xml, 'ProviderID', EntityIDValue::class), + self::getOptionalAttribute($xml, 'Name', SAMLStringValue::class, null), + self::getOptionalAttribute($xml, 'Loc', SAMLAnyURIValue::class, null), + ); } @@ -105,14 +104,14 @@ public static function fromXML(DOMElement $xml): static public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - $e->setAttribute('ProviderID', $this->getProviderId()); + $e->setAttribute('ProviderID', $this->getProviderId()->getValue()); if ($this->getName() !== null) { - $e->setAttribute('Name', $this->getName()); + $e->setAttribute('Name', $this->getName()->getValue()); } if ($this->getLoc() !== null) { - $e->setAttribute('Loc', $this->getLoc()); + $e->setAttribute('Loc', $this->getLoc()->getValue()); } return $e; @@ -130,9 +129,9 @@ public static function fromArray(array $data): static $data = self::processArrayContents($data); return new static( - $data['ProviderID'], - $data['Name'] ?? null, - $data['Loc'] ?? null, + EntityIDValue::fromString($data['ProviderID']), + $data['Name'] !== null ? SAMLStringValue::fromString($data['Name']) : null, + $data['Loc'] !== null ? SAMLAnyURIValue::fromString($data['Loc']) : null, ); } @@ -186,9 +185,9 @@ private static function processArrayContents(array $data): array public function toArray(): array { $data = [ - 'ProviderID' => $this->getProviderID(), - 'Name' => $this->getName(), - 'Loc' => $this->getLoc(), + 'ProviderID' => $this->getProviderID()->getValue(), + 'Name' => $this->getName()?->getValue(), + 'Loc' => $this->getLoc()?->getValue(), ]; return array_filter($data); diff --git a/src/XML/samlp/IDPList.php b/src/XML/samlp/IDPList.php index 2da7c2a4a..572959332 100644 --- a/src/XML/samlp/IDPList.php +++ b/src/XML/samlp/IDPList.php @@ -5,14 +5,14 @@ namespace SimpleSAML\SAML2\XML\samlp; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ArrayValidationException; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; use function array_change_key_case; use function array_filter; @@ -70,11 +70,11 @@ public function getGetComplete(): ?GetComplete * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingElementException + * @throws \SimpleSAML\XMLSchema\Exception\MissingElementException * if one of the mandatory child-elements is missing - * @throws \SimpleSAML\XML\Exception\TooManyElementsException + * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException * if too many child-elements of a type are specified */ public static function fromXML(DOMElement $xml): static diff --git a/src/XML/samlp/LogoutRequest.php b/src/XML/samlp/LogoutRequest.php index d626e0829..196b11d1e 100644 --- a/src/XML/samlp/LogoutRequest.php +++ b/src/XML/samlp/LogoutRequest.php @@ -4,24 +4,26 @@ namespace SimpleSAML\SAML2\XML\samlp; -use DateTimeImmutable; use DOMElement; use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooHighException; use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\IdentifierTrait; use SimpleSAML\SAML2\XML\saml\AbstractBaseID; use SimpleSAML\SAML2\XML\saml\EncryptedID; use SimpleSAML\SAML2\XML\saml\IdentifierInterface; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\saml\NameID; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function array_pop; @@ -40,36 +42,34 @@ final class LogoutRequest extends AbstractRequest implements SchemaValidatableEl /** * Constructor for SAML 2 AttributeQuery. * + * @param \SimpleSAML\XMLSchema\Type\IDValue $id * @param \SimpleSAML\SAML2\XML\saml\IdentifierInterface $identifier - * @param \DateTimeImmutable $issueInstant - * @param \DateTimeImmutable|null $notOnOrAfter - * @param string|null $reason + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue $issueInstant + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $notOnOrAfter + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $reason * @param \SimpleSAML\SAML2\XML\samlp\SessionIndex[] $sessionIndexes * @param \SimpleSAML\SAML2\XML\saml\Issuer|null $issuer - * @param string|null $id - * @param string $version - * @param string|null $destination - * @param string|null $consent + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $destination + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $consent * @param \SimpleSAML\SAML2\XML\samlp\Extensions $extensions * @throws \Exception */ public function __construct( + IDValue $id, IdentifierInterface $identifier, - DateTimeImmutable $issueInstant, - protected ?DateTimeImmutable $notOnOrAfter = null, - protected ?string $reason = null, + SAMLDateTimeValue $issueInstant, + protected ?SAMLDateTimeValue $notOnOrAfter = null, + protected ?SAMLStringValue $reason = null, protected array $sessionIndexes = [], ?Issuer $issuer = null, - ?string $id = null, - string $version = '2.0', - ?string $destination = null, - ?string $consent = null, + ?SAMLAnyURIValue $destination = null, + ?SAMLAnyURIValue $consent = null, ?Extensions $extensions = null, ) { Assert::maxCount($sessionIndexes, C::UNBOUNDED_LIMIT); Assert::allIsInstanceOf($sessionIndexes, SessionIndex::class); - parent::__construct($issuer, $id, $version, $issueInstant, $destination, $consent, $extensions); + parent::__construct($id, $issuer, $issueInstant, $destination, $consent, $extensions); $this->setIdentifier($identifier); } @@ -78,9 +78,9 @@ public function __construct( /** * Retrieve the expiration time of this request. * - * @return \DateTimeImmutable|null The expiration time of this request. + * @return \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null The expiration time of this request. */ - public function getNotOnOrAfter(): ?DateTimeImmutable + public function getNotOnOrAfter(): ?SAMLDateTimeValue { return $this->notOnOrAfter; } @@ -89,9 +89,9 @@ public function getNotOnOrAfter(): ?DateTimeImmutable /** * Retrieve the reason for this request. * - * @return string|null The reason for this request. + * @return \SimpleSAML\SAML2\Type\SAMLStringValue|null The reason for this request. */ - public function getReason(): ?string + public function getReason(): ?SAMLStringValue { return $this->reason; } @@ -115,13 +115,13 @@ public function getSessionIndexes(): array * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes - * @throws \SimpleSAML\XML\Exception\MissingElementException + * @throws \SimpleSAML\XMLSchema\Exception\MissingElementException * if one of the mandatory child-elements is missing - * @throws \SimpleSAML\XML\Exception\TooManyElementsException + * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException * if too many child-elements of a type are specified */ public static function fromXML(DOMElement $xml): static @@ -129,28 +129,14 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'LogoutRequest', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, LogoutRequest::NS, InvalidDOMElementException::class); - $version = self::getAttribute($xml, 'Version'); - Assert::true(version_compare('2.0', $version, '<='), RequestVersionTooLowException::class); - Assert::true(version_compare('2.0', $version, '>='), RequestVersionTooHighException::class); + $version = self::getAttribute($xml, 'Version', SAMLStringValue::class); + Assert::true(version_compare('2.0', strval($version), '<='), RequestVersionTooLowException::class); + Assert::true(version_compare('2.0', strval($version), '>='), RequestVersionTooHighException::class); - $id = self::getAttribute($xml, 'ID'); - Assert::validNCName($id); // Covers the empty string + $id = self::getAttribute($xml, 'ID', IDValue::Class); + $issueInstant = self::getAttribute($xml, 'IssueInstant', SAMLDateTimeValue::class); - $issueInstant = self::getAttribute($xml, 'IssueInstant'); - // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications - $issueInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $issueInstant, 1); - - Assert::validDateTime($issueInstant, ProtocolViolationException::class); - $issueInstant = new DateTimeImmutable($issueInstant); - - $notOnOrAfter = self::getOptionalAttribute($xml, 'NotOnOrAfter', null); - if ($notOnOrAfter !== null) { - // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications - $notOnOrAfter = preg_replace('/([.][0-9]+Z)$/', 'Z', $notOnOrAfter, 1); - - Assert::validDateTime($notOnOrAfter, ProtocolViolationException::class); - $notOnOrAfter = new DateTimeImmutable($notOnOrAfter); - } + $notOnOrAfter = self::getOptionalAttribute($xml, 'NotOnOrAfter', SAMLDateTimeValue::class, null); $issuer = Issuer::getChildrenOfClass($xml); Assert::countBetween($issuer, 0, 1); @@ -177,16 +163,15 @@ public static function fromXML(DOMElement $xml): static $sessionIndex = SessionIndex::getChildrenOfClass($xml); $request = new static( + $id, $identifier, $issueInstant, $notOnOrAfter, - self::getOptionalAttribute($xml, 'Reason', null), + self::getOptionalAttribute($xml, 'Reason', SAMLStringValue::class, null), $sessionIndex, array_pop($issuer), - $id, - $version, - self::getOptionalAttribute($xml, 'Destination', null), - self::getOptionalAttribute($xml, 'Consent', null), + self::getOptionalAttribute($xml, 'Destination', SAMLAnyURIValue::class, null), + self::getOptionalAttribute($xml, 'Consent', SAMLAnyURIValue::class, null), array_pop($extensions), ); @@ -211,14 +196,14 @@ protected function toUnsignedXML(?DOMElement $parent = null): DOMElement $e = parent::toUnsignedXML($parent); if ($this->getNotOnOrAfter() !== null) { - $e->setAttribute('NotOnOrAfter', $this->getNotOnOrAfter()->format(C::DATETIME_FORMAT)); + $e->setAttribute('NotOnOrAfter', $this->getNotOnOrAfter()->getValue()); } if ($this->getReason() !== null) { - $e->setAttribute('Reason', $this->getReason()); + $e->setAttribute('Reason', $this->getReason()->getValue()); } - /** @var \SimpleSAML\XML\SerializableElementInterface $identifier */ + /** @var \SimpleSAML\XML\SerializableElementInterface&\SimpleSAML\SAML2\XML\saml\IdentifierInterface $identifier */ $identifier = $this->getIdentifier(); $identifier->toXML($e); diff --git a/src/XML/samlp/LogoutResponse.php b/src/XML/samlp/LogoutResponse.php index 54e76df38..52bf38ac9 100644 --- a/src/XML/samlp/LogoutResponse.php +++ b/src/XML/samlp/LogoutResponse.php @@ -4,20 +4,23 @@ namespace SimpleSAML\SAML2\XML\samlp; -use DateTimeImmutable; use DOMElement; use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooHighException; use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\Issuer; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\NCNameValue; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function array_pop; -use function preg_replace; +use function strval; /** * Class for SAML 2 LogoutResponse messages. @@ -32,35 +35,32 @@ final class LogoutResponse extends AbstractStatusResponse implements SchemaValid /** * Constructor for SAML 2 LogoutResponse. * + * @param \SimpleSAML\XMLSchema\Type\IDValue $id * @param \SimpleSAML\SAML2\XML\samlp\Status $status - * @param \DateTimeImmutable $issueInstant + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue $issueInstant * @param \SimpleSAML\SAML2\XML\saml\Issuer|null $issuer - * @param string|null $id - * @param string $version - * @param string|null $inResponseTo - * @param string|null $destination - * @param string|null $consent + * @param \SimpleSAML\XMLSchema\Type\NCNameValue|null $inResponseTo + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $destination + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $consent * @param \SimpleSAML\SAML2\XML\samlp\Extensions|null $extensions * * @throws \Exception */ public function __construct( + IDValue $id, Status $status, - DateTimeImmutable $issueInstant, + SAMLDateTimeValue $issueInstant, ?Issuer $issuer = null, - ?string $id = null, - string $version = '2.0', - ?string $inResponseTo = null, - ?string $destination = null, - ?string $consent = null, + ?NCNameValue $inResponseTo = null, + ?SAMLAnyURIValue $destination = null, + ?SAMLAnyURIValue $consent = null, ?Extensions $extensions = null, ) { parent::__construct( + $id, $status, $issueInstant, $issuer, - $id, - $version, $inResponseTo, $destination, $consent, @@ -75,9 +75,9 @@ public function __construct( * @param \DOMElement $xml * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes */ public static function fromXML(DOMElement $xml): static @@ -85,19 +85,9 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'LogoutResponse', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, LogoutResponse::NS, InvalidDOMElementException::class); - $version = self::getAttribute($xml, 'Version'); - Assert::true(version_compare('2.0', $version, '<='), RequestVersionTooLowException::class); - Assert::true(version_compare('2.0', $version, '>='), RequestVersionTooHighException::class); - - $id = self::getAttribute($xml, 'ID'); - Assert::validNCName($id); // Covers the empty string - - $issueInstant = self::getAttribute($xml, 'IssueInstant'); - // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications - $issueInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $issueInstant, 1); - - Assert::validDateTime($issueInstant, ProtocolViolationException::class); - $issueInstant = new DateTimeImmutable($issueInstant); + $version = self::getAttribute($xml, 'Version', SAMLStringValue::class); + Assert::true(version_compare('2.0', strval($version), '<='), RequestVersionTooLowException::class); + Assert::true(version_compare('2.0', strval($version), '>='), RequestVersionTooHighException::class); $issuer = Issuer::getChildrenOfClass($xml); Assert::countBetween($issuer, 0, 1); @@ -112,14 +102,13 @@ public static function fromXML(DOMElement $xml): static Assert::maxCount($signature, 1, 'Only one ds:Signature element is allowed.'); $response = new static( + self::getAttribute($xml, 'ID', IDValue::class), array_pop($status), - $issueInstant, + self::getAttribute($xml, 'IssueInstant', SAMLDateTimeValue::class), array_pop($issuer), - $id, - $version, - self::getOptionalAttribute($xml, 'InResponseTo', null), - self::getOptionalAttribute($xml, 'Destination', null), - self::getOptionalAttribute($xml, 'Consent', null), + self::getOptionalAttribute($xml, 'InResponseTo', NCNameValue::class, null), + self::getOptionalAttribute($xml, 'Destination', SAMLAnyURIValue::class, null), + self::getOptionalAttribute($xml, 'Consent', SAMLAnyURIValue::class, null), empty($extensions) ? null : array_pop($extensions), ); diff --git a/src/XML/samlp/MessageFactory.php b/src/XML/samlp/MessageFactory.php index c1b863bfa..01f0586b4 100644 --- a/src/XML/samlp/MessageFactory.php +++ b/src/XML/samlp/MessageFactory.php @@ -5,9 +5,9 @@ namespace SimpleSAML\SAML2\XML\samlp; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; use function var_export; @@ -24,7 +24,7 @@ abstract class MessageFactory * @param \DOMElement $xml The root XML element * @return \SimpleSAML\SAML2\XML\samlp\AbstractMessage The message * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): AbstractMessage diff --git a/src/XML/samlp/NameIDPolicy.php b/src/XML/samlp/NameIDPolicy.php index 1e2f6ae84..e386ccc35 100644 --- a/src/XML/samlp/NameIDPolicy.php +++ b/src/XML/samlp/NameIDPolicy.php @@ -5,13 +5,15 @@ namespace SimpleSAML\SAML2\XML\samlp; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ArrayValidationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\XML\ArrayizableElementInterface; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Type\BooleanValue; use function array_change_key_case; use function array_filter; @@ -34,42 +36,40 @@ final class NameIDPolicy extends AbstractSamlpElement implements /** * Initialize a NameIDPolicy. * - * @param string|null $Format - * @param string|null $SPNameQualifier - * @param bool|null $AllowCreate + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $Format + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $SPNameQualifier + * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $AllowCreate */ public function __construct( - protected ?string $Format = null, - protected ?string $SPNameQualifier = null, - protected ?bool $AllowCreate = null, + protected ?SAMLAnyURIValue $Format = null, + protected ?SAMLStringValue $SPNameQualifier = null, + protected ?BooleanValue $AllowCreate = null, ) { - SAMLAssert::nullOrValidURI($Format); - Assert::nullOrNotWhitespaceOnly($SPNameQualifier); } /** - * @return string|null + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null */ - public function getFormat(): ?string + public function getFormat(): ?SAMLAnyURIValue { return $this->Format; } /** - * @return string|null + * @return \SimpleSAML\SAML2\Type\SAMLStringValue|null */ - public function getSPNameQualifier(): ?string + public function getSPNameQualifier(): ?SAMLStringValue { return $this->SPNameQualifier; } /** - * @return bool|null + * @return \SimpleSAML\XMLSchema\Type\BooleanValue|null */ - public function getAllowCreate(): ?bool + public function getAllowCreate(): ?BooleanValue { return $this->AllowCreate; } @@ -82,9 +82,9 @@ public function getAllowCreate(): ?bool */ public function isEmptyElement(): bool { - return empty($this->Format) - && empty($this->SPNameQualifier) - && empty($this->AllowCreate); + return empty($this->getFormat()) + && empty($this->getSPNameQualifier()) + && empty($this->getAllowCreate()); } @@ -94,7 +94,7 @@ public function isEmptyElement(): bool * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -102,9 +102,9 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'NameIDPolicy', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, NameIDPolicy::NS, InvalidDOMElementException::class); - $Format = self::getOptionalAttribute($xml, 'Format', null); - $SPNameQualifier = self::getOptionalAttribute($xml, 'SPNameQualifier', null); - $AllowCreate = self::getOptionalBooleanAttribute($xml, 'AllowCreate', null); + $Format = self::getOptionalAttribute($xml, 'Format', SAMLAnyURIValue::class, null); + $SPNameQualifier = self::getOptionalAttribute($xml, 'SPNameQualifier', SAMLStringValue::class, null); + $AllowCreate = self::getOptionalAttribute($xml, 'AllowCreate', BooleanValue::class, null); return new static( $Format, @@ -124,16 +124,16 @@ public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - if ($this->getFormat()) { - $e->setAttribute('Format', $this->getFormat()); + if ($this->getFormat() !== null) { + $e->setAttribute('Format', $this->getFormat()->getValue()); } - if ($this->getSPNameQualifier()) { - $e->setAttribute('SPNameQualifier', $this->getSPNameQualifier()); + if ($this->getSPNameQualifier() !== null) { + $e->setAttribute('SPNameQualifier', $this->getSPNameQualifier()->getValue()); } if ($this->getAllowCreate() !== null) { - $e->setAttribute('AllowCreate', var_export($this->getAllowCreate(), true)); + $e->setAttribute('AllowCreate', var_export($this->getAllowCreate()->toBoolean(), true)); } return $e; @@ -151,9 +151,9 @@ public static function fromArray(array $data): static $data = self::processArrayContents($data); return new static( - $data['Format'] ?? null, - $data['SPNameQualifier'] ?? null, - $data['AllowCreate'] ?? null, + $data['Format'] !== null ? SAMLAnyURIValue::fromString($data['Format']) : null, + $data['SPNameQualifier'] !== null ? SAMLStringValue::fromString($data['SPNameQualifier']) : null, + $data['AllowCreate'] !== null ? BooleanValue::fromBoolean($data['AllowCreate']) : null, ); } @@ -206,9 +206,9 @@ private static function processArrayContents(array $data): array public function toArray(): array { $data = [ - 'Format' => $this->getFormat(), - 'SPNameQualifier' => $this->getSPNameQualifier(), - 'AllowCreate' => $this->getAllowCreate(), + 'Format' => $this->getFormat()?->getValue(), + 'SPNameQualifier' => $this->getSPNameQualifier()?->getValue(), + 'AllowCreate' => $this->getAllowCreate()?->toBoolean(), ]; return array_filter($data); diff --git a/src/XML/samlp/RequestedAuthnContext.php b/src/XML/samlp/RequestedAuthnContext.php index b3c3d2914..504b09a99 100644 --- a/src/XML/samlp/RequestedAuthnContext.php +++ b/src/XML/samlp/RequestedAuthnContext.php @@ -5,17 +5,19 @@ namespace SimpleSAML\SAML2\XML\samlp; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\XML\Comparison; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\AuthnContextComparisonTypeValue; use SimpleSAML\SAML2\XML\saml\AuthnContextClassRef; use SimpleSAML\SAML2\XML\saml\AuthnContextDeclRef; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\SchemaViolationException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\SchemaViolationException; use function array_merge; +use function strval; /** * Class representing SAML2 RequestedAuthnContext @@ -34,11 +36,11 @@ final class RequestedAuthnContext extends AbstractSamlpElement implements Schema * \SimpleSAML\SAML2\XML\saml\AuthnContextClassRef| * \SimpleSAML\SAML2\XML\saml\AuthnContextDeclRef * )[] $requestedAuthnContexts - * @param \SimpleSAML\SAML2\XML\Comparison $Comparison + * @param \SimpleSAML\SAML2\Type\AuthnContextComparisonTypeValue $Comparison */ public function __construct( protected array $requestedAuthnContexts = [], - protected ?Comparison $Comparison = null, + protected ?AuthnContextComparisonTypeValue $Comparison = null, ) { Assert::maxCount($requestedAuthnContexts, C::UNBOUNDED_LIMIT); Assert::minCount($requestedAuthnContexts, 1, SchemaViolationException::class); @@ -53,12 +55,14 @@ public function __construct( $requestedAuthnContexts, AuthnContextClassRef::class, 'You need either AuthnContextClassRef or AuthnContextDeclRef, not both.', + ProtocolViolationException::class, ); } else { // Can only be AuthnContextDeclRef Assert::allIsInstanceOf( $requestedAuthnContexts, AuthnContextDeclRef::class, 'You need either AuthnContextClassRef or AuthnContextDeclRef, not both.', + ProtocolViolationException::class, ); } } @@ -78,9 +82,9 @@ public function getRequestedAuthnContexts(): array /** * Collect the value of the Comparison-property * - * @return \SimpleSAML\SAML2\XML\Comparison|null + * @return \SimpleSAML\SAML2\Type\AuthnContextComparisonTypeValue|null */ - public function getComparison(): ?Comparison + public function getComparison(): ?AuthnContextComparisonTypeValue { return $this->Comparison; } @@ -92,7 +96,7 @@ public function getComparison(): ?Comparison * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -100,13 +104,12 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'RequestedAuthnContext', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, RequestedAuthnContext::NS, InvalidDOMElementException::class); - $Comparison = self::getOptionalAttribute($xml, 'Comparison', 'unknown'); return new static( array_merge( AuthnContextClassRef::getChildrenOfClass($xml), AuthnContextDeclRef::getChildrenOfClass($xml), ), - Comparison::tryFrom($Comparison), + self::getOptionalAttribute($xml, 'Comparison', AuthnContextComparisonTypeValue::class, null), ); } @@ -126,7 +129,7 @@ public function toXML(?DOMElement $parent = null): DOMElement } if ($this->getComparison() !== null) { - $e->setAttribute('Comparison', $this->getComparison()->value); + $e->setAttribute('Comparison', strval($this->getComparison())); } return $e; diff --git a/src/XML/samlp/RequesterID.php b/src/XML/samlp/RequesterID.php index 741037d8e..a28b0cf9c 100644 --- a/src/XML/samlp/RequesterID.php +++ b/src/XML/samlp/RequesterID.php @@ -4,11 +4,12 @@ namespace SimpleSAML\SAML2\XML\samlp; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ArrayValidationException; -use SimpleSAML\SAML2\XML\URIElementTrait; +use SimpleSAML\SAML2\Type\EntityIDValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; use function array_key_first; @@ -20,16 +21,11 @@ final class RequesterID extends AbstractSamlpElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use URIElementTrait; + use TypedTextContentTrait; - /** - * @param string $content - */ - public function __construct(string $content) - { - $this->setContent($content); - } + /** @var string */ + public const TEXTCONTENT_TYPE = EntityIDValue::class; /** @@ -43,7 +39,9 @@ public static function fromArray(array $data): static Assert::allString($data, ArrayValidationException::class); $index = array_key_first($data); - return new static($data[$index]); + return new static( + EntityIDValue::fromString($data[$index]), + ); } @@ -54,6 +52,6 @@ public static function fromArray(array $data): static */ public function toArray(): array { - return [$this->getContent()]; + return [$this->getContent()->getValue()]; } } diff --git a/src/XML/samlp/Response.php b/src/XML/samlp/Response.php index 506617e0e..1f7afcc28 100644 --- a/src/XML/samlp/Response.php +++ b/src/XML/samlp/Response.php @@ -4,25 +4,29 @@ namespace SimpleSAML\SAML2\XML\samlp; -use DateTimeImmutable; use DOMElement; use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooHighException; use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\Assertion; use SimpleSAML\SAML2\XML\saml\EncryptedAssertion; use SimpleSAML\SAML2\XML\saml\Issuer; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\NCNameValue; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function array_merge; use function array_pop; +use function strval; /** * Class for SAML 2 Response messages. @@ -37,26 +41,24 @@ class Response extends AbstractStatusResponse implements SchemaValidatableElemen /** * Constructor for SAML 2 response messages. * + * @param \SimpleSAML\XMLSchema\Type\IDValue $id * @param \SimpleSAML\SAML2\XML\samlp\Status $status - * @param \DateTimeImmutable $issueInstant + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue $issueInstant * @param \SimpleSAML\SAML2\XML\saml\Issuer|null $issuer - * @param string|null $id - * @param string $version - * @param string $inResponseTo - * @param string|null $destination - * @param string|null $consent + * @param \SimpleSAML\XMLSchema\Type\NCNameValue|null $inResponseTo + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $destination + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $consent * @param \SimpleSAML\SAML2\XML\samlp\Extensions $extensions * @param (\SimpleSAML\SAML2\XML\saml\Assertion|\SimpleSAML\SAML2\XML\saml\EncryptedAssertion)[] $assertions */ final public function __construct( + IDValue $id, Status $status, - DateTimeImmutable $issueInstant, + SAMLDateTimeValue $issueInstant, ?Issuer $issuer = null, - ?string $id = null, - string $version = '2.0', - ?string $inResponseTo = null, - ?string $destination = null, - ?string $consent = null, + ?NCNameValue $inResponseTo = null, + ?SAMLAnyURIValue $destination = null, + ?SAMLAnyURIValue $consent = null, ?Extensions $extensions = null, protected array $assertions = [], ) { @@ -64,11 +66,10 @@ final public function __construct( Assert::allIsInstanceOfAny($assertions, [Assertion::class, EncryptedAssertion::class]); parent::__construct( + $id, $status, $issueInstant, $issuer, - $id, - $version, $inResponseTo, $destination, $consent, @@ -94,11 +95,11 @@ public function getAssertions(): array * @param \DOMElement $xml The input message. * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes - * @throws \SimpleSAML\XML\Exception\MissingElementException + * @throws \SimpleSAML\XMLSchema\Exception\MissingElementException * if one of the mandatory child-elements is missing */ public static function fromXML(DOMElement $xml): static @@ -106,27 +107,13 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'Response', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, Response::NS, InvalidDOMElementException::class); - $version = self::getAttribute($xml, 'Version'); - Assert::true(version_compare('2.0', $version, '<='), RequestVersionTooLowException::class); - Assert::true(version_compare('2.0', $version, '>='), RequestVersionTooHighException::class); + $version = self::getAttribute($xml, 'Version', SAMLStringValue::class); + Assert::true(version_compare('2.0', strval($version), '<='), RequestVersionTooLowException::class); + Assert::true(version_compare('2.0', strval($version), '>='), RequestVersionTooHighException::class); $signature = Signature::getChildrenOfClass($xml); Assert::maxCount($signature, 1, 'Only one ds:Signature element is allowed.', TooManyElementsException::class); - $id = self::getAttribute($xml, 'ID'); - Assert::validNCName($id); // Covers the empty string - - $inResponseTo = self::getOptionalAttribute($xml, 'InResponseTo', null); - $destination = self::getOptionalAttribute($xml, 'Destination', null); - $consent = self::getOptionalAttribute($xml, 'Consent', null); - - $issueInstant = self::getAttribute($xml, 'IssueInstant'); - // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications - $issueInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $issueInstant, 1); - - Assert::validDateTime($issueInstant, ProtocolViolationException::class); - $issueInstant = new DateTimeImmutable($issueInstant); - $issuer = Issuer::getChildrenOfClass($xml); Assert::countBetween($issuer, 0, 1); @@ -143,14 +130,13 @@ public static function fromXML(DOMElement $xml): static ); $response = new static( + self::getAttribute($xml, 'ID', IDValue::class), array_pop($status), - $issueInstant, + self::getAttribute($xml, 'IssueInstant', SAMLDateTimeValue::class), empty($issuer) ? null : array_pop($issuer), - $id, - $version, - $inResponseTo, - $destination, - $consent, + self::getOptionalAttribute($xml, 'InResponseTo', NCNameValue::class, null), + self::getOptionalAttribute($xml, 'Destination', SAMLAnyURIValue::class, null), + self::getOptionalAttribute($xml, 'Consent', SAMLAnyURIValue::class, null), empty($extensions) ? null : array_pop($extensions), array_merge(Assertion::getChildrenOfClass($xml), EncryptedAssertion::getChildrenOfClass($xml)), ); diff --git a/src/XML/samlp/Scoping.php b/src/XML/samlp/Scoping.php index 52e862169..3dfcd6d54 100644 --- a/src/XML/samlp/Scoping.php +++ b/src/XML/samlp/Scoping.php @@ -5,13 +5,15 @@ namespace SimpleSAML\SAML2\XML\samlp; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Type\NonNegativeIntegerValue; use function array_pop; +use function strval; /** * Class for handling SAML2 Scoping. @@ -26,18 +28,17 @@ final class Scoping extends AbstractSamlpElement implements SchemaValidatableEle /** * Initialize a Scoping element. * - * @param int|null $proxyCount + * @param \SimpleSAML\XMLSchema\Type\NonNegativeIntegerValue|null $proxyCount * @param \SimpleSAML\SAML2\XML\samlp\IDPList|null $IDPList * @param \SimpleSAML\SAML2\XML\samlp\RequesterID[] $requesterId */ public function __construct( - protected ?int $proxyCount = null, + protected ?NonNegativeIntegerValue $proxyCount = null, protected ?IDPList $IDPList = null, protected array $requesterId = [], ) { Assert::maxCount($requesterId, C::UNBOUNDED_LIMIT); Assert::allIsInstanceOf($requesterId, RequesterID::class); - Assert::nullOrNatural($proxyCount); } @@ -60,9 +61,9 @@ public function getRequesterId(): array /** - * @return int|null + * @return \SimpleSAML\XMLSchema\Type\NonNegativeIntegerValue|null */ - public function getProxyCount(): ?int + public function getProxyCount(): ?NonNegativeIntegerValue { return $this->proxyCount; } @@ -75,9 +76,9 @@ public function getProxyCount(): ?int */ public function isEmptyElement(): bool { - return empty($this->proxyCount) - && empty($this->IDPList) - && empty($this->requesterId); + return empty($this->getProxyCount()) + && empty($this->getIDPList()) + && empty($this->getRequesterId()); } @@ -87,7 +88,7 @@ public function isEmptyElement(): bool * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -95,12 +96,11 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'Scoping', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, Scoping::NS, InvalidDOMElementException::class); - $proxyCount = self::getOptionalIntegerAttribute($xml, 'ProxyCount', null); $idpList = IDPList::getChildrenOfClass($xml); $requesterId = RequesterID::getChildrenOfClass($xml); return new static( - $proxyCount, + self::getOptionalAttribute($xml, 'ProxyCount', NonNegativeIntegerValue::class, null), array_pop($idpList), $requesterId, ); diff --git a/src/XML/samlp/SessionIndex.php b/src/XML/samlp/SessionIndex.php index 6d7bee65b..747c254a1 100644 --- a/src/XML/samlp/SessionIndex.php +++ b/src/XML/samlp/SessionIndex.php @@ -4,9 +4,10 @@ namespace SimpleSAML\SAML2\XML\samlp; -use SimpleSAML\SAML2\XML\StringElementTrait; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class representing a samlp:SessionIndex element. @@ -16,14 +17,9 @@ final class SessionIndex extends AbstractSamlpElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use StringElementTrait; + use TypedTextContentTrait; - /** - * @param string $content - */ - public function __construct(string $content) - { - $this->setContent($content); - } + /** @var string */ + public const TEXTCONTENT_TYPE = SAMLStringValue::class; } diff --git a/src/XML/samlp/Status.php b/src/XML/samlp/Status.php index 877a8d1ee..92fd1cc5c 100644 --- a/src/XML/samlp/Status.php +++ b/src/XML/samlp/Status.php @@ -5,16 +5,17 @@ namespace SimpleSAML\SAML2\XML\samlp; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; use function array_pop; +use function strval; /** * SAML Status data type. @@ -39,7 +40,7 @@ public function __construct( protected array $statusDetails = [], ) { Assert::oneOf( - $statusCode->getValue(), + strval($statusCode->getValue()), [ C::STATUS_SUCCESS, C::STATUS_REQUESTER, @@ -93,11 +94,11 @@ public function getStatusDetails(): array * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\TooManyElementsException + * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException * if too many child-elements of a type are specified - * @throws \SimpleSAML\XML\Exception\MissingElementException + * @throws \SimpleSAML\XMLSchema\Exception\MissingElementException * if one of the mandatory child-elements is missing */ public static function fromXML(DOMElement $xml): static diff --git a/src/XML/samlp/StatusCode.php b/src/XML/samlp/StatusCode.php index 5f929ddbe..478df0255 100644 --- a/src/XML/samlp/StatusCode.php +++ b/src/XML/samlp/StatusCode.php @@ -5,12 +5,14 @@ namespace SimpleSAML\SAML2\XML\samlp; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; + +use function strval; /** * SAML StatusCode data type. @@ -25,14 +27,13 @@ final class StatusCode extends AbstractSamlpElement implements SchemaValidatable /** * Initialize a samlp:StatusCode * - * @param string $Value + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $Value * @param \SimpleSAML\SAML2\XML\samlp\StatusCode[] $subCodes */ public function __construct( - protected string $Value = C::STATUS_SUCCESS, + protected SAMLAnyURIValue $Value, protected array $subCodes = [], ) { - SAMLAssert::validURI($Value); Assert::maxCount($subCodes, C::UNBOUNDED_LIMIT); Assert::allIsInstanceOf($subCodes, StatusCode::class); } @@ -41,9 +42,9 @@ public function __construct( /** * Collect the Value * - * @return string + * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue */ - public function getValue(): string + public function getValue(): SAMLAnyURIValue { return $this->Value; } @@ -66,9 +67,9 @@ public function getSubCodes(): array * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong - * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException * if the supplied element is missing one of the mandatory attributes */ public static function fromXML(DOMElement $xml): static @@ -76,12 +77,9 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'StatusCode', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, StatusCode::NS, InvalidDOMElementException::class); - $Value = self::getAttribute($xml, 'Value'); - $subCodes = StatusCode::getChildrenOfClass($xml); - return new static( - $Value, - $subCodes, + self::getAttribute($xml, 'Value', SAMLAnyURIValue::class), + StatusCode::getChildrenOfClass($xml), ); } @@ -95,7 +93,7 @@ public static function fromXML(DOMElement $xml): static public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - $e->setAttribute('Value', $this->getValue()); + $e->setAttribute('Value', strval($this->getValue())); foreach ($this->getSubCodes() as $subCode) { $subCode->toXML($e); diff --git a/src/XML/samlp/StatusDetail.php b/src/XML/samlp/StatusDetail.php index fac25b122..fc88ac208 100644 --- a/src/XML/samlp/StatusDetail.php +++ b/src/XML/samlp/StatusDetail.php @@ -5,12 +5,12 @@ namespace SimpleSAML\SAML2\XML\samlp; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\XML\Exception\InvalidDOMElementException; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\XML\ExtendableElementTrait; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; -use SimpleSAML\XML\XsNamespace as NS; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\XML\Constants\NS; /** * SAML StatusDetail data type. @@ -55,7 +55,7 @@ public function isEmptyElement(): bool * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static diff --git a/src/XML/samlp/StatusMessage.php b/src/XML/samlp/StatusMessage.php index 00ee4b4f9..03c1e868e 100644 --- a/src/XML/samlp/StatusMessage.php +++ b/src/XML/samlp/StatusMessage.php @@ -4,9 +4,10 @@ namespace SimpleSAML\SAML2\XML\samlp; -use SimpleSAML\SAML2\XML\StringElementTrait; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class representing a samlp:StatusMessage element. @@ -16,14 +17,9 @@ final class StatusMessage extends AbstractSamlpElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use StringElementTrait; + use TypedTextContentTrait; - /** - * @param string $content - */ - public function __construct(string $content) - { - $this->setContent($content); - } + /** @var string */ + public const TEXTCONTENT_TYPE = SAMLStringValue::class; } diff --git a/src/XML/shibmd/KeyAuthority.php b/src/XML/shibmd/KeyAuthority.php index 75f1479c5..fd39bfb52 100644 --- a/src/XML/shibmd/KeyAuthority.php +++ b/src/XML/shibmd/KeyAuthority.php @@ -5,13 +5,14 @@ namespace SimpleSAML\SAML2\XML\shibmd; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\XML\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\ExtendableAttributesTrait; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; -use SimpleSAML\XML\XsNamespace as NS; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Type\UnsignedByteValue; +use SimpleSAML\XMLSchema\XML\Constants\NS; use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; use function strval; @@ -36,16 +37,15 @@ final class KeyAuthority extends AbstractShibmdElement implements SchemaValidata * Create a KeyAuthority. * * @param \SimpleSAML\XMLSecurity\XML\ds\KeyInfo[] $keys - * @param int|null $VerifyDepth + * @param \SimpleSAML\XMLSchema\Type\UnsignedByteValue|null $VerifyDepth * @param list<\SimpleSAML\XML\Attribute> $namespacedAttributes */ public function __construct( protected array $keys, - protected ?int $VerifyDepth = null, + protected ?UnsignedByteValue $VerifyDepth = null, array $namespacedAttributes = [], ) { Assert::maxCount($keys, C::UNBOUNDED_LIMIT); - Assert::nullOrRange($VerifyDepth, 0, 255); $this->setAttributesNS($namespacedAttributes); } @@ -54,9 +54,9 @@ public function __construct( /** * Collect the value of the VerifyDepth-property * - * @return int|null + * @return \SimpleSAML\XMLSchema\Type\UnsignedByteValue|null */ - public function getVerifyDepth(): ?int + public function getVerifyDepth(): UnsignedByteValue|null { return $this->VerifyDepth; } @@ -79,7 +79,7 @@ public function getKeys(): array * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -87,8 +87,7 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'KeyAuthority', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, KeyAuthority::NS, InvalidDOMElementException::class); - $verifyDepth = self::getOptionalIntegerAttribute($xml, 'VerifyDepth', 1); - Assert::natural($verifyDepth); + $verifyDepth = self::getOptionalAttribute($xml, 'VerifyDepth', UnsignedByteValue::class, null); $keys = KeyInfo::getChildrenOfClass($xml); Assert::minCount($keys, 1); @@ -98,9 +97,9 @@ public static function fromXML(DOMElement $xml): static /** - * Convert this Scope to XML. + * Convert this KeyAuthority to XML. * - * @param \DOMElement|null $parent The element we should append this Scope to. + * @param \DOMElement|null $parent The element we should append this KeyAuthority to. * @return \DOMElement */ public function toXML(?DOMElement $parent = null): DOMElement diff --git a/src/XML/shibmd/Scope.php b/src/XML/shibmd/Scope.php index 1635d22da..415170ec8 100644 --- a/src/XML/shibmd/Scope.php +++ b/src/XML/shibmd/Scope.php @@ -5,11 +5,13 @@ namespace SimpleSAML\SAML2\XML\shibmd; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\XML\StringElementTrait; -use SimpleSAML\XML\Exception\InvalidDOMElementException; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\XML\SchemaValidatableElementInterface; use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\TypedTextContentTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Type\BooleanValue; /** * Class which represents the Scope element found in Shibboleth metadata. @@ -20,18 +22,22 @@ final class Scope extends AbstractShibmdElement implements SchemaValidatableElementInterface { use SchemaValidatableElementTrait; - use StringElementTrait; + use TypedTextContentTrait; + + + /** @var string */ + public const TEXTCONTENT_TYPE = SAMLStringValue::class; /** * Create a Scope. * - * @param string $scope - * @param bool|null $regexp + * @param \SimpleSAML\SAML2\Type\SAMLStringValue $scope + * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $regexp */ public function __construct( - string $scope, - protected ?bool $regexp = false, + SAMLStringValue $scope, + protected ?BooleanValue $regexp = null, ) { $this->setContent($scope); } @@ -40,9 +46,9 @@ public function __construct( /** * Collect the value of the regexp-property * - * @return bool|null + * @return \SimpleSAML\XMLSchema\Type\BooleanValue|null */ - public function isRegexpScope(): ?bool + public function isRegexpScope(): ?BooleanValue { return $this->regexp; } @@ -54,7 +60,7 @@ public function isRegexpScope(): ?bool * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -62,10 +68,10 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->localName, 'Scope', InvalidDOMElementException::class); Assert::same($xml->namespaceURI, Scope::NS, InvalidDOMElementException::class); - $scope = $xml->textContent; - $regexp = self::getOptionalBooleanAttribute($xml, 'regexp', null); - - return new static($scope, $regexp); + return new static( + SAMLStringValue::fromString($xml->textContent), + self::getOptionalAttribute($xml, 'regexp', BooleanValue::class, null), + ); } @@ -78,10 +84,10 @@ public static function fromXML(DOMElement $xml): static public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - $e->textContent = $this->getContent(); + $e->textContent = strval($this->getContent()); if ($this->isRegexpScope() !== null) { - $e->setAttribute('regexp', $this->isRegexpScope() ? 'true' : 'false'); + $e->setAttribute('regexp', strval($this->isRegexpScope())); } return $e; diff --git a/tests/InterOperability/EntitiesDescriptorTest.php b/tests/InterOperability/EntitiesDescriptorTest.php index 4e971f518..1f3929b73 100644 --- a/tests/InterOperability/EntitiesDescriptorTest.php +++ b/tests/InterOperability/EntitiesDescriptorTest.php @@ -90,6 +90,9 @@ public static function provideMetadata(): array 'GRNET' => [ DOMDocumentFactory::fromFile('/tmp/metadata/grnet.xml')->documentElement, ], + 'EduID' => [ + DOMDocumentFactory::fromFile('/tmp/metadata/eduid.xml')->documentElement, + ], ]; } } diff --git a/tests/SAML2/Assert/CIDRTest.php b/tests/SAML2/Assert/CIDRTest.php new file mode 100644 index 000000000..d1e16fd69 --- /dev/null +++ b/tests/SAML2/Assert/CIDRTest.php @@ -0,0 +1,60 @@ +assertTrue($shouldPass); + } catch (ProtocolViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideCIDR(): array + { + return [ + 'ipv4' => [true, '192.168.0.1/32'], + 'ipv6' => [true, '2001:0000:130F:0000:0000:09C0:876A:130B/128'], + 'ipv4 too long' => [false, '192.168.0.1.5/32'], + 'ipv6 too long' => [false, '2001:0000:130F:0000:0000:09C0:876A:130B:130F:805B/128'], + 'ipv6 mixed notation' => [false, '805B:2D9D:DC28::FC57:212.200.31.255'], + 'ipv6 shortened notation' => [false, '::ffff:192.1.56.10/96'], + 'ipv6 compressed notation' => [false, '::212.200.31.255'], + 'ipv4 without length' => [false, '192.168.0.1'], + 'ipv6 wihtout length' => [false, '2001:0000:130F:0000:0000:09C0:876A:130B'], + 'ipv4 out of bounds length' => [false, '192.168.0.1/33'], + 'ipv6 out of bounds length' => [false, '2001:0000:130F:0000:0000:09C0:876A:130B/129'], + 'ipv4 out of bounds address' => [false, '256.168.0.1/32'], + 'ipv6 out of bounds address' => [false, '2001:0000:130G:0000:0000:09C0:876A:130B/128'], + ]; + } +} diff --git a/tests/SAML2/Assert/DomainTest.php b/tests/SAML2/Assert/DomainTest.php new file mode 100644 index 000000000..6b48f7a89 --- /dev/null +++ b/tests/SAML2/Assert/DomainTest.php @@ -0,0 +1,54 @@ +assertTrue($shouldPass); + } catch (ProtocolViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideDomain(): array + { + return [ + 'domain' => [true, 'simplesamlphp.org'], + 'subdomain' => [true, 'sub.simplesamlphp.org'], + 'ipv4' => [false, '192.168.0.1'], + 'ipv6' => [false, '2001:0000:130F:0000:0000:09C0:876A:130B'], + 'with scheme' => [false, 'https://simplesamlphp.org'], + 'start with dot' => [false, '.org'], + 'tld' => [true, 'nl'], + ]; + } +} diff --git a/tests/SAML2/Assert/EntityIDTest.php b/tests/SAML2/Assert/EntityIDTest.php index f1399f251..cbfc970f6 100644 --- a/tests/SAML2/Assert/EntityIDTest.php +++ b/tests/SAML2/Assert/EntityIDTest.php @@ -6,11 +6,12 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\Assert\Assert as SAML2Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\XML\Exception\SchemaViolationException; +use SimpleSAML\XMLSchema\Exception\SchemaViolationException; use function str_pad; @@ -19,7 +20,8 @@ * * @package simplesamlphp/saml2 */ -#[CoversClass(SAML2Assert::class)] +#[Group('assert')] +#[CoversClass(Assert::class)] final class EntityIDTest extends TestCase { /** @@ -30,7 +32,7 @@ final class EntityIDTest extends TestCase public function testValidEntityID(bool $shouldPass, string $entityID): void { try { - SAML2Assert::validEntityID($entityID); + Assert::validEntityID($entityID); $this->assertTrue($shouldPass); } catch (ProtocolViolationException | SchemaViolationException $e) { $this->assertFalse($shouldPass); diff --git a/tests/SAML2/Assert/URITest.php b/tests/SAML2/Assert/SAMLAnyURITest.php similarity index 77% rename from tests/SAML2/Assert/URITest.php rename to tests/SAML2/Assert/SAMLAnyURITest.php index a0be98a6a..520dbfc51 100644 --- a/tests/SAML2/Assert/URITest.php +++ b/tests/SAML2/Assert/SAMLAnyURITest.php @@ -6,28 +6,30 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\Assert\Assert as SAML2Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\XML\Exception\SchemaViolationException; +use SimpleSAML\XMLSchema\Exception\SchemaViolationException; /** - * Class \SimpleSAML\SAML2\Assert\URITest + * Class \SimpleSAML\SAML2\Assert\SAMLAnyURITest * * @package simplesamlphp/saml2 */ -#[CoversClass(SAML2Assert::class)] -final class URITest extends TestCase +#[Group('assert')] +#[CoversClass(Assert::class)] +final class SAMLAnyURITest extends TestCase { /** * @param boolean $shouldPass * @param string $uri */ #[DataProvider('provideURI')] - public function testValidURI(bool $shouldPass, string $uri): void + public function testValidSAMLAnyURI(bool $shouldPass, string $uri): void { try { - SAML2Assert::validURI($uri); + Assert::validSAMLAnyURI($uri); $this->assertTrue($shouldPass); } catch (ProtocolViolationException | SchemaViolationException $e) { $this->assertFalse($shouldPass); diff --git a/tests/SAML2/Assert/DateTimeTest.php b/tests/SAML2/Assert/SAMLDateTimeTest.php similarity index 74% rename from tests/SAML2/Assert/DateTimeTest.php rename to tests/SAML2/Assert/SAMLDateTimeTest.php index d7392a468..8b5c01cf4 100644 --- a/tests/SAML2/Assert/DateTimeTest.php +++ b/tests/SAML2/Assert/SAMLDateTimeTest.php @@ -6,29 +6,31 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; -use SimpleSAML\SAML2\Assert\Assert as SAML2Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\XML\Exception\SchemaViolationException; +use SimpleSAML\XMLSchema\Exception\SchemaViolationException; /** - * Class \SimpleSAML\SAML2\Assert\DateTimeTest + * Class \SimpleSAML\SAML2\Assert\SAMLDateTimeTest * * @package simplesamlphp/saml2 */ -#[CoversClass(SAML2Assert::class)] -final class DateTimeTest extends TestCase +#[Group('assert')] +#[CoversClass(Assert::class)] +final class SAMLDateTimeTest extends TestCase { /** * @param boolean $shouldPass * @param string $timestamp */ #[DataProvider('provideDateTime')] - public function testValidDateTime(bool $shouldPass, string $timestamp): void + public function testValidSAMLDateTime(bool $shouldPass, string $timestamp): void { try { - SAML2Assert::validDateTime($timestamp); + Assert::validSAMLDateTime($timestamp); $this->assertTrue($shouldPass); } catch (AssertionFailedException | ProtocolViolationException | SchemaViolationException $e) { $this->assertFalse($shouldPass); diff --git a/tests/SAML2/Assert/SAMLStringTest.php b/tests/SAML2/Assert/SAMLStringTest.php new file mode 100644 index 000000000..5ae3d24ab --- /dev/null +++ b/tests/SAML2/Assert/SAMLStringTest.php @@ -0,0 +1,52 @@ +assertTrue($shouldPass); + } catch (ProtocolViolationException | SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideString(): array + { + return [ + 'single letter' => [true, 't'], + 'single word' => [true, 'this'], + 'spaces' => [true, 'this is silly'], + 'empty' => [false, ''], + ]; + } +} diff --git a/tests/SAML2/Assertion/Transformer/NameIdDecryptionTransformerTest.php b/tests/SAML2/Assertion/Transformer/NameIdDecryptionTransformerTest.php index a5b36df69..221894d47 100644 --- a/tests/SAML2/Assertion/Transformer/NameIdDecryptionTransformerTest.php +++ b/tests/SAML2/Assertion/Transformer/NameIdDecryptionTransformerTest.php @@ -4,7 +4,6 @@ namespace SimpleSAML\Test\SAML2\Assertion\Transformer; -use DateTimeImmutable; use DOMDocument; use PHPUnit\Framework\Attributes\PreserveGlobalState; use PHPUnit\Framework\Attributes\RunInSeparateProcess; @@ -20,6 +19,9 @@ use SimpleSAML\SAML2\Configuration\PrivateKey; use SimpleSAML\SAML2\Configuration\ServiceProvider; use SimpleSAML\SAML2\Signature\Validator; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utilities\ArrayCollection; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\XML\saml\Assertion; @@ -34,6 +36,7 @@ use SimpleSAML\SAML2\XML\samlp\Status; use SimpleSAML\SAML2\XML\samlp\StatusCode; use SimpleSAML\Test\SAML2\Constants as C; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\Alg\KeyTransport\KeyTransportAlgorithmFactory; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; @@ -91,7 +94,13 @@ public static function setUpBeforeClass(): void self::$logger = new NullLogger(); self::$validator = new Validator(self::$logger); self::$destination = new Destination(C::ENTITY_SP); - self::$response = new Response(new Status(new StatusCode()), self::$clock->now()); + self::$response = new Response( + id: IDValue::fromString('SomeIDValue'), + status: new Status( + new StatusCode(SAMLAnyURIValue::fromString(C::STATUS_SUCCESS)), + ), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + ); self::$identityProviderConfiguration = new IdentityProvider(['assertionEncryptionEnabled' => true]); $base = getcwd() . DIRECTORY_SEPARATOR . self::FRAMEWORK; @@ -124,22 +133,29 @@ public static function setUpBeforeClass(): void C::KEY_TRANSPORT_RSA_1_5, PEMCertificatesMock::getPublicKey(PEMCertificatesMock::PUBLIC_KEY), ); - $nameId = new NameID('value', 'urn:x-simplesamlphp:namequalifier'); + $nameId = new NameID( + SAMLStringValue::fromString('value'), + SAMLStringValue::fromString('urn:x-simplesamlphp:namequalifier'), + ); $encryptedId = new EncryptedID($nameId->encrypt($encryptor)); $assertion = new Assertion( - issuer: new Issuer(C::ENTITY_IDP), - id: '_45e42090d8cbbfa52d5a394b01049fc2221e274182', - issueInstant: new DateTimeImmutable('2023-05-27T16:20:52Z'), + issuer: new Issuer( + SAMLStringValue::fromString(C::ENTITY_IDP), + ), + id: IDValue::fromString('_45e42090d8cbbfa52d5a394b01049fc2221e274182'), + issueInstant: SAMLDateTimeValue::fromString('2023-05-27T16:20:52Z'), subject: new Subject($encryptedId), statements: [ new AuthnStatement( new AuthnContext( - new AuthnContextClassRef(C::AUTHNCONTEXT_CLASS_REF_LOA1), + new AuthnContextClassRef( + SAMLAnyURIValue::fromString(C::AUTHNCONTEXT_CLASS_REF_LOA1), + ), null, null, ), - new DateTimeImmutable('2023-05-27T16:20:52Z'), + SAMLDateTimeValue::fromString('2023-05-27T16:20:52Z'), ), ], ); @@ -163,8 +179,8 @@ public function testBasicNameIdDecryption(): void $identifier = $processed->getSubject()->getIdentifier(); $this->assertInstanceOf(NameID::class, $identifier); - $this->assertEquals('value', $identifier->getContent()); - $this->assertEquals('urn:x-simplesamlphp:namequalifier', $identifier->getNameQualifier()); + $this->assertEquals('value', $identifier->getContent()->getValue()); + $this->assertEquals('urn:x-simplesamlphp:namequalifier', $identifier->getNameQualifier()->getValue()); } @@ -187,7 +203,7 @@ public function testDecryptionProcessAssertions(): void $identifier = $processed->getOnlyElement()->getSubject()->getIdentifier(); $this->assertInstanceOf(NameID::class, $identifier); - $this->assertEquals('value', $identifier->getContent()); - $this->assertEquals('urn:x-simplesamlphp:namequalifier', $identifier->getNameQualifier()); + $this->assertEquals('value', $identifier->getContent()->getValue()); + $this->assertEquals('urn:x-simplesamlphp:namequalifier', $identifier->getNameQualifier()->getValue()); } } diff --git a/tests/SAML2/Assertion/Validation/AssertionValidatorTest.php b/tests/SAML2/Assertion/Validation/AssertionValidatorTest.php index cbfb7d017..55ea4e808 100644 --- a/tests/SAML2/Assertion/Validation/AssertionValidatorTest.php +++ b/tests/SAML2/Assertion/Validation/AssertionValidatorTest.php @@ -21,6 +21,8 @@ use SimpleSAML\SAML2\Configuration\IdentityProvider; use SimpleSAML\SAML2\Configuration\ServiceProvider; use SimpleSAML\SAML2\Signature\Validator; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\XML\saml\Assertion; use SimpleSAML\SAML2\XML\samlp\Response; @@ -28,6 +30,7 @@ use SimpleSAML\SAML2\XML\samlp\StatusCode; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; +use SimpleSAML\XML\Type\IDValue; /** * Tests for the Assertion validators @@ -78,7 +81,15 @@ public static function setUpBeforeClass(): void self::$logger = new NullLogger(); self::$validator = new Validator(self::$logger); self::$destination = new Destination($destination); - self::$response = new Response(new Status(new StatusCode()), self::$clock->now()); + self::$response = new Response( + id: IDValue::fromString('abc123'), + status: new Status( + new StatusCode( + SAMLAnyURIValue::fromString(C::STATUS_SUCCESS), + ), + ), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + ); self::$identityProviderConfiguration = new IdentityProvider(['entityId' => $idpentity]); self::$serviceProviderConfiguration = new ServiceProvider(['entityId' => $spentity]); diff --git a/tests/SAML2/Assertion/Validation/ConstraintValidator/NotBeforeTest.php b/tests/SAML2/Assertion/Validation/ConstraintValidator/NotBeforeTest.php index 4b207c627..5ad521650 100644 --- a/tests/SAML2/Assertion/Validation/ConstraintValidator/NotBeforeTest.php +++ b/tests/SAML2/Assertion/Validation/ConstraintValidator/NotBeforeTest.php @@ -11,6 +11,9 @@ use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator\NotBefore; use SimpleSAML\SAML2\Assertion\Validation\Result; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\XML\saml\Assertion; use SimpleSAML\SAML2\XML\saml\AuthnContext; @@ -19,6 +22,7 @@ use SimpleSAML\SAML2\XML\saml\Conditions; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\Test\SAML2\Constants as C; +use SimpleSAML\XML\Type\IDValue; /** * @package simplesamlphp/saml2 @@ -43,16 +47,20 @@ public static function setUpBeforeClass(): void self::$clock = Utils::getContainer()->getClock(); // Create an Issuer - self::$issuer = new Issuer('urn:x-simplesamlphp:issuer'); + self::$issuer = new Issuer( + SAMLStringValue::fromString('urn:x-simplesamlphp:issuer'), + ); // Create the statements self::$authnStatement = new AuthnStatement( new AuthnContext( - new AuthnContextClassRef(C::AUTHNCONTEXT_CLASS_REF_LOA1), + new AuthnContextClassRef( + SAMLAnyURIValue::fromString(C::AUTHNCONTEXT_CLASS_REF_LOA1), + ), null, null, ), - self::$clock->now(), + SAMLDateTimeValue::fromDateTime(self::$clock->now()), ); } @@ -63,12 +71,17 @@ public static function setUpBeforeClass(): void public function testTimestampInTheFutureBeyondGraceperiodIsNotValid(): void { // Create Conditions - $conditions = new Conditions(self::$clock->now()->add(new DateInterval('PT61S'))); + $conditions = new Conditions( + SAMLDateTimeValue::fromDateTime( + self::$clock->now()->add(new DateInterval('PT61S')), + ), + ); // Create an assertion $assertion = new Assertion( + id: IDValue::fromString('abc123'), issuer: self::$issuer, - issueInstant: self::$clock->now(), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), conditions: $conditions, statements: [self::$authnStatement], ); @@ -89,12 +102,17 @@ public function testTimestampInTheFutureBeyondGraceperiodIsNotValid(): void public function testTimeWithinGraceperiodIsValid(): void { // Create Conditions - $conditions = new Conditions(self::$clock->now()->add(new DateInterval('PT60S'))); + $conditions = new Conditions( + SAMLDateTimeValue::fromDateTime( + self::$clock->now()->add(new DateInterval('PT60S')), + ), + ); // Create an assertion $assertion = new Assertion( + id: IDValue::fromString('abc123'), issuer: self::$issuer, - issueInstant: self::$clock->now(), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), conditions: $conditions, statements: [self::$authnStatement], ); @@ -114,12 +132,15 @@ public function testTimeWithinGraceperiodIsValid(): void public function testCurrentTimeIsValid(): void { // Create Conditions - $conditions = new Conditions(self::$clock->now()); + $conditions = new Conditions( + SAMLDateTimeValue::fromDateTime(self::$clock->now()), + ); // Create an assertion $assertion = new Assertion( + id: IDValue::fromString('abc123'), issuer: self::$issuer, - issueInstant: self::$clock->now(), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), conditions: $conditions, statements: [self::$authnStatement], ); diff --git a/tests/SAML2/Assertion/Validation/ConstraintValidator/NotOnOrAfterTest.php b/tests/SAML2/Assertion/Validation/ConstraintValidator/NotOnOrAfterTest.php index 92cb6e6ca..f0b3d386b 100644 --- a/tests/SAML2/Assertion/Validation/ConstraintValidator/NotOnOrAfterTest.php +++ b/tests/SAML2/Assertion/Validation/ConstraintValidator/NotOnOrAfterTest.php @@ -11,6 +11,9 @@ use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator\NotOnOrAfter; use SimpleSAML\SAML2\Assertion\Validation\Result; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\XML\saml\Assertion; use SimpleSAML\SAML2\XML\saml\AuthnContext; @@ -19,6 +22,7 @@ use SimpleSAML\SAML2\XML\saml\Conditions; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\Test\SAML2\Constants as C; +use SimpleSAML\XML\Type\IDValue; /** * @package simplesamlphp/saml2 @@ -43,16 +47,20 @@ public static function setUpBeforeClass(): void self::$clock = Utils::getContainer()->getClock(); // Create an Issuer - self::$issuer = new Issuer('urn:x-simplesamlphp:issuer'); + self::$issuer = new Issuer( + SAMLStringValue::fromString('urn:x-simplesamlphp:issuer'), + ); // Create the statements self::$authnStatement = new AuthnStatement( new AuthnContext( - new AuthnContextClassRef(C::AUTHNCONTEXT_CLASS_REF_URN), + new AuthnContextClassRef( + SAMLAnyURIValue::fromString(C::AUTHNCONTEXT_CLASS_REF_URN), + ), null, null, ), - self::$clock->now(), + SAMLDateTimeValue::fromDateTime(self::$clock->now()), ); } @@ -63,12 +71,18 @@ public static function setUpBeforeClass(): void public function testTimestampInThePastBeforeGraceperiodIsNotValid(): void { // Create Conditions - $conditions = new Conditions(null, self::$clock->now()->sub(new DateInterval('PT60S'))); + $conditions = new Conditions( + null, + SAMLDateTimeValue::fromDateTime( + self::$clock->now()->sub(new DateInterval('PT60S')), + ), + ); // Create an assertion $assertion = new Assertion( + id: IDValue::fromString('abc123'), issuer: self::$issuer, - issueInstant: self::$clock->now(), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), conditions: $conditions, statements: [self::$authnStatement], ); @@ -89,12 +103,18 @@ public function testTimestampInThePastBeforeGraceperiodIsNotValid(): void public function testTimeWithinGraceperiodIsValid(): void { // Create Conditions - $conditions = new Conditions(null, self::$clock->now()->sub(new DateInterval('PT59S'))); + $conditions = new Conditions( + null, + SAMLDateTimeValue::fromDateTime( + self::$clock->now()->sub(new DateInterval('PT59S')), + ), + ); // Create an assertion $assertion = new Assertion( + id: IDValue::fromString('abc123'), issuer: self::$issuer, - issueInstant: self::$clock->now(), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), conditions: $conditions, statements: [self::$authnStatement], ); @@ -114,12 +134,16 @@ public function testTimeWithinGraceperiodIsValid(): void public function testCurrentTimeIsValid(): void { // Create Conditions - $conditions = new Conditions(null, self::$clock->now()); + $conditions = new Conditions( + null, + SAMLDateTimeValue::fromDateTime(self::$clock->now()), + ); // Create an assertion $assertion = new Assertion( + id: IDValue::fromString('abc123'), issuer: self::$issuer, - issueInstant: self::$clock->now(), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), conditions: $conditions, statements: [self::$authnStatement], ); diff --git a/tests/SAML2/Assertion/Validation/ConstraintValidator/SessionNotOnOrAfterTest.php b/tests/SAML2/Assertion/Validation/ConstraintValidator/SessionNotOnOrAfterTest.php index ce0aab742..afb6e6795 100644 --- a/tests/SAML2/Assertion/Validation/ConstraintValidator/SessionNotOnOrAfterTest.php +++ b/tests/SAML2/Assertion/Validation/ConstraintValidator/SessionNotOnOrAfterTest.php @@ -11,6 +11,9 @@ use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator\SessionNotOnOrAfter; use SimpleSAML\SAML2\Assertion\Validation\Result; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\XML\saml\Assertion; use SimpleSAML\SAML2\XML\saml\AuthnContext; @@ -18,6 +21,7 @@ use SimpleSAML\SAML2\XML\saml\AuthnStatement; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\Test\SAML2\Constants as C; +use SimpleSAML\XML\Type\IDValue; /** * @package simplesamlphp/saml2 @@ -39,7 +43,9 @@ public static function setUpBeforeClass(): void self::$clock = Utils::getContainer()->getClock(); // Create an Issuer - self::$issuer = new Issuer('urn:x-simplesamlphp:issuer'); + self::$issuer = new Issuer( + SAMLStringValue::fromString('urn:x-simplesamlphp:issuer'), + ); } @@ -51,16 +57,25 @@ public function timestampInThePastBeforeGraceperiodIsNotValid(): void // Create the statements $authnStatement = new AuthnStatement( new AuthnContext( - new AuthnContextClassRef(C::AUTHNCONTEXT_CLASS_REF_LOA1), + new AuthnContextClassRef( + SAMLAnyURIValue::fromString(C::AUTHNCONTEXT_CLASS_REF_LOA1), + ), null, null, ), - self::$clock->now(), - self::$clock->now()->sub(new DateInterval('PT60S')), + SAMLDateTimeValue::fromDateTime(self::$clock->now()), + SAMLDateTimeValue::fromDateTime( + self::$clock->now()->sub(new DateInterval('PT60S')), + ), ); // Create an assertion - $assertion = new Assertion(self::$issuer, self::$clock->now(), null, null, null, [$authnStatement]); + $assertion = new Assertion( + issuer: self::$issuer, + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + id: IDValue::fromString('abc123'), + statements: [$authnStatement], + ); $validator = new SessionNotOnOrAfter(); $result = new Result(); @@ -80,16 +95,25 @@ public function timeWithinGraceperiodIsValid(): void // Create the statements $authnStatement = new AuthnStatement( new AuthnContext( - new AuthnContextClassRef(C::AUTHNCONTEXT_CLASS_REF_LOA1), + new AuthnContextClassRef( + SAMLAnyURIValue::fromString(C::AUTHNCONTEXT_CLASS_REF_LOA1), + ), null, null, ), - self::$clock->now(), - self::$clock->now()->sub(new DateInterval('PT59S')), + SAMLDateTimeValue::fromDateTime(self::$clock->now()), + SAMLDateTimeValue::fromDateTime( + self::$clock->now()->sub(new DateInterval('PT59S')), + ), ); // Create an assertion - $assertion = new Assertion(self::$issuer, self::$clock->now(), null, null, null, [$authnStatement]); + $assertion = new Assertion( + id: IDValue::fromString('abc123'), + issuer: self::$issuer, + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + statements: [$authnStatement], + ); $validator = new SessionNotOnOrAfter(); $result = new Result(); @@ -108,16 +132,23 @@ public function testCurrentTimeIsValid(): void // Create the statements $authnStatement = new AuthnStatement( new AuthnContext( - new AuthnContextClassRef(C::AUTHNCONTEXT_CLASS_REF_LOA1), + new AuthnContextClassRef( + SAMLAnyURIValue::fromString(C::AUTHNCONTEXT_CLASS_REF_LOA1), + ), null, null, ), - self::$clock->now(), - self::$clock->now(), + SAMLDateTimeValue::fromDateTime(self::$clock->now()), + SAMLDateTimeValue::fromDateTime(self::$clock->now()), ); // Create an assertion - $assertion = new Assertion(self::$issuer, self::$clock->now(), null, null, null, [$authnStatement]); + $assertion = new Assertion( + id: IDValue::fromString('abc123'), + issuer: self::$issuer, + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + statements: [$authnStatement], + ); $validator = new SessionNotOnOrAfter(); $result = new Result(); diff --git a/tests/SAML2/Assertion/Validation/ConstraintValidator/SpIsValidAudienceTest.php b/tests/SAML2/Assertion/Validation/ConstraintValidator/SpIsValidAudienceTest.php index 721e067b6..e4440f848 100644 --- a/tests/SAML2/Assertion/Validation/ConstraintValidator/SpIsValidAudienceTest.php +++ b/tests/SAML2/Assertion/Validation/ConstraintValidator/SpIsValidAudienceTest.php @@ -13,6 +13,9 @@ use SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator\SpIsValidAudience; use SimpleSAML\SAML2\Assertion\Validation\Result; use SimpleSAML\SAML2\Configuration\ServiceProvider; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\XML\saml\Assertion; use SimpleSAML\SAML2\XML\saml\Audience; @@ -23,6 +26,7 @@ use SimpleSAML\SAML2\XML\saml\Conditions; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\Test\SAML2\Constants as C; +use SimpleSAML\XML\Type\IDValue; /** * Because we're mocking a static call, we have to run it in separate processes so as to no contaminate the other @@ -56,24 +60,33 @@ public static function setUpBeforeClass(): void self::$clock = Utils::getContainer()->getClock(); // Create an Issuer - self::$issuer = new Issuer(C::ENTITY_IDP); + self::$issuer = new Issuer( + SAMLStringValue::fromString(C::ENTITY_IDP), + ); // Create the conditions self::$conditions = new Conditions( null, null, [], - [new AudienceRestriction([new Audience(C::ENTITY_SP), new Audience(C::ENTITY_URN)])], + [ + new AudienceRestriction([ + new Audience(SAMLAnyURIValue::fromString(C::ENTITY_SP)), + new Audience(SAMLAnyURIValue::fromString(C::ENTITY_URN)), + ]), + ], ); // Create the statements self::$authnStatement = new AuthnStatement( new AuthnContext( - new AuthnContextClassRef(C::AUTHNCONTEXT_CLASS_REF_LOA1), + new AuthnContextClassRef( + SAMLAnyURIValue::fromString(C::AUTHNCONTEXT_CLASS_REF_LOA1), + ), null, null, ), - self::$clock->now(), + SAMLDateTimeValue::fromDateTime(self::$clock->now()), ); } @@ -93,8 +106,9 @@ public function testWhenNoValidAudiencesAreGivenTheAssertionIsValid(): void { // Create an assertion $assertion = new Assertion( + id: IDValue::fromString('abc123'), issuer: self::$issuer, - issueInstant: self::$clock->now(), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), statements: [self::$authnStatement], ); @@ -117,8 +131,9 @@ public function testIfTheSpEntityIdIsNotInTheValidAudiencesTheAssertionIsInvalid { // Create an assertion $assertion = new Assertion( + id: IDValue::fromString('abc123'), issuer: self::$issuer, - issueInstant: self::$clock->now(), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), conditions: self::$conditions, statements: [self::$authnStatement], ); @@ -143,8 +158,9 @@ public function testTheAssertionIsValidWhenTheCurrentSpEntityIdIsAValidAudience( { // Create an assertion $assertion = new Assertion( + id: IDValue::fromString('abc123'), issuer: self::$issuer, - issueInstant: self::$clock->now(), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), conditions: self::$conditions, statements: [self::$authnStatement], ); diff --git a/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationMethodTest.php b/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationMethodTest.php index 56bf0d44d..10787da26 100644 --- a/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationMethodTest.php +++ b/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationMethodTest.php @@ -10,6 +10,7 @@ use SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator\SubjectConfirmationMethod; use SimpleSAML\SAML2\Assertion\Validation\Result; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\saml\SubjectConfirmation; /** @@ -23,7 +24,9 @@ final class SubjectConfirmationMethodTest extends TestCase #[Group('assertion-validation')] public function testASubjectConfirmationWithBearerMethodIsValid(): void { - $subjectConfirmation = new SubjectConfirmation(C::CM_BEARER); + $subjectConfirmation = new SubjectConfirmation( + SAMLAnyURIValue::fromString(C::CM_BEARER), + ); $validator = new SubjectConfirmationMethod(); $result = new Result(); @@ -39,7 +42,9 @@ public function testASubjectConfirmationWithBearerMethodIsValid(): void #[Group('assertion-validation')] public function testASubjectConfirmationWithHolderOfKeyMethodIsNotValid(): void { - $subjectConfirmation = new SubjectConfirmation(C::CM_HOK); + $subjectConfirmation = new SubjectConfirmation( + SAMLAnyURIValue::fromString(C::CM_HOK), + ); $validator = new SubjectConfirmationMethod(); $result = new Result(); diff --git a/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotBeforeTest.php b/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotBeforeTest.php index bb5dc11a6..c19f46e01 100644 --- a/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotBeforeTest.php +++ b/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotBeforeTest.php @@ -12,6 +12,8 @@ use SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator\SubjectConfirmationNotBefore; use SimpleSAML\SAML2\Assertion\Validation\Result; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\XML\saml\SubjectConfirmation; use SimpleSAML\SAML2\XML\saml\SubjectConfirmationData; @@ -39,8 +41,16 @@ public static function setUpBeforeClass(): void #[Group('assertion-validation')] public function testTimestampInTheFutureBeyondGraceperiodIsNotValid(): void { - $subjectConfirmationData = new SubjectConfirmationData(self::$clock->now()->add(new DateInterval('PT61S'))); - $subjectConfirmation = new SubjectConfirmation(C::CM_HOK, null, $subjectConfirmationData); + $subjectConfirmationData = new SubjectConfirmationData( + SAMLDateTimeValue::fromDateTime( + self::$clock->now()->add(new DateInterval('PT61S')), + ), + ); + $subjectConfirmation = new SubjectConfirmation( + SAMLAnyURIValue::fromString(C::CM_HOK), + null, + $subjectConfirmationData, + ); $validator = new SubjectConfirmationNotBefore(); $result = new Result(); @@ -59,9 +69,15 @@ public function testTimeWithinGraceperiodIsValid(): void { $subjectConfirmationData = new SubjectConfirmationData( null, - self::$clock->now()->add(new DateInterval('PT60S')), + SAMLDateTimeValue::fromDateTime( + self::$clock->now()->add(new DateInterval('PT60S')), + ), + ); + $subjectConfirmation = new SubjectConfirmation( + SAMLAnyURIValue::fromString(C::CM_HOK), + null, + $subjectConfirmationData, ); - $subjectConfirmation = new SubjectConfirmation(C::CM_HOK, null, $subjectConfirmationData); $validator = new SubjectConfirmationNotBefore(); $result = new Result(); @@ -77,8 +93,14 @@ public function testTimeWithinGraceperiodIsValid(): void #[Group('assertion-validation')] public function testCurrentTimeIsValid(): void { - $subjectConfirmationData = new SubjectConfirmationData(self::$clock->now()); - $subjectConfirmation = new SubjectConfirmation(C::CM_HOK, null, $subjectConfirmationData); + $subjectConfirmationData = new SubjectConfirmationData( + SAMLDateTimeValue::fromDateTime(self::$clock->now()), + ); + $subjectConfirmation = new SubjectConfirmation( + SAMLAnyURIValue::fromString(C::CM_HOK), + null, + $subjectConfirmationData, + ); $validator = new SubjectConfirmationNotBefore(); $result = new Result(); diff --git a/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotOnOrAfterTest.php b/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotOnOrAfterTest.php index 43631ba8e..fc0d2e672 100644 --- a/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotOnOrAfterTest.php +++ b/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotOnOrAfterTest.php @@ -13,6 +13,8 @@ use SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator\SubjectConfirmationNotOnOrAfter; use SimpleSAML\SAML2\Assertion\Validation\Result; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\XML\saml\SubjectConfirmation; use SimpleSAML\SAML2\XML\saml\SubjectConfirmationData; @@ -42,9 +44,15 @@ public function testTimestampInThePastBeforeGraceperiodIsNotValid(): void { $subjectConfirmationData = new SubjectConfirmationData( null, - self::$clock->now()->sub(new DateInterval('PT60S')), + SAMLDateTimeValue::fromDateTime( + self::$clock->now()->sub(new DateInterval('PT60S')), + ), + ); + $subjectConfirmation = new SubjectConfirmation( + SAMLAnyURIValue::fromString(C::CM_HOK), + null, + $subjectConfirmationData, ); - $subjectConfirmation = new SubjectConfirmation(C::CM_HOK, null, $subjectConfirmationData); $validator = new SubjectConfirmationNotOnOrAfter(); $result = new Result(); @@ -63,9 +71,15 @@ public function testTimeWithinGraceperiodIsValid(): void { $subjectConfirmationData = new SubjectConfirmationData( null, - self::$clock->now()->sub(new DateInterval('PT59S')), + SAMLDateTimeValue::fromDateTime( + self::$clock->now()->sub(new DateInterval('PT59S')), + ), + ); + $subjectConfirmation = new SubjectConfirmation( + SAMLAnyURIValue::fromString(C::CM_HOK), + null, + $subjectConfirmationData, ); - $subjectConfirmation = new SubjectConfirmation(C::CM_HOK, null, $subjectConfirmationData); $validator = new SubjectConfirmationNotOnOrAfter(); $result = new Result(); @@ -81,8 +95,15 @@ public function testTimeWithinGraceperiodIsValid(): void #[Group('assertion-validation')] public function testCurrentTimeIsValid(): void { - $subjectConfirmationData = new SubjectConfirmationData(null, self::$clock->now()); - $subjectConfirmation = new SubjectConfirmation(C::CM_HOK, null, $subjectConfirmationData); + $subjectConfirmationData = new SubjectConfirmationData( + null, + SAMLDateTimeValue::fromDateTime(self::$clock->now()), + ); + $subjectConfirmation = new SubjectConfirmation( + SAMLAnyURIValue::fromString(C::CM_HOK), + null, + $subjectConfirmationData, + ); $validator = new SubjectConfirmationNotBefore(); $result = new Result(); diff --git a/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationRecipientMatchesTest.php b/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationRecipientMatchesTest.php index e727827f8..1630b88b6 100644 --- a/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationRecipientMatchesTest.php +++ b/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationRecipientMatchesTest.php @@ -11,6 +11,8 @@ use SimpleSAML\SAML2\Assertion\Validation\Result; use SimpleSAML\SAML2\Configuration\Destination; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\saml\SubjectConfirmation; use SimpleSAML\SAML2\XML\saml\SubjectConfirmationData; @@ -25,11 +27,19 @@ final class SubjectConfirmationRecipientMatchesTest extends TestCase #[Group('assertion-validation')] public function testWhenTheSubjectConfirmationRecipientDiffersFromTheDestinationTheScIsInvalid(): void { - $subjectConfirmationData = new SubjectConfirmationData(null, null, 'someDestination'); - $subjectConfirmation = new SubjectConfirmation(C::CM_HOK, null, $subjectConfirmationData); + $subjectConfirmationData = new SubjectConfirmationData( + null, + null, + EntityIDValue::fromString('urn:x-simplesamlphp:someDestination'), + ); + $subjectConfirmation = new SubjectConfirmation( + SAMLAnyURIValue::fromString(C::CM_HOK), + null, + $subjectConfirmationData, + ); $validator = new SubjectConfirmationRecipientMatches( - new Destination('anotherDestination'), + new Destination('urn:x-simplesamlphp:anotherDestination'), ); $result = new Result(); @@ -45,11 +55,19 @@ public function testWhenTheSubjectConfirmationRecipientDiffersFromTheDestination #[Group('assertion-validation')] public function testWhenTheSubjectConfirmationRecipientEqualsTheDestinationTheScIsInvalid(): void { - $subjectConfirmationData = new SubjectConfirmationData(null, null, 'theSameDestination'); - $subjectConfirmation = new SubjectConfirmation(C::CM_HOK, null, $subjectConfirmationData); + $subjectConfirmationData = new SubjectConfirmationData( + null, + null, + EntityIDValue::fromString('urn:x-simplesamlphp:theSameDestination'), + ); + $subjectConfirmation = new SubjectConfirmation( + SAMLAnyURIValue::fromString(C::CM_HOK), + null, + $subjectConfirmationData, + ); $validator = new SubjectConfirmationRecipientMatches( - new Destination('theSameDestination'), + new Destination('urn:x-simplesamlphp:theSameDestination'), ); $result = new Result(); diff --git a/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationResponseToMatchesTest.php b/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationResponseToMatchesTest.php index 4ecdda6ad..725899162 100644 --- a/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationResponseToMatchesTest.php +++ b/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationResponseToMatchesTest.php @@ -12,9 +12,11 @@ use SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator\SubjectConfirmationResponseToMatches; use SimpleSAML\SAML2\Assertion\Validation\Result; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\saml\SubjectConfirmation; use SimpleSAML\SAML2\XML\saml\SubjectConfirmationData; use SimpleSAML\SAML2\XML\samlp\Response; +use SimpleSAML\XMLSchema\Type\NCNameValue; /** * @package simplesamlphp/saml2 @@ -40,8 +42,14 @@ public function setUp(): void public function testWhenTheResponseResponsetoIsNullTheSubjectConfirmationIsValid(): void { $this->response->shouldReceive('getInResponseTo')->andReturnNull(); - $subjectConfirmationData = new SubjectConfirmationData(null, null, null, 'someValue'); - $subjectConfirmation = new SubjectConfirmation(C::CM_HOK, null, $subjectConfirmationData); + $subjectConfirmationData = new SubjectConfirmationData( + inResponseTo: NCNameValue::fromString('someIDValue'), + ); + $subjectConfirmation = new SubjectConfirmation( + SAMLAnyURIValue::fromString(C::CM_HOK), + null, + $subjectConfirmationData, + ); $validator = new SubjectConfirmationResponseToMatches($this->response); $result = new Result(); @@ -57,9 +65,13 @@ public function testWhenTheResponseResponsetoIsNullTheSubjectConfirmationIsValid #[Group('assertion-validation')] public function testWhenTheSubjectconfirmationResponsetoIsNullTheSubjectconfirmationIsValid(): void { - $this->response->shouldReceive('getInResponseTo')->andReturn('someValue'); + $this->response->shouldReceive('getInResponseTo')->andReturn(NCNameValue::fromString('someIDValue')); $subjectConfirmationData = new SubjectConfirmationData(); - $subjectConfirmation = new SubjectConfirmation(C::CM_HOK, null, $subjectConfirmationData); + $subjectConfirmation = new SubjectConfirmation( + SAMLAnyURIValue::fromString(C::CM_HOK), + null, + $subjectConfirmationData, + ); $validator = new SubjectConfirmationResponseToMatches($this->response); $result = new Result(); @@ -77,7 +89,11 @@ public function testWhenTheSubjectconfirmationAndResponseResponsetoAreNullTheSub { $this->response->shouldReceive('getInResponseTo')->andReturnNull(); $subjectConfirmationData = new SubjectConfirmationData(); - $subjectConfirmation = new SubjectConfirmation(C::CM_HOK, null, $subjectConfirmationData); + $subjectConfirmation = new SubjectConfirmation( + SAMLAnyURIValue::fromString(C::CM_HOK), + null, + $subjectConfirmationData, + ); $validator = new SubjectConfirmationResponseToMatches($this->response); $result = new Result(); @@ -91,11 +107,17 @@ public function testWhenTheSubjectconfirmationAndResponseResponsetoAreNullTheSub /** */ #[Group('assertion-validation')] - public function testWhenTheSubjectconfirmationAndResponseResponsetoAreEqualTheSubjectconfirmationIsValid(): void + public function testWhenTheSubjectConfirmationAndResponseResponsetoAreEqualTheSubjectConfirmationIsValid(): void { - $this->response->shouldReceive('getInResponseTo')->andReturn('theSameValue'); - $subjectConfirmationData = new SubjectConfirmationData(null, null, null, 'theSameValue'); - $subjectConfirmation = new SubjectConfirmation(C::CM_HOK, null, $subjectConfirmationData); + $this->response->shouldReceive('getInResponseTo')->andReturn(NCNameValue::fromString('someIDValue')); + $subjectConfirmationData = new SubjectConfirmationData( + inResponseTo: NCNameValue::fromString('someIDValue'), + ); + $subjectConfirmation = new SubjectConfirmation( + SAMLAnyURIValue::fromString(C::CM_HOK), + null, + $subjectConfirmationData, + ); $validator = new SubjectConfirmationResponseToMatches($this->response); $result = new Result(); @@ -111,9 +133,15 @@ public function testWhenTheSubjectconfirmationAndResponseResponsetoAreEqualTheSu #[Group('assertion-validation')] public function testWhenTheSubjectconfirmationAndResponseResponsetoDifferTheSubjectconfirmationIsInvalid(): void { - $this->response->shouldReceive('getInResponseTo')->andReturn('someValue'); - $subjectConfirmationData = new SubjectConfirmationData(null, null, null, 'anotherValue'); - $subjectConfirmation = new SubjectConfirmation(C::CM_HOK, null, $subjectConfirmationData); + $this->response->shouldReceive('getInResponseTo')->andReturn(NCNameValue::fromString('someIDValue')); + $subjectConfirmationData = new SubjectConfirmationData( + inResponseTo: NCNameValue::fromString('someOtherIDValue'), + ); + $subjectConfirmation = new SubjectConfirmation( + SAMLAnyURIValue::fromString(C::CM_HOK), + null, + $subjectConfirmationData, + ); $validator = new SubjectConfirmationResponseToMatches($this->response); $result = new Result(); diff --git a/tests/SAML2/Assertion/Validation/SubjectConfirmationValidatorTest.php b/tests/SAML2/Assertion/Validation/SubjectConfirmationValidatorTest.php index b01449801..a3636aec9 100644 --- a/tests/SAML2/Assertion/Validation/SubjectConfirmationValidatorTest.php +++ b/tests/SAML2/Assertion/Validation/SubjectConfirmationValidatorTest.php @@ -19,6 +19,8 @@ use SimpleSAML\SAML2\Configuration\IdentityProvider; use SimpleSAML\SAML2\Configuration\ServiceProvider; use SimpleSAML\SAML2\Signature\Validator; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\XML\saml\Assertion; use SimpleSAML\SAML2\XML\samlp\Response; @@ -26,6 +28,8 @@ use SimpleSAML\SAML2\XML\samlp\StatusCode; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; +use SimpleSAML\XMLSchema\Constants as C_XSI; +use SimpleSAML\XMLSchema\Type\IDValue; /** * Tests for the SubjectConfirmation validators @@ -71,7 +75,15 @@ public static function setUpBeforeClass(): void self::$logger = new NullLogger(); self::$validator = new Validator(self::$logger); self::$destination = new Destination(C::ENTITY_SP); - self::$response = new Response(new Status(new StatusCode()), self::$clock->now()); + self::$response = new Response( + id: IDValue::fromString('abc123'), + status: new Status( + new StatusCode( + SAMLAnyURIValue::fromString(C::STATUS_SUCCESS), + ), + ), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + ); self::$identityProviderConfiguration = new IdentityProvider(['entityId' => C::ENTITY_IDP]); self::$serviceProviderConfiguration = new ServiceProvider(['entityId' => C::ENTITY_SP]); @@ -85,8 +97,8 @@ public static function setUpBeforeClass(): void self::$response, ); - $ns_xsi = C::NS_XSI; - $ns_xs = C::NS_XS; + $ns_xsi = C_XSI::NS_XSI; + $ns_xs = C_XSI::NS_XS; $ns_saml = C::NS_SAML; $nameid_persistent = C::NAMEID_PERSISTENT; $entity_idp = C::ENTITY_IDP; diff --git a/tests/SAML2/Binding/HTTPArtifactTest.php b/tests/SAML2/Binding/HTTPArtifactTest.php index d62b3cab6..460a1cf74 100644 --- a/tests/SAML2/Binding/HTTPArtifactTest.php +++ b/tests/SAML2/Binding/HTTPArtifactTest.php @@ -7,12 +7,14 @@ use Exception; use Nyholm\Psr7\ServerRequest; use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Binding\HTTPArtifact; /** * @package simplesamlphp\saml2 */ +#[Group('bindings')] #[CoversClass(HTTPArtifact::class)] final class HTTPArtifactTest extends TestCase { diff --git a/tests/SAML2/Binding/HTTPPostTest.php b/tests/SAML2/Binding/HTTPPostTest.php index ddc86da9e..76cdb6114 100644 --- a/tests/SAML2/Binding/HTTPPostTest.php +++ b/tests/SAML2/Binding/HTTPPostTest.php @@ -8,22 +8,28 @@ use Nyholm\Psr7\ServerRequest; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; +use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Binding\HTTPPost; +use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\samlp\AuthnRequest; use SimpleSAML\SAML2\XML\samlp\Response; use SimpleSAML\SAML2\XML\samlp\Status; use SimpleSAML\SAML2\XML\samlp\StatusCode; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\Alg\Signature\SignatureAlgorithmFactory; -use SimpleSAML\XMLSecurity\Constants as C; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; /** * @package simplesamlphp\saml2 */ +#[Group('bindings')] #[CoversClass(HTTPPost::class)] final class HTTPPostTest extends TestCase { @@ -106,7 +112,8 @@ public function testNoRequestParsing(): void public function testSendMissingDestination(): void { $request = new AuthnRequest( - issueInstant: self::$clock->now(), + id: IDValue::fromString('abc123'), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), ); $hp = new HTTPPost(); $this->expectException(Exception::class); @@ -122,7 +129,8 @@ public function testSendMissingDestination(): void public function testSendAuthnRequestWithDestinationInBinding(): void { $request = new AuthnRequest( - issueInstant: self::$clock->now(), + id: IDValue::fromString('abc123'), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), ); $hp = new HTTPPost(); $hp->setDestination('https://example.org'); @@ -137,8 +145,9 @@ public function testSendAuthnRequestWithDestinationInBinding(): void public function testSendAuthnRequestWithDestination(): void { $request = new AuthnRequest( - issueInstant: self::$clock->now(), - destination: 'https://example.org', + id: IDValue::fromString('abc123'), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + destination: SAMLAnyURIValue::fromString('https://example.org'), ); $hp = new HTTPPost(); $hp->send($request); @@ -152,14 +161,21 @@ public function testSendAuthnRequestWithDestination(): void #[DoesNotPerformAssertions] public function testSendAuthnResponse(): void { - $status = new Status(new StatusCode()); - $issuer = new Issuer('urn:x-simplesamlphp:issuer'); + $status = new Status( + new StatusCode( + SAMLAnyURIValue::fromString(C::STATUS_SUCCESS), + ), + ); + $issuer = new Issuer( + SAMLStringValue::fromString('urn:x-simplesamlphp:issuer'), + ); $response = new Response( - issueInstant: self::$clock->now(), + id: IDValue::fromString('abc123'), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), status: $status, issuer: $issuer, - destination: 'http://example.org/login?success=yes', + destination: SAMLAnyURIValue::fromString('http://example.org/login?success=yes'), ); $signer = (new SignatureAlgorithmFactory())->getAlgorithm( C::SIG_RSA_SHA256, diff --git a/tests/SAML2/Binding/HTTPRedirectTest.php b/tests/SAML2/Binding/HTTPRedirectTest.php index 3a0320227..8a465a9fe 100644 --- a/tests/SAML2/Binding/HTTPRedirectTest.php +++ b/tests/SAML2/Binding/HTTPRedirectTest.php @@ -8,21 +8,28 @@ use Nyholm\Psr7\ServerRequest; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; +use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Binding\HTTPRedirect; use SimpleSAML\SAML2\Compat\AbstractContainer; use SimpleSAML\SAML2\Compat\ContainerSingleton; +use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\samlp\AbstractRequest; use SimpleSAML\SAML2\XML\samlp\AuthnRequest; use SimpleSAML\SAML2\XML\samlp\Response; use SimpleSAML\SAML2\XML\samlp\Status; use SimpleSAML\SAML2\XML\samlp\StatusCode; +use SimpleSAML\XML\Type\IDValue; /** * @package simplesamlphp\saml2 */ +#[Group('bindings')] #[CoversClass(HTTPRedirect::class)] final class HTTPRedirectTest extends TestCase { @@ -182,6 +189,7 @@ public function testInvalidEncodingSpecified(): void $this->expectException(Exception::class); $this->expectExceptionMessage('Unknown SAMLEncoding:'); + $hr = new HTTPRedirect(); $hr->receive($request); } @@ -201,6 +209,7 @@ public function testNoSigAlgSpecified(): void $this->expectException(Exception::class); $this->expectExceptionMessage('Missing signature algorithm'); + $hr = new HTTPRedirect(); $hr->receive($request); } @@ -217,6 +226,7 @@ public function testInvalidRequestData(): void $this->expectException(Exception::class); $this->expectExceptionMessage('Error while base64 decoding SAML message.'); + $hr = new HTTPRedirect(); @$hr->receive($request); } @@ -233,6 +243,7 @@ public function testNoRequestOrResponse(): void $this->expectException(Exception::class); $this->expectExceptionMessage('Missing SAMLRequest or SAMLResponse parameter.'); + $hr = new HTTPRedirect(); $hr->receive($request); } @@ -243,7 +254,11 @@ public function testNoRequestOrResponse(): void */ public function testSendWithoutDestination(): void { - $request = new AuthnRequest(self::$clock->now()); + $request = new AuthnRequest( + id: IDValue::fromString('abc123'), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + ); + $hr = new HTTPRedirect(); $this->expectException(Exception::class); $this->expectExceptionMessage('Cannot build a redirect URL, no destination set.'); @@ -257,7 +272,10 @@ public function testSendWithoutDestination(): void #[DoesNotPerformAssertions] public function testSendAuthnrequest(): void { - $request = new AuthnRequest(self::$clock->now()); + $request = new AuthnRequest( + id: IDValue::fromString('abc123'), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + ); $hr = new HTTPRedirect(); $hr->setDestination('https://idp.example.org/'); $hr->send($request); @@ -271,14 +289,21 @@ public function testSendAuthnrequest(): void #[DoesNotPerformAssertions] public function testSendAuthnResponse(): void { - $status = new Status(new StatusCode()); - $issuer = new Issuer('urn:x-simplesamlphp:issuer'); + $status = new Status( + new StatusCode( + SAMLAnyURIValue::fromString(C::STATUS_SUCCESS), + ), + ); + $issuer = new Issuer( + SAMLStringValue::fromString('urn:x-simplesamlphp:issuer'), + ); $response = new Response( + id: IDValue::fromString('abc123'), status: $status, - issueInstant: self::$clock->now(), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), issuer: $issuer, - destination: 'http://example.org/login?success=yes', + destination: SAMLAnyURIValue::fromString('http://example.org/login?success=yes'), ); $hr = new HTTPRedirect(); @@ -293,10 +318,22 @@ public function testSendAuthnResponse(): void #[DoesNotPerformAssertions] public function testSendAuthnResponseBespokeDestination(): void { - $status = new Status(new StatusCode()); - $issuer = new Issuer('urn:x-simplesamlphp:issuer'); + $status = new Status( + new StatusCode( + SAMLAnyURIValue::fromString(C::STATUS_SUCCESS), + ), + ); + $issuer = new Issuer( + SAMLStringValue::fromString('urn:x-simplesamlphp:issuer'), + ); + + $response = new Response( + id: IDValue::fromString('abc123'), + status: $status, + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + issuer: $issuer, + ); - $response = new Response($status, self::$clock->now(), $issuer); $hr = new HTTPRedirect(); $hr->setDestination('gopher://myurl'); $hr->send($response); diff --git a/tests/SAML2/Binding/SOAPTest.php b/tests/SAML2/Binding/SOAPTest.php index 135611191..521178f75 100644 --- a/tests/SAML2/Binding/SOAPTest.php +++ b/tests/SAML2/Binding/SOAPTest.php @@ -7,13 +7,16 @@ use Mockery\Adapter\Phpunit\MockeryTestCase; use Nyholm\Psr7\ServerRequest; use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Group; use SimpleSAML\SAML2\Binding\SOAP; use SimpleSAML\SAML2\Exception\Protocol\UnsupportedBindingException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\ecp\RequestAuthenticated; use SimpleSAML\SAML2\XML\ecp\Response; use SimpleSAML\SAML2\XML\samlp\ArtifactResolve; use SimpleSAML\SAML2\XML\samlp\MessageFactory; -use SimpleSAML\SOAP\Constants as C; +use SimpleSAML\SOAP11\Constants as C; +use SimpleSAML\SOAP11\Type\MustUnderstandValue; use SimpleSAML\XML\DOMDocumentFactory; use function dirname; @@ -21,6 +24,7 @@ /** * @package simplesamlphp\saml2 */ +#[Group('bindings')] #[CoversClass(SOAP::class)] final class SOAPTest extends MockeryTestCase { @@ -86,7 +90,7 @@ public function testSendArtifactResponse(): void SOAP); /** @var \DOMElement $body */ - $body = $doc->getElementsByTagNameNS(C::NS_SOAP_ENV_11, 'Body')->item(0); + $body = $doc->getElementsByTagNameNS(C::NS_SOAP_ENV, 'Body')->item(0); $message->toXML($body); $soap = new SOAP(); @@ -109,17 +113,21 @@ public function testSendResponse(): void SOAP); - $requestAuthenticated = new RequestAuthenticated(true); - $ecpResponse = new Response('https://example.org/metadata'); + $requestAuthenticated = new RequestAuthenticated( + MustUnderstandValue::fromBoolean(true), + ); + $ecpResponse = new Response( + SAMLAnyURIValue::fromString('https://example.org/metadata'), + ); /** @var \DOMElement $header */ - $header = $doc->getElementsByTagNameNS(C::NS_SOAP_ENV_11, 'Header')->item(0); + $header = $doc->getElementsByTagNameNS(C::NS_SOAP_ENV, 'Header')->item(0); $requestAuthenticated->toXML($header); $ecpResponse->toXML($header); /** @var \DOMElement $body */ - $body = $doc->getElementsByTagNameNS(C::NS_SOAP_ENV_11, 'Body')->item(0); + $body = $doc->getElementsByTagNameNS(C::NS_SOAP_ENV, 'Body')->item(0); $message->toXML($body); $soap = new SOAP(); diff --git a/tests/SAML2/BindingTest.php b/tests/SAML2/BindingTest.php index 6b4363e71..d80735751 100644 --- a/tests/SAML2/BindingTest.php +++ b/tests/SAML2/BindingTest.php @@ -6,6 +6,7 @@ use Nyholm\Psr7\ServerRequest; use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Binding; use SimpleSAML\SAML2\Binding\HTTPArtifact; @@ -18,6 +19,7 @@ /** * @package simplesamlphp\saml2 */ +#[Group('bindings')] #[CoversClass(Binding::class)] final class BindingTest extends TestCase { diff --git a/tests/SAML2/CustomBaseID.php b/tests/SAML2/CustomBaseID.php index ed64faba9..94b1e4397 100644 --- a/tests/SAML2/CustomBaseID.php +++ b/tests/SAML2/CustomBaseID.php @@ -5,12 +5,15 @@ namespace SimpleSAML\Test\SAML2; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\AbstractBaseID; use SimpleSAML\SAML2\XML\saml\Audience; use SimpleSAML\Test\SAML2\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\SchemaViolationException; +use SimpleSAML\XMLSchema\Constants as C_XSI; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\SchemaViolationException; +use SimpleSAML\XMLSchema\Type\QNameValue; /** * Example class to demonstrate how BaseID can be extended. @@ -33,17 +36,23 @@ final class CustomBaseID extends AbstractBaseID * CustomBaseID constructor. * * @param \SimpleSAML\SAML2\XML\saml\Audience[] $audience - * @param string|null $NameQualifier - * @param string|null $SPNameQualifier + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $NameQualifier + * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $SPNameQualifier */ public function __construct( protected array $audience, - ?string $NameQualifier = null, - ?string $SPNameQualifier = null, + ?SAMLStringValue $NameQualifier = null, + ?SAMLStringValue $SPNameQualifier = null, ) { Assert::allIsInstanceOf($audience, Audience::class); - parent::__construct(self::XSI_TYPE_PREFIX . ':' . self::XSI_TYPE_NAME, $NameQualifier, $SPNameQualifier); + parent::__construct( + QNameValue::fromString( + '{' . self::XSI_TYPE_NAMESPACE . '}' . self::XSI_TYPE_PREFIX . ':' . self::XSI_TYPE_NAME, + ), + $NameQualifier, + $SPNameQualifier, + ); } @@ -67,18 +76,19 @@ public static function fromXML(DOMElement $xml): static Assert::notNull($xml->namespaceURI, InvalidDOMElementException::class); Assert::same($xml->namespaceURI, AbstractBaseID::NS, InvalidDOMElementException::class); Assert::true( - $xml->hasAttributeNS(C::NS_XSI, 'type'), + $xml->hasAttributeNS(C_XSI::NS_XSI, 'type'), 'Missing required xsi:type in element.', SchemaViolationException::class, ); - $type = $xml->getAttributeNS(C::NS_XSI, 'type'); + $type = $xml->getAttributeNS(C_XSI::NS_XSI, 'type'); Assert::same($type, self::XSI_TYPE_PREFIX . ':' . self::XSI_TYPE_NAME); - $nameQualifier = self::getOptionalAttribute($xml, 'NameQualifier', null); - $spNameQualifier = self::getOptionalAttribute($xml, 'SPNameQualifier', null); - - return new static(Audience::getChildrenOfClass($xml), $nameQualifier, $spNameQualifier); + return new static( + Audience::getChildrenOfClass($xml), + self::getOptionalAttribute($xml, 'NameQualifier', SAMLStringValue::class, null), + self::getOptionalAttribute($xml, 'SPNameQualifier', SAMLStringValue::class, null), + ); } diff --git a/tests/SAML2/CustomCondition.php b/tests/SAML2/CustomCondition.php index 6b88b7709..5c2b20152 100644 --- a/tests/SAML2/CustomCondition.php +++ b/tests/SAML2/CustomCondition.php @@ -5,11 +5,13 @@ namespace SimpleSAML\Test\SAML2; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\XML\saml\AbstractCondition; use SimpleSAML\SAML2\XML\saml\Audience; use SimpleSAML\Test\SAML2\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Constants as C_XSI; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Type\QNameValue; /** * Example class to demonstrate how Condition can be extended. @@ -38,7 +40,11 @@ public function __construct( ) { Assert::allIsInstanceOf($audience, Audience::class); - parent::__construct(self::XSI_TYPE_PREFIX . ':' . self::XSI_TYPE_NAME); + parent::__construct( + QNameValue::fromString( + '{' . self::XSI_TYPE_NAMESPACE . '}' . self::XSI_TYPE_PREFIX . ':' . self::XSI_TYPE_NAME, + ), + ); } @@ -59,7 +65,7 @@ public function getAudience(): array * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -68,12 +74,12 @@ public static function fromXML(DOMElement $xml): static Assert::notNull($xml->namespaceURI, InvalidDOMElementException::class); Assert::same($xml->namespaceURI, AbstractCondition::NS, InvalidDOMElementException::class); Assert::true( - $xml->hasAttributeNS(C::NS_XSI, 'type'), + $xml->hasAttributeNS(C_XSI::NS_XSI, 'type'), 'Missing required xsi:type in element.', InvalidDOMElementException::class, ); - $type = $xml->getAttributeNS(C::NS_XSI, 'type'); + $type = $xml->getAttributeNS(C_XSI::NS_XSI, 'type'); Assert::same($type, self::XSI_TYPE_PREFIX . ':' . self::XSI_TYPE_NAME); $audience = Audience::getChildrenOfClass($xml); diff --git a/tests/SAML2/CustomRoleDescriptor.php b/tests/SAML2/CustomRoleDescriptor.php index fba5d7403..0acd92d2f 100644 --- a/tests/SAML2/CustomRoleDescriptor.php +++ b/tests/SAML2/CustomRoleDescriptor.php @@ -4,20 +4,28 @@ namespace SimpleSAML\Test\SAML2; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\AnyURIListValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\SAML2\XML\md\AbstractRoleDescriptor; use SimpleSAML\SAML2\XML\md\ContactPerson; use SimpleSAML\SAML2\XML\md\Extensions; use SimpleSAML\SAML2\XML\md\KeyDescriptor; use SimpleSAML\SAML2\XML\md\Organization; use SimpleSAML\Test\SAML2\Constants as C; +use SimpleSAML\XML\Attribute as XMLAttribute; use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; +use SimpleSAML\XML\ExtendableElementTrait; +use SimpleSAML\XMLSchema\Constants as C_XSI; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\DurationValue; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\QNameValue; +use SimpleSAML\XMLSchema\XML\Constants\NS; /** * Example class to demonstrate how RoleDescriptor can be extended. @@ -26,6 +34,9 @@ */ final class CustomRoleDescriptor extends AbstractRoleDescriptor { + use ExtendableElementTrait; + + /** @var string */ protected const XSI_TYPE_NAME = 'CustomRoleDescriptorType'; @@ -35,17 +46,24 @@ final class CustomRoleDescriptor extends AbstractRoleDescriptor /** @var string */ protected const XSI_TYPE_PREFIX = 'ssp'; + /** The namespace-attribute for the xs:any element */ + public const XS_ANY_ELT_NAMESPACE = NS::OTHER; + /** * CustomRoleDescriptor constructor. * - * @param \SimpleSAML\XML\Chunk[] $chunk - * @param string[] $protocolSupportEnumeration A set of URI specifying the protocols supported. - * @param string|null $ID The ID for this document. Defaults to null. - * @param \DateTimeImmutable|null $validUntil Unix time of validity for this document. Defaults to null. - * @param string|null $cacheDuration Maximum time this document can be cached. Defaults to null. + * @param \SimpleSAML\XML\SerializableElementInterface[] $chunk + * @param \SimpleSAML\SAML2\Type\AnyURIListValue $protocolSupportEnumeration + * A set of URI specifying the protocols supported. + * @param \SimpleSAML\XMLSchema\Type\IDValue|null $ID The ID for this document. Defaults to null. + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil Unix time of validity for this document. + * Defaults to null. + * @param \SimpleSAML\XMLSchema\Type\DurationValue|null $cacheDuration Maximum time this document can be cached. + * Defaults to null. * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions An Extensions object. Defaults to null. - * @param string|null $errorURL An URI where to redirect users for support. Defaults to null. + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $errorURL An URI where to redirect users for support. + * Defaults to null. * @param \SimpleSAML\SAML2\XML\md\KeyDescriptor[] $keyDescriptor An array of KeyDescriptor elements. * Defaults to an empty array. * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization @@ -56,21 +74,24 @@ final class CustomRoleDescriptor extends AbstractRoleDescriptor */ public function __construct( protected array $chunk, - array $protocolSupportEnumeration, - ?string $ID = null, - ?DateTimeImmutable $validUntil = null, - ?string $cacheDuration = null, + AnyURIListValue $protocolSupportEnumeration, + ?IDValue $ID = null, + ?SAMLDateTimeValue $validUntil = null, + ?DurationValue $cacheDuration = null, ?Extensions $extensions = null, - ?string $errorURL = null, + ?SAMLAnyURIValue $errorURL = null, array $keyDescriptor = [], ?Organization $organization = null, array $contact = [], array $namespacedAttributes = [], ) { Assert::allIsInstanceOf($chunk, Chunk::class); + Assert::minCount($chunk, 1, 'At least one ssp:Chunk element must be provided.', MissingElementException::class); parent::__construct( - self::XSI_TYPE_PREFIX . ':' . self::XSI_TYPE_NAME, + QNameValue::fromString( + '{' . self::XSI_TYPE_NAMESPACE . '}' . self::XSI_TYPE_PREFIX . ':' . self::XSI_TYPE_NAME, + ), $protocolSupportEnumeration, $ID, $validUntil, @@ -88,7 +109,7 @@ public function __construct( /** * Get the value of the chunk-attribute. * - * @return \SimpleSAML\XML\Chunk[] + * @return \SimpleSAML\XML\SerializableElementInterface[] */ public function getChunk(): array { @@ -102,7 +123,7 @@ public function getChunk(): array * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -111,19 +132,14 @@ public static function fromXML(DOMElement $xml): static Assert::notNull($xml->namespaceURI, InvalidDOMElementException::class); Assert::same($xml->namespaceURI, AbstractRoleDescriptor::NS, InvalidDOMElementException::class); Assert::true( - $xml->hasAttributeNS(C::NS_XSI, 'type'), + $xml->hasAttributeNS(C_XSI::NS_XSI, 'type'), 'Missing required xsi:type in element.', InvalidDOMElementException::class, ); - $type = $xml->getAttributeNS(C::NS_XSI, 'type'); + $type = $xml->getAttributeNS(C_XSI::NS_XSI, 'type'); Assert::same($type, self::XSI_TYPE_PREFIX . ':' . self::XSI_TYPE_NAME); - $protocols = self::getAttribute($xml, 'protocolSupportEnumeration'); - - $validUntil = self::getOptionalAttribute($xml, 'validUntil', null); - SAMLAssert::nullOrValidDateTime($validUntil); - $orgs = Organization::getChildrenOfClass($xml); Assert::maxCount( $orgs, @@ -140,26 +156,14 @@ public static function fromXML(DOMElement $xml): static TooManyElementsException::class, ); - $chunk = []; - foreach ($xml->childNodes as $c) { - if (!($c instanceof DOMElement)) { - continue; - } elseif ($c->namespaceURI === C::NS_MD) { - continue; - } - - $chunk[] = new Chunk($c); - } - Assert::minCount($chunk, 1, 'At least one ssp:Chunk element must be provided.', MissingElementException::class); - return new static( - $chunk, - preg_split('/[\s]+/', trim($protocols)), - self::getOptionalAttribute($xml, 'ID', null), - $validUntil !== null ? new DateTimeImmutable($validUntil) : null, - self::getOptionalAttribute($xml, 'cacheDuration', null), + self::getChildElementsFromXML($xml), + self::getAttribute($xml, 'protocolSupportEnumeration', AnyURIListValue::class), + self::getOptionalAttribute($xml, 'ID', IDValue::class, null), + self::getOptionalAttribute($xml, 'validUntil', SAMLDateTimeValue::class, null), + self::getOptionalAttribute($xml, 'cacheDuration', DurationValue::class, null), !empty($extensions) ? $extensions[0] : null, - self::getOptionalAttribute($xml, 'errorURL', null), + self::getOptionalAttribute($xml, 'errorURL', SAMLAnyURIValue::class, null), KeyDescriptor::getChildrenOfClass($xml), !empty($orgs) ? $orgs[0] : null, ContactPerson::getChildrenOfClass($xml), @@ -178,6 +182,21 @@ public function toUnsignedXML(?DOMElement $parent = null): DOMElement { $e = parent::toUnsignedXML($parent); + if (!$e->lookupPrefix($this->getXsiType()->getNamespaceURI()->getValue())) { + $namespace = new XMLAttribute( + 'http://www.w3.org/2000/xmlns/', + 'xmlns', + $this->getXsiType()->getNamespacePrefix()->getValue(), + $this->getXsiType()->getNamespaceURI(), + ); + $namespace->toXML($e); + } + + if (!$e->lookupPrefix('xsi')) { + $type = new XMLAttribute(C_XSI::NS_XSI, 'xsi', 'type', $this->getXsiType()); + $type->toXML($e); + } + foreach ($this->getChunk() as $chunk) { $chunk->toXML($e); } diff --git a/tests/SAML2/CustomStatement.php b/tests/SAML2/CustomStatement.php index edcba56f1..7c2847b0a 100644 --- a/tests/SAML2/CustomStatement.php +++ b/tests/SAML2/CustomStatement.php @@ -5,11 +5,13 @@ namespace SimpleSAML\Test\SAML2; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\XML\saml\AbstractStatement; use SimpleSAML\SAML2\XML\saml\Audience; use SimpleSAML\Test\SAML2\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Constants as C_XSI; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Type\QNameValue; /** * Example class to demonstrate how Statement can be extended. @@ -38,7 +40,11 @@ public function __construct( ) { Assert::allIsInstanceOf($audience, Audience::class); - parent::__construct(self::XSI_TYPE_PREFIX . ':' . self::XSI_TYPE_NAME); + parent::__construct( + QNameValue::fromString( + '{' . self::XSI_TYPE_NAMESPACE . '}' . self::XSI_TYPE_PREFIX . ':' . self::XSI_TYPE_NAME, + ), + ); } @@ -59,7 +65,7 @@ public function getAudience(): array * @param \DOMElement $xml The XML element we should load * @return static * - * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException * if the qualified name of the supplied element is wrong */ public static function fromXML(DOMElement $xml): static @@ -68,12 +74,12 @@ public static function fromXML(DOMElement $xml): static Assert::notNull($xml->namespaceURI, InvalidDOMElementException::class); Assert::same($xml->namespaceURI, AbstractStatement::NS, InvalidDOMElementException::class); Assert::true( - $xml->hasAttributeNS(C::NS_XSI, 'type'), + $xml->hasAttributeNS(C_XSI::NS_XSI, 'type'), 'Missing required xsi:type in element.', InvalidDOMElementException::class, ); - $type = $xml->getAttributeNS(C::NS_XSI, 'type'); + $type = $xml->getAttributeNS(C_XSI::NS_XSI, 'type'); Assert::same($type, self::XSI_TYPE_PREFIX . ':' . self::XSI_TYPE_NAME); $audience = Audience::getChildrenOfClass($xml); diff --git a/tests/SAML2/Response/Validation/ConstraintValidator/DestinationMatchesTest.php b/tests/SAML2/Response/Validation/ConstraintValidator/DestinationMatchesTest.php index 6e3631452..8de74abe3 100644 --- a/tests/SAML2/Response/Validation/ConstraintValidator/DestinationMatchesTest.php +++ b/tests/SAML2/Response/Validation/ConstraintValidator/DestinationMatchesTest.php @@ -12,6 +12,7 @@ use SimpleSAML\SAML2\Configuration\Destination; use SimpleSAML\SAML2\Response\Validation\ConstraintValidator\DestinationMatches; use SimpleSAML\SAML2\Response\Validation\Result; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\samlp\Response; /** @@ -37,8 +38,10 @@ public function setUp(): void #[Group('response-validation')] public function testAResponseIsValidWhenTheDestinationsMatch(): void { - $expectedDestination = new Destination('VALID DESTINATION'); - $this->response->shouldReceive('getDestination')->once()->andReturn('VALID DESTINATION'); + $expectedDestination = new Destination('urn:x-simplesamlphp:validDestination'); + $this->response->shouldReceive('getDestination')->once()->andReturn( + SAMLAnyURIValue::fromString('urn:x-simplesamlphp:validDestination'), + ); $validator = new DestinationMatches($expectedDestination); $result = new Result(); @@ -53,9 +56,11 @@ public function testAResponseIsValidWhenTheDestinationsMatch(): void #[Group('response-validation')] public function testAResponseIsNotValidWhenTheDestinationsAreNotEqual(): void { - $this->response->shouldReceive('getDestination')->once()->andReturn('FOO'); + $this->response->shouldReceive('getDestination')->once()->andReturn( + SAMLAnyURIValue::fromString('urn:x-simplesamlphp:invalidDestination'), + ); $validator = new DestinationMatches( - new Destination('BAR'), + new Destination('urn:x-simplesamlphp:validDestination'), ); $result = new Result(); @@ -64,6 +69,13 @@ public function testAResponseIsNotValidWhenTheDestinationsAreNotEqual(): void $this->assertFalse($result->isValid()); $this->assertCount(1, $errors); - $this->assertEquals('Destination in response "FOO" does not match the expected destination "BAR"', $errors[0]); + $this->assertEquals( + sprintf( + 'Destination in response "%s" does not match the expected destination "%s"', + 'urn:x-simplesamlphp:invalidDestination', + 'urn:x-simplesamlphp:validDestination', + ), + $errors[0], + ); } } diff --git a/tests/SAML2/Response/Validation/ConstraintValidator/IsSuccessfulTest.php b/tests/SAML2/Response/Validation/ConstraintValidator/IsSuccessfulTest.php index 88a51446c..a0dc0a8bb 100644 --- a/tests/SAML2/Response/Validation/ConstraintValidator/IsSuccessfulTest.php +++ b/tests/SAML2/Response/Validation/ConstraintValidator/IsSuccessfulTest.php @@ -12,6 +12,8 @@ use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Response\Validation\ConstraintValidator\IsSuccessful; use SimpleSAML\SAML2\Response\Validation\Result; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\samlp\Response; use SimpleSAML\SAML2\XML\samlp\Status; use SimpleSAML\SAML2\XML\samlp\StatusCode; @@ -58,14 +60,16 @@ public function testAnUnsuccessfulResponseIsNotValidAndGeneratesAProperErrorMess { $responseStatus = new Status( new StatusCode( - C::STATUS_SUCCESS, + SAMLAnyURIValue::fromString(C::STATUS_SUCCESS), [ new StatusCode( - C::STATUS_PREFIX . 'bar', + SAMLAnyURIVAlue::fromString(C::STATUS_PREFIX . 'bar'), ), ], ), - new StatusMessage('this is a test message'), + new StatusMessage( + SAMLStringValue::fromString('this is a test message'), + ), ); $this->response->shouldReceive('isSuccess')->once()->andReturn(false); diff --git a/tests/SAML2/Response/XmlSignatureWrappingTest.php b/tests/SAML2/Response/XmlSignatureWrappingTest.php index f76c8881e..ccf6a4776 100644 --- a/tests/SAML2/Response/XmlSignatureWrappingTest.php +++ b/tests/SAML2/Response/XmlSignatureWrappingTest.php @@ -66,8 +66,10 @@ public function testThatASignatureReferencingAnotherAssertionIsNotValid(): void */ private function getSignedAssertionWithSignatureThatReferencesAnotherAssertion(): Assertion { - $doc = DOMDocumentFactory::fromFile(__DIR__ . '/signedAssertionWithInvalidReferencedId.xml'); - return Assertion::fromXML($doc->firstChild); + $document = DOMDocumentFactory::fromFile(__DIR__ . '/signedAssertionWithInvalidReferencedId.xml'); + /** @var \DOMElement $element */ + $element = $document->firstChild; + return Assertion::fromXML($element); } @@ -77,6 +79,8 @@ private function getSignedAssertionWithSignatureThatReferencesAnotherAssertion() private function getSignedAssertionWithEmbeddedAssertionReferencedInSignature(): Assertion { $document = DOMDocumentFactory::fromFile(__DIR__ . '/signedAssertionReferencedEmbeddedAssertion.xml'); - return Assertion::fromXML($document->firstChild); + /** @var \DOMElement $element */ + $element = $document->firstChild; + return Assertion::fromXML($element); } } diff --git a/tests/SAML2/Signature/ValidatorChainTest.php b/tests/SAML2/Signature/ValidatorChainTest.php index 441e02a2b..8925d3b5d 100644 --- a/tests/SAML2/Signature/ValidatorChainTest.php +++ b/tests/SAML2/Signature/ValidatorChainTest.php @@ -10,12 +10,16 @@ use Psr\Clock\ClockInterface; use Psr\Log\NullLogger; use SimpleSAML\SAML2\Configuration\IdentityProvider; +use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Signature\MissingConfigurationException; use SimpleSAML\SAML2\Signature\ValidatorChain; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\XML\samlp\Response; use SimpleSAML\SAML2\XML\samlp\Status; use SimpleSAML\SAML2\XML\samlp\StatusCode; +use SimpleSAML\XML\Type\IDValue; /** * @package simplesamlphp/saml2 @@ -23,6 +27,9 @@ #[CoversClass(ValidatorChain::class)] final class ValidatorChainTest extends TestCase { + /** @var \SimpleSAML\SAML2\XML\samlp\Response */ + private static Response $response; + /** @var \SimpleSAML\SAML2\Signature\ValidatorChain */ private static ValidatorChain $chain; @@ -36,6 +43,15 @@ public static function setUpBeforeClass(): void { self::$chain = new ValidatorChain(new NullLogger(), []); self::$clock = Utils::getContainer()->getClock(); + self::$response = new Response( + id: IDValue::fromString('abc123'), + status: new Status( + new StatusCode( + SAMLAnyURIValue::fromString(C::STATUS_SUCCESS), + ), + ), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + ); } @@ -49,7 +65,7 @@ public function testIfNoValidatorsCanValidateAnExceptionIsThrown(): void $this->expectException(MissingConfigurationException::class); self::$chain->hasValidSignature( - new Response(new Status(new StatusCode()), self::$clock->now()), + self::$response, new IdentityProvider([]), ); } @@ -65,7 +81,7 @@ public function testAllRegisteredValidatorsShouldBeTried(): void self::$chain->appendValidator(new MockChainedValidator(true, false)); $validationResult = self::$chain->hasValidSignature( - new Response(new Status(new StatusCode()), self::$clock->now()), + self::$response, new IdentityProvider([]), ); $this->assertFalse($validationResult, 'The validation result is not what is expected'); @@ -82,7 +98,7 @@ public function testItUsesTheResultOfTheFirstValidatorThatCanValidate(): void self::$chain->appendValidator(new MockChainedValidator(false, true)); $validationResult = self::$chain->hasValidSignature( - new Response(new Status(new StatusCode()), self::$clock->now()), + self::$response, new IdentityProvider([]), ); $this->assertFalse($validationResult, 'The validation result is not what is expected'); diff --git a/tests/SAML2/Type/AnyURIListValueTest.php b/tests/SAML2/Type/AnyURIListValueTest.php new file mode 100644 index 000000000..e66553f04 --- /dev/null +++ b/tests/SAML2/Type/AnyURIListValueTest.php @@ -0,0 +1,62 @@ +assertTrue($shouldPass); + } catch (ProtocolViolationException | SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * Test the toArray function + */ + public function testToArray(): void + { + $anyURIList = AnyURIListValue::fromString("urn:x-simplesamlphp:namespace urn:x-ssp:ns"); + $this->assertEquals(['urn:x-simplesamlphp:namespace', 'urn:x-ssp:ns'], $anyURIList->toArray()); + } + + + /** + * @return array + */ + public static function provideAnyURIList(): array + { + return [ + 'single' => [true, "urn:x-simplesamlphp:namespace"], + 'multiple' => [true, 'urn:x-simplesamlphp:namespace urn:x-ssp:ns'], + 'normalization' => [true, "urn:x-simplesamlphp:namespace \n urn:x-ssp:ns"], + 'empty' => [false, ''], + ]; + } +} diff --git a/tests/SAML2/Type/AuthnContextComparisonTypeValueTest.php b/tests/SAML2/Type/AuthnContextComparisonTypeValueTest.php new file mode 100644 index 000000000..f7a18dcba --- /dev/null +++ b/tests/SAML2/Type/AuthnContextComparisonTypeValueTest.php @@ -0,0 +1,65 @@ +assertTrue($shouldPass); + } catch (SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * Test helpers + */ + public function testHelpers(): void + { + $x = AuthnContextComparisonTypeValue::fromEnum(AuthnContextComparisonTypeEnum::Exact); + $this->assertEquals(AuthnContextComparisonTypeEnum::Exact, $x->toEnum()); + + $y = AuthnContextComparisonTypeValue::fromString('exact'); + $this->assertEquals(AuthnContextComparisonTypeEnum::Exact, $y->toEnum()); + } + + + /** + * @return array + */ + public static function provideAuthnContextComparison(): array + { + return [ + 'better' => ['better', true], + 'exact' => ['exact', true], + 'maximum' => ['maximum', true], + 'minimum' => ['minimum', true], + 'undefined' => ['undefined', false], + 'empty' => ['', false], + ]; + } +} diff --git a/tests/SAML2/Type/CIDRValueTest.php b/tests/SAML2/Type/CIDRValueTest.php new file mode 100644 index 000000000..5e9466745 --- /dev/null +++ b/tests/SAML2/Type/CIDRValueTest.php @@ -0,0 +1,65 @@ +assertTrue($shouldPass); + } catch (AssertionFailedException | ProtocolViolationException | SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideCIDR(): array + { + return [ + 'ipv4' => [true, '192.168.0.1/32'], + 'ipv6' => [true, '2001:0000:130F:0000:0000:09C0:876A:130B/128'], + 'ipv4 too long' => [false, '192.168.0.1.5/32'], + 'whitespace suffix' => [true, '192.168.1.5/32 '], + 'whitespace prefix' => [true, ' 192.168.1.5/32'], + 'whitespace center' => [false, '192.168. 1.5/32'], + 'ipv6 too long' => [false, '2001:0000:130F:0000:0000:09C0:876A:130B:130F:805B/128'], + 'ipv6 mixed notation' => [false, '805B:2D9D:DC28::FC57:212.200.31.255'], + 'ipv6 shortened notation' => [false, '::ffff:192.1.56.10/96'], + 'ipv6 compressed notation' => [false, '::212.200.31.255'], + 'ipv4 without length' => [false, '192.168.0.1'], + 'ipv6 wihtout length' => [false, '2001:0000:130F:0000:0000:09C0:876A:130B'], + 'ipv4 out of bounds length' => [false, '192.168.0.1/33'], + 'ipv6 out of bounds length' => [false, '2001:0000:130F:0000:0000:09C0:876A:130B/129'], + 'ipv4 out of bounds address' => [false, '256.168.0.1/32'], + 'ipv6 out of bounds address' => [false, '2001:0000:130G:0000:0000:09C0:876A:130B/128'], + ]; + } +} diff --git a/tests/SAML2/Type/DecisionTypeValueTest.php b/tests/SAML2/Type/DecisionTypeValueTest.php new file mode 100644 index 000000000..9da378f15 --- /dev/null +++ b/tests/SAML2/Type/DecisionTypeValueTest.php @@ -0,0 +1,64 @@ +assertTrue($shouldPass); + } catch (SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * Test helpers + */ + public function testHelpers(): void + { + $x = DecisionTypeValue::fromEnum(DecisionTypeEnum::Deny); + $this->assertEquals(DecisionTypeEnum::Deny, $x->toEnum()); + + $y = DecisionTypeValue::fromString('Deny'); + $this->assertEquals(DecisionTypeEnum::Deny, $y->toEnum()); + } + + + /** + * @return array + */ + public static function provideDecisionType(): array + { + return [ + 'deny' => ['Deny', true], + 'indeterminate' => ['Indeterminate', true], + 'permit' => ['Permit', true], + 'undefined' => ['undefined', false], + 'empty' => ['', false], + ]; + } +} diff --git a/tests/SAML2/Type/EntityIDValueTest.php b/tests/SAML2/Type/EntityIDValueTest.php new file mode 100644 index 000000000..2c5b1029c --- /dev/null +++ b/tests/SAML2/Type/EntityIDValueTest.php @@ -0,0 +1,59 @@ +assertTrue($shouldPass); + } catch (ProtocolViolationException | SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideEntityID(): array + { + return [ + 'urn' => [true, 'urn:x-simplesamlphp:phpunit'], + 'same-doc' => [false, '#_53d830ab1be17291a546c95c7f1cdf8d3d23c959e6'], + 'url' => [true, 'https://www.simplesamlphp.org'], + 'diacritical' => [true, 'https://aä.com'], + 'spn' => [true, 'spn:a4cf592f-a64c-46ff-a788-b260f474525b'], + 'typos' => [false, 'https//www.uni.l/en/'], + 'spaces' => [false, 'this is silly'], + 'empty' => [false, ''], + 'azure-common' => [true, 'https://sts.windows.net/{tenantid}/'], + 'too_long' => [false, str_pad('urn:x-simplesamlphp-phpunit:', C::ENTITYID_MAX_LENGTH + 1, 'a')], + ]; + } +} diff --git a/tests/SAML2/Type/ListOfStringsValueTest.php b/tests/SAML2/Type/ListOfStringsValueTest.php new file mode 100644 index 000000000..a679971b5 --- /dev/null +++ b/tests/SAML2/Type/ListOfStringsValueTest.php @@ -0,0 +1,59 @@ +assertTrue($shouldPass); + } catch (SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * Test the toArray function + */ + public function testToArray(): void + { + $listOfStrings = ListOfStringsValue::fromString("foo+bar baz"); + $this->assertEquals(['foo bar', 'baz'], $listOfStrings->toArray()); + } + + + /** + * @return array + */ + public static function provideListOfStrings(): array + { + return [ + 'whitespace collapse' => [true, "foo+bar"], + 'normalization' => [true, 'foo+bar baz'], + ]; + } +} diff --git a/tests/SAML2/Type/SAMLAnyURIValueTest.php b/tests/SAML2/Type/SAMLAnyURIValueTest.php new file mode 100644 index 000000000..65796ffe5 --- /dev/null +++ b/tests/SAML2/Type/SAMLAnyURIValueTest.php @@ -0,0 +1,57 @@ +assertTrue($shouldPass); + } catch (ProtocolViolationException | SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideURI(): array + { + return [ + 'urn' => [true, 'urn:x-simplesamlphp:phpunit'], + 'same-doc' => [false, '#_53d830ab1be17291a546c95c7f1cdf8d3d23c959e6'], + 'url' => [true, 'https://www.simplesamlphp.org'], + 'diacritical' => [true, 'https://aä.com'], + 'spn' => [true, 'spn:a4cf592f-a64c-46ff-a788-b260f474525b'], + 'typos' => [false, 'https//www.uni.l/en/'], + 'spaces' => [false, 'this is silly'], + 'empty' => [false, ''], + 'azure-common' => [true, 'https://sts.windows.net/{tenantid}/'], + ]; + } +} diff --git a/tests/SAML2/Type/SAMLDateTimeValueTest.php b/tests/SAML2/Type/SAMLDateTimeValueTest.php new file mode 100644 index 000000000..78b5f6550 --- /dev/null +++ b/tests/SAML2/Type/SAMLDateTimeValueTest.php @@ -0,0 +1,65 @@ +assertTrue($shouldPass); + } catch (AssertionFailedException | ProtocolViolationException | SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideDateTime(): array + { + return [ + 'valid' => [true, '2001-10-26T21:32:52Z'], + 'invalid with numeric difference' => [false, '2001-10-26T21:32:52+02:00'], + 'invalid with Zulu' => [false, '2001-10-26T19:32:52'], + 'invalid with 00:00 difference' => [false, '2001-10-26T19:32:52+00:00'], + 'valid with negative value' => [true, '-2001-10-26T21:32:52Z'], + 'valid with subseconds' => [true, '2001-10-26T21:32:52.12679Z'], + 'valid with more than four digit year' => [true, '-22001-10-26T21:32:52Z'], + 'valid with sub-seconds' => [true, '2001-10-26T21:32:52.12679Z'], + 'empty' => [false, ''], + 'whitespace collapse' => [true, ' 2001-10-26T21:32:52Z '], + 'missing time' => [false, '2001-10-26'], + 'missing second' => [false, '2001-10-26T21:32'], + 'hour out of range' => [false, '2001-10-26T25:32:52+02:00'], + 'year 0000' => [false, '0000-10-26T25:32:52+02:00'], + 'prefixed zero' => [false, '02001-10-26T25:32:52+02:00'], + 'wrong format' => [false, '01-10-26T21:32'], + ]; + } +} diff --git a/tests/SAML2/Type/SAMLStringValueTest.php b/tests/SAML2/Type/SAMLStringValueTest.php new file mode 100644 index 000000000..f8d380962 --- /dev/null +++ b/tests/SAML2/Type/SAMLStringValueTest.php @@ -0,0 +1,50 @@ +assertTrue($shouldPass); + } catch (ProtocolViolationException | SchemaViolationException $e) { + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideString(): array + { + return [ + 'empty string' => [false, ''], + 'some thing' => [true, 'Snoopy '], + ]; + } +} diff --git a/tests/SAML2/UtilsTest.php b/tests/SAML2/UtilsTest.php index 304f3477c..c064383ef 100644 --- a/tests/SAML2/UtilsTest.php +++ b/tests/SAML2/UtilsTest.php @@ -8,11 +8,15 @@ use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\saml\NameID; use SimpleSAML\SAML2\XML\saml\Subject; use SimpleSAML\SAML2\XML\samlp\AttributeQuery; +use SimpleSAML\XML\Type\IDValue; use function count; @@ -42,13 +46,17 @@ public static function setUpBeforeClass(): void public function testXpQuery(): void { $nameId_before = new NameID( - 'NameIDValue', - 'urn:x-simplesamlphp:namequalifier', - 'urn:x-simplesamlphp:spnamequalifier', - C::NAMEID_TRANSIENT, + SAMLStringValue::fromString('NameIDValue'), + SAMLStringValue::fromString('urn:x-simplesamlphp:namequalifier'), + SAMLStringValue::fromString('urn:x-simplesamlphp:spnamequalifier'), + SAMLAnyURIValue::fromString(C::NAMEID_TRANSIENT), ); - $aq = new AttributeQuery(new Subject($nameId_before), self::$clock->now()); + $aq = new AttributeQuery( + id: IDValue::fromString('abc123'), + subject: new Subject($nameId_before), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + ); $xml = $aq->toXML(); diff --git a/tests/SAML2/XML/alg/DigestMethodTest.php b/tests/SAML2/XML/alg/DigestMethodTest.php index 117f8d9ca..5640374ce 100644 --- a/tests/SAML2/XML/alg/DigestMethodTest.php +++ b/tests/SAML2/XML/alg/DigestMethodTest.php @@ -7,14 +7,15 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\alg\AbstractAlgElement; use SimpleSAML\SAML2\XML\alg\DigestMethod; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\Chunk; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; use function dirname; use function strval; @@ -50,7 +51,7 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $digestMethod = new DigestMethod( - C::DIGEST_SHA256, + SAMLAnyURIValue::fromString(C::DIGEST_SHA256), [ new Chunk(DOMDocumentFactory::fromString( 'Some', diff --git a/tests/SAML2/XML/alg/SigningMethodTest.php b/tests/SAML2/XML/alg/SigningMethodTest.php index 9bc124c0a..6e9c1de42 100644 --- a/tests/SAML2/XML/alg/SigningMethodTest.php +++ b/tests/SAML2/XML/alg/SigningMethodTest.php @@ -7,14 +7,16 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\alg\AbstractAlgElement; use SimpleSAML\SAML2\XML\alg\SigningMethod; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\Chunk; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Type\PositiveIntegerValue; use function dirname; use function strval; @@ -50,9 +52,9 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $signingMethod = new SigningMethod( - C::SIG_RSA_SHA256, - 1024, - 4096, + SAMLAnyURIValue::fromString(C::SIG_RSA_SHA256), + PositiveIntegerValue::fromString('1024'), + PositiveIntegerValue::fromString('4096'), [ new Chunk(DOMDocumentFactory::fromString( 'Some', diff --git a/tests/SAML2/XML/ecp/RelayStateTest.php b/tests/SAML2/XML/ecp/RelayStateTest.php index a6032d3a9..8ef12e4a2 100644 --- a/tests/SAML2/XML/ecp/RelayStateTest.php +++ b/tests/SAML2/XML/ecp/RelayStateTest.php @@ -7,13 +7,14 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\ecp\AbstractEcpElement; use SimpleSAML\SAML2\XML\ecp\RelayState; -use SimpleSAML\SOAP\Constants as SOAP; +use SimpleSAML\SOAP11\Constants as SOAP; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; use function dirname; use function strval; @@ -46,7 +47,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $relayState = new RelayState('AGDY854379dskssda'); + $relayState = new RelayState( + SAMLStringValue::fromString('AGDY854379dskssda'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), @@ -60,7 +63,7 @@ public function testMarshalling(): void public function testUnmarshallingWithMissingMustUnderstandThrowsException(): void { $document = clone self::$xmlRepresentation->documentElement; - $document->removeAttributeNS(SOAP::NS_SOAP_ENV_11, 'mustUnderstand'); + $document->removeAttributeNS(SOAP::NS_SOAP_ENV, 'mustUnderstand'); $this->expectException(MissingAttributeException::class); $this->expectExceptionMessage('Missing env:mustUnderstand attribute in .'); @@ -74,7 +77,7 @@ public function testUnmarshallingWithMissingMustUnderstandThrowsException(): voi public function testUnmarshallingWithMissingActorThrowsException(): void { $document = clone self::$xmlRepresentation->documentElement; - $document->removeAttributeNS(SOAP::NS_SOAP_ENV_11, 'actor'); + $document->removeAttributeNS(SOAP::NS_SOAP_ENV, 'actor'); $this->expectException(MissingAttributeException::class); $this->expectExceptionMessage('Missing env:actor attribute in .'); diff --git a/tests/SAML2/XML/ecp/RequestAuthenticatedTest.php b/tests/SAML2/XML/ecp/RequestAuthenticatedTest.php index 31c8aa9b9..720b3c449 100644 --- a/tests/SAML2/XML/ecp/RequestAuthenticatedTest.php +++ b/tests/SAML2/XML/ecp/RequestAuthenticatedTest.php @@ -9,11 +9,12 @@ use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\XML\ecp\AbstractEcpElement; use SimpleSAML\SAML2\XML\ecp\RequestAuthenticated; -use SimpleSAML\SOAP\Constants as C; +use SimpleSAML\SOAP11\Constants as C; +use SimpleSAML\SOAP11\Type\MustUnderstandValue; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; use function dirname; use function strval; @@ -46,7 +47,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $ra = new RequestAuthenticated(false); + $ra = new RequestAuthenticated( + MustUnderstandValue::fromBoolean(false), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), @@ -60,7 +63,7 @@ public function testMarshalling(): void public function testUnmarshallingWithMissingActorThrowsException(): void { $document = clone self::$xmlRepresentation->documentElement; - $document->removeAttributeNS(C::NS_SOAP_ENV_11, 'actor'); + $document->removeAttributeNS(C::NS_SOAP_ENV, 'actor'); $this->expectException(MissingAttributeException::class); $this->expectExceptionMessage('Missing env:actor attribute in .'); diff --git a/tests/SAML2/XML/ecp/RequestTest.php b/tests/SAML2/XML/ecp/RequestTest.php index ebce837d0..f88ba0f4f 100644 --- a/tests/SAML2/XML/ecp/RequestTest.php +++ b/tests/SAML2/XML/ecp/RequestTest.php @@ -7,17 +7,21 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\ecp\AbstractEcpElement; use SimpleSAML\SAML2\XML\ecp\Request; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\samlp\GetComplete; use SimpleSAML\SAML2\XML\samlp\IDPEntry; use SimpleSAML\SAML2\XML\samlp\IDPList; -use SimpleSAML\SOAP\Constants as SOAP; +use SimpleSAML\SOAP11\Constants as SOAP; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Type\BooleanValue; use function dirname; use function strval; @@ -51,18 +55,33 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $issuer = new Issuer( - 'urn:x-simplesamlphp:issuer', - 'urn:x-simplesamlphp:namequalifier', - 'urn:x-simplesamlphp:spnamequalifier', - 'urn:the:format', - 'TheSPProvidedID', + SAMLStringValue::fromString('urn:x-simplesamlphp:issuer'), + SAMLStringValue::fromString('urn:x-simplesamlphp:namequalifier'), + SAMLStringValue::fromString('urn:x-simplesamlphp:spnamequalifier'), + SAMLAnyURIValue::fromString('urn:the:format'), + SAMLStringValue::fromString('TheSPProvidedID'), + ); + $entry1 = new IDPEntry( + EntityIDValue::fromString('urn:some:requester1'), + SAMLStringValue::fromString('testName1'), + SAMLAnyURIValue::fromString('urn:test:testLoc1'), + ); + $entry2 = new IDPEntry( + EntityIDValue::fromString('urn:some:requester2'), + SAMLStringValue::fromString('testName2'), + SAMLAnyURIValue::fromString('urn:test:testLoc2'), + ); + $getComplete = new GetComplete( + SAMLAnyURIValue::fromString('https://some/location'), ); - $entry1 = new IDPEntry('urn:some:requester1', 'testName1', 'urn:test:testLoc1'); - $entry2 = new IDPEntry('urn:some:requester2', 'testName2', 'urn:test:testLoc2'); - $getComplete = new GetComplete('https://some/location'); $idpList = new IDPList([$entry1, $entry2], $getComplete); - $request = new Request($issuer, $idpList, 'PHPUnit', true); + $request = new Request( + $issuer, + $idpList, + SAMLStringValue::fromString('PHPUnit'), + BooleanValue::fromBoolean(true), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), @@ -76,7 +95,7 @@ public function testMarshalling(): void public function testUnmarshallingWithMissingMustUnderstandThrowsException(): void { $document = clone self::$xmlRepresentation->documentElement; - $document->removeAttributeNS(SOAP::NS_SOAP_ENV_11, 'mustUnderstand'); + $document->removeAttributeNS(SOAP::NS_SOAP_ENV, 'mustUnderstand'); $this->expectException(MissingAttributeException::class); $this->expectExceptionMessage('Missing env:mustUnderstand attribute in .'); @@ -90,7 +109,7 @@ public function testUnmarshallingWithMissingMustUnderstandThrowsException(): voi public function testUnmarshallingWithMissingActorThrowsException(): void { $document = clone self::$xmlRepresentation->documentElement; - $document->removeAttributeNS(SOAP::NS_SOAP_ENV_11, 'actor'); + $document->removeAttributeNS(SOAP::NS_SOAP_ENV, 'actor'); $this->expectException(MissingAttributeException::class); $this->expectExceptionMessage('Missing env:actor attribute in .'); diff --git a/tests/SAML2/XML/ecp/ResponseTest.php b/tests/SAML2/XML/ecp/ResponseTest.php index bfc0d43a4..d02db909d 100644 --- a/tests/SAML2/XML/ecp/ResponseTest.php +++ b/tests/SAML2/XML/ecp/ResponseTest.php @@ -9,14 +9,14 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\ecp\AbstractEcpElement; use SimpleSAML\SAML2\XML\ecp\Response; -use SimpleSAML\SOAP\Constants as SOAP; +use SimpleSAML\SOAP11\Constants as SOAP; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; use function dirname; use function strval; @@ -49,7 +49,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $response = new Response('https://example.com/ACS'); + $response = new Response( + SAMLAnyURIValue::fromString('https://example.com/ACS'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), @@ -65,7 +67,9 @@ public function testToXMLResponseAppended(): void $doc = new DOMDocument('1.0', 'UTF-8'); $element = $doc->createElement('Foobar'); - $response = new Response('https://example.com/ACS'); + $response = new Response( + SAMLAnyURIValue::fromString('https://example.com/ACS'), + ); $return = $response->toXML($element); $elements = $element->getElementsByTagNameNS(C::NS_ECP, 'Response'); @@ -75,22 +79,12 @@ public function testToXMLResponseAppended(): void } - /** - */ - public function testInvalidACSThrowsException(): void - { - $this->expectException(ProtocolViolationException::class); - - new Response('some non-url'); - } - - /** */ public function testUnmarshallingWithMissingMustUnderstandThrowsException(): void { $document = clone self::$xmlRepresentation->documentElement; - $document->removeAttributeNS(SOAP::NS_SOAP_ENV_11, 'mustUnderstand'); + $document->removeAttributeNS(SOAP::NS_SOAP_ENV, 'mustUnderstand'); $this->expectException(MissingAttributeException::class); $this->expectExceptionMessage('Missing env:mustUnderstand attribute in .'); @@ -104,7 +98,7 @@ public function testUnmarshallingWithMissingMustUnderstandThrowsException(): voi public function testUnmarshallingWithMissingActorThrowsException(): void { $document = clone self::$xmlRepresentation->documentElement; - $document->removeAttributeNS(SOAP::NS_SOAP_ENV_11, 'actor'); + $document->removeAttributeNS(SOAP::NS_SOAP_ENV, 'actor'); $this->expectException(MissingAttributeException::class); $this->expectExceptionMessage('Missing env:actor attribute in .'); diff --git a/tests/SAML2/XML/ecp/SubjectConfirmationTest.php b/tests/SAML2/XML/ecp/SubjectConfirmationTest.php index 2f49ff981..7b6fd9fd1 100644 --- a/tests/SAML2/XML/ecp/SubjectConfirmationTest.php +++ b/tests/SAML2/XML/ecp/SubjectConfirmationTest.php @@ -4,21 +4,26 @@ namespace SimpleSAML\Test\SAML2\XML\ecp; -use DateTimeImmutable; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\ecp\AbstractEcpElement; use SimpleSAML\SAML2\XML\ecp\SubjectConfirmation; use SimpleSAML\SAML2\XML\saml\SubjectConfirmationData; -use SimpleSAML\SOAP\Constants as SOAP; +use SimpleSAML\SOAP11\Constants as SOAP; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\Attribute as XMLAttribute; use SimpleSAML\XML\Chunk; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Type\NCNameValue; +use SimpleSAML\XMLSchema\Type\StringValue; use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; use SimpleSAML\XMLSecurity\XML\ds\KeyName; @@ -55,23 +60,38 @@ public function testMarshalling(): void { $arbitrary = DOMDocumentFactory::fromString('Arbitrary Element'); - $attr1 = new XMLAttribute('urn:test:something', 'test', 'attr1', 'testval1'); - $attr2 = new XMLAttribute('urn:test:something', 'test', 'attr2', 'testval2'); + $attr1 = new XMLAttribute( + 'urn:test:something', + 'test', + 'attr1', + SAMLStringValue::fromString('testval1'), + ); + $attr2 = new XMLAttribute( + 'urn:test:something', + 'test', + 'attr2', + SAMLStringValue::fromString('testval2'), + ); $subjectConfirmationData = new SubjectConfirmationData( - new DateTimeImmutable('2001-04-19T04:25:21Z'), - new DateTimeImmutable('2009-02-13T23:31:30Z'), - C::ENTITY_SP, - 'SomeRequestID', - '127.0.0.1', + SAMLDateTimeValue::fromString('2001-04-19T04:25:21Z'), + SAMLDateTimeValue::fromString('2009-02-13T23:31:30Z'), + EntityIDValue::fromString(C::ENTITY_SP), + NCNameValue::fromString('SomeRequestID'), + SAMLStringValue::fromString('127.0.0.1'), [ - new KeyInfo([new KeyName('SomeKey')]), + new KeyInfo([ + new KeyName(StringValue::fromString('SomeKey')), + ]), new Chunk($arbitrary->documentElement), ], [$attr1, $attr2], ); - $subjectConfirmation = new SubjectConfirmation(C::CM_BEARER, $subjectConfirmationData); + $subjectConfirmation = new SubjectConfirmation( + SAMLAnyURIValue::fromString(C::CM_BEARER), + $subjectConfirmationData, + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), @@ -85,7 +105,7 @@ public function testMarshalling(): void public function testUnmarshallingWithMissingMustUnderstandThrowsException(): void { $document = clone self::$xmlRepresentation->documentElement; - $document->removeAttributeNS(SOAP::NS_SOAP_ENV_11, 'mustUnderstand'); + $document->removeAttributeNS(SOAP::NS_SOAP_ENV, 'mustUnderstand'); $this->expectException(MissingAttributeException::class); $this->expectExceptionMessage('Missing env:mustUnderstand attribute in .'); @@ -99,7 +119,7 @@ public function testUnmarshallingWithMissingMustUnderstandThrowsException(): voi public function testUnmarshallingWithMissingActorThrowsException(): void { $document = clone self::$xmlRepresentation->documentElement; - $document->removeAttributeNS(SOAP::NS_SOAP_ENV_11, 'actor'); + $document->removeAttributeNS(SOAP::NS_SOAP_ENV, 'actor'); $this->expectException(MissingAttributeException::class); $this->expectExceptionMessage('Missing env:actor attribute in .'); diff --git a/tests/SAML2/XML/emd/RepublishRequestTest.php b/tests/SAML2/XML/emd/RepublishRequestTest.php index 279f8f7a8..0f0a94567 100644 --- a/tests/SAML2/XML/emd/RepublishRequestTest.php +++ b/tests/SAML2/XML/emd/RepublishRequestTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\emd\AbstractEmdElement; use SimpleSAML\SAML2\XML\emd\RepublishRequest; use SimpleSAML\SAML2\XML\emd\RepublishTarget; @@ -55,7 +56,9 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $republishRequest = new RepublishRequest( - new RepublishTarget('http://edugain.org/'), + new RepublishTarget( + SAMLAnyURIValue::fromString('http://edugain.org/'), + ), ); $this->assertEquals( diff --git a/tests/SAML2/XML/emd/RepublishTargetTest.php b/tests/SAML2/XML/emd/RepublishTargetTest.php index 2906a500e..0ac09b067 100644 --- a/tests/SAML2/XML/emd/RepublishTargetTest.php +++ b/tests/SAML2/XML/emd/RepublishTargetTest.php @@ -8,6 +8,7 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\emd\AbstractEmdElement; use SimpleSAML\SAML2\XML\emd\RepublishTarget; use SimpleSAML\XML\DOMDocumentFactory; @@ -46,7 +47,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $republishTarget = new RepublishTarget('http://edugain.org/'); + $republishTarget = new RepublishTarget( + SAMLAnyURIValue::fromString('http://edugain.org/'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), @@ -64,6 +67,6 @@ public function testMarshallingIncorrectValueThrowsException(): void 'Expected a value identical to "http://edugain.org/". Got: "http://example.org/"', ); - new RepublishTarget('http://example.org/'); + new RepublishTarget(SAMLAnyURIValue::fromString('http://example.org/')); } } diff --git a/tests/SAML2/XML/idpdisc/DiscoveryResponseTest.php b/tests/SAML2/XML/idpdisc/DiscoveryResponseTest.php index f36410109..8ca9bdd69 100644 --- a/tests/SAML2/XML/idpdisc/DiscoveryResponseTest.php +++ b/tests/SAML2/XML/idpdisc/DiscoveryResponseTest.php @@ -8,6 +8,8 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\idpdisc\DiscoveryResponse; use SimpleSAML\SAML2\XML\md\AbstractIndexedEndpointType; use SimpleSAML\SAML2\XML\md\AbstractMdElement; @@ -18,6 +20,8 @@ use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\BooleanValue; +use SimpleSAML\XMLSchema\Type\UnsignedShortValue; use function dirname; use function strval; @@ -51,7 +55,12 @@ public static function setUpBeforeClass(): void { self::$testedClass = DiscoveryResponse::class; - self::$attr = new XMLAttribute('urn:x-simplesamlphp:namespace', 'ssp', 'attr1', 'testval1'); + self::$attr = new XMLAttribute( + 'urn:x-simplesamlphp:namespace', + 'ssp', + 'attr1', + SAMLStringValue::fromString('testval1'), + ); self::$ext = new Chunk(DOMDocumentFactory::fromString( 'SomeExtension', @@ -82,10 +91,10 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $discoResponse = new DiscoveryResponse( - 43, - C::BINDING_IDPDISC, - C::LOCATION_A, - false, + UnsignedShortValue::fromInteger(43), + SAMLAnyURIValue::fromString(C::BINDING_IDPDISC), + SAMLAnyURIValue::fromString(C::LOCATION_A), + BooleanValue::fromBoolean(false), null, [self::$ext], [self::$attr], @@ -108,11 +117,11 @@ public function testMarshallingWithResponseLocation(): void 'The \'ResponseLocation\' attribute must be omitted for idpdisc:DiscoveryResponse.', ); new DiscoveryResponse( - 42, - C::BINDING_IDPDISC, - C::LOCATION_A, - false, - 'https://response.location/', + UnsignedShortValue::fromInteger(42), + SAMLAnyURIValue::fromString(C::BINDING_IDPDISC), + SAMLAnyURIValue::fromString(C::LOCATION_A), + BooleanValue::fromBoolean(false), + SAMLAnyURIValue::fromString('https://response.location/'), ); } diff --git a/tests/SAML2/XML/init/RequestInitiatorTest.php b/tests/SAML2/XML/init/RequestInitiatorTest.php index f96b9642a..94985f8d7 100644 --- a/tests/SAML2/XML/init/RequestInitiatorTest.php +++ b/tests/SAML2/XML/init/RequestInitiatorTest.php @@ -8,6 +8,8 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\init\RequestInitiator; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\Test\SAML2\Constants as C; @@ -62,8 +64,13 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $attr = new XMLAttribute(C::NAMESPACE, 'test', 'attr', 'value'); - $requestInitiator = new RequestInitiator(C::LOCATION_A, C::LOCATION_B, [self::$ext], [$attr]); + $attr = new XMLAttribute(C::NAMESPACE, 'test', 'attr', SAMLStringValue::fromString('value')); + $requestInitiator = new RequestInitiator( + SAMLAnyURIValue::fromString(C::LOCATION_A), + SAMLAnyURIValue::fromString(C::LOCATION_B), + [self::$ext], + [$attr], + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/md/AbstractLocalizedNameTest.php b/tests/SAML2/XML/md/AbstractLocalizedNameTest.php index bf915ffca..0fe2181d0 100644 --- a/tests/SAML2/XML/md/AbstractLocalizedNameTest.php +++ b/tests/SAML2/XML/md/AbstractLocalizedNameTest.php @@ -14,7 +14,8 @@ use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\ServiceDescription; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Exception\SchemaViolationException; use function dirname; @@ -43,33 +44,6 @@ public static function setUpBeforeClass(): void } - // test marshalling - - - /** - * Test that creating a ServiceDescription from scratch with an empty language fails. - */ - public function testMarshallingWithEmptyLang(): void - { - $this->expectException(ProtocolViolationException::class); - $this->expectExceptionMessage('Expected a non-whitespace string. Got: ""'); - - new ServiceDescription('', 'Academic Journals R US and only us'); - } - - - /** - * Test that creating a ServiceDescription from scratch with an empty value works. - */ - public function testMarshallingWithEmptyValue(): void - { - $this->expectException(ProtocolViolationException::class); - $this->expectExceptionMessage('Expected a non-whitespace string. Got: ""'); - - new ServiceDescription('en', ''); - } - - // test unmarshalling @@ -96,8 +70,8 @@ public function testUnmarshallingWithEmptyLang(): void $xmlRepresentation = clone self::$xmlRepresentation; $xmlRepresentation->documentElement->setAttributeNS(C::NS_XML, 'lang', ''); - $this->expectException(ProtocolViolationException::class); - $this->expectExceptionMessage('Expected a non-whitespace string. Got: ""'); + $this->expectException(SchemaViolationException::class); + $this->expectExceptionMessage('"" is not a valid xs:language'); ServiceDescription::fromXML($xmlRepresentation->documentElement); } @@ -112,7 +86,7 @@ public function testUnmarshallingWithEmptyValue(): void $xmlRepresentation->documentElement->textContent = ''; $this->expectException(ProtocolViolationException::class); - $this->expectExceptionMessage('Expected a non-whitespace string. Got: ""'); + $this->expectExceptionMessage('"" is not a SAML2.0-compliant string'); ServiceDescription::fromXML($xmlRepresentation->documentElement); } diff --git a/tests/SAML2/XML/md/AdditionalMetadataLocationTest.php b/tests/SAML2/XML/md/AdditionalMetadataLocationTest.php index 5d87eb259..0fa4cf06c 100644 --- a/tests/SAML2/XML/md/AdditionalMetadataLocationTest.php +++ b/tests/SAML2/XML/md/AdditionalMetadataLocationTest.php @@ -7,14 +7,14 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\AdditionalMetadataLocation; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; use function dirname; use function strval; @@ -53,7 +53,10 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $additionalMetadataLocation = new AdditionalMetadataLocation(C::NAMESPACE, C::LOCATION_A); + $additionalMetadataLocation = new AdditionalMetadataLocation( + SAMLAnyURIValue::fromString(C::NAMESPACE), + SAMLAnyURIValue::fromString(C::LOCATION_A), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), @@ -62,16 +65,6 @@ public function testMarshalling(): void } - /** - * Test that creating an AdditionalMetadataLocation from scratch with an empty namespace fails. - */ - public function testMarshallingWithEmptyNamespace(): void - { - $this->expectException(ProtocolViolationException::class); - new AdditionalMetadataLocation('', C::LOCATION_A); - } - - // test unmarshalling diff --git a/tests/SAML2/XML/md/AffiliateMemberTest.php b/tests/SAML2/XML/md/AffiliateMemberTest.php index 406358773..9edf811ab 100644 --- a/tests/SAML2/XML/md/AffiliateMemberTest.php +++ b/tests/SAML2/XML/md/AffiliateMemberTest.php @@ -7,8 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\EntityIDValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\AffiliateMember; use SimpleSAML\XML\DOMDocumentFactory; @@ -16,8 +15,6 @@ use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; use function dirname; -use function sprintf; -use function str_pad; use function strval; /** @@ -54,34 +51,13 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $affiliateMember = new AffiliateMember('https://some.entity.org/id'); + $affiliateMember = new AffiliateMember( + EntityIDValue::fromString('https://some.entity.org/id'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), strval($affiliateMember), ); } - - - /** - */ - public function testMarshallingEmptyThrowsException(): void - { - $this->expectException(ProtocolViolationException::class); - - new AffiliateMember(''); - } - - - /** - */ - public function testMarshallingTooLongContentThrowsException(): void - { - $this->expectException(ProtocolViolationException::class); - $this->expectExceptionMessage( - sprintf('An entityID cannot be longer than %d characters.', C::ENTITYID_MAX_LENGTH), - ); - - new AffiliateMember(str_pad('https://some.entity.org/id', C::ENTITYID_MAX_LENGTH + 1, 'a')); - } } diff --git a/tests/SAML2/XML/md/AffiliationDescriptorTest.php b/tests/SAML2/XML/md/AffiliationDescriptorTest.php index 433de1a0e..6d889a28e 100644 --- a/tests/SAML2/XML/md/AffiliationDescriptorTest.php +++ b/tests/SAML2/XML/md/AffiliationDescriptorTest.php @@ -4,24 +4,29 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use DateTimeImmutable; use Exception; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\KeyTypesValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\AbstractMetadataDocument; use SimpleSAML\SAML2\XML\md\AbstractSignedMdElement; use SimpleSAML\SAML2\XML\md\AffiliateMember; use SimpleSAML\SAML2\XML\md\AffiliationDescriptor; use SimpleSAML\SAML2\XML\md\KeyDescriptor; +use SimpleSAML\SAML2\XML\md\KeyTypesEnum; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\Attribute as XMLAttribute; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Type\DurationValue; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; use SimpleSAML\XMLSecurity\XML\ds\KeyName; @@ -67,22 +72,33 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $affiliationDescriptor = new AffiliationDescriptor( - affiliationOwnerId: C::ENTITY_IDP, - affiliateMember: [new AffiliateMember(C::ENTITY_SP), new AffiliateMember(C::ENTITY_OTHER)], - ID: 'TheID', - validUntil: new DateTimeImmutable('2009-02-13T23:31:30Z'), - cacheDuration: 'PT5000S', + affiliationOwnerId: EntityIDValue::fromString(C::ENTITY_IDP), + affiliateMember: [ + new AffiliateMember( + EntityIDValue::fromString(C::ENTITY_SP), + ), + new AffiliateMember( + EntityIDValue::fromString(C::ENTITY_OTHER), + ), + ], + ID: IDValue::fromString('TheID'), + validUntil: SAMLDateTimeValue::fromString('2009-02-13T23:31:30Z'), + cacheDuration: DurationValue::fromString('PT5000S'), keyDescriptor: [ new KeyDescriptor( new KeyInfo( [ - new KeyName('IdentityProvider.com SSO Key'), + new KeyName( + SAMLStringValue::fromString('IdentityProvider.com SSO Key'), + ), ], ), - 'signing', + KeyTypesValue::fromEnum(KeyTypesEnum::SIGNING), ), ], - namespacedAttribute: [new XMLAttribute(C::NAMESPACE, 'ssp', 'attr1', 'value1')], + namespacedAttribute: [ + new XMLAttribute(C::NAMESPACE, 'ssp', 'attr1', SAMLStringValue::fromString('value1')), + ], ); $this->assertEquals( @@ -92,19 +108,6 @@ public function testMarshalling(): void } - /** - * Test that creating an AffiliationDescriptor with an empty owner ID fails. - */ - public function testMarhsallingWithEmptyOwnerID(): void - { - $this->expectException(ProtocolViolationException::class); - new AffiliationDescriptor( - affiliationOwnerId: '', - affiliateMember: [new AffiliateMember(C::ENTITY_SP), new AffiliateMember(C::ENTITY_OTHER)], - ); - } - - /** * Test that creating an AffiliationDescriptor with an empty list of members fails. */ @@ -113,7 +116,7 @@ public function testMarshallingWithEmptyMemberList(): void $this->expectException(Exception::class); $this->expectExceptionMessage('List of affiliated members must not be empty.'); new AffiliationDescriptor( - affiliationOwnerId: C::ENTITY_IDP, + affiliationOwnerId: EntityIDValue::fromString(C::ENTITY_IDP), affiliateMember: [], ); } diff --git a/tests/SAML2/XML/md/ArtifactResolutionServiceTest.php b/tests/SAML2/XML/md/ArtifactResolutionServiceTest.php index b13041b99..e0d5e2038 100644 --- a/tests/SAML2/XML/md/ArtifactResolutionServiceTest.php +++ b/tests/SAML2/XML/md/ArtifactResolutionServiceTest.php @@ -8,6 +8,7 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\md\AbstractIndexedEndpointType; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\ArtifactResolutionService; @@ -18,6 +19,9 @@ use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\BooleanValue; +use SimpleSAML\XMLSchema\Type\StringValue; +use SimpleSAML\XMLSchema\Type\UnsignedShortValue; use function array_merge; use function dirname; @@ -54,7 +58,12 @@ public static function setUpBeforeClass(): void 'SomeExtension', )->documentElement); - self::$attr = new XMLAttribute('urn:x-simplesamlphp:namespace', 'ssp', 'attr1', 'testval1'); + self::$attr = new XMLAttribute( + 'urn:x-simplesamlphp:namespace', + 'ssp', + 'attr1', + StringValue::fromString('testval1'), + ); self::$testedClass = ArtifactResolutionService::class; @@ -82,10 +91,10 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $ars = new ArtifactResolutionService( - 42, - C::BINDING_HTTP_ARTIFACT, - 'https://simplesamlphp.org/some/endpoint', - false, + UnsignedShortValue::fromInteger(42), + SAMLAnyURIValue::fromString(C::BINDING_HTTP_ARTIFACT), + SAMLAnyURIValue::fromString('https://simplesamlphp.org/some/endpoint'), + BooleanValue::fromBoolean(false), null, [self::$ext], [self::$attr], @@ -107,7 +116,13 @@ public function testMarshallingWithResponseLocation(): void $this->expectExceptionMessage( 'The \'ResponseLocation\' attribute must be omitted for md:ArtifactResolutionService.', ); - new ArtifactResolutionService(42, C::BINDING_HTTP_ARTIFACT, C::LOCATION_A, false, 'https://response.location/'); + new ArtifactResolutionService( + UnsignedShortValue::fromInteger(42), + SAMLAnyURIValue::fromString(C::BINDING_HTTP_ARTIFACT), + SAMLAnyURIValue::fromString(C::LOCATION_A), + BooleanValue::fromBoolean(false), + SAMLAnyURIValue::fromString('https://response.location/'), + ); } diff --git a/tests/SAML2/XML/md/AssertionConsumerServiceTest.php b/tests/SAML2/XML/md/AssertionConsumerServiceTest.php index f130a1e52..271350de0 100644 --- a/tests/SAML2/XML/md/AssertionConsumerServiceTest.php +++ b/tests/SAML2/XML/md/AssertionConsumerServiceTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\md\AbstractIndexedEndpointType; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\AssertionConsumerService; @@ -17,6 +18,9 @@ use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\BooleanValue; +use SimpleSAML\XMLSchema\Type\StringValue; +use SimpleSAML\XMLSchema\Type\UnsignedShortValue; use function dirname; use function strval; @@ -52,7 +56,12 @@ public static function setUpBeforeClass(): void 'SomeExtension', )->documentElement); - self::$attr = new XMLAttribute('urn:x-simplesamlphp:namespace', 'ssp', 'attr1', 'testval1'); + self::$attr = new XMLAttribute( + 'urn:x-simplesamlphp:namespace', + 'ssp', + 'attr1', + StringValue::fromString('testval1'), + ); self::$testedClass = AssertionConsumerService::class; @@ -81,11 +90,11 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $idxep = new AssertionConsumerService( - 42, - C::BINDING_HTTP_POST, - C::LOCATION_A, - false, - 'https://foo.bar/', + UnsignedShortValue::fromInteger(42), + SAMLAnyURIValue::fromString(C::BINDING_HTTP_POST), + SAMLAnyURIValue::fromString(C::LOCATION_A), + BooleanValue::fromBoolean(false), + SAMLAnyURIValue::fromString('https://foo.bar/'), [self::$ext], [self::$attr], ); diff --git a/tests/SAML2/XML/md/AttributeAuthorityDescriptorTest.php b/tests/SAML2/XML/md/AttributeAuthorityDescriptorTest.php index e927016a1..14802714c 100644 --- a/tests/SAML2/XML/md/AttributeAuthorityDescriptorTest.php +++ b/tests/SAML2/XML/md/AttributeAuthorityDescriptorTest.php @@ -4,12 +4,13 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use Exception; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\AnyURIListValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\AbstractMetadataDocument; use SimpleSAML\SAML2\XML\md\AbstractRoleDescriptor; @@ -26,6 +27,8 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -68,13 +71,13 @@ public static function setUpBeforeClass(): void ); self::$as = new AttributeService( - C::BINDING_SOAP, - "https://IdentityProvider.com/SAML/AA/SOAP", + SAMLAnyURIValue::fromString(C::BINDING_SOAP), + SAMLAnyURIValue::fromString('https://IdentityProvider.com/SAML/AA/SOAP'), ); self::$aidrs = new AssertionIDRequestService( - C::BINDING_URI, - "https://IdentityProvider.com/SAML/AA/URI", + SAMLAnyURIValue::fromString(C::BINDING_URI), + SAMLAnyURIValue::fromString('https://IdentityProvider.com/SAML/AA/URI'), ); } @@ -88,15 +91,15 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $attr1 = new Attribute( - "urn:oid:1.3.6.1.4.1.5923.1.1.1.6", - C::NAMEFORMAT_URI, - "eduPersonPrincipalName", + SAMLStringValue::fromString('urn:oid:1.3.6.1.4.1.5923.1.1.1.6'), + SAMLAnyURIValue::fromString(C::NAMEFORMAT_URI), + SAMLStringValue::fromString("eduPersonPrincipalName"), ); $attr2 = new Attribute( - "urn:oid:1.3.6.1.4.1.5923.1.1.1.1", - C::NAMEFORMAT_URI, - 'eduPersonAffiliation', + SAMLStringValue::fromString('urn:oid:1.3.6.1.4.1.5923.1.1.1.1'), + SAMLAnyURIValue::fromString(C::NAMEFORMAT_URI), + SAMLStringValue::fromString('eduPersonAffiliation'), [ new AttributeValue('member'), new AttributeValue('student'), @@ -107,19 +110,29 @@ public function testMarshalling(): void ); $aad = new AttributeAuthorityDescriptor( [self::$as], - [C::NS_SAMLP], + AnyURIListValue::fromString(C::NS_SAMLP), [self::$aidrs], [ - new NameIDFormat(C::NAMEID_X509_SUBJECT_NAME), - new NameIDFormat(C::NAMEID_PERSISTENT), - new NameIDFormat(C::NAMEID_TRANSIENT), + new NameIDFormat( + SAMLAnyURIValue::fromString(C::NAMEID_X509_SUBJECT_NAME), + ), + new NameIDFormat( + SAMLAnyURIValue::fromString(C::NAMEID_PERSISTENT), + ), + new NameIDFormat( + SAMLAnyURIValue::fromString(C::NAMEID_TRANSIENT), + ), ], [ - new AttributeProfile(C::PROFILE_1), - new AttributeProfile(C::PROFILE_2), + new AttributeProfile( + SAMLAnyURIValue::fromString(C::PROFILE_1), + ), + new AttributeProfile( + SAMLAnyURIValue::fromString(C::PROFILE_2), + ), ], [$attr1, $attr2], - 'phpunit', + IDValue::fromString('phpunit'), ); $this->assertEquals( @@ -129,26 +142,13 @@ public function testMarshalling(): void } - /** - * Test that creating an AttributeAuthorityDescriptor with no supported protocols fails. - */ - public function testMarshallingWithoutSupportedProtocols(): void - { - $this->expectException(Exception::class); - $this->expectExceptionMessage( - 'At least one protocol must be supported by this md:AttributeAuthorityDescriptor.', - ); - new AttributeAuthorityDescriptor([self::$as], []); - } - - /** * Test that creating an AttributeAuthorityDescriptor with an empty supported protocol fails. */ public function testMarshallingWithEmptySupportedProtocols(): void { - $this->expectException(AssertionFailedException::class); - new AttributeAuthorityDescriptor([self::$as], []); + $this->expectException(ProtocolViolationException::class); + new AttributeAuthorityDescriptor([self::$as], AnyURIListValue::fromString('')); } @@ -157,9 +157,9 @@ public function testMarshallingWithEmptySupportedProtocols(): void */ public function testMarshallingWithoutAttributeServices(): void { - $this->expectException(AssertionFailedException::class); + $this->expectException(MissingElementException::class); $this->expectExceptionMessage('AttributeAuthorityDescriptor must contain at least one AttributeService.'); - new AttributeAuthorityDescriptor([], [C::NS_SAMLP]); + new AttributeAuthorityDescriptor([], AnyURIListValue::fromString(C::NS_SAMLP)); } @@ -168,7 +168,7 @@ public function testMarshallingWithoutAttributeServices(): void */ public function testMarshallingWithoutOptionalParameters(): void { - $aad = new AttributeAuthorityDescriptor([self::$as], [C::NS_SAMLP]); + $aad = new AttributeAuthorityDescriptor([self::$as], AnyURIListValue::fromString(C::NS_SAMLP)); $this->assertEmpty($aad->getAssertionIDRequestService()); $this->assertEmpty($aad->getNameIDFormat()); $this->assertEmpty($aad->getID()); @@ -187,7 +187,7 @@ public function testMarshallingWithoutOptionalParameters(): void */ public function testMarshallingWithEmptyAssertionIDRequestService(): void { - $aad = new AttributeAuthorityDescriptor([self::$as], [C::NS_SAMLP], []); + $aad = new AttributeAuthorityDescriptor([self::$as], AnyURIListValue::fromString(C::NS_SAMLP), []); $this->assertEmpty($aad->getAssertionIDRequestService()); $this->assertEmpty($aad->getNameIDFormat()); $this->assertEmpty($aad->getID()); @@ -201,32 +201,6 @@ public function testMarshallingWithEmptyAssertionIDRequestService(): void } - /** - * Test that creating an AttributeAuthorityDescriptor with an empty NameIDFormat fails. - */ - public function testMarshallingWithEmptyNameIDFormat(): void - { - $this->expectException(ProtocolViolationException::class); - new AttributeAuthorityDescriptor([self::$as], [C::NS_SAMLP], [self::$aidrs], [new NameIDFormat('')]); - } - - - /** - * Test that creating an AttributeAuthorityDescriptor with an empty AttributeProfile fails. - */ - public function testMarshallingWithEmptyAttributeProfile(): void - { - $this->expectException(ProtocolViolationException::class); - new AttributeAuthorityDescriptor( - [self::$as], - [C::NS_SAMLP], - [self::$aidrs], - [new NameIDFormat(C::NAMEID_TRANSIENT)], - [new AttributeProfile('')], - ); - } - - // test unmarshalling diff --git a/tests/SAML2/XML/md/AttributeConsumingServiceTest.php b/tests/SAML2/XML/md/AttributeConsumingServiceTest.php index 9a7c6ceac..729ba25ad 100644 --- a/tests/SAML2/XML/md/AttributeConsumingServiceTest.php +++ b/tests/SAML2/XML/md/AttributeConsumingServiceTest.php @@ -7,8 +7,9 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\AttributeConsumingService; use SimpleSAML\SAML2\XML\md\RequestedAttribute; @@ -16,10 +17,13 @@ use SimpleSAML\SAML2\XML\md\ServiceName; use SimpleSAML\SAML2\XML\saml\AttributeValue; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; -use SimpleSAML\XML\Exception\MissingElementException; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Type\BooleanValue; +use SimpleSAML\XMLSchema\Type\LanguageValue; +use SimpleSAML\XMLSchema\Type\UnsignedShortValue; use function dirname; use function strval; @@ -53,9 +57,9 @@ public static function setUpBeforeClass(): void ); self::$requestedAttribute = new RequestedAttribute( - Name: 'urn:oid:1.3.6.1.4.1.5923.1.1.1.7', - NameFormat: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri', - FriendlyName: 'eduPersonEntitlement', + Name: SAMLStringValue::fromString('urn:oid:1.3.6.1.4.1.5923.1.1.1.7'), + NameFormat: SAMLAnyURIValue::fromString('urn:oasis:names:tc:SAML:2.0:attrname-format:uri'), + FriendlyName: SAMLStringValue::fromString('eduPersonEntitlement'), AttributeValues: [new AttributeValue('https://ServiceProvider.com/entitlements/123456789')], ); } @@ -70,11 +74,21 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $acs = new AttributeConsumingService( - 2, - [new ServiceName('en', 'Academic Journals R US')], + UnsignedShortValue::fromInteger(2), + [ + new ServiceName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Academic Journals R US'), + ), + ], [self::$requestedAttribute], - true, - [new ServiceDescription('en', 'Academic Journals R US and only us')], + BooleanValue::fromBoolean(true), + [ + new ServiceDescription( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Academic Journals R US and only us'), + ), + ], ); $this->assertEquals( @@ -90,10 +104,15 @@ public function testMarshalling(): void public function testMarshallingWithoutDescription(): void { $acs = new AttributeConsumingService( - 2, - [new ServiceName('en', 'Academic Journals R US')], + UnsignedShortValue::fromInteger(2), + [ + new ServiceName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Academic Journals R US'), + ), + ], [self::$requestedAttribute], - false, + BooleanValue::fromBoolean(false), ); $xmlRepresentation = clone self::$xmlRepresentation; @@ -125,10 +144,20 @@ public function testMarshallingWithoutDescription(): void public function testMarshallingWithoutIsDefault(): void { $acs = new AttributeConsumingService( - index: 2, - serviceName: [new ServiceName('en', 'Academic Journals R US')], + index: UnsignedShortValue::fromInteger(2), + serviceName: [ + new ServiceName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Academic Journals R US'), + ), + ], requestedAttribute: [self::$requestedAttribute], - serviceDescription: [new ServiceDescription('en', 'Academic Journals R US and only us')], + serviceDescription: [ + new ServiceDescription( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Academic Journals R US and only us'), + ), + ], ); $xmlRepresentation = clone self::$xmlRepresentation; $xmlRepresentation->documentElement->removeAttribute('isDefault'); @@ -147,7 +176,7 @@ public function testMarshallingWithEmptyServiceName(): void $this->expectException(MissingElementException::class); $this->expectExceptionMessage('Missing at least one ServiceName in AttributeConsumingService.'); new AttributeConsumingService( - 2, + UnsignedShortValue::fromInteger(2), [], [self::$requestedAttribute], ); @@ -162,8 +191,13 @@ public function testMarshallingWithEmptyRequestedAttributes(): void $this->expectException(MissingElementException::class); $this->expectExceptionMessage('Missing at least one RequestedAttribute in AttributeConsumingService.'); new AttributeConsumingService( - 2, - [new ServiceName('en', 'Academic Journals R US')], + UnsignedShortValue::fromInteger(2), + [ + new ServiceName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Academic Journals R US'), + ), + ], [], ); } @@ -185,44 +219,6 @@ public function testUnmarshallingWithoutIndex(): void } - /** - * Test that creating an AssertionConsumerService from XML works if isDefault is missing. - */ - public function testUnmarshallingWithoutIsDefault(): void - { - $xmlRepresentation = clone self::$xmlRepresentation; - $xmlRepresentation->documentElement->removeAttribute('isDefault'); - $acs = AttributeConsumingService::fromXML($xmlRepresentation->documentElement); - $this->assertNull($acs->getIsDefault()); - } - - - /** - * Test that creating an AssertionConsumerService from XML fails if isDefault is not boolean - */ - public function testUnmarshallingWithWrongIsDefault(): void - { - $xmlRepresentation = clone self::$xmlRepresentation; - $xmlRepresentation->documentElement->setAttribute('isDefault', 'xxx'); - $this->expectException(AssertionFailedException::class); - $this->expectExceptionMessage("The 'isDefault' attribute of md:AttributeConsumingService must be a boolean."); - AttributeConsumingService::fromXML($xmlRepresentation->documentElement); - } - - - /** - * Test that creating an AssertionConsumerService from XML fails if index is not numerical. - */ - public function testUnmarshallingWithNonNumericIndex(): void - { - $xmlRepresentation = clone self::$xmlRepresentation; - $xmlRepresentation->documentElement->setAttribute('index', 'x'); - $this->expectException(AssertionFailedException::class); - $this->expectExceptionMessage('The \'index\' attribute of md:AttributeConsumingService must be numerical.'); - AttributeConsumingService::fromXML($xmlRepresentation->documentElement); - } - - /** * Test that creating an AssertionConsumerService from XMl fails if no ServiceName was provided. */ diff --git a/tests/SAML2/XML/md/AttributeProfileTest.php b/tests/SAML2/XML/md/AttributeProfileTest.php index 0d5f3c990..4c61a1b17 100644 --- a/tests/SAML2/XML/md/AttributeProfileTest.php +++ b/tests/SAML2/XML/md/AttributeProfileTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\AttributeProfile; use SimpleSAML\Test\SAML2\Constants as C; @@ -50,7 +51,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $attributeProfile = new AttributeProfile(C::PROFILE_1); + $attributeProfile = new AttributeProfile( + SAMLAnyURIValue::fromString(C::PROFILE_1), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/md/AuthnAuthorityDescriptorTest.php b/tests/SAML2/XML/md/AuthnAuthorityDescriptorTest.php index 7bc02a6f1..6f44198fe 100644 --- a/tests/SAML2/XML/md/AuthnAuthorityDescriptorTest.php +++ b/tests/SAML2/XML/md/AuthnAuthorityDescriptorTest.php @@ -10,6 +10,8 @@ use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\AnyURIListValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\AbstractMetadataDocument; use SimpleSAML\SAML2\XML\md\AbstractRoleDescriptor; @@ -23,6 +25,7 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -62,8 +65,15 @@ public static function setUpBeforeClass(): void dirname(__FILE__, 4) . '/resources/xml/md_AuthnAuthorityDescriptor.xml', ); - self::$aqs = new AuthnQueryService(C::BINDING_HTTP_POST, 'http://www.example.com/aqs'); - self::$aidrs = new AssertionIDRequestService(C::BINDING_HTTP_POST, 'http://www.example.com/aidrs'); + self::$aqs = new AuthnQueryService( + SAMLAnyURIValue::fromString(C::BINDING_HTTP_POST), + SAMLAnyURIValue::fromString('http://www.example.com/aqs'), + ); + + self::$aidrs = new AssertionIDRequestService( + SAMLAnyURIValue::fromString(C::BINDING_HTTP_POST), + SAMLAnyURIValue::fromString('http://www.example.com/aidrs'), + ); } @@ -77,10 +87,17 @@ public function testMarshalling(): void { $aad = new AuthnAuthorityDescriptor( [self::$aqs], - [C::NS_SAMLP, C::PROTOCOL], + AnyURIListValue::fromArray([C::NS_SAMLP, C::PROTOCOL]), [self::$aidrs], - [new NameIDFormat(C::NAMEID_PERSISTENT), new NameIDFormat(C::NAMEID_TRANSIENT)], - 'phpunit', + [ + new NameIDFormat( + SAMLAnyURIValue::fromString(C::NAMEID_PERSISTENT), + ), + new NameIDFormat( + SAMLAnyURIValue::fromString(C::NAMEID_TRANSIENT), + ), + ], + IDValue::fromString('phpunit'), ); $this->assertEquals( @@ -99,9 +116,16 @@ public function testMarshallingWithoutAuthnQueryServices(): void $this->expectExceptionMessage('Missing at least one AuthnQueryService in AuthnAuthorityDescriptor.'); new AuthnAuthorityDescriptor( [], - [C::NS_SAMLP, C::PROTOCOL], + AnyURIListValue::fromArray([C::NS_SAMLP, C::PROTOCOL]), [self::$aidrs], - [new NameIDFormat(C::NAMEID_PERSISTENT), new NameIDFormat(C::NAMEID_TRANSIENT)], + [ + new NameIDFormat( + SAMLAnyURIValue::fromString(C::NAMEID_PERSISTENT), + ), + new NameIDFormat( + SAMLAnyURIValue::fromString(C::NAMEID_TRANSIENT), + ), + ], ); } @@ -114,22 +138,7 @@ public function testMarshallingWithoutOptionalElements(): void { new AuthnAuthorityDescriptor( [self::$aqs], - [C::NS_SAMLP, C::PROTOCOL], - ); - } - - - /** - * Test that creating an AuthnAuthorityDescriptor with an empty NameIDFormat fails. - */ - public function testMarshallWithEmptyNameIDFormat(): void - { - $this->expectException(ProtocolViolationException::class); - new AuthnAuthorityDescriptor( - [self::$aqs], - [C::NS_SAMLP, C::PROTOCOL], - [self::$aidrs], - [new NameIDFormat(''), new NameIDFormat(C::NAMEID_TRANSIENT)], + AnyURIListValue::fromArray([C::NS_SAMLP, C::PROTOCOL]), ); } @@ -141,11 +150,19 @@ public function testMarshallingWithWrongAuthnQueryService(): void { $this->expectException(AssertionFailedException::class); $this->expectExceptionMessage('AuthnQueryService must be an instance of EndpointType'); + new AuthnAuthorityDescriptor( [self::$aqs, ''], - [C::NS_SAMLP, C::PROTOCOL], + AnyURIListValue::fromArray([C::NS_SAMLP, C::PROTOCOL]), [self::$aidrs], - [new NameIDFormat(C::NAMEID_PERSISTENT), new NameIDFormat(C::NAMEID_TRANSIENT)], + [ + new NameIDFormat( + SAMLAnyURIValue::fromString(C::NAMEID_PERSISTENT), + ), + new NameIDFormat( + SAMLAnyURIValue::fromString(C::NAMEID_TRANSIENT), + ), + ], ); } @@ -157,11 +174,19 @@ public function testMarshallingWithWrongAssertionIDRequestService(): void { $this->expectException(AssertionFailedException::class); $this->expectExceptionMessage('AssertionIDRequestServices must be an instance of EndpointType'); + new AuthnAuthorityDescriptor( [self::$aqs], - [C::NS_SAMLP, C::PROTOCOL], + AnyURIListValue::fromArray([C::NS_SAMLP, C::PROTOCOL]), [self::$aidrs, ''], - [new NameIDFormat(C::NAMEID_PERSISTENT), new NameIDFormat(C::NAMEID_TRANSIENT)], + [ + new NameIDFormat( + SAMLAnyURIValue::fromString(C::NAMEID_PERSISTENT), + ), + new NameIDFormat( + SAMLAnyURIValue::fromString(C::NAMEID_TRANSIENT), + ), + ], ); } diff --git a/tests/SAML2/XML/md/CompanyTest.php b/tests/SAML2/XML/md/CompanyTest.php index 139530b56..f3847d82d 100644 --- a/tests/SAML2/XML/md/CompanyTest.php +++ b/tests/SAML2/XML/md/CompanyTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\Company; use SimpleSAML\XML\DOMDocumentFactory; @@ -50,7 +51,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $name = new Company('Company'); + $name = new Company( + SAMLStringValue::fromString('Company'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/md/ContactPersonTest.php b/tests/SAML2/XML/md/ContactPersonTest.php index da29b7f06..b6f5de8d4 100644 --- a/tests/SAML2/XML/md/ContactPersonTest.php +++ b/tests/SAML2/XML/md/ContactPersonTest.php @@ -10,6 +10,8 @@ use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\EmailAddressValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\Company; use SimpleSAML\SAML2\XML\md\ContactPerson; @@ -21,10 +23,11 @@ use SimpleSAML\XML\Attribute as XMLAttribute; use SimpleSAML\XML\Chunk; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Type\StringValue; use function dirname; use function strval; @@ -90,21 +93,38 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $attr1 = new XMLAttribute('urn:test:something', 'test', 'attr1', 'testval1'); - $attr2 = new XMLAttribute('urn:test:something', 'test', 'attr2', 'testval2'); + $attr1 = new XMLAttribute('urn:test:something', 'test', 'attr1', StringValue::fromString('testval1')); + $attr2 = new XMLAttribute('urn:test:something', 'test', 'attr2', StringValue::fromString('testval2')); $contactPerson = new ContactPerson( - 'other', - new Company('Test Company'), - new GivenName('John'), - new SurName('Doe'), + SAMLStringValue::fromString('other'), + new Company( + SAMLStringValue::fromString('Test Company'), + ), + new GivenName( + SAMLStringValue::fromString('John'), + ), + new SurName( + SAMLStringValue::fromString('Doe'), + ), new Extensions( [ new Chunk(self::$ext->documentElement), ], ), - [new EmailAddress('jdoe@test.company'), new EmailAddress('john.doe@test.company')], - [new TelephoneNumber('1-234-567-8901')], + [ + new EmailAddress( + EmailAddressValue::fromString('jdoe@test.company'), + ), + new EmailAddress( + EmailAddressValue::fromString('john.doe@test.company'), + ), + ], + [ + new TelephoneNumber( + SAMLStringValue::fromString('1-234-567-8901'), + ), + ], [$attr1, $attr2], ); @@ -124,7 +144,9 @@ public function testMarshallingWithWrongType(): void $this->expectExceptionMessage( 'Expected one of: "technical", "support", "administrative", "billing", "other". Got: "wrong"', ); - new ContactPerson('wrong'); + new ContactPerson( + SAMLStringValue::fromString('wrong'), + ); } diff --git a/tests/SAML2/XML/md/EmailAddressTest.php b/tests/SAML2/XML/md/EmailAddressTest.php index c469bbef0..bfe3d4009 100644 --- a/tests/SAML2/XML/md/EmailAddressTest.php +++ b/tests/SAML2/XML/md/EmailAddressTest.php @@ -8,6 +8,7 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; +use SimpleSAML\SAML2\Type\EmailAddressValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\EmailAddress; use SimpleSAML\XML\DOMDocumentFactory; @@ -52,7 +53,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $email = new EmailAddress('john.doe@example.org'); + $email = new EmailAddress( + EmailAddressValue::fromString('john.doe@example.org'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), @@ -67,7 +70,9 @@ public function testInvalidEmailThrowsException(): void { $this->expectException(AssertionFailedException::class); $this->expectExceptionMessage('Expected a value to be a valid e-mail address. Got: "not so valid"'); - new EmailAddress('not so valid'); + new EmailAddress( + EmailAddressValue::fromString('not so valid'), + ); } diff --git a/tests/SAML2/XML/md/EncryptionMethodTest.php b/tests/SAML2/XML/md/EncryptionMethodTest.php index fc09ed132..70558c3e4 100644 --- a/tests/SAML2/XML/md/EncryptionMethodTest.php +++ b/tests/SAML2/XML/md/EncryptionMethodTest.php @@ -8,14 +8,17 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\EncryptionMethod; use SimpleSAML\XML\Chunk; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Type\Base64BinaryValue; +use SimpleSAML\XMLSecurity\Type\KeySizeValue; use SimpleSAML\XMLSecurity\XML\xenc\KeySize; use SimpleSAML\XMLSecurity\XML\xenc\OAEPparams; @@ -58,13 +61,21 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $alg = C::KEY_TRANSPORT_OAEP_MGF1P; $chunkXml = DOMDocumentFactory::fromString( 'Value', ); $chunk = Chunk::fromXML($chunkXml->documentElement); - $encryptionMethod = new EncryptionMethod($alg, new KeySize(10), new OAEPparams('9lWu3Q=='), [$chunk]); + $encryptionMethod = new EncryptionMethod( + SAMLAnyURIValue::fromString(C::KEY_TRANSPORT_OAEP_MGF1P), + new KeySize( + KeySizeValue::fromInteger(10), + ), + new OAEPparams( + Base64BinaryValue::fromString('9lWu3Q=='), + ), + [$chunk], + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), @@ -78,7 +89,9 @@ public function testMarshalling(): void */ public function testMarshallingWithoutOptionalParameters(): void { - $encryptionMethod = new EncryptionMethod(C::KEY_TRANSPORT_OAEP_MGF1P); + $encryptionMethod = new EncryptionMethod( + SAMLAnyURIValue::fromString(C::KEY_TRANSPORT_OAEP_MGF1P), + ); $document = DOMDocumentFactory::fromString(sprintf( '', C::NS_MD, @@ -99,7 +112,16 @@ public function testMarshallingElementOrdering(): void ); $chunk = Chunk::fromXML($chunkXml->documentElement); - $em = new EncryptionMethod($alg, new KeySize(10), new OAEPparams('9lWu3Q=='), [$chunk]); + $em = new EncryptionMethod( + SAMLAnyURIValue::fromString(C::KEY_TRANSPORT_OAEP_MGF1P), + new KeySize( + KeySizeValue::fromInteger(10), + ), + new OAEPparams( + Base64BinaryValue::fromString('9lWu3Q=='), + ), + [$chunk], + ); // Marshall it to a \DOMElement $emElement = $em->toXML(); diff --git a/tests/SAML2/XML/md/EndpointTypeTest.php b/tests/SAML2/XML/md/EndpointTypeTest.php index 10c33c6b1..81053ebc4 100644 --- a/tests/SAML2/XML/md/EndpointTypeTest.php +++ b/tests/SAML2/XML/md/EndpointTypeTest.php @@ -9,6 +9,7 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\md\AbstractEndpointType; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\AssertionIDRequestService; @@ -17,11 +18,12 @@ use SimpleSAML\XML\Attribute as XMLAttribute; use SimpleSAML\XML\Chunk; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingAttributeException; use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Type\StringValue; use function dirname; use function strval; @@ -60,7 +62,14 @@ public static function setUpBeforeClass(): void 'Location' => 'https://whatever/', 'ResponseLocation' => 'https://foo.bar/', 'children' => [new Chunk(self::$ext->documentElement)], - 'attributes' => [(new XMLAttribute('urn:x-simplesamlphp:namespace', 'test', 'attr', 'value'))->toArray()], + 'attributes' => [ + (new XMLAttribute( + 'urn:x-simplesamlphp:namespace', + 'test', + 'attr', + StringValue::fromString('value'), + ))->toArray(), + ], ]; self::$xmlRepresentation = DOMDocumentFactory::fromFile( @@ -77,12 +86,12 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $attr = new XMLAttribute(C::NAMESPACE, 'test', 'attr', 'value'); + $attr = new XMLAttribute(C::NAMESPACE, 'test', 'attr', StringValue::fromString('value')); $endpointType = new AttributeService( - C::BINDING_HTTP_POST, - 'https://whatever/', - 'https://foo.bar/', + SAMLAnyURIValue::fromString(C::BINDING_HTTP_POST), + SAMLAnyURIValue::fromString('https://whatever/'), + SAMLAnyURIValue::fromString('https://foo.bar/'), [new Chunk(self::$ext->documentElement)], [$attr], ); @@ -94,32 +103,15 @@ public function testMarshalling(): void } - /** - * Test that creating an EndpointType from scratch with an empty Binding fails. - */ - public function testMarshallingWithEmptyBinding(): void - { - $this->expectException(ProtocolViolationException::class); - new AttributeService('', C::LOCATION_A); - } - - - /** - * Test that creating an EndpointType from scratch with an empty Location fails. - */ - public function testMarshallingWithEmptyLocation(): void - { - $this->expectException(ProtocolViolationException::class); - new AttributeService(C::BINDING_HTTP_POST, ''); - } - - /** * Test that creating an EndpointType from scratch without optional attributes works. */ public function testMarshallingWithoutOptionalAttributes(): void { - $endpointType = new AttributeService(C::BINDING_HTTP_POST, C::LOCATION_A); + $endpointType = new AttributeService( + SAMLAnyURIValue::fromString(C::BINDING_HTTP_POST), + SAMLAnyURIValue::fromString(C::LOCATION_A), + ); $this->assertNull($endpointType->getResponseLocation()); $this->assertEmpty($endpointType->getAttributesNS()); } diff --git a/tests/SAML2/XML/md/EntitiesDescriptorTest.php b/tests/SAML2/XML/md/EntitiesDescriptorTest.php index d484afa79..e4342c92b 100644 --- a/tests/SAML2/XML/md/EntitiesDescriptorTest.php +++ b/tests/SAML2/XML/md/EntitiesDescriptorTest.php @@ -4,12 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use DateTimeImmutable; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\AbstractMetadataDocument; use SimpleSAML\SAML2\XML\md\AbstractSignedMdElement; @@ -21,6 +23,8 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\LanguageValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -65,9 +69,14 @@ public function testMarshalling(): void { $extensions = new Extensions([ new PublicationInfo( - publisher: 'http://publisher.ra/', - creationInstant: new DateTimeImmutable('2020-02-03T13:46:24Z'), - usagePolicy: [new UsagePolicy('en', 'http://publisher.ra/policy.txt')], + publisher: SAMLStringValue::fromString('http://publisher.ra/'), + creationInstant: SAMLDateTimeValue::fromString('2020-02-03T13:46:24Z'), + usagePolicy: [ + new UsagePolicy( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('http://publisher.ra/policy.txt'), + ), + ], ), ]); $entitiesdChildElement = self::$xmlRepresentation->documentElement->getElementsByTagNameNS( @@ -88,9 +97,9 @@ public function testMarshalling(): void $entitiesd = new EntitiesDescriptor( entityDescriptors: [$childEntityd], entitiesDescriptors: [$childEntitiesd], - Name: 'Federation', + Name: SAMLStringValue::fromString('Federation'), extensions: $extensions, - ID: 'phpunit', + ID: IDValue::fromString('phpunit'), ); $this->assertEquals( @@ -164,18 +173,6 @@ public function testUnmarshallingWithoutName(): void } - /** - * Test that creating an EntitiesDescriptor with an empty Name from XML works. - */ - public function testUnmarshallingWithEmptyName(): void - { - $xmlRepresentation = clone self::$xmlRepresentation; - $xmlRepresentation->documentElement->setAttribute('Name', ''); - $entitiesd = EntitiesDescriptor::fromXML($xmlRepresentation->documentElement); - $this->assertEquals('', $entitiesd->getName()); - } - - /** * Test that creating an EntitiesDescriptor without nested EntitiesDescriptor elements from XML works. */ diff --git a/tests/SAML2/XML/md/EntityDescriptorTest.php b/tests/SAML2/XML/md/EntityDescriptorTest.php index 902c5984d..1f8b68c4a 100644 --- a/tests/SAML2/XML/md/EntityDescriptorTest.php +++ b/tests/SAML2/XML/md/EntityDescriptorTest.php @@ -4,13 +4,17 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use DateTimeImmutable; use DOMText; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\AnyURIListValue; +use SimpleSAML\SAML2\Type\EmailAddressValue; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\AbstractMetadataDocument; use SimpleSAML\SAML2\XML\md\AbstractSignedMdElement; @@ -39,14 +43,18 @@ use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\Attribute as XMLAttribute; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Constants as C_XSI; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\DurationValue; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\LanguageValue; +use SimpleSAML\XMLSchema\Type\StringValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; -use function str_pad; use function strval; /** @@ -86,83 +94,120 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $attr1 = new XMLAttribute('urn:test:something', 'test', 'attr1', 'testval1'); + $attr1 = new XMLAttribute('urn:test:something', 'test', 'attr1', StringValue::fromString('testval1')); - $entityid = C::ENTITY_IDP; - $id = "_5A3CHB081"; - $now = 1580895565; - $duration = "P2Y6M5DT12H35M30S"; + $entityid = EntityIDValue::fromString(C::ENTITY_IDP); + $id = IDValue::fromString("_5A3CHB081"); + $duration = DurationValue::fromString("P2Y6M5DT12H35M30S"); $idpssod = new IDPSSODescriptor( [ new SingleSignOnService( - C::BINDING_HTTP_REDIRECT, - 'https://engine.test.example.edu/authentication/idp/single-sign-on', + SAMLAnyURIValue::fromString(C::BINDING_HTTP_REDIRECT), + SAMLAnyURIValue::fromString('https://engine.test.example.edu/authentication/idp/single-sign-on'), ), ], - [C::NS_SAMLP], + AnyURIListValue::fromString(C::NS_SAMLP), ); $attrad = new AttributeAuthorityDescriptor( [ new AttributeService( - C::BINDING_SOAP, - 'https://idp.example.org/AttributeService', + SAMLAnyURIValue::fromString(C::BINDING_SOAP), + SAMLAnyURIValue::fromString('https://idp.example.org/AttributeService'), ), ], - [C::NS_SAMLP], + AnyURIListValue::fromString(C::NS_SAMLP), ); $authnad = new AuthnAuthorityDescriptor( [ new AuthnQueryService( - C::BINDING_HTTP_REDIRECT, - 'http://www.example.com/aqs', + SAMLAnyURIValue::fromString(C::BINDING_HTTP_REDIRECT), + SAMLAnyURIValue::fromString('http://www.example.com/aqs'), ), ], - [C::NS_SAMLP], + AnyURIListValue::fromString(C::NS_SAMLP), ); $pdpd = new PDPDescriptor( [ new AuthzService( - C::BINDING_SOAP, - 'https://IdentityProvider.com/SAML/AA/SOAP', + SAMLAnyURIValue::fromString(C::BINDING_SOAP), + SAMLAnyURIValue::fromString('https://IdentityProvider.com/SAML/AA/SOAP'), ), ], - [C::NS_SAMLP], + AnyURIListValue::fromString(C::NS_SAMLP), ); $org = new Organization( - [new OrganizationName('en', 'orgNameTest (en)')], - [new OrganizationDisplayName('en', 'orgDispNameTest (en)')], - [new OrganizationURL('en', 'https://IdentityProvider.com')], + [ + new OrganizationName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('orgNameTest (en)'), + ), + ], + [ + new OrganizationDisplayName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('orgDispNameTest (en)'), + ), + ], + [ + new OrganizationURL( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('https://IdentityProvider.com'), + ), + ], ); $contacts = [ new ContactPerson( - contactType: 'support', - emailAddress: [new EmailAddress('help@example.edu')], + contactType: SAMLStringValue::fromString('support'), + emailAddress: [ + new EmailAddress( + EmailAddressValue::fromString('help@example.edu'), + ), + ], ), new ContactPerson( - contactType: 'technical', - emailAddress: [new EmailAddress('root@example.edu')], + contactType: SAMLStringValue::fromString('technical'), + emailAddress: [ + new EmailAddress( + EmailAddressValue::fromString('root@example.edu'), + ), + ], ), new ContactPerson( - contactType: 'administrative', - emailAddress: [new EmailAddress('info@example.edu')], + contactType: SAMLStringValue::fromString('administrative'), + emailAddress: [ + new EmailAddress( + EmailAddressValue::fromString('info@example.edu'), + ), + ], ), ]; $mdloc = [ - new AdditionalMetadataLocation(C::NAMESPACE, 'https://example.edu/some/metadata.xml'), - new AdditionalMetadataLocation(C::NAMESPACE, 'https://example.edu/more/metadata.xml'), + new AdditionalMetadataLocation( + SAMLAnyURIValue::fromString(C::NAMESPACE), + SAMLAnyURIValue::fromString('https://example.edu/some/metadata.xml'), + ), + new AdditionalMetadataLocation( + SAMLAnyURIValue::fromString(C::NAMESPACE), + SAMLAnyURIValue::fromString('https://example.edu/more/metadata.xml'), + ), ]; $extensions = new Extensions([ new PublicationInfo( - publisher: 'http://publisher.ra/', - creationInstant: new DateTimeImmutable('2020-02-03T13:46:24Z'), - usagePolicy: [new UsagePolicy('en', 'http://publisher.ra/policy.txt')], + publisher: SAMLStringValue::fromString('http://publisher.ra/'), + creationInstant: SAMLDateTimeValue::fromString('2020-02-03T13:46:24Z'), + usagePolicy: [ + new UsagePolicy( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('http://publisher.ra/policy.txt'), + ), + ], ), ]); $ed = new EntityDescriptor( entityId: $entityid, id: $id, - validUntil: new DateTimeImmutable('2020-02-05T09:39:25Z'), + validUntil: SAMLDateTimeValue::fromString('2020-02-05T09:39:25Z'), cacheDuration: $duration, extensions: $extensions, roleDescriptor: [ @@ -190,16 +235,16 @@ public function testMarshalling(): void public function testMarshallingWithAffiliationDescriptor(): void { $ns_md = C::NS_MD; + $ns_mdrpi = C::NS_MDRPI; $entity_idp = C::ENTITY_IDP; $entity_other = C::ENTITY_OTHER; $document = DOMDocumentFactory::fromString( << - + http://publisher.ra/policy.txt @@ -229,45 +274,90 @@ public function testMarshallingWithAffiliationDescriptor(): void , ); - $entityid = C::ENTITY_IDP; - $id = "_5A3CHB081"; - $duration = "P2Y6M5DT12H35M30S"; - $ad = new AffiliationDescriptor(C::ENTITY_IDP, [new AffiliateMember(C::ENTITY_OTHER)]); + $entityid = EntityIDValue::fromString(C::ENTITY_IDP); + $id = IDValue::fromString("_5A3CHB081"); + $duration = DurationValue::fromString("P2Y6M5DT12H35M30S"); + $ad = new AffiliationDescriptor( + $entityid, + [ + new AffiliateMember( + EntityIDValue::fromString(C::ENTITY_OTHER), + ), + ], + ); $org = new Organization( - [new OrganizationName('en', 'orgNameTest (en)')], - [new OrganizationDisplayName('en', 'orgDispNameTest (en)')], - [new OrganizationURL('en', 'https://IdentityProvider.com')], + [ + new OrganizationName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('orgNameTest (en)'), + ), + ], + [ + new OrganizationDisplayName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('orgDispNameTest (en)'), + ), + ], + [ + new OrganizationURL( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('https://IdentityProvider.com'), + ), + ], ); $contacts = [ new ContactPerson( - contactType: 'support', - emailAddress: [new EmailAddress('help@example.edu')], + contactType: SAMLStringValue::fromString('support'), + emailAddress: [ + new EmailAddress( + EmailAddressValue::fromString('help@example.edu'), + ), + ], ), new ContactPerson( - contactType: 'technical', - emailAddress: [new EmailAddress('root@example.edu')], + contactType: SAMLStringValue::fromString('technical'), + emailAddress: [ + new EmailAddress( + EmailAddressValue::fromString('root@example.edu'), + ), + ], ), new ContactPerson( - contactType: 'administrative', - emailAddress: [new EmailAddress('info@example.edu')], + contactType: SAMLStringValue::fromString('administrative'), + emailAddress: [ + new EmailAddress( + EmailAddressValue::fromString('info@example.edu'), + ), + ], ), ]; $mdloc = [ - new AdditionalMetadataLocation(C::NAMESPACE, 'https://example.edu/some/metadata.xml'), - new AdditionalMetadataLocation(C::NAMESPACE, 'https://example.edu/more/metadata.xml'), + new AdditionalMetadataLocation( + SAMLAnyURIValue::fromString(C::NAMESPACE), + SAMLAnyURIValue::fromString('https://example.edu/some/metadata.xml'), + ), + new AdditionalMetadataLocation( + SAMLAnyURIValue::fromString(C::NAMESPACE), + SAMLAnyURIValue::fromString('https://example.edu/more/metadata.xml'), + ), ]; $extensions = new Extensions([ new PublicationInfo( - publisher: 'http://publisher.ra/', - creationInstant: new DateTimeImmutable('2020-02-03T13:46:24Z'), - usagePolicy: [new UsagePolicy('en', 'http://publisher.ra/policy.txt')], + publisher: SAMLStringValue::fromString('http://publisher.ra/'), + creationInstant: SAMLDateTimeValue::fromString('2020-02-03T13:46:24Z'), + usagePolicy: [ + new UsagePolicy( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('http://publisher.ra/policy.txt'), + ), + ], ), ]); $ed = new EntityDescriptor( entityId: $entityid, id: $id, - validUntil: new DateTimeImmutable('2020-02-05T09:39:25Z'), + validUntil: SAMLDateTimeValue::fromString('2020-02-05T09:39:25Z'), cacheDuration: $duration, extensions: $extensions, affiliationDescriptor: $ad, @@ -275,10 +365,10 @@ public function testMarshallingWithAffiliationDescriptor(): void contactPerson: $contacts, additionalMetadataLocation: $mdloc, ); - $this->assertEquals($entityid, $ed->getEntityID()); - $this->assertEquals($id, $ed->getID()); - $this->assertEquals('2020-02-05T09:39:25Z', $ed->getValidUntil()->format(C::DATETIME_FORMAT)); - $this->assertEquals($duration, $ed->getCacheDuration()); + $this->assertEquals($entityid, $ed->getEntityID()->getValue()); + $this->assertEquals($id, $ed->getID()->getValue()); + $this->assertEquals('2020-02-05T09:39:25Z', $ed->getValidUntil()->getValue()); + $this->assertEquals($duration, $ed->getCacheDuration()->getValue()); $this->assertEmpty($ed->getRoleDescriptor()); $this->assertInstanceOf(AffiliationDescriptor::class, $ed->getAffiliationDescriptor()); $this->assertEquals( @@ -297,7 +387,9 @@ public function testMarshallingWithoutDescriptors(): void $this->expectExceptionMessage( 'Must have either one of the RoleDescriptors or an AffiliationDescriptor in EntityDescriptor.', ); - new EntityDescriptor(C::ENTITY_SP); + new EntityDescriptor( + EntityIDValue::fromString(C::ENTITY_SP), + ); } @@ -307,7 +399,14 @@ public function testMarshallingWithoutDescriptors(): void public function testMarshallingWithAffiliationAndRoleDescriptors(): void { $xmlRepresentation = clone self::$xmlRepresentation; - $affiliationDescriptor = new AffiliationDescriptor(C::ENTITY_IDP, [new AffiliateMember(C::ENTITY_SP)]); + $affiliationDescriptor = new AffiliationDescriptor( + EntityIDValue::fromString(C::ENTITY_IDP), + [ + new AffiliateMember( + EntityIDValue::fromString(C::ENTITY_SP), + ), + ], + ); $affiliationDescriptor->toXML($xmlRepresentation->documentElement); $this->expectException(ProtocolViolationException::class); @@ -319,36 +418,6 @@ public function testMarshallingWithAffiliationAndRoleDescriptors(): void } - /** - * Test that creating an EntityDescriptor from scratch fails if an empty entityID is provided. - */ - public function testMarshallingWithEmptyEntityID(): void - { - $this->expectException(ProtocolViolationException::class); - new EntityDescriptor( - entityId: '', - affiliationDescriptor: new AffiliationDescriptor(C::ENTITY_IDP, [new AffiliateMember(C::ENTITY_SP)]), - ); - } - - - /** - * Test that creating an EntityDescriptor from scratch with a very long entityID fails. - */ - public function testMarshallingWithLongEntityID(): void - { - $this->expectException(ProtocolViolationException::class); - $this->expectExceptionMessage( - sprintf('An entityID cannot be longer than %d characters.', C::ENTITYID_MAX_LENGTH), - ); - - new EntityDescriptor( - entityId: str_pad('urn:x-simplesamlphp:', C::ENTITYID_MAX_LENGTH + 1, 'a'), - affiliationDescriptor: new AffiliationDescriptor(C::ENTITY_IDP, [new AffiliateMember(C::ENTITY_OTHER)]), - ); - } - - // test unmarshalling @@ -367,7 +436,7 @@ public function testUnmarshalling(): void 'urn:x-simplesamlphp:namespace', ); - $type = new XMLAttribute(C::NS_XSI, 'xsi', 'type', 'ssp:UnknownRoleDescriptor'); + $type = new XMLAttribute(C_XSI::NS_XSI, 'xsi', 'type', StringValue::fromString('ssp:UnknownRoleDescriptor')); $type->toXML($customd); $newline = new DOMText("\n "); @@ -394,7 +463,7 @@ public function testUnmarshalling(): void ); $this->assertEquals(C::ENTITY_IDP, $entityDescriptor->getEntityID()); $this->assertEquals('_5A3CHB081', $entityDescriptor->getID()); - $this->assertEquals('2020-02-05T09:39:25Z', $entityDescriptor->getValidUntil()->format(C::DATETIME_FORMAT)); + $this->assertEquals('2020-02-05T09:39:25Z', $entityDescriptor->getValidUntil()->getValue()); $this->assertEquals('P2Y6M5DT12H35M30S', $entityDescriptor->getCacheDuration()); $roleDescriptors = $entityDescriptor->getRoleDescriptor(); @@ -425,10 +494,17 @@ public function testUnmarshalling(): void $entityDescriptor->getAdditionalMetadataLocation()[1], ); - $this->assertEquals( + // Normalize both documents before comparing + $expectedDoc = DOMDocumentFactory::fromString( $xmlRepresentation->saveXML($xmlRepresentation->documentElement), - strval($entityDescriptor), ); + $expected = DOMDocumentFactory::normalizeDocument($expectedDoc); + + $actualDoc = DOMDocumentFactory::fromString((string) $entityDescriptor); + $actual = DOMDocumentFactory::normalizeDocument($actualDoc); + + // Compare normalized XML + $this->assertXmlStringEqualsXmlString($expected->saveXML(), $actual->saveXML()); } @@ -478,30 +554,6 @@ public function testUnmarshallingWithoutDescriptors(): void } - /** - * Test that creating an EntityDescriptor from XML fails with an invalid validUntil attribute. - */ - public function testUnmarshallingWithInvalidValidUntil(): void - { - $entity_idp = C::ENTITY_IDP; - $entity_sp = C::ENTITY_SP; - - $document = DOMDocumentFactory::fromString( - << - - {$entity_sp} - - -XML - , - ); - $this->expectException(AssertionFailedException::class); - $this->expectExceptionMessage('\'asdf\' is not a valid xs:dateTime'); - EntityDescriptor::fromXML($document->documentElement); - } - - /** * Test that creating an EntityDescriptor from XML works when an AffiliationDescriptor is used. */ diff --git a/tests/SAML2/XML/md/ExtensionsTest.php b/tests/SAML2/XML/md/ExtensionsTest.php index 1c661be94..a0fcdc374 100644 --- a/tests/SAML2/XML/md/ExtensionsTest.php +++ b/tests/SAML2/XML/md/ExtensionsTest.php @@ -9,6 +9,9 @@ use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\CIDRValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\alg\DigestMethod; use SimpleSAML\SAML2\XML\alg\SigningMethod; use SimpleSAML\SAML2\XML\emd\RepublishRequest; @@ -31,6 +34,9 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\LanguageValue; +use SimpleSAML\XMLSchema\Type\PositiveIntegerValue; +use SimpleSAML\XMLSchema\Type\UnsignedShortValue; use function dirname; use function strval; @@ -71,20 +77,51 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $scope = new Scope('SomeScope'); - $ra = new RegistrationInfo('SomeAuthority'); - $pubInfo = new PublicationInfo('SomePublisher'); + $scope = new Scope( + SAMLStringValue::fromString('SomeScope'), + ); + $ra = new RegistrationInfo( + SAMLStringValue::fromString('SomeAuthority'), + ); + $pubInfo = new PublicationInfo( + SAMLStringValue::fromString('SomePublisher'), + ); $pubPath = new PublicationPath( [ - new Publication('SomePublisher'), + new Publication( + SAMLStringValue::fromString('SomePublisher'), + ), ], ); - $uiinfo = new UIInfo([new DisplayName('en', 'Example')]); - $idpdisc = new DiscoveryResponse(1, C::NS_IDPDISC, 'https://example.org/authenticate/sp'); - $discoHints = new DiscoHints([], [new IPHint('127.0.0.1')]); - $digestMethod = new DigestMethod(C::DIGEST_SHA256); - $signingMethod = new SigningMethod(C::SIG_RSA_SHA256, 1024, 4096); - $republishRequest = new RepublishRequest(new RepublishTarget('http://edugain.org/')); + $uiinfo = new UIInfo([ + new DisplayName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Example'), + ), + ]); + $idpdisc = new DiscoveryResponse( + UnsignedShortValue::fromInteger(1), + SAMLAnyURIValue::fromString(C::NS_IDPDISC), + SAMLAnyURIValue::fromString('https://example.org/authenticate/sp'), + ); + $discoHints = new DiscoHints([], [ + new IPHint( + CIDRValue::fromString('127.0.0.0/8'), + ), + ]); + $digestMethod = new DigestMethod( + SAMLAnyURIValue::fromString(C::DIGEST_SHA256), + ); + $signingMethod = new SigningMethod( + SAMLAnyURIValue::fromString(C::SIG_RSA_SHA256), + PositiveIntegerValue::fromInteger(1024), + PositiveIntegerValue::fromInteger(4096), + ); + $republishRequest = new RepublishRequest( + new RepublishTarget( + SAMLAnyURIValue::fromString('http://edugain.org/'), + ), + ); $extensions = new Extensions([ $scope, @@ -174,7 +211,7 @@ public function testUnmarshalling(): void Example - 127.0.0.1 + 127.0.0.0/8 assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/md/IDPSSODescriptorTest.php b/tests/SAML2/XML/md/IDPSSODescriptorTest.php index b009c066c..598e98f89 100644 --- a/tests/SAML2/XML/md/IDPSSODescriptorTest.php +++ b/tests/SAML2/XML/md/IDPSSODescriptorTest.php @@ -9,6 +9,10 @@ use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\AnyURIListValue; +use SimpleSAML\SAML2\Type\KeyTypesValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\AbstractMetadataDocument; use SimpleSAML\SAML2\XML\md\AbstractRoleDescriptor; @@ -19,6 +23,7 @@ use SimpleSAML\SAML2\XML\md\AttributeProfile; use SimpleSAML\SAML2\XML\md\IDPSSODescriptor; use SimpleSAML\SAML2\XML\md\KeyDescriptor; +use SimpleSAML\SAML2\XML\md\KeyTypesEnum; use SimpleSAML\SAML2\XML\md\ManageNameIDService; use SimpleSAML\SAML2\XML\md\NameIDFormat; use SimpleSAML\SAML2\XML\md\NameIDMappingService; @@ -30,6 +35,9 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\BooleanValue; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\UnsignedShortValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; use SimpleSAML\XMLSecurity\XML\ds\KeyName; @@ -77,53 +85,57 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $idpssod = new IDPSSODescriptor( - ID: 'phpunit', + ID: IDValue::fromString('phpunit'), singleSignOnService: [ new SingleSignOnService( - C::BINDING_HTTP_REDIRECT, - 'https://IdentityProvider.com/SAML/SSO/Browser', + SAMLAnyURIValue::fromString(C::BINDING_HTTP_REDIRECT), + SAMLAnyURIValue::fromString('https://IdentityProvider.com/SAML/SSO/Browser'), ), new SingleSignOnService( - C::BINDING_HTTP_POST, - 'https://IdentityProvider.com/SAML/SSO/Browser', + SAMLAnyURIValue::fromString(C::BINDING_HTTP_POST), + SAMLAnyURIValue::fromString('https://IdentityProvider.com/SAML/SSO/Browser'), ), ], - protocolSupportEnumeration: [C::NS_SAMLP], - wantAuthnRequestsSigned: true, + protocolSupportEnumeration: AnyURIListValue::fromString(C::NS_SAMLP), + wantAuthnRequestsSigned: BooleanValue::fromBoolean(true), nameIDMappingService: [ new NameIDMappingService( - C::BINDING_HTTP_REDIRECT, - 'https://IdentityProvider.com/SAML/SSO/Browser', + SAMLAnyURIValue::fromString(C::BINDING_HTTP_REDIRECT), + SAMLAnyURIValue::fromString('https://IdentityProvider.com/SAML/SSO/Browser'), ), new NameIDMappingService( - C::BINDING_HTTP_POST, - 'https://IdentityProvider.com/SAML/SSO/Browser', + SAMLAnyURIValue::fromString(C::BINDING_HTTP_POST), + SAMLAnyURIValue::fromString('https://IdentityProvider.com/SAML/SSO/Browser'), ), ], assertionIDRequestService: [ new AssertionIDRequestService( - C::BINDING_HTTP_REDIRECT, - 'https://IdentityProvider.com/SAML/SSO/Browser', + SAMLAnyURIValue::fromString(C::BINDING_HTTP_REDIRECT), + SAMLAnyURIValue::fromString('https://IdentityProvider.com/SAML/SSO/Browser'), ), new AssertionIDRequestService( - C::BINDING_HTTP_POST, - 'https://IdentityProvider.com/SAML/SSO/Browser', + SAMLAnyURIValue::fromString(C::BINDING_HTTP_POST), + SAMLAnyURIValue::fromString('https://IdentityProvider.com/SAML/SSO/Browser'), ), ], attributeProfile: [ - new AttributeProfile('urn:attribute:profile1'), - new AttributeProfile('urn:attribute:profile2'), + new AttributeProfile( + SAMLAnyURIValue::fromString('urn:attribute:profile1'), + ), + new AttributeProfile( + SAMLAnyURIValue::fromString('urn:attribute:profile2'), + ), ], attribute: [ new Attribute( - 'urn:oid:1.3.6.1.4.1.5923.1.1.1.6', - C::NAMEFORMAT_URI, - 'eduPersonPrincipalName', + SAMLStringValue::fromString('urn:oid:1.3.6.1.4.1.5923.1.1.1.6'), + SAMLAnyURIValue::fromString(C::NAMEFORMAT_URI), + SAMLStringValue::fromString('eduPersonPrincipalName'), ), new Attribute( - 'urn:oid:1.3.6.1.4.1.5923.1.1.1.1', - C::NAMEFORMAT_URI, - 'eduPersonAffiliation', + SAMLStringValue::fromString('urn:oid:1.3.6.1.4.1.5923.1.1.1.1'), + SAMLAnyURIValue::fromString(C::NAMEFORMAT_URI), + SAMLStringValue::fromString('eduPersonAffiliation'), [ new AttributeValue('member'), new AttributeValue('student'), @@ -135,41 +147,49 @@ public function testMarshalling(): void ], keyDescriptor: [ new KeyDescriptor( - new KeyInfo( - [new KeyName('IdentityProvider.com SSO Key')], - ), - 'signing', + new KeyInfo([ + new KeyName( + SAMLStringValue::fromString('IdentityProvider.com SSO Key'), + ), + ]), + KeyTypesValue::fromEnum(KeyTypesEnum::SIGNING), ), ], artifactResolutionService: [ new ArtifactResolutionService( - 0, - C::BINDING_SOAP, - 'https://IdentityProvider.com/SAML/Artifact', - true, + UnsignedShortValue::fromInteger(0), + SAMLAnyURIValue::fromString(C::BINDING_SOAP), + SAMLAnyURIValue::fromString('https://IdentityProvider.com/SAML/Artifact'), + BooleanValue::fromBoolean(true), ), ], singleLogoutService: [ new SingleLogoutService( - C::BINDING_SOAP, - 'https://IdentityProvider.com/SAML/SLO/SOAP', + SAMLAnyURIValue::fromString(C::BINDING_SOAP), + SAMLAnyURIValue::fromString('https://IdentityProvider.com/SAML/SLO/SOAP'), ), new SingleLogoutService( - C::BINDING_HTTP_REDIRECT, - 'https://IdentityProvider.com/SAML/SLO/Browser', - 'https://IdentityProvider.com/SAML/SLO/Response', + SAMLAnyURIValue::fromString(C::BINDING_HTTP_REDIRECT), + SAMLAnyURIValue::fromString('https://IdentityProvider.com/SAML/SLO/Browser'), + SAMLAnyURIValue::fromString('https://IdentityProvider.com/SAML/SLO/Response'), ), ], manageNameIDService: [ new ManageNameIDService( - C::BINDING_HTTP_POST, - 'https://IdentityProvider.com/SAML/SSO/Browser', + SAMLAnyURIValue::fromString(C::BINDING_HTTP_POST), + SAMLAnyURIValue::fromString('https://IdentityProvider.com/SAML/SSO/Browser'), ), ], nameIDFormat: [ - new NameIDFormat(C::NAMEID_X509_SUBJECT_NAME), - new NameIDFormat(C::NAMEID_PERSISTENT), - new NameIDFormat(C::NAMEID_TRANSIENT), + new NameIDFormat( + SAMLAnyURIValue::fromString(C::NAMEID_X509_SUBJECT_NAME), + ), + new NameIDFormat( + SAMLAnyURIValue::fromString(C::NAMEID_PERSISTENT), + ), + new NameIDFormat( + SAMLAnyURIValue::fromString(C::NAMEID_TRANSIENT), + ), ], ); @@ -187,7 +207,7 @@ public function testMarshallingWithEmptySingleSignOnService(): void { $this->expectException(AssertionFailedException::class); $this->expectExceptionMessage('At least one SingleSignOnService must be specified.'); - new IDPSSODescriptor([], [C::NS_SAMLP]); + new IDPSSODescriptor([], AnyURIListValue::fromString(C::NS_SAMLP)); } @@ -195,27 +215,17 @@ public function testMarshallingWithEmptySingleSignOnService(): void * Test that creating an IDPSSODescriptor from scratch fails if no protocol is passed. */ public function testMarshallingWithoutProtocolSupportThrowsException(): void - { - $this->expectException(AssertionFailedException::class); - $this->expectExceptionMessage('At least one protocol must be supported by this md:IDPSSODescriptor.'); - - new IDPSSODescriptor( - [new SingleSignOnService(C::BINDING_HTTP_POST, C::LOCATION_A)], - [], - ); - } - - - /** - * Test that creating an IDPSSODescriptor from scratch fails if an empty AttributeProfile is provided. - */ - public function testMarshallingWithEmptyAttributeProfile(): void { $this->expectException(ProtocolViolationException::class); + new IDPSSODescriptor( - singleSignOnService: [new SingleSignOnService(C::BINDING_HTTP_POST, C::LOCATION_A)], - protocolSupportEnumeration: [C::NS_SAMLP], - attributeProfile: [new AttributeProfile('profile1'), new AttributeProfile('')], + [ + new SingleSignOnService( + SAMLAnyURIValue::fromString(C::BINDING_HTTP_POST), + SAMLAnyURIValue::fromString(C::LOCATION_A), + ), + ], + AnyURIListValue::fromString(''), ); } @@ -227,10 +237,16 @@ public function testMarshallingWithoutOptionalArguments(): void { $idpssod = new IDPSSODescriptor( [ - new SingleSignOnService(C::BINDING_HTTP_POST, C::LOCATION_A), - new SingleSignOnService(C::BINDING_HTTP_REDIRECT, C::LOCATION_B), + new SingleSignOnService( + SAMLAnyURIValue::fromString(C::BINDING_HTTP_POST), + SAMLAnyURIValue::fromString(C::LOCATION_A), + ), + new SingleSignOnService( + SAMLAnyURIValue::fromString(C::BINDING_HTTP_REDIRECT), + SAMLAnyURIValue::fromString(C::LOCATION_B), + ), ], - [C::NS_SAMLP, C::PROTOCOL], + AnyURIListValue::fromArray([C::NS_SAMLP, C::PROTOCOL]), ); $this->assertNull($idpssod->wantAuthnRequestsSigned()); $this->assertEquals([], $idpssod->getNameIDMappingService()); @@ -259,23 +275,6 @@ public function testUnmarshallingWithoutSingleSignOnService(): void } - /** - * Test that creating an IDPSSODescriptor from XML fails if WantAuthnRequestsSigned is not boolean. - */ - public function testUnmarshallingWithWrongWantAuthnRequestsSigned(): void - { - $xmlRepresentation = clone self::$xmlRepresentation; - $xmlRepresentation->documentElement->setAttribute('WantAuthnRequestsSigned', 'not a boolean'); - - $this->expectException(AssertionFailedException::class); - $this->expectExceptionMessage( - 'The \'WantAuthnRequestsSigned\' attribute of md:IDPSSODescriptor must be a boolean.', - ); - - IDPSSODescriptor::fromXML($xmlRepresentation->documentElement); - } - - /** * Test that creating an IDPSSODescriptor from XML fails if an empty AttributeProfile is provided. */ diff --git a/tests/SAML2/XML/md/IndexedEndpointTypeTest.php b/tests/SAML2/XML/md/IndexedEndpointTypeTest.php index 470e3dada..52d05a604 100644 --- a/tests/SAML2/XML/md/IndexedEndpointTypeTest.php +++ b/tests/SAML2/XML/md/IndexedEndpointTypeTest.php @@ -8,7 +8,7 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use SimpleSAML\Assert\AssertionFailedException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\idpdisc\DiscoveryResponse; use SimpleSAML\SAML2\XML\md\AbstractIndexedEndpointType; use SimpleSAML\SAML2\XML\md\AbstractMdElement; @@ -16,8 +16,9 @@ use SimpleSAML\SAML2\XML\md\AssertionConsumerService; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Type\UnsignedShortValue; use function dirname; use function sprintf; @@ -56,7 +57,11 @@ public static function setUpBeforeClass(): void public function testMarshallingWithoutIsDefault(string $class, string $xmlRepresentation): void { $binding = ($class === DiscoveryResponse::class) ? C::BINDING_IDPDISC : C::BINDING_HTTP_POST; - $idxep = new $class(42, $binding, C::LOCATION_A); + $idxep = new $class( + UnsignedShortValue::fromInteger(42), + SAMLAnyURIValue::fromString($binding), + SAMLAnyURIValue::fromString(C::LOCATION_A), + ); $this->assertNull($idxep->getIsDefault()); } @@ -79,7 +84,7 @@ public function testUnmarshallingWithNumericString(string $class, string $xmlRep $xmlRepresentation->documentElement->setAttribute('index', '+0000000000000000000005'); $endpoint = $class::fromXML($xmlRepresentation->documentElement); - $this->assertEquals(5, $endpoint->getIndex()); + $this->assertEquals(5, $endpoint->getIndex()->toInteger()); } @@ -126,31 +131,6 @@ public function testUnmarshallingWithoutIndex(string $class, string $xmlRepresen } - /** - * Test that creating an IndexedEndpointType from XML with a non-numeric index fails. - * - * @param class-string $class - * @param string $xmlRepresentation - */ - #[DataProvider('classProvider')] - public function testUnmarshallingWithWrongIndex(string $class, string $xmlRepresentation): void - { - $xmlRepresentation = DOMDocumentFactory::fromFile( - self::$resourcePath . $xmlRepresentation, - ); - $xmlRepresentation->documentElement->setAttribute('index', 'value'); - - $this->expectException(AssertionFailedException::class); - $this->expectExceptionMessage(sprintf( - 'The \'index\' attribute of %s:%s must be numerical.', - $class::getNamespacePrefix(), - $class::getLocalName(), - )); - - $class::fromXML($xmlRepresentation->documentElement); - } - - /** * Test that creating an IndexedEndpointType from XML without isDefault works. * @@ -170,31 +150,6 @@ public function testUnmarshallingWithoutIsDefault(string $class, string $xmlRepr } - /** - * Test that creating an IndexedEndpointType from XML with isDefault of a non-boolean value fails. - * - * @param class-string $class - * @param string $xmlRepresentation - */ - #[DataProvider('classProvider')] - public function testUnmarshallingWithWrongIsDefault(string $class, string $xmlRepresentation): void - { - $xmlRepresentation = DOMDocumentFactory::fromFile( - self::$resourcePath . $xmlRepresentation, - ); - $xmlRepresentation->documentElement->setAttribute('isDefault', 'non-bool'); - - $this->expectException(AssertionFailedException::class); - $this->expectExceptionMessage(sprintf( - 'The \'isDefault\' attribute of %s:%s must be a boolean.', - $class::getNamespacePrefix(), - $class::getLocalName(), - )); - - $class::fromXML($xmlRepresentation->documentElement); - } - - /** */ public static function classProvider(): array diff --git a/tests/SAML2/XML/md/KeyDescriptorTest.php b/tests/SAML2/XML/md/KeyDescriptorTest.php index a0c629b40..f333f01df 100644 --- a/tests/SAML2/XML/md/KeyDescriptorTest.php +++ b/tests/SAML2/XML/md/KeyDescriptorTest.php @@ -7,13 +7,17 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use SimpleSAML\Assert\AssertionFailedException; +use SimpleSAML\SAML2\Type\KeyTypesValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\EncryptionMethod; use SimpleSAML\SAML2\XML\md\KeyDescriptor; +use SimpleSAML\SAML2\XML\md\KeyTypesEnum; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\SchemaViolationException; +use SimpleSAML\XMLSchema\Type\StringValue; use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; use SimpleSAML\XMLSecurity\XML\ds\KeyName; @@ -55,9 +59,17 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $kd = new KeyDescriptor( - new KeyInfo([new KeyName('IdentityProvider.com SSO Key')]), - 'signing', - [new EncryptionMethod('http://www.w3.org/2001/04/xmlenc#rsa-1_5')], + new KeyInfo([ + new KeyName( + StringValue::fromString('IdentityProvider.com SSO Key'), + ), + ]), + KeyTypesValue::fromEnum(KeyTypesEnum::SIGNING), + [ + new EncryptionMethod( + SAMLAnyURIValue::fromString('http://www.w3.org/2001/04/xmlenc#rsa-1_5'), + ), + ], ); $this->assertEquals( @@ -67,35 +79,26 @@ public function testMarshalling(): void } - /** - * Test that creating a KeyDescriptor from scratch with a wrong use fails. - */ - public function testMarshallingWrongUse(): void - { - $this->expectException(AssertionFailedException::class); - $this->expectExceptionMessage('The "use" attribute of a KeyDescriptor can only be "encryption" or "signing".'); - - new KeyDescriptor( - new KeyInfo([new KeyName('IdentityProvider.com SSO Key')]), - 'wrong', - ); - } - - /** * Test that creating a KeyDescriptor from scratch without any optional argument works. */ public function testMarshallingWithoutOptionalParameters(): void { - $kd = new KeyDescriptor(new KeyInfo([new KeyName('IdentityProvider.com SSO Key')])); + $kd = new KeyDescriptor( + new KeyInfo([ + new KeyName( + StringValue::fromString('IdentityProvider.com SSO Key'), + ), + ]), + ); $this->assertNull($kd->getUse()); $this->assertEmpty($kd->getEncryptionMethod()); $this->assertEquals( << - + + IdentityProvider.com SSO Key @@ -117,8 +120,8 @@ public function testUnmarshallingWithWrongUse(): void $xmlRepresentation = clone self::$xmlRepresentation; $xmlRepresentation->documentElement->setAttribute('use', 'wrong'); - $this->expectException(AssertionFailedException::class); - $this->expectExceptionMessage('The "use" attribute of a KeyDescriptor can only be "encryption" or "signing".'); + $this->expectException(SchemaViolationException::class); + $this->expectExceptionMessage('Expected one of: "signing", "encryption". Got: "wrong"'); KeyDescriptor::fromXML($xmlRepresentation->documentElement); } @@ -131,8 +134,8 @@ public function testUnmarshallingWithoutOptionalParameters(): void { $document = DOMDocumentFactory::fromString( << - + + IdentityProvider.com SSO Key diff --git a/tests/SAML2/XML/md/NameIDFormatTest.php b/tests/SAML2/XML/md/NameIDFormatTest.php index 9df3b5b21..ee2cb9e07 100644 --- a/tests/SAML2/XML/md/NameIDFormatTest.php +++ b/tests/SAML2/XML/md/NameIDFormatTest.php @@ -8,6 +8,7 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\NameIDFormat; use SimpleSAML\XML\DOMDocumentFactory; @@ -50,7 +51,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $nameIdFormat = new NameIDFormat(C::NAMEID_PERSISTENT); + $nameIdFormat = new NameIDFormat( + SAMLAnyURIValue::fromString(C::NAMEID_PERSISTENT), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/md/NameIDMappingServiceTest.php b/tests/SAML2/XML/md/NameIDMappingServiceTest.php index 349c5eb0a..ea1ecce2d 100644 --- a/tests/SAML2/XML/md/NameIDMappingServiceTest.php +++ b/tests/SAML2/XML/md/NameIDMappingServiceTest.php @@ -8,6 +8,7 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\NameIDMappingService; use SimpleSAML\Test\SAML2\Constants as C; @@ -52,7 +53,10 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $nidmsep = new NameIDMappingService(C::BINDING_HTTP_POST, C::LOCATION_A); + $nidmsep = new NameIDMappingService( + SAMLAnyURIValue::fromString(C::BINDING_HTTP_POST), + SAMLAnyURIValue::fromString(C::LOCATION_A), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), @@ -70,7 +74,12 @@ public function testMarshallingWithResponseLocation(): void $this->expectExceptionMessage( 'The \'ResponseLocation\' attribute must be omitted for md:NameIDMappingService.', ); - new NameIDMappingService(C::BINDING_HTTP_POST, C::LOCATION_A, 'https://response.location/'); + + new NameIDMappingService( + SAMLAnyURIValue::fromString(C::BINDING_HTTP_POST), + SAMLAnyURIValue::fromString(C::LOCATION_A), + SAMLAnyURIValue::fromString('https://response.location/'), + ); } diff --git a/tests/SAML2/XML/md/OrganizationDisplayNameTest.php b/tests/SAML2/XML/md/OrganizationDisplayNameTest.php index 3dd660e89..a933446ab 100644 --- a/tests/SAML2/XML/md/OrganizationDisplayNameTest.php +++ b/tests/SAML2/XML/md/OrganizationDisplayNameTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\OrganizationDisplayName; @@ -14,6 +15,7 @@ use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\LanguageValue; use function dirname; use function strval; @@ -56,7 +58,10 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $name = new OrganizationDisplayName('en', 'Identity Providers R US, a Division of Lerxst Corp.'); + $name = new OrganizationDisplayName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Identity Providers R US, a Division of Lerxst Corp.'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/md/OrganizationNameTest.php b/tests/SAML2/XML/md/OrganizationNameTest.php index 9a7de991a..ca3d686e8 100644 --- a/tests/SAML2/XML/md/OrganizationNameTest.php +++ b/tests/SAML2/XML/md/OrganizationNameTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\OrganizationName; @@ -14,6 +15,7 @@ use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\LanguageValue; use function dirname; use function strval; @@ -56,7 +58,10 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $name = new OrganizationName('en', 'Identity Providers R US'); + $name = new OrganizationName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Identity Providers R US'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/md/OrganizationTest.php b/tests/SAML2/XML/md/OrganizationTest.php index 015f48a33..027f72e0c 100644 --- a/tests/SAML2/XML/md/OrganizationTest.php +++ b/tests/SAML2/XML/md/OrganizationTest.php @@ -8,6 +8,8 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\Extensions; use SimpleSAML\SAML2\XML\md\Organization; @@ -21,6 +23,8 @@ use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\LanguageValue; +use SimpleSAML\XMLSchema\Type\StringValue; use function dirname; use function strval; @@ -84,15 +88,30 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $org = new Organization( - [new OrganizationName('en', 'Identity Providers R US')], - [new OrganizationDisplayName('en', 'Identity Providers R US, a Division of Lerxst Corp.')], - [new OrganizationURL('en', 'https://IdentityProvider.com')], + [ + new OrganizationName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Identity Providers R US'), + ), + ], + [ + new OrganizationDisplayName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Identity Providers R US, a Division of Lerxst Corp.'), + ), + ], + [ + new OrganizationURL( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('https://IdentityProvider.com'), + ), + ], new Extensions( [ new Chunk(self::$ext->documentElement), ], ), - [new XMLAttribute(C::NAMESPACE, 'ssp', 'attr1', 'value1')], + [new XMLAttribute(C::NAMESPACE, 'ssp', 'attr1', StringValue::fromString('value1'))], ); $this->assertEquals( diff --git a/tests/SAML2/XML/md/OrganizationURLTest.php b/tests/SAML2/XML/md/OrganizationURLTest.php index e6decbacf..7a8fa3ac5 100644 --- a/tests/SAML2/XML/md/OrganizationURLTest.php +++ b/tests/SAML2/XML/md/OrganizationURLTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; use SimpleSAML\SAML2\XML\md\AbstractLocalizedURI; use SimpleSAML\SAML2\XML\md\AbstractMdElement; @@ -15,6 +16,7 @@ use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\LanguageValue; use function dirname; use function strval; @@ -58,7 +60,10 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $name = new OrganizationURL('en', 'https://IdentityProvider.com'); + $name = new OrganizationURL( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('https://IdentityProvider.com'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/md/PDPDescriptorTest.php b/tests/SAML2/XML/md/PDPDescriptorTest.php index a04a6441e..e845c1619 100644 --- a/tests/SAML2/XML/md/PDPDescriptorTest.php +++ b/tests/SAML2/XML/md/PDPDescriptorTest.php @@ -9,6 +9,8 @@ use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\AnyURIListValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\AbstractMetadataDocument; use SimpleSAML\SAML2\XML\md\AbstractRoleDescriptor; @@ -21,6 +23,7 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -63,13 +66,13 @@ public static function setUpBeforeClass(): void ); self::$authzService = new AuthzService( - C::BINDING_SOAP, - 'https://IdentityProvider.com/SAML/AA/SOAP', + SAMLAnyURIValue::fromString(C::BINDING_SOAP), + SAMLAnyURIValue::fromString('https://IdentityProvider.com/SAML/AA/SOAP'), ); self::$assertionIDRequestService = new AssertionIDRequestService( - C::BINDING_URI, - 'https://IdentityProvider.com/SAML/AA/URI', + SAMLAnyURIValue::fromString(C::BINDING_URI), + SAMLAnyURIValue::fromString('https://IdentityProvider.com/SAML/AA/URI'), ); } @@ -84,14 +87,20 @@ public function testMarshalling(): void { $pdpd = new PDPDescriptor( [self::$authzService], - ["urn:oasis:names:tc:SAML:2.0:protocol"], + AnyURIListValue::fromString(C::NS_SAMLP), [self::$assertionIDRequestService], [ - new NameIDFormat(C::NAMEID_X509_SUBJECT_NAME), - new NameIDFormat(C::NAMEID_PERSISTENT), - new NameIDFormat(C::NAMEID_TRANSIENT), + new NameIDFormat( + SAMLAnyURIValue::fromString(C::NAMEID_X509_SUBJECT_NAME), + ), + new NameIDFormat( + SAMLAnyURIValue::fromString(C::NAMEID_PERSISTENT), + ), + new NameIDFormat( + SAMLAnyURIValue::fromString(C::NAMEID_TRANSIENT), + ), ], - 'phpunit', + IDValue::fromString('phpunit'), ); $this->assertEquals( @@ -112,7 +121,7 @@ public function testMarshallingWithWrongAuthzService(): void new PDPDescriptor( /** @phpstan-ignore argument.type */ [self::$authzService, self::$assertionIDRequestService], - ["urn:oasis:names:tc:SAML:2.0:protocol"], + AnyURIListValue::fromString(C::NS_SAMLP), ); } @@ -129,7 +138,7 @@ public function testMarshallingWithWrongAssertionIDRequestService(): void new PDPDescriptor( [self::$authzService], - ["urn:oasis:names:tc:SAML:2.0:protocol"], + AnyURIListValue::fromString(C::NS_SAMLP), /** @phpstan-ignore argument.type */ [self::$assertionIDRequestService, self::$authzService], ); @@ -143,7 +152,7 @@ public function testMarshallingWithoutOptionalArguments(): void { $pdpd = new PDPDescriptor( [self::$authzService], - ["urn:oasis:names:tc:SAML:2.0:protocol"], + AnyURIListValue::fromString(C::NS_SAMLP), ); $this->assertEmpty($pdpd->getAssertionIDRequestService()); $this->assertEmpty($pdpd->getNameIDFormat()); diff --git a/tests/SAML2/XML/md/RequestedAttributeTest.php b/tests/SAML2/XML/md/RequestedAttributeTest.php index 44da963cc..b555f7570 100644 --- a/tests/SAML2/XML/md/RequestedAttributeTest.php +++ b/tests/SAML2/XML/md/RequestedAttributeTest.php @@ -7,14 +7,16 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\RequestedAttribute; use SimpleSAML\SAML2\XML\saml\AttributeValue; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\BooleanValue; use function dirname; use function strval; @@ -54,11 +56,13 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $ra = new RequestedAttribute( - 'attr', - true, - C::NAMEFORMAT_BASIC, - 'Attribute', - [new AttributeValue('value1')], + SAMLStringValue::fromString('attr'), + BooleanValue::fromBoolean(true), + SAMLAnyURIValue::fromString(C::NAMEFORMAT_BASIC), + SAMLStringValue::fromString('Attribute'), + [ + new AttributeValue('value1'), + ], ); $this->assertEquals( @@ -73,29 +77,13 @@ public function testMarshalling(): void */ public function testMarshallingWithoutOptionalArguments(): void { - $ra = new RequestedAttribute('attr'); - $this->assertEquals('attr', $ra->getName()); + $ra = new RequestedAttribute( + SAMLStringValue::fromString('attr'), + ); + $this->assertEquals('attr', $ra->getName()->getValue()); $this->assertNull($ra->getIsRequired()); $this->assertNull($ra->getNameFormat()); $this->assertNull($ra->getFriendlyName()); $this->assertEquals([], $ra->getAttributeValues()); } - - - // test unmarshalling - - - /** - * Test that creating a RequestedAttribute object from XML fails when isRequired is not boolean. - */ - public function testUnmarshallingWithWrongIsRequired(): void - { - $xmlRepresentation = clone self::$xmlRepresentation; - $xmlRepresentation->documentElement->setAttribute('isRequired', 'wrong'); - - $this->expectException(AssertionFailedException::class); - $this->expectExceptionMessage('The \'isRequired\' attribute of md:RequestedAttribute must be a boolean.'); - - RequestedAttribute::fromXML($xmlRepresentation->documentElement); - } } diff --git a/tests/SAML2/XML/md/RoleDescriptorTest.php b/tests/SAML2/XML/md/RoleDescriptorTest.php index 4d002064e..fca7b349b 100644 --- a/tests/SAML2/XML/md/RoleDescriptorTest.php +++ b/tests/SAML2/XML/md/RoleDescriptorTest.php @@ -4,13 +4,18 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use DateTimeImmutable; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Compat\AbstractContainer; use SimpleSAML\SAML2\Compat\ContainerSingleton; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\AnyURIListValue; +use SimpleSAML\SAML2\Type\EmailAddressValue; +use SimpleSAML\SAML2\Type\KeyTypesValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\AbstractMetadataDocument; use SimpleSAML\SAML2\XML\md\AbstractRoleDescriptor; @@ -23,6 +28,7 @@ use SimpleSAML\SAML2\XML\md\Extensions; use SimpleSAML\SAML2\XML\md\GivenName; use SimpleSAML\SAML2\XML\md\KeyDescriptor; +use SimpleSAML\SAML2\XML\md\KeyTypesEnum; use SimpleSAML\SAML2\XML\md\Organization; use SimpleSAML\SAML2\XML\md\OrganizationDisplayName; use SimpleSAML\SAML2\XML\md\OrganizationName; @@ -35,9 +41,15 @@ use SimpleSAML\XML\Attribute as XMLAttribute; use SimpleSAML\XML\Chunk; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Constants as C_XSI; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Type\AnyURIValue; +use SimpleSAML\XMLSchema\Type\DurationValue; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\LanguageValue; +use SimpleSAML\XMLSchema\Type\StringValue; use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; use SimpleSAML\XMLSecurity\XML\ds\KeyName; @@ -86,14 +98,6 @@ public static function setUpBeforeClass(): void } - public function setUp(): void - { - self::$xmlRepresentation = DOMDocumentFactory::fromFile( - dirname(dirname(dirname(dirname(__FILE__)))) . '/resources/xml/md_RoleDescriptor.xml', - ); - } - - /** */ public static function tearDownAfterClass(): void @@ -109,9 +113,9 @@ public static function tearDownAfterClass(): void */ public function testMarshalling(): void { - $attr_cp_1 = new XMLAttribute('urn:test:something', 'test', 'attr1', 'testval1'); - $attr_cp_2 = new XMLAttribute('urn:test:something', 'test', 'attr2', 'testval2'); - $attr_3 = new XMLAttribute('urn:x-simplesamlphp:namespace', 'ssp', 'phpunit', 'test'); + $attr_cp_1 = new XMLAttribute('urn:test:something', 'test', 'attr1', StringValue::fromString('testval1')); + $attr_cp_2 = new XMLAttribute('urn:test:something', 'test', 'attr2', StringValue::fromString('testval2')); + $attr_3 = new XMLAttribute('urn:x-simplesamlphp:namespace', 'ssp', 'phpunit', StringValue::fromString('test')); $roleDescriptor = new CustomRoleDescriptor( [ @@ -119,48 +123,95 @@ public function testMarshalling(): void 'Some', )->documentElement), ], - [C::NS_SAMLP, C::PROTOCOL], - 'TheID', - new DateTimeImmutable('2009-02-13T23:31:30Z'), - 'PT5000S', - new Extensions([new Chunk( - DOMDocumentFactory::fromString( - 'Some', - )->documentElement, - )]), - 'https://error.reporting/', + AnyURIListValue::fromArray([C::NS_SAMLP, C::PROTOCOL]), + IDValue::fromString('TheID'), + SAMLDateTimeValue::fromString('2009-02-13T23:31:30Z'), + DurationValue::fromString('PT5000S'), + new Extensions([ + new Chunk( + DOMDocumentFactory::fromString( + 'Some', + )->documentElement, + ), + ]), + SAMLAnyURIValue::fromString('https://error.reporting/'), [ new KeyDescriptor( - new KeyInfo([new KeyName('IdentityProvider.com SSO Signing Key')]), - 'signing', + new KeyInfo([ + new KeyName( + StringValue::fromString('IdentityProvider.com SSO Signing Key'), + ), + ]), + KeyTypesValue::fromEnum(KeyTypesEnum::SIGNING), ), new KeyDescriptor( - new KeyInfo([new KeyName('IdentityProvider.com SSO Encryption Key')]), - 'encryption', - [new EncryptionMethod(C::KEY_TRANSPORT_OAEP_MGF1P)], + new KeyInfo([ + new KeyName( + StringValue::fromString('IdentityProvider.com SSO Encryption Key'), + ), + ]), + KeyTypesValue::fromEnum(KeyTypesEnum::ENCRYPTION), + [ + new EncryptionMethod( + AnyURIValue::fromString(C::KEY_TRANSPORT_OAEP_MGF1P), + ), + ], ), ], new Organization( - [new OrganizationName('en', 'Identity Providers R US')], - [new OrganizationDisplayName('en', 'Identity Providers R US, a Division of Lerxst Corp.')], - [new OrganizationURL('en', 'https://IdentityProvider.com')], + [ + new OrganizationName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Identity Providers R US'), + ), + ], + [ + new OrganizationDisplayName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Identity Providers R US, a Division of Lerxst Corp.'), + ), + ], + [ + new OrganizationURL( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('https://IdentityProvider.com'), + ), + ], ), [ new ContactPerson( - contactType: 'other', - company: new Company('Test Company'), - givenName: new GivenName('John'), - surName: new SurName('Doe'), + contactType: SAMLStringValue::fromString('other'), + company: new Company( + SAMLStringValue::fromString('Test Company'), + ), + givenName: new GivenName( + SAMLStringValue::fromString('John'), + ), + surName: new SurName( + SAMLStringValue::fromString('Doe'), + ), emailAddress: [ - new EmailAddress('mailto:jdoe@test.company'), - new EmailAddress('mailto:john.doe@test.company'), + new EmailAddress( + EmailAddressValue::fromString('mailto:jdoe@test.company'), + ), + new EmailAddress( + EmailAddressValue::fromString('mailto:john.doe@test.company'), + ), + ], + telephoneNumber: [ + new TelephoneNumber( + SAMLStringValue::fromString('1-234-567-8901'), + ), ], - telephoneNumber: [new TelephoneNumber('1-234-567-8901')], namespacedAttribute: [$attr_cp_1, $attr_cp_2], ), new ContactPerson( - contactType: 'technical', - telephoneNumber: [new TelephoneNumber('1-234-567-8901')], + contactType: SAMLStringValue::fromString('technical'), + telephoneNumber: [ + new TelephoneNumber( + SAMLStringValue::fromString('1-234-567-8901'), + ), + ], ), ], [$attr_3], @@ -183,22 +234,22 @@ public function testUnmarshalling(): void { $descriptor = AbstractRoleDescriptor::fromXML(self::$xmlRepresentation->documentElement); - $this->assertInstanceOf(CustomRoleDescriptor::class, $descriptor); + $this->assertInstanceOf(AbstractRoleDescriptor::class, $descriptor); $this->assertCount(2, $descriptor->getKeyDescriptor()); $this->assertInstanceOf(KeyDescriptor::class, $descriptor->getKeyDescriptor()[0]); $this->assertInstanceOf(KeyDescriptor::class, $descriptor->getKeyDescriptor()[1]); $this->assertEquals( [C::NS_SAMLP, C::PROTOCOL], - $descriptor->getProtocolSupportEnumeration(), + $descriptor->getProtocolSupportEnumeration()->toArray(), ); $this->assertInstanceOf(Organization::class, $descriptor->getOrganization()); $this->assertCount(2, $descriptor->getContactPerson()); $this->assertInstanceOf(ContactPerson::class, $descriptor->getContactPerson()[0]); $this->assertInstanceOf(ContactPerson::class, $descriptor->getContactPerson()[1]); $this->assertEquals('TheID', $descriptor->getID()); - $this->assertEquals('2009-02-13T23:31:30Z', $descriptor->getValidUntil()->format(C::DATETIME_FORMAT)); - $this->assertEquals('PT5000S', $descriptor->getCacheDuration()); - $this->assertEquals('https://error.reporting/', $descriptor->getErrorURL()); + $this->assertEquals('2009-02-13T23:31:30Z', $descriptor->getValidUntil()->getValue()); + $this->assertEquals('PT5000S', $descriptor->getCacheDuration()->getValue()); + $this->assertEquals('https://error.reporting/', $descriptor->getErrorURL()->getValue()); $extElement = $descriptor->getExtensions(); $this->assertInstanceOf(Extensions::class, $extElement); @@ -220,14 +271,15 @@ public function testUnmarshalling(): void */ public function testUnmarshallingUnregistered(): void { - $element = self::$xmlRepresentation->documentElement; - $element->setAttributeNS( - 'http://www.w3.org/2000/xmlns/', - 'xmlns:ssp', - 'urn:x-simplesamlphp:namespace', + $element = clone self::$xmlRepresentation->documentElement; + $element->setAttributeNS(C_XSI::NS_XSI, 'xsi:type', 'ssp:UnknownRoleDescriptorType'); + + $type = new XMLAttribute( + C_XSI::NS_XSI, + 'xsi', + 'type', + StringValue::fromString('ssp:UnknownRoleDescriptorType'), ); - - $type = new XMLAttribute(C::NS_XSI, 'xsi', 'type', 'ssp:UnknownRoleDescriptorType'); $type->toXML($element); $descriptor = AbstractRoleDescriptor::fromXML($element); @@ -238,16 +290,16 @@ public function testUnmarshallingUnregistered(): void $this->assertInstanceOf(KeyDescriptor::class, $descriptor->getKeyDescriptor()[1]); $this->assertEquals( [C::NS_SAMLP, C::PROTOCOL], - $descriptor->getProtocolSupportEnumeration(), + $descriptor->getProtocolSupportEnumeration()->toArray(), ); $this->assertInstanceOf(Organization::class, $descriptor->getOrganization()); $this->assertCount(2, $descriptor->getContactPerson()); $this->assertInstanceOf(ContactPerson::class, $descriptor->getContactPerson()[0]); $this->assertInstanceOf(ContactPerson::class, $descriptor->getContactPerson()[1]); - $this->assertEquals('TheID', $descriptor->getID()); - $this->assertEquals('2009-02-13T23:31:30Z', $descriptor->getValidUntil()->format(C::DATETIME_FORMAT)); - $this->assertEquals('PT5000S', $descriptor->getCacheDuration()); - $this->assertEquals('https://error.reporting/', $descriptor->getErrorURL()); + $this->assertEquals('TheID', $descriptor->getID()->getValue()); + $this->assertEquals('2009-02-13T23:31:30Z', $descriptor->getValidUntil()->getValue()); + $this->assertEquals('PT5000S', $descriptor->getCacheDuration()->getValue()); + $this->assertEquals('https://error.reporting/', $descriptor->getErrorURL()->getValue()); $chunk = $descriptor->getRawRoleDescriptor(); $this->assertEquals('md', $chunk->getPrefix()); @@ -263,7 +315,7 @@ public function testUnmarshallingUnregistered(): void $this->assertEquals('urn:x-simplesamlphp:namespace', $extensions[0]->getNamespaceURI()); $this->assertEquals('Chunk', $extensions[0]->getLocalName()); - $this->assertEquals($element->ownerDocument->saveXML($element), strval($chunk)); + $this->assertEquals($element->ownerDocument?->saveXML($element), strval($descriptor)); } @@ -272,14 +324,15 @@ public function testUnmarshallingUnregistered(): void */ public function testUnmarshallingWithoutSupportedProtocols(): void { - self::$xmlRepresentation->documentElement->removeAttribute('protocolSupportEnumeration'); + $element = clone self::$xmlRepresentation->documentElement; + $element->removeAttribute('protocolSupportEnumeration'); $this->expectException(MissingAttributeException::class); $this->expectExceptionMessage( 'Missing \'protocolSupportEnumeration\' attribute on md:RoleDescriptor.', ); - UnknownRoleDescriptor::fromXML(self::$xmlRepresentation->documentElement); + UnknownRoleDescriptor::fromXML($element); } @@ -288,23 +341,11 @@ public function testUnmarshallingWithoutSupportedProtocols(): void */ public function testUnmarshallingWithEmptySupportedProtocols(): void { - self::$xmlRepresentation->documentElement->setAttribute('protocolSupportEnumeration', ''); - - $this->expectException(ProtocolViolationException::class); - - UnknownRoleDescriptor::fromXML(self::$xmlRepresentation->documentElement); - } - - - /** - * Test that creating an UnknownRoleDescriptor from XML fails if errorURL is not a valid URL. - */ - public function testUnmarshallingWithInvalidErrorURL(): void - { - self::$xmlRepresentation->documentElement->setAttribute('errorURL', 'not a URL'); + $element = clone self::$xmlRepresentation->documentElement; + $element->setAttribute('protocolSupportEnumeration', ''); $this->expectException(ProtocolViolationException::class); - UnknownRoleDescriptor::fromXML(self::$xmlRepresentation->documentElement); + UnknownRoleDescriptor::fromXML($element); } } diff --git a/tests/SAML2/XML/md/SPSSODescriptorTest.php b/tests/SAML2/XML/md/SPSSODescriptorTest.php index 6d6b96d2a..24140b0b9 100644 --- a/tests/SAML2/XML/md/SPSSODescriptorTest.php +++ b/tests/SAML2/XML/md/SPSSODescriptorTest.php @@ -4,11 +4,16 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use DateTimeImmutable; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; +use SimpleSAML\SAML2\Type\AnyURIListValue; +use SimpleSAML\SAML2\Type\EmailAddressValue; +use SimpleSAML\SAML2\Type\KeyTypesValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\AbstractMetadataDocument; use SimpleSAML\SAML2\XML\md\AbstractRoleDescriptor; @@ -21,6 +26,7 @@ use SimpleSAML\SAML2\XML\md\EmailAddress; use SimpleSAML\SAML2\XML\md\Extensions; use SimpleSAML\SAML2\XML\md\KeyDescriptor; +use SimpleSAML\SAML2\XML\md\KeyTypesEnum; use SimpleSAML\SAML2\XML\md\ManageNameIDService; use SimpleSAML\SAML2\XML\md\NameIDFormat; use SimpleSAML\SAML2\XML\md\Organization; @@ -38,6 +44,13 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\SchemaViolationException; +use SimpleSAML\XMLSchema\Type\BooleanValue; +use SimpleSAML\XMLSchema\Type\DurationValue; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\LanguageValue; +use SimpleSAML\XMLSchema\Type\StringValue; +use SimpleSAML\XMLSchema\Type\UnsignedShortValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; use SimpleSAML\XMLSecurity\XML\ds\KeyName; @@ -85,80 +98,136 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $slo1 = new SingleLogoutService( - C::BINDING_SOAP, - 'https://ServiceProvider.com/SAML/SLO/SOAP', + SAMLAnyURIValue::fromString(C::BINDING_SOAP), + SAMLAnyURIValue::fromString('https://ServiceProvider.com/SAML/SLO/SOAP'), ); $slo2 = new SingleLogoutService( - C::BINDING_HTTP_REDIRECT, - 'https://ServiceProvider.com/SAML/SLO/Browser', - 'https://ServiceProvider.com/SAML/SLO/Response', + SAMLAnyURIValue::fromString(C::BINDING_HTTP_REDIRECT), + SAMLAnyURIValue::fromString('https://ServiceProvider.com/SAML/SLO/Browser'), + SAMLAnyURIValue::fromString('https://ServiceProvider.com/SAML/SLO/Response'), ); $acs1 = new AssertionConsumerService( - 0, - C::BINDING_HTTP_ARTIFACT, - 'https://ServiceProvider.com/SAML/SSO/Artifact', - true, + UnsignedShortValue::fromInteger(0), + SAMLAnyURIValue::fromString(C::BINDING_HTTP_ARTIFACT), + SAMLAnyURIValue::fromString('https://ServiceProvider.com/SAML/SSO/Artifact'), + BooleanValue::fromBoolean(true), ); $acs2 = new AssertionConsumerService( - 1, - C::BINDING_HTTP_POST, - 'https://ServiceProvider.com/SAML/SSO/POST', + UnsignedShortValue::fromInteger(1), + SAMLAnyURIValue::fromString(C::BINDING_HTTP_POST), + SAMLAnyURIValue::fromString('https://ServiceProvider.com/SAML/SSO/POST'), ); $reqAttr = new RequestedAttribute( - Name: 'urn:oid:1.3.6.1.4.1.5923.1.1.1.7', - NameFormat: C::NAMEFORMAT_URI, - FriendlyName: 'eduPersonEntitlement', - AttributeValues: [new AttributeValue('https://ServiceProvider.com/entitlements/123456789')], + Name: SAMLStringValue::fromString('urn:oid:1.3.6.1.4.1.5923.1.1.1.7'), + NameFormat: SAMLAnyURIValue::fromString(C::NAMEFORMAT_URI), + FriendlyName: SAMLStringValue::fromString('eduPersonEntitlement'), + AttributeValues: [ + new AttributeValue( + 'https://ServiceProvider.com/entitlements/123456789', + ), + ], ); $attrcs1 = new AttributeConsumingService( - 0, - [new ServiceName('en', 'Academic Journals R US')], + UnsignedShortValue::fromInteger(0), + [ + new ServiceName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Academic Journals R US'), + ), + ], [$reqAttr], - true, + BooleanValue::fromBoolean(true), ); $attrcs2 = new AttributeConsumingService( - 1, - [new ServiceName('en', 'Academic Journals R US')], + UnsignedShortValue::fromInteger(1), + [ + new ServiceName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Academic Journals R US'), + ), + ], [$reqAttr], ); $extensions = new Extensions([ new PublicationInfo( - publisher: 'http://publisher.ra/', - creationInstant: new DateTimeImmutable('2020-02-03T13:46:24Z'), - usagePolicy: [new UsagePolicy('en', 'http://publisher.ra/policy.txt')], + publisher: SAMLStringValue::fromString('http://publisher.ra/'), + creationInstant: SAMLDateTimeValue::fromString('2020-02-03T13:46:24Z'), + usagePolicy: [ + new UsagePolicy( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('http://publisher.ra/policy.txt'), + ), + ], ), ]); - $kd = new KeyDescriptor(new KeyInfo([new KeyName('ServiceProvider.com SSO Key')]), 'signing'); + $kd = new KeyDescriptor( + new KeyInfo([ + new KeyName( + StringValue::fromString('ServiceProvider.com SSO Key'), + ), + ]), + KeyTypesValue::fromEnum(KeyTypesEnum::SIGNING), + ); $org = new Organization( - [new OrganizationName('en', 'Identity Providers R US')], - [new OrganizationDisplayName('en', 'Identity Providers R US, a Division of Lerxst Corp.')], - [new OrganizationURL('en', 'https://IdentityProvider.com')], + [ + new OrganizationName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Identity Providers R US'), + ), + ], + [ + new OrganizationDisplayName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Identity Providers R US, a Division of Lerxst Corp.'), + ), + ], + [ + new OrganizationURL( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('https://IdentityProvider.com'), + ), + ], ); $contact = new ContactPerson( - contactType: 'other', - emailAddress: [new EmailAddress('john.doe@test.company')], + contactType: SAMLStringValue::fromString('other'), + emailAddress: [ + new EmailAddress( + EmailAddressValue::fromString('john.doe@test.company'), + ), + ], + ); + $ars = new ArtifactResolutionService( + UnsignedShortValue::fromInteger(0), + SAMLAnyURIValue::fromString(C::BINDING_HTTP_ARTIFACT), + SAMLAnyURIValue::fromString(C::LOCATION_A), + ); + $mnids = new ManageNameIDService( + SAMLAnyURIValue::fromString(C::BINDING_HTTP_POST), + SAMLAnyURIValue::fromString(C::LOCATION_B), ); - $ars = new ArtifactResolutionService(0, C::BINDING_HTTP_ARTIFACT, C::LOCATION_A); - $mnids = new ManageNameIDService(C::BINDING_HTTP_POST, C::LOCATION_B); $spssod = new SPSSODescriptor( [$acs1, $acs2], - [C::NS_SAMLP], - true, - false, + AnyURIListValue::fromString(C::NS_SAMLP), + BooleanValue::fromBoolean(true), + BooleanValue::fromBoolean(false), [$attrcs1, $attrcs2], - 'someID', - new DateTimeImmutable('2010-02-01T12:34:56Z'), - 'PT9000S', + IDValue::fromString('someID'), + SAMLDateTimeValue::fromString('2010-02-01T12:34:56Z'), + DurationValue::fromString('PT9000S'), $extensions, - 'https://error.url/', + SAMLAnyURIValue::fromString('https://error.url/'), [$kd], $org, [$contact], [$ars], [$slo1, $slo2], [$mnids], - [new NameIDFormat(C::NAMEID_TRANSIENT)], + [ + new NameIDFormat( + SAMLAnyURIValue::fromString(C::NAMEID_TRANSIENT), + ), + ], ); $this->assertEquals( @@ -178,7 +247,7 @@ public function testMarshallingWithoutAssertionConsumerService(): void new SPSSODescriptor( [], - [C::NS_SAMLP], + AnyURIListValue::fromString(C::NS_SAMLP), ); } @@ -189,8 +258,14 @@ public function testMarshallingWithoutAssertionConsumerService(): void public function testMarshallingWithoutOptionalArguments(): void { $spssod = new SPSSODescriptor( - [new AssertionConsumerService(0, C::BINDING_HTTP_POST, C::LOCATION_A)], - [C::NS_SAMLP], + [ + new AssertionConsumerService( + UnsignedShortValue::fromInteger(0), + SAMLAnyURIValue::fromString(C::BINDING_HTTP_POST), + SAMLAnyURIValue::fromString(C::LOCATION_A), + ), + ], + AnyURIListValue::fromString(C::NS_SAMLP), ); $this->assertNull($spssod->getAuthnRequestsSigned()); @@ -228,9 +303,7 @@ public function testUnmarshallingWithNonBooleanAuthnRequestsSigned(): void $xmlRepresentation = clone self::$xmlRepresentation; $xmlRepresentation->documentElement->setAttribute('AuthnRequestsSigned', 'not a boolean'); - $this->expectException(AssertionFailedException::class); - $this->expectExceptionMessage('The \'AuthnRequestsSigned\' attribute of md:SPSSODescriptor must be a boolean.'); - + $this->expectException(SchemaViolationException::class); SPSSODescriptor::fromXML($xmlRepresentation->documentElement); } @@ -243,11 +316,7 @@ public function testUnmarshallingWithNonBooleanWantAssertionsSigned(): void $xmlRepresentation = clone self::$xmlRepresentation; $xmlRepresentation->documentElement->setAttribute('WantAssertionsSigned', 'not a boolean'); - $this->expectException(AssertionFailedException::class); - $this->expectExceptionMessage( - 'The \'WantAssertionsSigned\' attribute of md:SPSSODescriptor must be a boolean.', - ); - + $this->expectException(SchemaViolationException::class); SPSSODescriptor::fromXML($xmlRepresentation->documentElement); } diff --git a/tests/SAML2/XML/md/ServiceDescriptionTest.php b/tests/SAML2/XML/md/ServiceDescriptionTest.php index 9073457ea..e8c5a54fe 100644 --- a/tests/SAML2/XML/md/ServiceDescriptionTest.php +++ b/tests/SAML2/XML/md/ServiceDescriptionTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\ServiceDescription; @@ -14,6 +15,7 @@ use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\LanguageValue; use function dirname; use function strval; @@ -56,7 +58,10 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $name = new ServiceDescription('en', 'Academic Journals R US and only us'); + $name = new ServiceDescription( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Academic Journals R US and only us'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/md/ServiceNameTest.php b/tests/SAML2/XML/md/ServiceNameTest.php index abd7928e7..f6cbb202d 100644 --- a/tests/SAML2/XML/md/ServiceNameTest.php +++ b/tests/SAML2/XML/md/ServiceNameTest.php @@ -7,9 +7,8 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\ServiceName; @@ -17,6 +16,8 @@ use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Type\LanguageValue; use function dirname; use function strval; @@ -59,7 +60,10 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $name = new ServiceName('en', 'Academic Journals R US'); + $name = new ServiceName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Academic Journals R US'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), @@ -68,18 +72,6 @@ public function testMarshalling(): void } - /** - * Test that creating a ServiceName from scratch with an empty language fails. - */ - public function testMarshallingWithEmptyLang(): void - { - $this->expectException(ProtocolViolationException::class); - $this->expectExceptionMessage('Expected a non-whitespace string. Got: ""'); - - new ServiceName('', 'Academic Journals R US'); - } - - // test unmarshalling @@ -91,24 +83,9 @@ public function testUnmarshallingWithoutLang(): void $xmlRepresentation = clone self::$xmlRepresentation; $xmlRepresentation->documentElement->removeAttributeNS(C::NS_XML, 'lang'); - $this->expectException(AssertionFailedException::class); + $this->expectException(MissingAttributeException::class); $this->expectExceptionMessage('Missing xml:lang from ServiceName'); ServiceName::fromXML($xmlRepresentation->documentElement); } - - - /** - * Test that creating a ServiceName from XML fails when xml:lang is empty. - */ - public function testUnmarshallingWithEmptyLang(): void - { - $xmlRepresentation = clone self::$xmlRepresentation; - $xmlRepresentation->documentElement->setAttributeNS(C::NS_XML, 'lang', ''); - - $this->expectException(ProtocolViolationException::class); - $this->expectExceptionMessage('Expected a non-whitespace string. Got: ""'); - - ServiceName::fromXML($xmlRepresentation->documentElement); - } } diff --git a/tests/SAML2/XML/md/SingleSignOnServiceTest.php b/tests/SAML2/XML/md/SingleSignOnServiceTest.php index fb0270489..9be2f2d66 100644 --- a/tests/SAML2/XML/md/SingleSignOnServiceTest.php +++ b/tests/SAML2/XML/md/SingleSignOnServiceTest.php @@ -7,7 +7,8 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use SimpleSAML\Assert\AssertionFailedException; +use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\SingleSignOnService; use SimpleSAML\Test\SAML2\Constants as C; @@ -52,7 +53,10 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $ssoep = new SingleSignOnService(C::BINDING_HTTP_POST, C::LOCATION_A); + $ssoep = new SingleSignOnService( + SAMLAnyURIValue::fromString(C::BINDING_HTTP_POST), + SAMLAnyURIValue::fromString(C::LOCATION_A), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), @@ -66,12 +70,16 @@ public function testMarshalling(): void */ public function testMarshallingWithResponseLocation(): void { - $this->expectException(AssertionFailedException::class); + $this->expectException(ProtocolViolationException::class); $this->expectExceptionMessage( 'The \'ResponseLocation\' attribute must be omitted for md:SingleSignOnService.', ); - new SingleSignOnService(C::BINDING_HTTP_POST, C::LOCATION_A, 'https://response.location/'); + new SingleSignOnService( + SAMLAnyURIValue::fromString(C::BINDING_HTTP_POST), + SAMLAnyURIValue::fromString(C::LOCATION_A), + SAMLAnyURIValue::fromString('https://response.location/'), + ); } @@ -86,7 +94,7 @@ public function testUnmarshallingWithResponseLocation(): void $xmlRepresentation = clone self::$xmlRepresentation; $xmlRepresentation->documentElement->setAttribute('ResponseLocation', 'https://response.location/'); - $this->expectException(AssertionFailedException::class); + $this->expectException(ProtocolViolationException::class); $this->expectExceptionMessage( 'The \'ResponseLocation\' attribute must be omitted for md:SingleSignOnService.', ); diff --git a/tests/SAML2/XML/md/SurNameTest.php b/tests/SAML2/XML/md/SurNameTest.php index 7b643fec5..0d2c99cc2 100644 --- a/tests/SAML2/XML/md/SurNameTest.php +++ b/tests/SAML2/XML/md/SurNameTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\SurName; use SimpleSAML\XML\DOMDocumentFactory; @@ -50,7 +51,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $name = new SurName('Doe'); + $name = new SurName( + SAMLStringValue::fromString('Doe'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/md/TelephoneNumberTest.php b/tests/SAML2/XML/md/TelephoneNumberTest.php index 1cad00914..f5bb3fe9d 100644 --- a/tests/SAML2/XML/md/TelephoneNumberTest.php +++ b/tests/SAML2/XML/md/TelephoneNumberTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\TelephoneNumber; use SimpleSAML\XML\DOMDocumentFactory; @@ -15,7 +16,7 @@ use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; /** - * Tests for SurName. + * Tests for TelephoneNumber. * * @package simplesamlphp/saml2 */ @@ -47,11 +48,13 @@ public static function setUpBeforeClass(): void /** - * Test creating a TelehponeNumber object from scratch. + * Test creating a TelephoneNumber object from scratch. */ public function testMarshalling(): void { - $name = new TelephoneNumber('+1234567890'); + $name = new TelephoneNumber( + SAMLStringValue::fromString('+1234567890'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/mdattr/EntityAttributesTest.php b/tests/SAML2/XML/mdattr/EntityAttributesTest.php index 04bf98a8a..395074470 100644 --- a/tests/SAML2/XML/mdattr/EntityAttributesTest.php +++ b/tests/SAML2/XML/mdattr/EntityAttributesTest.php @@ -4,10 +4,12 @@ namespace SimpleSAML\Test\SAML2\XML\mdattr; -use DateTimeImmutable; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\mdattr\AbstractMdattrElement; use SimpleSAML\SAML2\XML\mdattr\EntityAttributes; use SimpleSAML\SAML2\XML\saml\Assertion; @@ -24,6 +26,7 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\Alg\Signature\SignatureAlgorithmFactory; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; @@ -61,8 +64,8 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $attribute1 = new Attribute( - name: 'attrib1', - nameFormat: C::NAMEFORMAT_BASIC, + name: SAMLStringValue::fromString('attrib1'), + nameFormat: SAMLAnyURIValue::fromString(C::NAMEFORMAT_BASIC), attributeValue: [ new AttributeValue('is'), new AttributeValue('really'), @@ -71,15 +74,21 @@ public function testMarshalling(): void ); // Create an Issuer - $issuer = new Issuer('urn:x-simplesamlphp:issuer'); + $issuer = new Issuer( + SAMLStringValue::fromString('urn:x-simplesamlphp:issuer'), + ); // Create the conditions $conditions = new Conditions( condition: [], audienceRestriction: [ new AudienceRestriction([ - new Audience(C::ENTITY_IDP), - new Audience(C::ENTITY_URN), + new Audience( + SAMLAnyURIValue::fromString(C::ENTITY_IDP), + ), + new Audience( + SAMLAnyURIValue::fromString(C::ENTITY_URN), + ), ]), ], ); @@ -87,31 +96,31 @@ public function testMarshalling(): void // Create the statements $attrStatement = new AttributeStatement([ new Attribute( - name: 'urn:mace:dir:attribute-def:uid', - nameFormat: C::NAMEFORMAT_URI, + name: SAMLStringValue::fromString('urn:mace:dir:attribute-def:uid'), + nameFormat: SAMLAnyURIValue::fromString(C::NAMEFORMAT_URI), attributeValue: [ new AttributeValue('student2'), ], ), new Attribute( - name: 'urn:mace:terena.org:attribute-def:schacHomeOrganization', - nameFormat: C::NAMEFORMAT_URI, + name: SAMLStringValue::fromString('urn:mace:terena.org:attribute-def:schacHomeOrganization'), + nameFormat: SAMLAnyURIValue::fromString(C::NAMEFORMAT_URI), attributeValue: [ new AttributeValue('university.example.org'), new AttributeValue('bbb.cc'), ], ), new Attribute( - name: 'urn:schac:attribute-def:schacPersonalUniqueCode', - nameFormat: C::NAMEFORMAT_URI, + name: SAMLStringValue::fromString('urn:schac:attribute-def:schacPersonalUniqueCode'), + nameFormat: SAMLAnyURIValue::fromString(C::NAMEFORMAT_URI), attributeValue: [ new AttributeValue('urn:schac:personalUniqueCode:nl:local:uvt.nl:memberid:524020'), new AttributeValue('urn:schac:personalUniqueCode:nl:local:surfnet.nl:studentid:12345'), ], ), new Attribute( - name: 'urn:mace:dir:attribute-def:eduPersonAffiliation', - nameFormat: C::NAMEFORMAT_URI, + name: SAMLStringValue::fromString('urn:mace:dir:attribute-def:eduPersonAffiliation'), + nameFormat: SAMLAnyURIValue::fromString(C::NAMEFORMAT_URI), attributeValue: [ new AttributeValue('member'), new AttributeValue('student'), @@ -119,16 +128,18 @@ public function testMarshalling(): void ), ]); - $subject = new Subject(new NameID( - value: 'some:entity', - Format: C::NAMEID_ENTITY, - )); + $subject = new Subject( + new NameID( + value: SAMLStringValue::fromString('some:entity'), + Format: SAMLAnyURIValue::FromString(C::NAMEID_ENTITY), + ), + ); // Create an assertion $unsignedAssertion = new Assertion( $issuer, - new DateTimeImmutable('2024-07-23T20:35:34Z'), - '_93af655219464fb403b34436cfb0c5cb1d9a5502', + SAMLDateTimeValue::fromString('2024-07-23T20:35:34Z'), + IDValue::fromString('_93af655219464fb403b34436cfb0c5cb1d9a5502'), $subject, $conditions, [$attrStatement], @@ -143,8 +154,8 @@ public function testMarshalling(): void $signedAssertion = Assertion::fromXML($unsignedAssertion->toXML()); $attribute2 = new Attribute( - name: 'foo', - nameFormat: 'urn:simplesamlphp:v1:simplesamlphp', + name: SAMLStringValue::fromString('foo'), + nameFormat: SAMLAnyURIValue::fromString('urn:simplesamlphp:v1:simplesamlphp'), attributeValue: [ new AttributeValue('is'), new AttributeValue('really'), diff --git a/tests/SAML2/XML/mdrpi/PublicationInfoTest.php b/tests/SAML2/XML/mdrpi/PublicationInfoTest.php index 849ff1303..c1fbe7ef1 100644 --- a/tests/SAML2/XML/mdrpi/PublicationInfoTest.php +++ b/tests/SAML2/XML/mdrpi/PublicationInfoTest.php @@ -4,19 +4,28 @@ namespace SimpleSAML\Test\SAML2\XML\mdrpi; -use DateTimeImmutable; +use DOMDocument; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\SAML2\XML\md\AffiliationDescriptor; +use SimpleSAML\SAML2\XML\md\EntitiesDescriptor; +use SimpleSAML\SAML2\XML\md\EntityDescriptor; +use SimpleSAML\SAML2\XML\md\Extensions; use SimpleSAML\SAML2\XML\mdrpi\AbstractMdrpiElement; use SimpleSAML\SAML2\XML\mdrpi\PublicationInfo; use SimpleSAML\SAML2\XML\mdrpi\UsagePolicy; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Type\LanguageValue; use function dirname; use function strval; @@ -36,6 +45,10 @@ final class PublicationInfoTest extends TestCase use SerializableElementTestTrait; + /** @var \DOMDocument */ + private static DOMDocument $affiliationDescriptor; + + /** */ public static function setUpBeforeClass(): void @@ -46,6 +59,10 @@ public static function setUpBeforeClass(): void dirname(__FILE__, 4) . '/resources/xml/mdrpi_PublicationInfo.xml', ); + self::$affiliationDescriptor = DOMDocumentFactory::fromFile( + dirname(__FILE__, 4) . '/resources/xml/md_AffiliationDescriptor.xml', + ); + self::$arrayRepresentation = [ 'publisher' => 'SomePublisher', 'creationInstant' => '2011-01-01T00:00:00Z', @@ -60,12 +77,18 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $publicationInfo = new PublicationInfo( - 'SomePublisher', - new DateTimeImmutable('2011-01-01T00:00:00Z'), - 'SomePublicationId', + SAMLStringValue::fromString('SomePublisher'), + SAMLDateTimeValue::fromString('2011-01-01T00:00:00Z'), + SAMLStringValue::fromString('SomePublicationId'), [ - new UsagePolicy('en', 'http://TheEnglishUsagePolicy'), - new UsagePolicy('no', 'http://TheNorwegianUsagePolicy'), + new UsagePolicy( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('http://TheEnglishUsagePolicy'), + ), + new UsagePolicy( + LanguageValue::fromString('no'), + SAMLAnyURIValue::fromString('http://TheNorwegianUsagePolicy'), + ), ], ); @@ -84,10 +107,6 @@ public function testCreationInstantTimezoneNotZuluThrowsException(): void $document->setAttribute('creationInstant', '2011-01-01T00:00:00WT'); $this->expectException(ProtocolViolationException::class); - $this->expectExceptionMessage( - "\"2011-01-01T00:00:00WT\" is not a DateTime expressed in the UTC timezone" - . " using the 'Z' timezone identifier.", - ); PublicationInfo::fromXML($document); } @@ -119,7 +138,10 @@ public function testMultipleUsagePoliciesWithSameLanguageThrowsException(): void $document = clone self::$xmlRepresentation->documentElement; // Append another 'en' UsagePolicy to the document - $x = new UsagePolicy('en', 'https://example.org'); + $x = new UsagePolicy( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('https://example.org'), + ); $x->toXML($document); $this->expectException(ProtocolViolationException::class); @@ -129,4 +151,29 @@ public function testMultipleUsagePoliciesWithSameLanguageThrowsException(): void ); PublicationInfo::fromXML($document); } + + + /** + */ + public function testNestedPublicationInfoThrowsException(): void + { + $publicationInfo = PublicationInfo::fromXML(self::$xmlRepresentation->documentElement); + $extensions = new Extensions([$publicationInfo]); + + $ed = new EntityDescriptor( + entityId: EntityIDValue::fromString('urn:x-simplesamlphp:entity'), + affiliationDescriptor: AffiliationDescriptor::fromXML(self::$affiliationDescriptor->documentElement), + ); + + $this->expectException(ProtocolViolationException::class); + new EntitiesDescriptor( + extensions: $extensions, + entitiesDescriptors: [ + new EntitiesDescriptor( + extensions: $extensions, + entityDescriptors: [$ed], + ), + ], + ); + } } diff --git a/tests/SAML2/XML/mdrpi/PublicationPathTest.php b/tests/SAML2/XML/mdrpi/PublicationPathTest.php index ed1bfef07..5fc34bd66 100644 --- a/tests/SAML2/XML/mdrpi/PublicationPathTest.php +++ b/tests/SAML2/XML/mdrpi/PublicationPathTest.php @@ -4,10 +4,11 @@ namespace SimpleSAML\Test\SAML2\XML\mdrpi; -use DateTimeImmutable; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\mdrpi\AbstractMdrpiElement; use SimpleSAML\SAML2\XML\mdrpi\Publication; use SimpleSAML\SAML2\XML\mdrpi\PublicationPath; @@ -64,11 +65,15 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $publicationPath = new PublicationPath([ - new Publication('SomePublisher', new DateTimeImmutable('2011-01-01T00:00:00Z'), 'SomePublicationId'), new Publication( - 'SomeOtherPublisher', - new DateTimeImmutable('2011-01-01T00:00:00Z'), - 'SomeOtherPublicationId', + SAMLStringValue::fromString('SomePublisher'), + SAMLDateTimeValue::fromString('2011-01-01T00:00:00Z'), + SAMLStringValue::fromString('SomePublicationId'), + ), + new Publication( + SAMLStringValue::fromString('SomeOtherPublisher'), + SAMLDateTimeValue::fromString('2011-01-01T00:00:00Z'), + SAMLStringValue::fromString('SomeOtherPublicationId'), ), ]); diff --git a/tests/SAML2/XML/mdrpi/PublicationTest.php b/tests/SAML2/XML/mdrpi/PublicationTest.php index 08f6ef11b..a0d07fb9f 100644 --- a/tests/SAML2/XML/mdrpi/PublicationTest.php +++ b/tests/SAML2/XML/mdrpi/PublicationTest.php @@ -4,18 +4,19 @@ namespace SimpleSAML\Test\SAML2\XML\mdrpi; -use DateTimeImmutable; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\mdrpi\AbstractMdrpiElement; use SimpleSAML\SAML2\XML\mdrpi\Publication; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; use function dirname; use function strval; @@ -58,9 +59,9 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $publication = new Publication( - 'SomePublisher', - new DateTimeImmutable('2011-01-01T00:00:00Z'), - 'SomePublicationId', + SAMLStringValue::fromString('SomePublisher'), + SAMLDateTimeValue::fromString('2011-01-01T00:00:00Z'), + SAMLStringValue::fromString('SomePublicationId'), ); $this->assertEquals( @@ -78,10 +79,6 @@ public function testCreationInstantTimezoneNotZuluThrowsException(): void $document->setAttribute('creationInstant', '2011-01-01T00:00:00WT'); $this->expectException(ProtocolViolationException::class); - $this->expectExceptionMessage( - "\"2011-01-01T00:00:00WT\" is not a DateTime expressed in the UTC timezone " - . "using the 'Z' timezone identifier.", - ); Publication::fromXML($document); } diff --git a/tests/SAML2/XML/mdrpi/RegistrationInfoTest.php b/tests/SAML2/XML/mdrpi/RegistrationInfoTest.php index 498146382..7f667e3af 100644 --- a/tests/SAML2/XML/mdrpi/RegistrationInfoTest.php +++ b/tests/SAML2/XML/mdrpi/RegistrationInfoTest.php @@ -4,19 +4,28 @@ namespace SimpleSAML\Test\SAML2\XML\mdrpi; -use DateTimeImmutable; +use DOMDocument; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\SAML2\XML\md\AffiliationDescriptor; +use SimpleSAML\SAML2\XML\md\EntitiesDescriptor; +use SimpleSAML\SAML2\XML\md\EntityDescriptor; +use SimpleSAML\SAML2\XML\md\Extensions; use SimpleSAML\SAML2\XML\mdrpi\AbstractMdrpiElement; use SimpleSAML\SAML2\XML\mdrpi\RegistrationInfo; use SimpleSAML\SAML2\XML\mdrpi\RegistrationPolicy; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Type\LanguageValue; use function dirname; use function strval; @@ -36,6 +45,10 @@ final class RegistrationInfoTest extends TestCase use SerializableElementTestTrait; + /** @var \DOMDocument */ + private static DOMDocument $affiliationDescriptor; + + /** */ public static function setUpBeforeClass(): void @@ -46,6 +59,10 @@ public static function setUpBeforeClass(): void dirname(__FILE__, 4) . '/resources/xml/mdrpi_RegistrationInfo.xml', ); + self::$affiliationDescriptor = DOMDocumentFactory::fromFile( + dirname(__FILE__, 4) . '/resources/xml/md_AffiliationDescriptor.xml', + ); + self::$arrayRepresentation = [ 'registrationAuthority' => 'https://ExampleAuthority', 'registrationInstant' => '2011-01-01T00:00:00Z', @@ -62,11 +79,17 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $registrationInfo = new RegistrationInfo( - 'https://ExampleAuthority', - new DateTimeImmutable('2009-02-13T23:31:30Z'), + SAMLStringValue::fromString('https://ExampleAuthority'), + SAMLDateTimeValue::fromString('2009-02-13T23:31:30Z'), [ - new RegistrationPolicy('en', 'http://www.example.org/aai/metadata/en_registration.html'), - new RegistrationPolicy('de', 'http://www.example.org/aai/metadata/de_registration.html'), + new RegistrationPolicy( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('http://www.example.org/aai/metadata/en_registration.html'), + ), + new RegistrationPolicy( + LanguageValue::fromString('de'), + SAMLAnyURIValue::fromString('http://www.example.org/aai/metadata/de_registration.html'), + ), ], ); @@ -98,15 +121,21 @@ public function testMissingPublisherThrowsException(): void /** */ - public function testRegistrationInstantTimezoneNotZuluThrowsException(): void + public function testMultipleRegistrationPoliciesWithSameLanguageThrowsException(): void { $document = clone self::$xmlRepresentation->documentElement; - $document->setAttribute('registrationInstant', '2011-01-01T00:00:00WT'); + + // Append another 'en' RegistrationPolicy to the document + $x = new RegistrationPolicy( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('https://example.org'), + ); + $x->toXML($document); $this->expectException(ProtocolViolationException::class); $this->expectExceptionMessage( - "\"2011-01-01T00:00:00WT\" is not a DateTime expressed in the UTC timezone " - . "using the 'Z' timezone identifier.", + 'There MUST NOT be more than one ,' + . ' within a given , for a given language', ); RegistrationInfo::fromXML($document); } @@ -114,19 +143,25 @@ public function testRegistrationInstantTimezoneNotZuluThrowsException(): void /** */ - public function testMultipleRegistrationPoliciesWithSameLanguageThrowsException(): void + public function testNestedRegistrationInfoThrowsException(): void { - $document = clone self::$xmlRepresentation->documentElement; + $registrationInfo = RegistrationInfo::fromXML(self::$xmlRepresentation->documentElement); + $extensions = new Extensions([$registrationInfo]); - // Append another 'en' RegistrationPolicy to the document - $x = new RegistrationPolicy('en', 'https://example.org'); - $x->toXML($document); + $ed = new EntityDescriptor( + entityId: EntityIDValue::fromString('urn:x-simplesamlphp:entity'), + affiliationDescriptor: AffiliationDescriptor::fromXML(self::$affiliationDescriptor->documentElement), + ); $this->expectException(ProtocolViolationException::class); - $this->expectExceptionMessage( - 'There MUST NOT be more than one ,' - . ' within a given , for a given language', + new EntitiesDescriptor( + extensions: $extensions, + entitiesDescriptors: [ + new EntitiesDescriptor( + extensions: $extensions, + entityDescriptors: [$ed], + ), + ], ); - RegistrationInfo::fromXML($document); } } diff --git a/tests/SAML2/XML/mdrpi/RegistrationPolicyTest.php b/tests/SAML2/XML/mdrpi/RegistrationPolicyTest.php index c85517674..06ec31c06 100644 --- a/tests/SAML2/XML/mdrpi/RegistrationPolicyTest.php +++ b/tests/SAML2/XML/mdrpi/RegistrationPolicyTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; use SimpleSAML\SAML2\XML\md\AbstractLocalizedURI; use SimpleSAML\SAML2\XML\mdrpi\AbstractMdrpiElement; @@ -14,6 +15,7 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\LanguageValue; use function dirname; use function strval; @@ -56,7 +58,10 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $name = new RegistrationPolicy('en', 'http://www.example.edu/en/'); + $name = new RegistrationPolicy( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('http://www.example.edu/en/'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/mdrpi/UsagePolicyTest.php b/tests/SAML2/XML/mdrpi/UsagePolicyTest.php index 4e9f732bf..2e0f55a53 100644 --- a/tests/SAML2/XML/mdrpi/UsagePolicyTest.php +++ b/tests/SAML2/XML/mdrpi/UsagePolicyTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; use SimpleSAML\SAML2\XML\md\AbstractLocalizedURI; use SimpleSAML\SAML2\XML\mdrpi\AbstractMdrpiElement; @@ -14,6 +15,7 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\LanguageValue; use function dirname; use function strval; @@ -56,7 +58,10 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $name = new UsagePolicy('en', 'http://www.example.edu/en/'); + $name = new UsagePolicy( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('http://www.example.edu/en/'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/mdui/DescriptionTest.php b/tests/SAML2/XML/mdui/DescriptionTest.php index 1e956819a..c4789cd57 100644 --- a/tests/SAML2/XML/mdui/DescriptionTest.php +++ b/tests/SAML2/XML/mdui/DescriptionTest.php @@ -7,12 +7,14 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\mdui\Description; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\LanguageValue; use function dirname; use function strval; @@ -54,7 +56,10 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $name = new Description('en', 'Just an example'); + $name = new Description( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Just an example'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/mdui/DiscoHintsTest.php b/tests/SAML2/XML/mdui/DiscoHintsTest.php index d3a453a87..bf351e17e 100644 --- a/tests/SAML2/XML/mdui/DiscoHintsTest.php +++ b/tests/SAML2/XML/mdui/DiscoHintsTest.php @@ -7,6 +7,10 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\CIDRValue; +use SimpleSAML\SAML2\Type\DomainValue; +use SimpleSAML\SAML2\Type\GeolocationValue; +use SimpleSAML\SAML2\Type\ListOfStringsValue; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\mdui\AbstractMduiElement; use SimpleSAML\SAML2\XML\mdui\DiscoHints; @@ -19,6 +23,7 @@ use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\LanguageValue; use function dirname; use function strval; @@ -62,11 +67,29 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $discoHints = new DiscoHints( - ipHint: [new IPHint("130.59.0.0/16"), new IPHint("2001:620::0/96")], - domainHint: [new DomainHint("example.com"), new DomainHint("www.example.com")], + ipHint: [ + new IPHint( + CIDRValue::fromString("130.59.0.0/16"), + ), + new IPHint( + CIDRValue::fromString("2001:620::0/96"), + ), + ], + domainHint: [ + new DomainHint( + DomainValue::fromString("example.com"), + ), + new DomainHint( + DomainValue::fromString("www.example.com"), + ), + ], geolocationHint: [ - new GeolocationHint("geo:47.37328,8.531126"), - new GeolocationHint("geo:19.34343,12.342514"), + new GeolocationHint( + GeolocationValue::fromString("geo:47.37328,8.531126"), + ), + new GeolocationHint( + GeolocationValue::fromString("geo:19.34343,12.342514"), + ), ], ); @@ -97,7 +120,10 @@ public function testMarshallingEmptyElement(): void */ public function testMarshallingChildren(): void { - $keywords = new Keywords("nl", ["voorbeeld", "specimen"]); + $keywords = new Keywords( + LanguageValue::fromString("nl"), + ListOfStringsValue::fromString("voorbeeld+specimen"), + ); $discoHints = new DiscoHints(); $discoHints->addChild(new Chunk($keywords->toXML())); $this->assertCount(1, $discoHints->getElements()); @@ -138,7 +164,7 @@ public function testUnmarshallingChildren(): void $disco = DiscoHints::fromXML($document->documentElement); $this->assertCount(1, $disco->getGeolocationHint()); - $this->assertEquals('geo:47.37328,8.531126', $disco->getGeolocationHint()[0]->getContent()); + $this->assertEquals('geo:47.37328,8.531126', $disco->getGeolocationHint()[0]->getContent()->getValue()); $this->assertCount(1, $disco->getElements()); /** @var \SimpleSAML\XML\Chunk[] $elements */ $elements = $disco->getElements(); diff --git a/tests/SAML2/XML/mdui/DisplayNameTest.php b/tests/SAML2/XML/mdui/DisplayNameTest.php index 7e7b5951a..1da768cac 100644 --- a/tests/SAML2/XML/mdui/DisplayNameTest.php +++ b/tests/SAML2/XML/mdui/DisplayNameTest.php @@ -7,12 +7,14 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\mdui\DisplayName; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\LanguageValue; use function dirname; use function strval; @@ -54,7 +56,10 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $name = new DisplayName('en', 'University of Examples'); + $name = new DisplayName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('University of Examples'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/mdui/DomainHintTest.php b/tests/SAML2/XML/mdui/DomainHintTest.php index 54e239359..b2442107f 100644 --- a/tests/SAML2/XML/mdui/DomainHintTest.php +++ b/tests/SAML2/XML/mdui/DomainHintTest.php @@ -7,7 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\Exception\InvalidArgumentException; +use SimpleSAML\SAML2\Type\DomainValue; use SimpleSAML\SAML2\XML\mdui\AbstractMduiElement; use SimpleSAML\SAML2\XML\mdui\DomainHint; use SimpleSAML\XML\DOMDocumentFactory; @@ -51,27 +51,13 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $hint = new DomainHint('www.example.com'); + $hint = new DomainHint( + DomainValue::fromString('www.example.com'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), strval($hint), ); } - - - // test unmarshalling - - - /** - * Test creating a DomainHint from XML with false domain - */ - public function testUnmarshallingFalseDomain(): void - { - $xmlRepresentation = clone self::$xmlRepresentation; - $xmlRepresentation->documentElement->textContent = 'Not`@#%$&*()!ADo><$#mainName'; - - $this->expectException(InvalidArgumentException::class); - DomainHint::fromXML($xmlRepresentation->documentElement); - } } diff --git a/tests/SAML2/XML/mdui/GeolocationHintTest.php b/tests/SAML2/XML/mdui/GeolocationHintTest.php index 44ffb1e7c..6396da36e 100644 --- a/tests/SAML2/XML/mdui/GeolocationHintTest.php +++ b/tests/SAML2/XML/mdui/GeolocationHintTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\GeolocationValue; use SimpleSAML\SAML2\XML\mdui\AbstractMduiElement; use SimpleSAML\SAML2\XML\mdui\GeolocationHint; use SimpleSAML\XML\DOMDocumentFactory; @@ -50,7 +51,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $hint = new GeolocationHint('geo:47.37328,8.531126'); + $hint = new GeolocationHint( + GeolocationValue::fromString('geo:47.37328,8.531126'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/mdui/IPHintTest.php b/tests/SAML2/XML/mdui/IPHintTest.php index 4255bf39d..a952414fe 100644 --- a/tests/SAML2/XML/mdui/IPHintTest.php +++ b/tests/SAML2/XML/mdui/IPHintTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\CIDRValue; use SimpleSAML\SAML2\XML\mdui\AbstractMduiElement; use SimpleSAML\SAML2\XML\mdui\IPHint; use SimpleSAML\XML\DOMDocumentFactory; @@ -50,7 +51,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $hint = new IPHint('130.59.0.0/16'); + $hint = new IPHint( + CIDRValue::fromString('130.59.0.0/16'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/mdui/InformationURLTest.php b/tests/SAML2/XML/mdui/InformationURLTest.php index bca032371..b5064923d 100644 --- a/tests/SAML2/XML/mdui/InformationURLTest.php +++ b/tests/SAML2/XML/mdui/InformationURLTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; use SimpleSAML\SAML2\XML\md\AbstractLocalizedURI; use SimpleSAML\SAML2\XML\md\AbstractMdElement; @@ -14,6 +15,7 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\LanguageValue; use function dirname; use function strval; @@ -56,7 +58,10 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $name = new InformationURL('en', 'http://www.example.edu/en/'); + $name = new InformationURL( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('http://www.example.edu/en/'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/mdui/KeywordsTest.php b/tests/SAML2/XML/mdui/KeywordsTest.php index 2aaab9c85..ab18c68b8 100644 --- a/tests/SAML2/XML/mdui/KeywordsTest.php +++ b/tests/SAML2/XML/mdui/KeywordsTest.php @@ -7,13 +7,15 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use SimpleSAML\Assert\AssertionFailedException; +use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\ListOfStringsValue; use SimpleSAML\SAML2\XML\mdui\AbstractMduiElement; use SimpleSAML\SAML2\XML\mdui\Keywords; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\LanguageValue; use function dirname; use function strval; @@ -54,8 +56,10 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $keywords = new Keywords("nl", ["KLM", "koninklijke luchtvaart"]); - $keywords->addKeyword("maatschappij"); + $keywords = new Keywords( + LanguageValue::fromString("nl"), + ListOfStringsValue::fromString("KLM koninklijke+luchtvaart+maatschappij"), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), @@ -69,23 +73,11 @@ public function testMarshalling(): void */ public function testKeywordWithPlusSignThrowsException(): void { - $this->expectException(AssertionFailedException::class); - $this->expectExceptionMessage('Keywords may not contain a "+" character'); - - new Keywords("en", ["csharp", "pascal", "c++"]); - } + $this->expectException(ProtocolViolationException::class); - - /** - * Unmarshalling fails if attribute is empty - */ - public function testUnmarshallingFailsMissingKeywords(): void - { - $document = clone self::$xmlRepresentation; - $document->documentElement->textContent = ''; - - $this->expectException(AssertionFailedException::class); - $this->expectExceptionMessage('Missing value for Keywords'); - Keywords::fromXML($document->documentElement); + new Keywords( + LanguageValue::fromString("en"), + ListOfStringsValue::fromArray(["csharp", "pascal", "c++"]), + ); } } diff --git a/tests/SAML2/XML/mdui/LogoTest.php b/tests/SAML2/XML/mdui/LogoTest.php index afea872b3..6a91b8cbb 100644 --- a/tests/SAML2/XML/mdui/LogoTest.php +++ b/tests/SAML2/XML/mdui/LogoTest.php @@ -4,18 +4,21 @@ namespace SimpleSAML\Test\SAML2\XML\mdui; -use InvalidArgumentException; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; +use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\mdui\AbstractMduiElement; use SimpleSAML\SAML2\XML\mdui\Logo; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Type\LanguageValue; +use SimpleSAML\XMLSchema\Type\PositiveIntegerValue; use function dirname; use function strval; @@ -68,7 +71,12 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $logo = new Logo(self::URL, 200, 300, "nl"); + $logo = new Logo( + SAMLAnyURIValue::fromString(self::URL), + PositiveIntegerValue::fromInteger(200), + PositiveIntegerValue::fromInteger(300), + LanguageValue::fromString('nl'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), @@ -87,12 +95,16 @@ public function testUnmarshallingWithoutLanguage(): void $logo = Logo::fromXML($xmlRepresentation); $this->assertNull($logo->getLanguage()); - $this->assertEquals(200, $logo->getHeight()); - $this->assertEquals(300, $logo->getWidth()); + $this->assertEquals(200, $logo->getHeight()->toInteger()); + $this->assertEquals(300, $logo->getWidth()->toInteger()); $this->assertEquals(self::URL, $logo->getContent()); $this->assertEquals( $logo->toArray(), - ['url' => $logo->getContent(), 'width' => $logo->getWidth(), 'height' => $logo->getHeight()], + [ + 'url' => $logo->getContent()->getValue(), + 'width' => $logo->getWidth()->toInteger(), + 'height' => $logo->getHeight()->toInteger(), + ], ); } @@ -108,9 +120,9 @@ public function testUnmarshallingDataURL(): void $document->documentElement->setAttribute('width', '1'); $logo = Logo::fromXML($document->documentElement); - $this->assertEquals(1, $logo->getHeight()); - $this->assertEquals(1, $logo->getWidth()); - $this->assertEquals(self::DATA, $logo->getContent()); + $this->assertEquals(1, $logo->getHeight()->toInteger()); + $this->assertEquals(1, $logo->getWidth()->toInteger()); + $this->assertEquals(self::DATA, $logo->getContent()->getValue()); } @@ -136,8 +148,8 @@ public function testUnmarshallingFailsInvalidURL(): void $document = clone self::$xmlRepresentation; $document->documentElement->textContent = 'this is no url'; - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('mdui:Logo is not a valid URL.'); + $this->expectException(ProtocolViolationException::class); + $this->expectExceptionMessage('"this is no url" is not a SAML2-compliant URI'); Logo::fromXML($document->documentElement); } diff --git a/tests/SAML2/XML/mdui/PrivacyStatementURLTest.php b/tests/SAML2/XML/mdui/PrivacyStatementURLTest.php index 4ecde7714..d60abcd67 100644 --- a/tests/SAML2/XML/mdui/PrivacyStatementURLTest.php +++ b/tests/SAML2/XML/mdui/PrivacyStatementURLTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; use SimpleSAML\SAML2\XML\md\AbstractLocalizedURI; use SimpleSAML\SAML2\XML\md\AbstractMdElement; @@ -14,6 +15,7 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\LanguageValue; use function dirname; use function strval; @@ -56,7 +58,10 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $name = new PrivacyStatementURL('en', 'https://example.org/privacy'); + $name = new PrivacyStatementURL( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('https://example.org/privacy'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/mdui/UIInfoTest.php b/tests/SAML2/XML/mdui/UIInfoTest.php index f39a00320..d6f7df287 100644 --- a/tests/SAML2/XML/mdui/UIInfoTest.php +++ b/tests/SAML2/XML/mdui/UIInfoTest.php @@ -8,6 +8,10 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\CIDRValue; +use SimpleSAML\SAML2\Type\ListOfStringsValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\mdui\AbstractMduiElement; use SimpleSAML\SAML2\XML\mdui\Description; @@ -24,6 +28,8 @@ use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\LanguageValue; +use SimpleSAML\XMLSchema\Type\PositiveIntegerValue; use function dirname; use function strval; @@ -70,22 +76,45 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $logo = new Logo("https://example.org/idp/images/logo_87x88.png", 88, 87, "fy"); + $logo = new Logo( + SAMLAnyURIValue::fromString("https://example.org/idp/images/logo_87x88.png"), + PositiveIntegerValue::fromInteger(88), + PositiveIntegerValue::fromInteger(87), + LanguageValue::fromString('fy'), + ); $uiinfo = new UIInfo( displayName: [ - new DisplayName("en", "University of Examples"), - new DisplayName("el", "Univërsitä øf Exåmpleß"), + new DisplayName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('University of Examples'), + ), + new DisplayName( + LanguageValue::fromString('el'), + SAMLStringValue::fromString('Univërsitä øf Exåmpleß'), + ), ], description: [ - new Description("en", "Just an example"), + new Description( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Just an example'), + ), ], informationURL: [ - new InformationURL("en", "http://www.example.edu/en/"), - new InformationURL("el", "http://www.example.edu/"), + new InformationURL( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('http://www.example.edu/en/'), + ), + new InformationURL( + LanguageValue::fromString('el'), + SAMLAnyURIValue::fromString('http://www.example.edu/'), + ), ], privacyStatementURL: [ - new PrivacyStatementURL("en", "https://example.org/privacy"), + new PrivacyStatementURL( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('https://example.org/privacy'), + ), ], children: [ new Chunk(DOMDocumentFactory::fromString( @@ -97,10 +126,16 @@ public function testMarshalling(): void ], ); - $keyword = new Keywords('en', ['University Fictional']); + $keyword = new Keywords( + LanguageValue::fromString('en'), + ListOfStringsValue::fromString('University Fictional'), + ); $uiinfo->addKeyword($keyword); - $keyword = new Keywords('fr', ['Université Fictif']); + $keyword = new Keywords( + LanguageValue::fromString('fr'), + ListOfStringsValue::fromString('Université Fictif'), + ); $uiinfo->addKeyword($keyword); $uiinfo->addLogo($logo); @@ -117,12 +152,27 @@ public function testMarshalling(): void */ public function testMarshallingChildren(): void { - $keywords = new Keywords("nl", ["voorbeeld", "specimen"]); - $logo = new Logo("https://example.edu/logo.png", 30, 20, "nl"); + $keywords = new Keywords( + LanguageValue::fromString('nl'), + ListOfStringsValue::fromString("voorbeeld+specimen"), + ); + $logo = new Logo( + SAMLAnyURIValue::fromString('https://example.edu/logo.png'), + PositiveIntegerValue::fromInteger(30), + PositiveIntegerValue::fromInteger(20), + LanguageValue::fromString('nl'), + ); $discohints = new DiscoHints( [], - [new IPHint("192.168.6.0/24"), new IPHint("fd00:0123:aa:1001::/64")], + [ + new IPHint( + CIDRValue::fromString("192.168.6.0/24"), + ), + new IPHint( + CIDRValue::fromString("fd00:0123:aa:1001::/64"), + ), + ], ); // keywords appears twice, directly under UIinfo and as child of DiscoHints @@ -202,7 +252,10 @@ public function testMultipleDescriptionWithSameLanguageThrowsException(): void $document = clone self::$xmlRepresentation; // Append another 'en' mdui:Description to the document - $x = new Description('en', 'Something'); + $x = new Description( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Something'), + ); $x->toXML($document->documentElement); $this->expectException(ProtocolViolationException::class); @@ -221,7 +274,10 @@ public function testMultipleDisplayNameWithSameLanguageThrowsException(): void $document = clone self::$xmlRepresentation; // Append another 'en' mdui:DisplayName to the document - $x = new DisplayName('en', 'Something'); + $x = new DisplayName( + LanguageValue::fromString('en'), + SAMLStringValue::fromString('Something'), + ); $x->toXML($document->documentElement); $this->expectException(ProtocolViolationException::class); @@ -240,7 +296,10 @@ public function testMultipleKeywordsWithSameLanguageThrowsException(): void $document = clone self::$xmlRepresentation; // Append another 'en' mdui:Keywords to the document - $x = new Keywords('en', ['Something', 'else']); + $x = new Keywords( + LanguageValue::fromString('en'), + ListOfStringsValue::fromString('Something else'), + ); $x->toXML($document->documentElement); $this->expectException(ProtocolViolationException::class); @@ -259,7 +318,10 @@ public function testMultipleInformationURLWithSameLanguageThrowsException(): voi $document = clone self::$xmlRepresentation; // Append another 'en' mdui:InformationURL to the document - $x = new InformationURL('en', 'https://example.org'); + $x = new InformationURL( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('https://example.org'), + ); $x->toXML($document->documentElement); $this->expectException(ProtocolViolationException::class); @@ -278,7 +340,10 @@ public function testMultiplePrivacyStatementURLWithSameLanguageThrowsException() $document = clone self::$xmlRepresentation; // Append another 'en' mdui:PrivacyStatementURL to the document - $x = new PrivacyStatementURL('en', 'https://example.org'); + $x = new PrivacyStatementURL( + LanguageValue::fromString('en'), + SAMLAnyURIValue::fromString('https://example.org'), + ); $x->toXML($document->documentElement); $this->expectException(ProtocolViolationException::class); diff --git a/tests/SAML2/XML/saml/ActionTest.php b/tests/SAML2/XML/saml/ActionTest.php index 3ba83267d..96486a3fc 100644 --- a/tests/SAML2/XML/saml/ActionTest.php +++ b/tests/SAML2/XML/saml/ActionTest.php @@ -7,6 +7,8 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\Action; use SimpleSAML\Test\SAML2\Constants as C; @@ -49,8 +51,8 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $action = new Action( - C::NAMESPACE, - 'SomeAction', + SAMLAnyURIValue::fromString(C::NAMESPACE), + SAMLStringValue::fromString('SomeAction'), ); $this->assertEquals( diff --git a/tests/SAML2/XML/saml/AdviceTest.php b/tests/SAML2/XML/saml/AdviceTest.php index 5f8c2f469..1bbc35098 100644 --- a/tests/SAML2/XML/saml/AdviceTest.php +++ b/tests/SAML2/XML/saml/AdviceTest.php @@ -13,7 +13,6 @@ use SimpleSAML\SAML2\XML\saml\Assertion; use SimpleSAML\SAML2\XML\saml\AssertionIDRef; use SimpleSAML\SAML2\XML\saml\AssertionURIRef; -use SimpleSAML\SAML2\XML\saml\EncryptedAssertion; use SimpleSAML\XML\Chunk; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; @@ -45,9 +44,6 @@ final class AdviceTest extends TestCase /** @var \DOMDocument $assertion */ private static DOMDocument $assertion; - /** @var \DOMDocument $encryptedAssertion */ - private static DOMDocument $encryptedAssertion; - /** */ @@ -70,10 +66,6 @@ public static function setUpBeforeClass(): void self::$assertion = DOMDocumentFactory::fromFile( dirname(__FILE__, 4) . '/resources/xml/saml_Assertion.xml', ); - - self::$encryptedAssertion = DOMDocumentFactory::fromFile( - dirname(__FILE__, 4) . '/resources/xml/saml_EncryptedAssertion.xml', - ); } @@ -90,7 +82,7 @@ public function testMarshalling(): void [AssertionIDRef::fromXML(self::$assertionIDRef->documentElement)], [AssertionURIRef::fromXML(self::$assertionURIRef->documentElement)], [Assertion::fromXML(self::$assertion->documentElement)], - [EncryptedAssertion::fromXML(self::$encryptedAssertion->documentElement)], + [], [$chunk], ); diff --git a/tests/SAML2/XML/saml/AssertionIDRefTest.php b/tests/SAML2/XML/saml/AssertionIDRefTest.php index 29cc7355f..6c455c88e 100644 --- a/tests/SAML2/XML/saml/AssertionIDRefTest.php +++ b/tests/SAML2/XML/saml/AssertionIDRefTest.php @@ -12,6 +12,7 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\NCNameValue; use function dirname; use function strval; @@ -46,7 +47,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $assertionIDRef = new AssertionIDRef('_Test'); + $assertionIDRef = new AssertionIDRef( + NCNameValue::fromString('_Test'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/saml/AssertionTest.php b/tests/SAML2/XML/saml/AssertionTest.php index 634534474..21b665ef1 100644 --- a/tests/SAML2/XML/saml/AssertionTest.php +++ b/tests/SAML2/XML/saml/AssertionTest.php @@ -4,7 +4,6 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use DateTimeImmutable; use Exception; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; @@ -12,6 +11,12 @@ use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Compat\AbstractContainer; use SimpleSAML\SAML2\Compat\ContainerSingleton; +use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException; +use SimpleSAML\SAML2\Type\DomainValue; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; @@ -37,9 +42,12 @@ use SimpleSAML\SAML2\XML\saml\SubjectLocality; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingElementException; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Type\Base64BinaryValue; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\NCNameValue; use SimpleSAML\XMLSecurity\Alg\KeyTransport\KeyTransportAlgorithmFactory; use SimpleSAML\XMLSecurity\Alg\Signature\SignatureAlgorithmFactory; use SimpleSAML\XMLSecurity\Exception\SignatureVerificationFailedException; @@ -106,63 +114,81 @@ public static function tearDownAfterClass(): void public function testMarshalling(): void { // Create an Issuer - $issuer = new Issuer('urn:x-simplesamlphp:issuer'); + $issuer = new Issuer( + SAMLStringValue::fromString('urn:x-simplesamlphp:issuer'), + ); // Create the conditions $conditions = new Conditions( - notBefore: new DateTimeImmutable('2011-08-31T08:51:05Z'), - notOnOrAfter: new DateTimeImmutable('2011-08-31T10:51:05Z'), + notBefore: SAMLDateTimeValue::fromString('2011-08-31T08:51:05Z'), + notOnOrAfter: SAMLDateTimeValue::fromString('2011-08-31T10:51:05Z'), condition: [], - audienceRestriction: [new AudienceRestriction([new Audience(C::ENTITY_SP)])], + audienceRestriction: [ + new AudienceRestriction([ + new Audience( + EntityIDValue::fromString(C::ENTITY_SP), + ), + ]), + ], ); // Create the AuthnStatement $authnStatement = new AuthnStatement( authnContext: new AuthnContext( - new AuthnContextClassRef(C::AC_PASSWORD_PROTECTED_TRANSPORT), + new AuthnContextClassRef( + SAMLAnyURIValue::fromString(C::AC_PASSWORD_PROTECTED_TRANSPORT), + ), null, null, ), - authnInstant: new DateTimeImmutable('2011-08-31T08:51:05Z'), - sessionIndex: '_93af655219464fb403b34436cfb0c5cb1d9a5502', - subjectLocality: new SubjectLocality('127.0.0.1'), + authnInstant: SAMLDateTimeValue::fromString('2011-08-31T08:51:05Z'), + sessionIndex: SAMLStringValue::fromString('_93af655219464fb403b34436cfb0c5cb1d9a5502'), + subjectLocality: new SubjectLocality( + SAMLStringValue::fromString('127.0.0.1'), + ), ); // Create the AttributeStatement $attrStatement = new AttributeStatement([ new Attribute( - name: 'urn:test:ServiceID', - attributeValue: [new AttributeValue(1)], + name: SAMLStringValue::fromString('urn:test:ServiceID'), + attributeValue: [ + new AttributeValue(1), + ], ), new Attribute( - name: 'urn:test:EntityConcernedID', - attributeValue: [new AttributeValue(1)], + name: SAMLStringValue::fromString('urn:test:EntityConcernedID'), + attributeValue: [ + new AttributeValue(1), + ], ), new Attribute( - name: 'urn:test:EntityConcernedSubID', - attributeValue: [new AttributeValue(1)], + name: SAMLStringValue::fromString('urn:test:EntityConcernedSubID'), + attributeValue: [ + new AttributeValue(1), + ], ), ]); // Create the Subject $subject = new Subject( new NameID( - value: 'SomeNameIDValue', - SPNameQualifier: 'https://sp.example.org/authentication/sp/metadata', - Format: C::NAMEID_TRANSIENT, + value: SAMLStringValue::fromString('SomeNameIDValue'), + SPNameQualifier: SAMLStringValue::fromString('https://sp.example.org/authentication/sp/metadata'), + Format: SAMLAnyURIValue::fromString(C::NAMEID_TRANSIENT), ), [ new SubjectConfirmation( - 'urn:oasis:names:tc:SAML:2.0:cm:bearer', + SAMLAnyURIValue::fromString('urn:oasis:names:tc:SAML:2.0:cm:bearer'), new NameID( - value: 'SomeOtherNameIDValue', - SPNameQualifier: 'https://sp.example.org/authentication/sp/metadata', - Format: C::NAMEID_TRANSIENT, + value: SAMLStringValue::fromString('SomeOtherNameIDValue'), + SPNameQualifier: SAMLStringValue::fromString('https://sp.example.org/authentication/sp/metadata'), + Format: SAMLAnyURIValue::fromString(C::NAMEID_TRANSIENT), ), new SubjectConfirmationData( - notOnOrAfter: new DateTimeImmutable('2011-08-31T08:51:05Z'), - recipient: 'https://sp.example.org/authentication/sp/consume-assertion', - inResponseTo: '_13603a6565a69297e9809175b052d115965121c8', + notOnOrAfter: SAMLDateTimeValue::fromString('2011-08-31T08:51:05Z'), + recipient: EntityIDValue::fromString('https://sp.example.org/authentication/sp/consume-assertion'), + inResponseTo: NCNameValue::fromString('_13603a6565a69297e9809175b052d115965121c8'), ), ), ], @@ -171,8 +197,8 @@ public function testMarshalling(): void // Create an assertion $assertion = new Assertion( $issuer, - new DateTimeImmutable('1970-01-01T01:33:31Z'), - '_93af655219464fb403b34436cfb0c5cb1d9a5502', + SAMLDateTimeValue::fromString('1970-01-01T01:33:31Z'), + IDValue::fromString('_93af655219464fb403b34436cfb0c5cb1d9a5502'), $subject, $conditions, [$authnStatement, $attrStatement], @@ -253,15 +279,20 @@ public function testUnmarshalling(): void public function testMarshallingUnmarshallingChristmas(): void { // Create an Issuer - $issuer = new Issuer('urn:x-simplesamlphp:issuer'); + $issuer = new Issuer( + SAMLStringValue::fromString('urn:x-simplesamlphp:issuer'), + ); // Create Conditions $conditions = new Conditions( - notBefore: new DateTimeImmutable('2011-08-31T08:51:05Z'), - notOnOrAfter: new DateTimeImmutable('2011-08-31T10:51:05Z'), + notBefore: SAMLDateTimeValue::fromString('2011-08-31T08:51:05Z'), + notOnOrAfter: SAMLDateTimeValue::fromString('2011-08-31T10:51:05Z'), audienceRestriction: [ new AudienceRestriction( - [new Audience(C::ENTITY_SP), new Audience(C::ENTITY_OTHER)], + [ + new Audience(EntityIDValue::fromString(C::ENTITY_SP)), + new Audience(EntityIDValue::fromString(C::ENTITY_OTHER)), + ], ), ], ); @@ -269,18 +300,29 @@ public function testMarshallingUnmarshallingChristmas(): void // Create AuthnStatement $authnStatement = new AuthnStatement( new AuthnContext( - new AuthnContextClassRef(C::AUTHNCONTEXT_CLASS_REF_LOA1), + new AuthnContextClassRef( + SAMLAnyURIValue::fromString(C::AUTHNCONTEXT_CLASS_REF_LOA1), + ), null, - new AuthnContextDeclRef('https://example.org/relative/path/to/document.xml'), + new AuthnContextDeclRef( + SAMLAnyURIValue::fromString('https://example.org/relative/path/to/document.xml'), + ), [ - new AuthenticatingAuthority(C::ENTITY_IDP), - new AuthenticatingAuthority(C::ENTITY_OTHER), + new AuthenticatingAuthority( + EntityIDValue::fromString(C::ENTITY_IDP), + ), + new AuthenticatingAuthority( + EntityIDValue::fromString(C::ENTITY_OTHER), + ), ], ), - new DateTimeImmutable('2011-08-31T08:51:04Z'), - new DateTimeImmutable('2011-08-31T08:54:25Z'), - 'idx1', - new SubjectLocality('127.0.0.1', 'no.place.like.home'), + SAMLDateTimeValue::fromString('2011-08-31T08:51:04Z'), + SAMLDateTimeValue::fromString('2011-08-31T08:54:25Z'), + SAMLStringValue::fromString('idx1'), + new SubjectLocality( + SAMLStringValue::fromString('127.0.0.1'), + DomainValue::fromString('no.place.like.home'), + ), ); // Create AttributeStatement @@ -288,18 +330,25 @@ public function testMarshallingUnmarshallingChristmas(): void // Attribute [ new Attribute( - name: 'name1', - attributeValue: [new AttributeValue('value1'), new AttributeValue('value2')], + name: SAMLStringValue::fromString('name1'), + attributeValue: [ + new AttributeValue('value1'), + new AttributeValue('value2'), + ], ), new Attribute( - name: 'name2', - nameFormat: C::NAMEFORMAT_UNSPECIFIED, - attributeValue: [new AttributeValue(2)], + name: SAMLStringValue::fromString('name2'), + nameFormat: SAMLAnyURIValue::fromString(C::NAMEFORMAT_UNSPECIFIED), + attributeValue: [ + new AttributeValue(2), + ], ), new Attribute( - name: 'name3', - nameFormat: C::NAMEFORMAT_BASIC, - attributeValue: [new AttributeValue(null)], + name: SAMLStringValue::fromString('name3'), + nameFormat: SAMLAnyURIValue::fromString(C::NAMEFORMAT_BASIC), + attributeValue: [ + new AttributeValue(null), + ], ), ], ); @@ -308,8 +357,8 @@ public function testMarshallingUnmarshallingChristmas(): void $statements = [$authnStatement, $attributeStatement]; $assertion = new Assertion( issuer: $issuer, - id: '_123abc', - issueInstant: new DateTimeImmutable('2011-08-31T08:51:05Z'), + id: IDValue::fromString('_123abc'), + issueInstant: SAMLDateTimeValue::fromString('2011-08-31T08:51:05Z'), conditions: $conditions, statements: $statements, ); @@ -326,22 +375,22 @@ public function testMarshallingUnmarshallingChristmas(): void $authnStatement = $authnStatements[0]; $this->assertEquals( 'https://example.org/relative/path/to/document.xml', - $authnStatement->getAuthnContext()->getAuthnContextDeclRef()?->getContent(), + $authnStatement->getAuthnContext()->getAuthnContextDeclRef()?->getContent()->getValue(), ); - $this->assertEquals('_123abc', $assertionToVerify->getId()); - $this->assertEquals('2011-08-31T08:51:05Z', $assertionToVerify->getIssueInstant()->format(C::DATETIME_FORMAT)); - $this->assertEquals('2011-08-31T08:54:25Z', $authnStatement->getSessionNotOnOrAfter()->format(C::DATETIME_FORMAT)); - $this->assertEquals('2011-08-31T08:51:04Z', $authnStatement->getAuthnInstant()->format(C::DATETIME_FORMAT)); - $this->assertEquals('idx1', $authnStatement->getSessionIndex()); + $this->assertEquals('_123abc', $assertionToVerify->getId()->getValue()); + $this->assertEquals('2011-08-31T08:51:05Z', $assertionToVerify->getIssueInstant()->getValue()); + $this->assertEquals('2011-08-31T08:54:25Z', $authnStatement->getSessionNotOnOrAfter()->getValue()); + $this->assertEquals('2011-08-31T08:51:04Z', $authnStatement->getAuthnInstant()->getValue()); + $this->assertEquals('idx1', $authnStatement->getSessionIndex()->getValue()); $subjectLocality = $authnStatement->getSubjectLocality(); - $this->assertEquals('127.0.0.1', $subjectLocality?->getAddress()); - $this->assertEquals('no.place.like.home', $subjectLocality?->getDnsName()); + $this->assertEquals('127.0.0.1', $subjectLocality->getAddress()->getValue()); + $this->assertEquals('no.place.like.home', $subjectLocality->getDnsName()->getValue()); $authauth = $authnStatement->getAuthnContext()->getAuthenticatingAuthorities(); $this->assertCount(2, $authauth); - $this->assertEquals(C::ENTITY_IDP, $authauth[0]->getContent()); - $this->assertEquals(C::ENTITY_OTHER, $authauth[1]->getContent()); + $this->assertEquals(C::ENTITY_IDP, $authauth[0]->getContent()->getValue()); + $this->assertEquals(C::ENTITY_OTHER, $authauth[1]->getContent()->getValue()); $attributeStatements = $assertionToVerify->getAttributeStatements(); $this->assertCount(1, $attributeStatements); @@ -513,7 +562,9 @@ public function testCorrectSignatureMethodCanBeExtracted(): void ); $keyInfo = new KeyInfo([ new X509Data([ - new X509Certificate(PEMCertificatesMock::getPlainPublicKeyContents(PEMCertificatesMock::PUBLIC_KEY)), + new X509Certificate( + Base64BinaryValue::fromString(PEMCertificatesMock::getPlainPublicKeyContents(PEMCertificatesMock::PUBLIC_KEY)), + ), ]), ]); @@ -687,7 +738,7 @@ public function testVerifySignedAssertion(): void $assertion = Assertion::fromXML($doc->documentElement); $verifier = (new SignatureAlgorithmFactory())->getAlgorithm( - $assertion->getSignature()?->getSignedInfo()->getSignatureMethod()->getAlgorithm(), + $assertion->getSignature()?->getSignedInfo()->getSignatureMethod()->getAlgorithm()->getValue(), PEMCertificatesMock::getPublicKey(PEMCertificatesMock::SELFSIGNED_PUBLIC_KEY), ); @@ -700,7 +751,7 @@ public function testVerifySignedAssertion(): void // Double-check that we can actually retrieve some basics. $this->assertEquals("_93af655219464fb403b34436cfb0c5cb1d9a5502", $verified->getId()); $this->assertEquals("urn:x-simplesamlphp:issuer", $verified->getIssuer()->getContent()); - $this->assertEquals("1970-01-01T01:33:31Z", $verified->getIssueInstant()->format(C::DATETIME_FORMAT)); + $this->assertEquals("1970-01-01T01:33:31Z", $verified->getIssueInstant()->getValue()); } @@ -714,7 +765,7 @@ public function testCommentsInSignedAssertion(): void $assertion = Assertion::fromXML($doc->documentElement); $verifier = (new SignatureAlgorithmFactory())->getAlgorithm( - $assertion->getSignature()?->getSignedInfo()->getSignatureMethod()->getAlgorithm(), + $assertion->getSignature()?->getSignedInfo()->getSignatureMethod()->getAlgorithm()->getValue(), PEMCertificatesMock::getPublicKey(PEMCertificatesMock::SELFSIGNED_PUBLIC_KEY), ); @@ -740,7 +791,7 @@ public function testVerifySignedAssertionChangedBody(): void $assertion = Assertion::fromXML($doc->documentElement); $verifier = (new SignatureAlgorithmFactory())->getAlgorithm( - $assertion->getSignature()?->getSignedInfo()->getSignatureMethod()->getAlgorithm(), + $assertion->getSignature()?->getSignedInfo()->getSignatureMethod()->getAlgorithm()->getValue(), PEMCertificatesMock::getPublicKey(PEMCertificatesMock::SELFSIGNED_PUBLIC_KEY), ); @@ -782,7 +833,7 @@ public function testVerifySignedAssertionWrongKey(): void $assertion = Assertion::fromXML($doc->documentElement); $verifier = (new SignatureAlgorithmFactory())->getAlgorithm( - $assertion->getSignature()?->getSignedInfo()->getSignatureMethod()->getAlgorithm(), + $assertion->getSignature()?->getSignedInfo()->getSignatureMethod()->getAlgorithm()->getValue(), PEMCertificatesMock::getPublicKey(PEMCertificatesMock::OTHER_PUBLIC_KEY), ); @@ -843,8 +894,7 @@ public function testAssertionVersionOtherThan20ThrowsException(): void $document = clone self::$xmlRepresentation; $document->documentElement->setAttribute('Version', '1.3'); - $this->expectException(Exception::class); - $this->expectExceptionMessage('Unsupported version: "1.3"'); + $this->expectException(RequestVersionTooLowException::class); Assertion::fromXML($document->documentElement); } @@ -1072,21 +1122,26 @@ public function testConditionAllowedTypes(): void public function testNameIdEncryption(): void { // Create an Issuer - $issuer = new Issuer('urn:x-simplesamlphp:issuer'); + $issuer = new Issuer( + SAMLStringValue::fromString('urn:x-simplesamlphp:issuer'), + ); // Create the Conditions $conditions = new Conditions( audienceRestriction: [ new AudienceRestriction( - [new Audience(C::ENTITY_SP), new Audience(C::ENTITY_OTHER)], + [ + new Audience(SAMLAnyURIValue::fromString(C::ENTITY_SP)), + new Audience(SAMLAnyURIValue::fromString(C::ENTITY_OTHER)), + ], ), ], ); // Create a Subject $nameId = new NameID( - value: "just_a_basic_identifier", - Format: C::NAMEID_TRANSIENT, + value: SAMLStringValue::fromString("just_a_basic_identifier"), + Format: SAMLAnyURIValue::fromString(C::NAMEID_TRANSIENT), ); $this->assertInstanceOf(NameID::class, $nameId); @@ -1101,17 +1156,20 @@ public function testNameIdEncryption(): void // Create the statements $authnStatement = new AuthnStatement( new AuthnContext( - new AuthnContextClassRef(C::AUTHNCONTEXT_CLASS_REF_LOA2), + new AuthnContextClassRef( + SAMLAnyURIValue::fromString(C::AUTHNCONTEXT_CLASS_REF_LOA2), + ), null, null, ), - self::$clock->now(), + SAMLDateTimeValue::fromDateTime(self::$clock->now()), ); // Create an assertion $assertion = new Assertion( issuer: $issuer, - issueInstant: self::$clock->now(), + id: IDValue::fromString('phpunit'), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), subject: $subject, conditions: $conditions, statements: [$authnStatement], @@ -1124,27 +1182,36 @@ public function testNameIdEncryption(): void $identifier = $assertionToVerify->getSubject()?->getIdentifier(); $this->assertInstanceOf(EncryptedID::class, $identifier); - +//var_dump( $identifier->getEncryptedData()->getKeyInfo()->getInfo() ); +// This contains a Chunk instead of an EncryptedKey-object +// ToDo: figure out why $decryptor = (new KeyTransportAlgorithmFactory())->getAlgorithm( - $identifier->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm(), + $identifier->getEncryptedKeys()[0]->getEncryptionMethod()?->getAlgorithm()->getValue(), PEMCertificatesMock::getPrivateKey(PEMCertificatesMock::PRIVATE_KEY), ); $nameID = $identifier->decrypt($decryptor); $this->assertInstanceOf(NameID::class, $nameID); - $this->assertEquals('just_a_basic_identifier', $nameID->getContent()); - $this->assertEquals(C::NAMEID_TRANSIENT, $nameID->getFormat()); + $this->assertEquals('just_a_basic_identifier', $nameID->getContent()->getValue()); + $this->assertEquals(C::NAMEID_TRANSIENT, $nameID->getFormat()->getValue()); } public function testMarshallingElementOrdering(): void { // Create an Issuer - $issuer = new Issuer('urn:x-simplesamlphp:issuer'); + $issuer = new Issuer( + SAMLStringValue::fromString('urn:x-simplesamlphp:issuer'), + ); // Create the conditions $conditions = new Conditions( - audienceRestriction: [new AudienceRestriction([new Audience(C::ENTITY_SP), new Audience(C::ENTITY_OTHER)])], + audienceRestriction: [ + new AudienceRestriction([ + new Audience(SAMLAnyURIValue::fromString(C::ENTITY_SP)), + new Audience(SAMLAnyURIValue::fromString(C::ENTITY_OTHER)), + ]), + ], ); // Create AttributeStatement @@ -1152,14 +1219,19 @@ public function testMarshallingElementOrdering(): void // Attribute [ new Attribute( - name: 'name1', - nameFormat: C::NAMEFORMAT_UNSPECIFIED, - attributeValue: [new AttributeValue('value1'), new AttributeValue('value2')], + name: SAMLStringValue::fromString('name1'), + nameFormat: SAMLAnyURIValue::fromString(C::NAMEFORMAT_UNSPECIFIED), + attributeValue: [ + new AttributeValue('value1'), + new AttributeValue('value2'), + ], ), new Attribute( - name: 'name2', - nameFormat: C::NAMEFORMAT_UNSPECIFIED, - attributeValue: [new AttributeValue('value3')], + name: SAMLStringValue::fromString('name2'), + nameFormat: SAMLAnyURIValue::fromString(C::NAMEFORMAT_UNSPECIFIED), + attributeValue: [ + new AttributeValue('value3'), + ], ), ], ); @@ -1167,16 +1239,21 @@ public function testMarshallingElementOrdering(): void // Create the statements $authnStatement = new AuthnStatement( new AuthnContext( - new AuthnContextClassRef(C::AUTHNCONTEXT_CLASS_REF_URN), + new AuthnContextClassRef( + SAMLAnyURIValue::fromString(C::AUTHNCONTEXT_CLASS_REF_URN), + ), null, null, ), - self::$clock->now(), + SAMLDateTimeValue::fromDateTime(self::$clock->now()), ); // Create Subject $subject = new Subject( - new NameID("just_a_basic_identifier", C::NAMEID_TRANSIENT), + new NameID( + value: SAMLStringValue::fromString("just_a_basic_identifier"), + Format: SAMLAnyURIValue::fromString(C::NAMEID_TRANSIENT), + ), ); $statements = [$authnStatement, $attributeStatement]; @@ -1184,7 +1261,8 @@ public function testMarshallingElementOrdering(): void // Create a signed assertion $assertion = new Assertion( issuer: $issuer, - issueInstant: self::$clock->now(), + id: IDValue::fromString('phpunit'), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), subject: $subject, conditions: $conditions, statements: $statements, @@ -1264,7 +1342,7 @@ public function testEncryption(): void $doc = DOMDocumentFactory::fromString(strval($encass)); $decryptor = (new KeyTransportAlgorithmFactory())->getAlgorithm( - $encass->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm(), + $encass->getEncryptedKeys()[0]->getEncryptionMethod()?->getAlgorithm()->getValue(), PEMCertificatesMock::getPrivateKey(PEMCertificatesMock::OTHER_PRIVATE_KEY), ); diff --git a/tests/SAML2/XML/saml/AssertionURIRefTest.php b/tests/SAML2/XML/saml/AssertionURIRefTest.php index 069b3f78a..bd78c1280 100644 --- a/tests/SAML2/XML/saml/AssertionURIRefTest.php +++ b/tests/SAML2/XML/saml/AssertionURIRefTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\AssertionURIRef; use SimpleSAML\XML\DOMDocumentFactory; @@ -46,7 +47,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $assertionURIRef = new AssertionURIRef('urn:x-simplesamlphp:reference'); + $assertionURIRef = new AssertionURIRef( + SAMLAnyURIValue::fromString('urn:x-simplesamlphp:reference'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/saml/AttributeStatementTest.php b/tests/SAML2/XML/saml/AttributeStatementTest.php index d340df880..d5c2a5f12 100644 --- a/tests/SAML2/XML/saml/AttributeStatementTest.php +++ b/tests/SAML2/XML/saml/AttributeStatementTest.php @@ -8,6 +8,7 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\Attribute; use SimpleSAML\SAML2\XML\saml\AttributeStatement; @@ -55,16 +56,22 @@ public function testMarshalling(): void $attrStatement = new AttributeStatement( [ new Attribute( - name: 'urn:ServiceID', - attributeValue: [new AttributeValue(1)], + name: SAMLStringValue::fromString('urn:ServiceID'), + attributeValue: [ + new AttributeValue(1), + ], ), new Attribute( - name: 'urn:EntityConcernedID', - attributeValue: [new AttributeValue(1)], + name: SAMLStringValue::fromString('urn:EntityConcernedID'), + attributeValue: [ + new AttributeValue(1), + ], ), new Attribute( - name: 'urn:EntityConcernedSubID', - attributeValue: [new AttributeValue(1)], + name: SAMLStringValue::fromString('urn:EntityConcernedSubID'), + attributeValue: [ + new AttributeValue(1), + ], ), ], ); diff --git a/tests/SAML2/XML/saml/AttributeTest.php b/tests/SAML2/XML/saml/AttributeTest.php index 9b264f8a3..42b668ea1 100644 --- a/tests/SAML2/XML/saml/AttributeTest.php +++ b/tests/SAML2/XML/saml/AttributeTest.php @@ -11,15 +11,18 @@ use SimpleSAML\SAML2\Compat\AbstractContainer; use SimpleSAML\SAML2\Compat\ContainerSingleton; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\Attribute; use SimpleSAML\SAML2\XML\saml\AttributeValue; use SimpleSAML\SAML2\XML\saml\EncryptedAttribute; use SimpleSAML\XML\Attribute as XMLAttribute; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Type\StringValue; use SimpleSAML\XMLSecurity\Alg\KeyTransport\KeyTransportAlgorithmFactory; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; @@ -79,13 +82,13 @@ public static function tearDownAfterClass(): void */ public function testMarshalling(): void { - $attr1 = new XMLAttribute('urn:test:something', 'test', 'attr1', 'testval1'); - $attr2 = new XMLAttribute('urn:test:something', 'test', 'attr2', 'testval2'); + $attr1 = new XMLAttribute('urn:test:something', 'test', 'attr1', StringValue::fromString('testval1')); + $attr2 = new XMLAttribute('urn:test:something', 'test', 'attr2', StringValue::fromString('testval2')); $attribute = new Attribute( - 'TheName', - C::NAMEFORMAT_BASIC, - 'TheFriendlyName', + SAMLStringValue::fromString('TheName'), + SAMLAnyURIValue::fromString(C::NAMEFORMAT_BASIC), + SAMLStringValue::fromString('TheFriendlyName'), [ new AttributeValue('FirstValue'), new AttributeValue('SecondValue'), @@ -138,7 +141,7 @@ public function testEncryption(): void $encattr = EncryptedAttribute::fromXML($doc->documentElement); $decryptor = (new KeyTransportAlgorithmFactory())->getAlgorithm( - $encattr->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm(), + $encattr->getEncryptedKeys()[0]->getEncryptionMethod()?->getAlgorithm()->getValue(), PEMCertificatesMock::getPrivateKey(PEMCertificatesMock::PRIVATE_KEY), ); diff --git a/tests/SAML2/XML/saml/AttributeValueTest.php b/tests/SAML2/XML/saml/AttributeValueTest.php index 385f6579f..17337852f 100644 --- a/tests/SAML2/XML/saml/AttributeValueTest.php +++ b/tests/SAML2/XML/saml/AttributeValueTest.php @@ -15,6 +15,7 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Constants as C_XSI; use function dirname; use function strval; @@ -88,8 +89,8 @@ public function testMarshallingInteger(): void $this->assertEquals('xs:integer', $av->getXsiType()); $nssaml = C::NS_SAML; - $nsxs = C::NS_XS; - $nsxsi = C::NS_XSI; + $nsxs = C_XSI::NS_XS; + $nsxsi = C_XSI::NS_XSI; $xml = <<3 XML; @@ -113,8 +114,8 @@ public function testMarshallingDateTime(): void $this->assertEquals('xs:dateTime', $av->getXsiType()); $nssaml = C::NS_SAML; - $nsxs = C::NS_XS; - $nsxsi = C::NS_XSI; + $nsxs = C_XSI::NS_XS; + $nsxsi = C_XSI::NS_XSI; $xml = <<2024-04-04T04:44:44Z XML; @@ -134,7 +135,7 @@ public function testMarshallingNull(): void $this->assertEquals('xs:nil', $av->getXsiType()); $nssaml = C::NS_SAML; - $nsxsi = C::NS_XSI; + $nsxsi = C_XSI::NS_XSI; $xml = << XML; @@ -148,17 +149,13 @@ public function testMarshallingNull(): void /** * Verifies that supplying an empty string as attribute value will * generate a tag with no content (instead of e.g. an empty tag). - * */ public function testEmptyStringAttribute(): void { $av = new AttributeValue(''); $xmlRepresentation = clone self::$xmlRepresentation; $xmlRepresentation->documentElement->textContent = ''; -// $this->assertEqualXMLStructure( -// $this->xmlRepresentation->documentElement, -// $av->toXML(), -// ); + $this->assertEquals('', $av->getValue()); $this->assertEquals('xs:string', $av->getXsiType()); } @@ -202,22 +199,22 @@ public function testSerializeEncryptedID(): void { $document = DOMDocumentFactory::fromString( << + - + - + vErnRkA0oSmtQGamjZGa9RFN25SUx1UVLsLAOtopt7pyywTD7wu9pyocfD4HqduXCsvaiZpJykz11utZdvtJ0sOdm9oE+lAtNTUnKzGSNoSopGCzwNu5pqwhIEvWEWeilmJayAC2elpRYOnUs/rePxibz0Wbqa7BItLt6ZkKTtMkv0U0PpgGenF1pWzsahRtw6Y5tFq7xFQkG/z0Lz5rJ+IxExYXgB3LN6FBmVcB1ioahk2ovOwbLQ+lNAdqUMhpZx6fgdL2v7g4OYPK0rDgSALU3gU3dvU4hC/Kk9N5Rkw= - + - + - + _b420654655d491b49555c698f80efb7bda3ac6ef diff --git a/tests/SAML2/XML/saml/AudienceRestrictionTest.php b/tests/SAML2/XML/saml/AudienceRestrictionTest.php index 79ede6cdd..8b281b905 100644 --- a/tests/SAML2/XML/saml/AudienceRestrictionTest.php +++ b/tests/SAML2/XML/saml/AudienceRestrictionTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\Audience; use SimpleSAML\SAML2\XML\saml\AudienceRestriction; @@ -52,8 +53,12 @@ public function testMarshalling(): void { $condition = new AudienceRestriction( [ - new Audience('urn:test:audience1'), - new Audience('urn:test:audience2'), + new Audience( + SAMLAnyURIValue::fromString('urn:test:audience1'), + ), + new Audience( + SAMLAnyURIValue::fromString('urn:test:audience2'), + ), ], ); diff --git a/tests/SAML2/XML/saml/AudienceTest.php b/tests/SAML2/XML/saml/AudienceTest.php index 09acf3cdc..06500997c 100644 --- a/tests/SAML2/XML/saml/AudienceTest.php +++ b/tests/SAML2/XML/saml/AudienceTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\saml\AbstractConditionType; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\Audience; @@ -48,7 +49,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $audience = new Audience('urn:test:audience1'); + $audience = new Audience( + SAMLAnyURIValue::fromString('urn:test:audience1'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/saml/AuthenticatingAuthorityTest.php b/tests/SAML2/XML/saml/AuthenticatingAuthorityTest.php index 0859bd356..153c418b2 100644 --- a/tests/SAML2/XML/saml/AuthenticatingAuthorityTest.php +++ b/tests/SAML2/XML/saml/AuthenticatingAuthorityTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\EntityIDValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\AuthenticatingAuthority; use SimpleSAML\XML\DOMDocumentFactory; @@ -46,7 +47,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $authenticatingAuthority = new AuthenticatingAuthority('https://idp.example.com/SAML2'); + $authenticatingAuthority = new AuthenticatingAuthority( + EntityIDValue::fromString('https://idp.example.com/SAML2'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/saml/AuthnContextClassRefTest.php b/tests/SAML2/XML/saml/AuthnContextClassRefTest.php index 17c77cb8d..9eb541994 100644 --- a/tests/SAML2/XML/saml/AuthnContextClassRefTest.php +++ b/tests/SAML2/XML/saml/AuthnContextClassRefTest.php @@ -8,6 +8,7 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\AuthnContextClassRef; use SimpleSAML\XML\DOMDocumentFactory; @@ -48,7 +49,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $authnContextClassRef = new AuthnContextClassRef(C::AC_PASSWORD_PROTECTED_TRANSPORT); + $authnContextClassRef = new AuthnContextClassRef( + SAMLAnyURIValue::fromString(C::AC_PASSWORD_PROTECTED_TRANSPORT), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/saml/AuthnContextDeclRefTest.php b/tests/SAML2/XML/saml/AuthnContextDeclRefTest.php index bba871b3c..4c8b45413 100644 --- a/tests/SAML2/XML/saml/AuthnContextDeclRefTest.php +++ b/tests/SAML2/XML/saml/AuthnContextDeclRefTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\AuthnContextDeclRef; use SimpleSAML\XML\DOMDocumentFactory; @@ -49,7 +50,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $authnContextDeclRef = new AuthnContextDeclRef('https://example.org/relative/path/to/document.xml'); + $authnContextDeclRef = new AuthnContextDeclRef( + SAMLAnyURIValue::fromString('https://example.org/relative/path/to/document.xml'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/saml/AuthnContextDeclTest.php b/tests/SAML2/XML/saml/AuthnContextDeclTest.php index 93a92706a..abc63245e 100644 --- a/tests/SAML2/XML/saml/AuthnContextDeclTest.php +++ b/tests/SAML2/XML/saml/AuthnContextDeclTest.php @@ -14,6 +14,7 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\StringValue; use function dirname; use function strval; @@ -66,7 +67,9 @@ public function testMarshalling(): void $authnContextDecl = new AuthnContextDecl( [$chunk], - [new XMLAttribute('urn:x-simplesamlphp:namespace', 'ssp', 'attr1', 'testval1')], + [ + new XMLAttribute('urn:x-simplesamlphp:namespace', 'ssp', 'attr1', StringValue::fromString('testval1')), + ], ); $this->assertEquals( diff --git a/tests/SAML2/XML/saml/AuthnContextTest.php b/tests/SAML2/XML/saml/AuthnContextTest.php index 9ff1a39f4..655ad206c 100644 --- a/tests/SAML2/XML/saml/AuthnContextTest.php +++ b/tests/SAML2/XML/saml/AuthnContextTest.php @@ -10,6 +10,8 @@ use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\AuthenticatingAuthority; use SimpleSAML\SAML2\XML\saml\AuthnContext; @@ -17,7 +19,7 @@ use SimpleSAML\SAML2\XML\saml\AuthnContextDecl; use SimpleSAML\SAML2\XML\saml\AuthnContextDeclRef; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; use function dirname; @@ -52,9 +54,16 @@ public static function setUpBeforeClass(): void */ public function testMarshallingIllegalCombination(): void { - $authnContextClassRef = new AuthnContextClassRef(C::AC_PASSWORD_PROTECTED_TRANSPORT); + $authnContextClassRef = new AuthnContextClassRef( + SAMLAnyURIValue::fromString(C::AC_PASSWORD_PROTECTED_TRANSPORT), + ); $authnContextDecl = AuthnContextDecl::fromXML(self::$decl->documentElement); - $authnContextDeclRef = new AuthnContextDeclRef('https://example.org/relative/path/to/document.xml'); + $authnContextDeclRef = new AuthnContextDeclRef( + SAMLAnyURIValue::fromString('https://example.org/relative/path/to/document.xml'), + ); + $authenticatingAuthority = new AuthenticatingAuthority( + EntityIDValue::fromString('https://idp.example.com/SAML2'), + ); $this->expectException(AssertionFailedException::class); $this->expectExceptionMessage('Can only have one of AuthnContextDecl/AuthnContextDeclRef'); @@ -63,9 +72,7 @@ public function testMarshallingIllegalCombination(): void $authnContextClassRef, $authnContextDecl, $authnContextDeclRef, - [ - new AuthenticatingAuthority('https://idp.example.com/SAML2'), - ], + [$authenticatingAuthority], ); } diff --git a/tests/SAML2/XML/saml/AuthnContextWithClassRefAndDeclRefTest.php b/tests/SAML2/XML/saml/AuthnContextWithClassRefAndDeclRefTest.php index 16895212c..a524c47da 100644 --- a/tests/SAML2/XML/saml/AuthnContextWithClassRefAndDeclRefTest.php +++ b/tests/SAML2/XML/saml/AuthnContextWithClassRefAndDeclRefTest.php @@ -8,6 +8,8 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\AuthenticatingAuthority; use SimpleSAML\SAML2\XML\saml\AuthnContext; @@ -52,10 +54,18 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $authnContext = new AuthnContext( - authnContextClassRef: new AuthnContextClassRef(C::AC_PASSWORD_PROTECTED_TRANSPORT), - authnContextDeclRef: new AuthnContextDeclRef('https://example.org/relative/path/to/document.xml'), + authnContextClassRef: new AuthnContextClassRef( + SAMLAnyURIValue::fromString(C::AC_PASSWORD_PROTECTED_TRANSPORT), + ), + authnContextDeclRef: new AuthnContextDeclRef( + SAMLAnyURIValue::fromString('https://example.org/relative/path/to/document.xml'), + ), authnContextDecl: null, - authenticatingAuthorities: [new AuthenticatingAuthority('https://idp.example.com/SAML2')], + authenticatingAuthorities: [ + new AuthenticatingAuthority( + EntityIDValue::fromString('https://idp.example.com/SAML2'), + ), + ], ); $this->assertEquals( diff --git a/tests/SAML2/XML/saml/AuthnContextWithClassRefAndDeclTest.php b/tests/SAML2/XML/saml/AuthnContextWithClassRefAndDeclTest.php index 81af59d72..d1e44cb7e 100644 --- a/tests/SAML2/XML/saml/AuthnContextWithClassRefAndDeclTest.php +++ b/tests/SAML2/XML/saml/AuthnContextWithClassRefAndDeclTest.php @@ -8,6 +8,8 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\AuthenticatingAuthority; use SimpleSAML\SAML2\XML\saml\AuthnContext; @@ -18,6 +20,7 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\StringValue; use function dirname; use function strval; @@ -68,14 +71,20 @@ public function testMarshalling(): void $authnContextDecl = new AuthnContextDecl( [$chunk], - [new XMLAttribute('urn:x-simplesamlphp:namespace', 'ssp', 'attr1', 'testval1')], + [new XMLAttribute('urn:x-simplesamlphp:namespace', 'ssp', 'attr1', StringValue::fromString('testval1'))], ); $authnContext = new AuthnContext( - authnContextClassRef: new AuthnContextClassRef(C::AC_PASSWORD_PROTECTED_TRANSPORT), + authnContextClassRef: new AuthnContextClassRef( + SAMLAnyURIValue::fromString(C::AC_PASSWORD_PROTECTED_TRANSPORT), + ), authnContextDecl: $authnContextDecl, authnContextDeclRef: null, - authenticatingAuthorities: [new AuthenticatingAuthority('https://idp.example.com/SAML2')], + authenticatingAuthorities: [ + new AuthenticatingAuthority( + EntityIDValue::fromString('https://idp.example.com/SAML2'), + ), + ], ); $this->assertEquals( diff --git a/tests/SAML2/XML/saml/AuthnContextWithClassRefTest.php b/tests/SAML2/XML/saml/AuthnContextWithClassRefTest.php index 0e27fa5d1..8620433ae 100644 --- a/tests/SAML2/XML/saml/AuthnContextWithClassRefTest.php +++ b/tests/SAML2/XML/saml/AuthnContextWithClassRefTest.php @@ -8,6 +8,8 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\AuthenticatingAuthority; use SimpleSAML\SAML2\XML\saml\AuthnContext; @@ -51,10 +53,16 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $authnContext = new AuthnContext( - authnContextClassRef: new AuthnContextClassRef(C::AC_PASSWORD_PROTECTED_TRANSPORT), + authnContextClassRef: new AuthnContextClassRef( + SAMLAnyURIValue::fromString(C::AC_PASSWORD_PROTECTED_TRANSPORT), + ), authnContextDeclRef: null, authnContextDecl: null, - authenticatingAuthorities: [new AuthenticatingAuthority('https://idp.example.com/SAML2')], + authenticatingAuthorities: [ + new AuthenticatingAuthority( + EntityIDValue::fromString('https://idp.example.com/SAML2'), + ), + ], ); $this->assertEquals( diff --git a/tests/SAML2/XML/saml/AuthnContextWithDeclRefTest.php b/tests/SAML2/XML/saml/AuthnContextWithDeclRefTest.php index 17e30605a..5d8d87143 100644 --- a/tests/SAML2/XML/saml/AuthnContextWithDeclRefTest.php +++ b/tests/SAML2/XML/saml/AuthnContextWithDeclRefTest.php @@ -7,6 +7,8 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\AuthenticatingAuthority; use SimpleSAML\SAML2\XML\saml\AuthnContext; @@ -51,9 +53,15 @@ public function testMarshalling(): void { $authnContext = new AuthnContext( authnContextClassRef: null, - authnContextDeclRef: new AuthnContextDeclRef('https://example.org/relative/path/to/document.xml'), + authnContextDeclRef: new AuthnContextDeclRef( + SAMLAnyURIValue::fromString('https://example.org/relative/path/to/document.xml'), + ), authnContextDecl: null, - authenticatingAuthorities: [new AuthenticatingAuthority('https://idp.example.com/SAML2')], + authenticatingAuthorities: [ + new AuthenticatingAuthority( + EntityIDValue::fromString('https://idp.example.com/SAML2'), + ), + ], ); $this->assertEquals( diff --git a/tests/SAML2/XML/saml/AuthnContextWithDeclTest.php b/tests/SAML2/XML/saml/AuthnContextWithDeclTest.php index c8581a1e9..e6e45ea90 100644 --- a/tests/SAML2/XML/saml/AuthnContextWithDeclTest.php +++ b/tests/SAML2/XML/saml/AuthnContextWithDeclTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\EntityIDValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\AuthenticatingAuthority; use SimpleSAML\SAML2\XML\saml\AuthnContext; @@ -16,6 +17,7 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\StringValue; use function dirname; use function strval; @@ -66,14 +68,18 @@ public function testMarshalling(): void $authnContextDecl = new AuthnContextDecl( [$chunk], - [new XMLAttribute('urn:x-simplesamlphp:namespace', 'ssp', 'attr1', 'testval1')], + [new XMLAttribute('urn:x-simplesamlphp:namespace', 'ssp', 'attr1', StringValue::fromString('testval1'))], ); $authnContext = new AuthnContext( authnContextClassRef: null, authnContextDecl: $authnContextDecl, authnContextDeclRef: null, - authenticatingAuthorities: [new AuthenticatingAuthority('https://idp.example.com/SAML2')], + authenticatingAuthorities: [ + new AuthenticatingAuthority( + EntityIDValue::fromString('https://idp.example.com/SAML2'), + ), + ], ); $this->assertEquals( diff --git a/tests/SAML2/XML/saml/AuthnStatementTest.php b/tests/SAML2/XML/saml/AuthnStatementTest.php index 9faf5a008..5b1721ee9 100644 --- a/tests/SAML2/XML/saml/AuthnStatementTest.php +++ b/tests/SAML2/XML/saml/AuthnStatementTest.php @@ -4,11 +4,15 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use DateTimeImmutable; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\DomainValue; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\AuthenticatingAuthority; @@ -17,11 +21,11 @@ use SimpleSAML\SAML2\XML\saml\AuthnStatement; use SimpleSAML\SAML2\XML\saml\SubjectLocality; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; -use SimpleSAML\XML\Exception\MissingElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; use function dirname; use function strval; @@ -61,15 +65,24 @@ public function testMarshalling(): void { $authnStatement = new AuthnStatement( new AuthnContext( - new AuthnContextClassRef(C::AC_PASSWORD_PROTECTED_TRANSPORT), + new AuthnContextClassRef( + SAMLAnyURIValue::fromString(C::AC_PASSWORD_PROTECTED_TRANSPORT), + ), null, null, - [new AuthenticatingAuthority('https://idp.example.com/SAML2')], + [ + new AuthenticatingAuthority( + EntityIDValue::fromString('https://idp.example.com/SAML2'), + ), + ], + ), + SAMLDateTimeValue::fromString('2020-03-23T23:37:24Z'), + SAMLDateTimeValue::fromString('2020-03-23T23:37:24Z'), + SAMLStringValue::fromString('123'), + new SubjectLocality( + SAMLStringValue::fromString('1.1.1.1'), + DomainValue::fromString('idp.example.org'), ), - new DateTimeImmutable('2020-03-23T23:37:24Z'), - new DateTimeImmutable('2020-03-23T23:37:24Z'), - '123', - new SubjectLocality('1.1.1.1', 'idp.example.org'), ); $this->assertEquals( @@ -85,15 +98,24 @@ public function testMarshallingElementOrdering(): void { $authnStatement = new AuthnStatement( new AuthnContext( - new AuthnContextClassRef(C::AC_PASSWORD_PROTECTED_TRANSPORT), + new AuthnContextClassRef( + SAMLAnyURIValue::fromString(C::AC_PASSWORD_PROTECTED_TRANSPORT), + ), null, null, - [new AuthenticatingAuthority('https://idp.example.com/SAML2')], + [ + new AuthenticatingAuthority( + EntityIDValue::fromString('https://idp.example.com/SAML2'), + ), + ], + ), + SAMLDateTimeValue::fromString('2020-03-23T23:37:24Z'), + SAMLDateTimeValue::fromString('2020-03-23T23:37:24Z'), + SAMLStringValue::fromString('123'), + new SubjectLocality( + SAMLStringValue::fromString('1.1.1.1'), + DomainValue::fromString('idp.example.org'), ), - new DateTimeImmutable('2020-03-23T23:37:24Z'), - new DateTimeImmutable('2020-03-23T23:37:24Z'), - '123', - new SubjectLocality('1.1.1.1', 'idp.example.org'), ); // Marshall it to a \DOMElement diff --git a/tests/SAML2/XML/saml/AuthzDecisionStatementTest.php b/tests/SAML2/XML/saml/AuthzDecisionStatementTest.php index 220b783cf..3a5441820 100644 --- a/tests/SAML2/XML/saml/AuthzDecisionStatementTest.php +++ b/tests/SAML2/XML/saml/AuthzDecisionStatementTest.php @@ -8,11 +8,17 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\Decision; +use SimpleSAML\SAML2\Type\DecisionTypeValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\AbstractStatement; use SimpleSAML\SAML2\XML\saml\Action; +use SimpleSAML\SAML2\XML\saml\Assertion; +use SimpleSAML\SAML2\XML\saml\AssertionIDRef; +use SimpleSAML\SAML2\XML\saml\AssertionURIRef; use SimpleSAML\SAML2\XML\saml\AuthzDecisionStatement; +use SimpleSAML\SAML2\XML\saml\DecisionTypeEnum; use SimpleSAML\SAML2\XML\saml\Evidence; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; @@ -36,8 +42,14 @@ final class AuthzDecisionStatementTest extends TestCase use SerializableElementTestTrait; - /** @var \DOMDocument $evidence */ - private static DOMDocument $evidence; + /** @var \DOMDocument $assertionIDRef */ + private static DOMDocument $assertionIDRef; + + /** @var \DOMDocument $assertionURIRef */ + private static DOMDocument $assertionURIRef; + + /** @var \DOMDocument $assertion */ + private static DOMDocument $assertion; /** @@ -50,8 +62,16 @@ public static function setUpBeforeClass(): void dirname(__FILE__, 4) . '/resources/xml/saml_AuthzDecisionStatement.xml', ); - self::$evidence = DOMDocumentFactory::fromFile( - dirname(__FILE__, 4) . '/resources/xml/saml_Evidence.xml', + self::$assertionIDRef = DOMDocumentFactory::fromFile( + dirname(__FILE__, 4) . '/resources/xml/saml_AssertionIDRef.xml', + ); + + self::$assertionURIRef = DOMDocumentFactory::fromFile( + dirname(__FILE__, 4) . '/resources/xml/saml_AssertionURIRef.xml', + ); + + self::$assertion = DOMDocumentFactory::fromFile( + dirname(__FILE__, 4) . '/resources/xml/saml_Assertion.xml', ); } @@ -60,14 +80,26 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { + $evidence = new Evidence( + [AssertionIDRef::fromXML(self::$assertionIDRef->documentElement)], + [AssertionURIRef::fromXML(self::$assertionURIRef->documentElement)], + [Assertion::fromXML(self::$assertion->documentElement)], + ); + $authzDecisionStatement = new AuthzDecisionStatement( - 'urn:x-simplesamlphp:resource', - Decision::PERMIT, + SAMLAnyURIValue::fromString('urn:x-simplesamlphp:resource'), + DecisionTypeValue::fromEnum(DecisionTypeEnum::Permit), [ - new Action('urn:x-simplesamlphp:namespace', 'SomeAction'), - new Action('urn:x-simplesamlphp:namespace', 'OtherAction'), + new Action( + SAMLAnyURIValue::fromString('urn:x-simplesamlphp:namespace'), + SAMLStringValue::fromString('SomeAction'), + ), + new Action( + SAMLAnyURIValue::fromString('urn:x-simplesamlphp:namespace'), + SAMLStringValue::fromString('OtherAction'), + ), ], - Evidence::fromXML(self::$evidence->documentElement), + $evidence, ); $this->assertEquals( diff --git a/tests/SAML2/XML/saml/BaseIDTest.php b/tests/SAML2/XML/saml/BaseIDTest.php index 67ed575e6..58c81b632 100644 --- a/tests/SAML2/XML/saml/BaseIDTest.php +++ b/tests/SAML2/XML/saml/BaseIDTest.php @@ -9,6 +9,8 @@ use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Compat\AbstractContainer; use SimpleSAML\SAML2\Compat\ContainerSingleton; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\AbstractBaseID; use SimpleSAML\SAML2\XML\saml\AbstractBaseIDType; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; @@ -19,6 +21,7 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Constants as C_XSI; use function dirname; use function strval; @@ -79,9 +82,13 @@ public static function tearDownAfterClass(): void public function testMarshalling(): void { $baseId = new CustomBaseID( - [new Audience('urn:some:audience')], - 'urn:x-simplesamlphp:namequalifier', - 'urn:x-simplesamlphp:spnamequalifier', + [ + new Audience( + SAMLAnyURIValue::fromString('urn:some:audience'), + ), + ], + SAMLStringValue::fromString('urn:x-simplesamlphp:namequalifier'), + SAMLStringValue::fromString('urn:x-simplesamlphp:spnamequalifier'), ); $this->assertEquals( @@ -122,14 +129,17 @@ public function testUnmarshalling(): void public function testUnmarshallingUnregistered(): void { $element = clone self::$xmlRepresentation->documentElement; - $element->setAttributeNS(C::NS_XSI, 'xsi:type', 'ssp:UnknownBaseIDType'); + $element->setAttributeNS(C_XSI::NS_XSI, 'xsi:type', 'ssp:UnknownBaseIDType'); $baseId = AbstractBaseID::fromXML($element); $this->assertInstanceOf(UnknownID::class, $baseId); $this->assertEquals('urn:x-simplesamlphp:namequalifier', $baseId->getNameQualifier()); $this->assertEquals('urn:x-simplesamlphp:spnamequalifier', $baseId->getSPNameQualifier()); - $this->assertEquals('urn:x-simplesamlphp:namespace:UnknownBaseIDType', $baseId->getXsiType()); + $this->assertEquals( + '{urn:x-simplesamlphp:namespace}ssp:UnknownBaseIDType', + $baseId->getXsiType()->getRawValue(), + ); $chunk = $baseId->getRawIdentifier(); $this->assertEquals('saml', $chunk->getPrefix()); diff --git a/tests/SAML2/XML/saml/ConditionTest.php b/tests/SAML2/XML/saml/ConditionTest.php index 3c4bd262b..125a8be58 100644 --- a/tests/SAML2/XML/saml/ConditionTest.php +++ b/tests/SAML2/XML/saml/ConditionTest.php @@ -9,6 +9,7 @@ use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Compat\AbstractContainer; use SimpleSAML\SAML2\Compat\ContainerSingleton; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\saml\AbstractCondition; use SimpleSAML\SAML2\XML\saml\AbstractConditionType; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; @@ -19,6 +20,7 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Constants as C_XSI; use function dirname; use function strval; @@ -78,9 +80,11 @@ public static function tearDownAfterClass(): void */ public function testMarshalling(): void { - $condition = new CustomCondition( - [new Audience('urn:some:audience')], - ); + $condition = new CustomCondition([ + new Audience( + SAMLAnyURIValue::fromString('urn:some:audience'), + ), + ]); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), @@ -97,12 +101,15 @@ public function testMarshalling(): void public function testUnmarshallingUnregistered(): void { $element = clone self::$xmlRepresentation->documentElement; - $element->setAttributeNS(C::NS_XSI, 'xsi:type', 'ssp:UnknownConditionType'); + $element->setAttributeNS(C_XSI::NS_XSI, 'xsi:type', 'ssp:UnknownConditionType'); $condition = AbstractCondition::fromXML($element); $this->assertInstanceOf(UnknownCondition::class, $condition); - $this->assertEquals('urn:x-simplesamlphp:namespace:UnknownConditionType', $condition->getXsiType()); + $this->assertEquals( + '{urn:x-simplesamlphp:namespace}ssp:UnknownConditionType', + $condition->getXsiType()->getRawValue(), + ); $chunk = $condition->getRawCondition(); $this->assertEquals('saml', $chunk->getPrefix()); diff --git a/tests/SAML2/XML/saml/ConditionsTest.php b/tests/SAML2/XML/saml/ConditionsTest.php index 74140c1cf..b4eb78638 100644 --- a/tests/SAML2/XML/saml/ConditionsTest.php +++ b/tests/SAML2/XML/saml/ConditionsTest.php @@ -4,11 +4,12 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use DateTimeImmutable; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\Audience; use SimpleSAML\SAML2\XML\saml\AudienceRestriction; @@ -18,6 +19,7 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\NonNegativeIntegerValue; use function dirname; use function strval; @@ -56,22 +58,26 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $conditions = new Conditions( - new DateTimeImmutable('2014-07-17T01:01:18Z'), - new DateTimeImmutable('2024-01-18T06:21:48Z'), + SAMLDateTimeValue::fromString('2014-07-17T01:01:18Z'), + SAMLDateTimeValue::fromString('2024-01-18T06:21:48Z'), [], [ new AudienceRestriction( [ - new Audience('http://sp.example.com/demo1/metadata.php'), + new Audience( + SAMLAnyURIValue::fromString('http://sp.example.com/demo1/metadata.php'), + ), ], ), ], new OneTimeUse(), new ProxyRestriction( [ - new Audience('http://sp.example.com/demo2/metadata.php'), + new Audience( + SAMLAnyURIValue::fromString('http://sp.example.com/demo2/metadata.php'), + ), ], - 2, + NonNegativeIntegerValue::fromInteger(2), ), ); diff --git a/tests/SAML2/XML/saml/EncryptedAssertionTest.php b/tests/SAML2/XML/saml/EncryptedAssertionTest.php index 07487f386..ab55542e3 100644 --- a/tests/SAML2/XML/saml/EncryptedAssertionTest.php +++ b/tests/SAML2/XML/saml/EncryptedAssertionTest.php @@ -10,6 +10,9 @@ use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Compat\AbstractContainer; use SimpleSAML\SAML2\Compat\ContainerSingleton; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\Assertion; use SimpleSAML\SAML2\XML\saml\EncryptedAssertion; @@ -20,6 +23,10 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\AnyURIValue; +use SimpleSAML\XMLSchema\Type\Base64BinaryValue; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\StringValue; use SimpleSAML\XMLSecurity\Alg\KeyTransport\KeyTransportAlgorithmFactory; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; @@ -32,6 +39,7 @@ use SimpleSAML\XMLSecurity\XML\xenc\EncryptedData; use SimpleSAML\XMLSecurity\XML\xenc\EncryptedKey; use SimpleSAML\XMLSecurity\XML\xenc\EncryptionMethod; +use SimpleSAML\XPath\Constants as C_XPATH; use function dirname; use function strval; @@ -92,24 +100,42 @@ public static function tearDownAfterClass(): void */ public function testMarshalling(): void { - $transforms = new Transforms( - [new Transform(C::XPATH10_URI, new XPath('self::xenc:CipherValue[@Id="example1"]'))], + $transforms = new Transforms([ + new Transform( + SAMLAnyURIValue::fromString(C_XPATH::XPATH10_URI), + new XPath( + StringValue::fromString('self::xenc:CipherValue[@Id="example1"]'), + ), + ), + ]); + + $retrievalMethod = new RetrievalMethod( + $transforms, + AnyURIValue::fromString('#Encrypted_KEY_ID'), + AnyURIValue::fromString(C::XMLENC_ENCRYPTEDKEY), ); - $retrievalMethod = new RetrievalMethod($transforms, '#Encrypted_KEY_ID', C::XMLENC_ENCRYPTEDKEY); $ek = new EncryptedKey( cipherData: new CipherData( - new CipherValue('sNLWjwyj/R0oPwSgNnqowahiOwM0YU3YaH3jsH0t2YUDcHkcgouvW5x6YbNdgvGq0ImsNrkjI//0hrL4HvrOX33+DkhCo2FX5+a7UCdftfBfSjvt0houF8z3Zq/XOm6HxBUbWt5MULYpMKMZ9iAY6+raydxk2tFWgnAyHaBfzvU='), + new CipherValue( + Base64BinaryValue::fromString('sNLWjwyj/R0oPwSgNnqowahiOwM0YU3YaH3jsH0t2YUDcHkcgouvW5x6YbNdgvGq0ImsNrkjI//0hrL4HvrOX33+DkhCo2FX5+a7UCdftfBfSjvt0houF8z3Zq/XOm6HxBUbWt5MULYpMKMZ9iAY6+raydxk2tFWgnAyHaBfzvU='), + ), + ), + encryptionMethod: new EncryptionMethod( + AnyURIValue::fromString(C::KEY_TRANSPORT_OAEP_MGF1P), ), - encryptionMethod: new EncryptionMethod(C::KEY_TRANSPORT_OAEP_MGF1P), ); $ed = new EncryptedData( cipherData: new CipherData( - new CipherValue('mlo++g0c4lTsVbL7ArhQh5/xu6t9EuNoRZXF8dqYIq0hARzKiZC5OhTZtHpQlwVd5f4N/lDsur2hhFAu5dxGVdWF+xN4wGMVoQDcyqipwH00w4lO5GNPD16mb1I5l3v3LJf9jKm+090Mv54BPsSOhSYvPBGbv2Uj6LzRE6z0l9zTWtyj2Z7lShrOYR6ZgG254HoltAA6veBXROEdPBBax0ezvoKmOBUcN1RX15Bfj0fVOX1FzS27SX+GCWYgCr0xPnhNBxaMhvU/2ayW6S8A5HWHWb1K2h/VVx6eumXaKzUFoEO5MxfC3Kxni3R3jyaGXmAZ4LhzcpWxJvz9LCpq5+9ovjnRNhheMrtQr/eZ6kWQ12pzKlHCfuFESB0IK2V2NbBDSe6C4n6TAS9mia9tT7CaKsRhVKlNMfkMKC+B6AOkTvlt6Rma5iz/QKL0A7t4LufQ/17YSb3eNOesmV/l3T8bEFqTRHiO8CwiT28ctfDjd0OKB4q1gh0PSidZL/yuaFTG/WXDpnpIV9qZELUgLVjFzW5+Rb/Alv2U7tE68c8oXv7xqmBUhkFQhYBy84cwHrCeKqn2iiJkh19aXYdgAZxys9Dp2+B2wX86coLU2CDJlyyCEohkXn5w8TkU0zNDZnh8J1oz5iawSx1d0aPy+uLNYVUMmx2hcrb3PlWdUApnyts38DcNwTkTy2/uxZmBU/4VGi3JzdnQ7KbW7EUXe3veExb63mRlU+cWl8LMRgP1FExg3CKT6HhW3roTu9GI51ofHpjPCPi41xQvoRrUo2VytBV/IZi4ArD4Y9d2tIcK2O0ZblUNjpRsNhPsVuCDLH23Fx42/5eGVkeTLPOt+Mr6IfY2d1NJGzqz9vJ4/h3L5PelDBQiD/o+5ZvgS5I5HL0bVbGXkT+v6k2GhHQDKNE3qJviXLRPjWv+Eaq+wJhukmcivA1z75/IydZhSPBZfhgORe6n5coiCf2mqiaZpI1YEZRR2g77NXf7I8qAuR7umkEpLC1ciLUpwZjaLNb7ojmC7cogXv8FmcWOk1xWdr7+kY3FXaWWwhUgxO4CSUYGdcOvydybcvAFTnf09+lR0RKVTGgnuukgYROyl8ulY2hoAFm+/jy9qcGqE/7JBlm6qx0B815TZY0aC3ulgwYDvUhdk9Sxq7Dp44h7BMBQezY2o4PBsY6nJNbCAkSULQ1rMY1nZViAAtZntTeHsnlFYm3pJo7MEhrGLYE/nSVcEHuP0z4WpwSb4CW2eOFBmrHcJfqBmDTnFtRwBQZfhQvcSyLy9Vyy//Hj7oDpC6GKmC3m9QTH+9T95sVxhHYkHN10YfHHQhn2pouNzo95QKVVtF98UGMEqrpIbtgGd+CE4icDjq8Qm8iQzJD/DB1YIjpwS0ftoD5+n/YlFYCbbOedN7uxsh9a3Q4NhbkYhNwYQN+/nkr90j6X9PS6uon04TS5GfxpX9gGczxMfeUKHh93in+UksVdzWqgrGxtdXGg7eataR2AcWoTIzsOTWC1sUIi/cOD1N2WR7dMBajNI1vZEsc2+DF3JgfYMigT0sa804LwZNeuopjcgP6qUxL+N+uFO+mobnMZAWK2zBmVwG60psV5zkOShGxq+l+AuobD0pKl0PH4qwhOIUbTc72F2snuKEAJvnpaW2kWymATnbuYsUrpUwoWUmAT4l9o6mD4XGAaYG6YUjD0JJDSJrHKgWy7j5Dqb6ocEMubzOAzpFT6H+BPd09ZraBDLELjX+yYow/adGsGw3sOwDZYfHwM+2f78j8xqCbWgaCME02umAfbkXGbIZ1l7cQv3w0QIDPKreePjI6vMHKJtSsOz9yMwb7RqMf53+m4e+HTlBZEV1m5Dd99qp3ESUYvUEg8rHmx+GeY1KyjZz14AXyxxvepQ4TZFPbROcNvL6EUm4gV7MV+MdkyRznA3nMro5vuGteuEAmqyFGuK/mmTGboA5FDBGnvRGzMt87eJtwWyeaPca7YZttaZJRv2Gbko9T7YNU9bdcJ41m9XC3BApUNQ3nQwWoallQrGX3r862to2Cl7z3MegrSt3GBDCI7RgmBPuEaVAFQQz0Rgr50zBtG834r7/RJ4gQtD0VksO1NoJoM/aifqWjKgRpawOnn2UkztqXEAkTwry04nNkMdLHCegDtl8cqdEAI5kzXMUf7fNxO19eOa+Yc4LYlNIPLOUIw3bGdCjZhhRuP9WR6UpQc69u6zK38e5Sxe+ff+XAdDB9OoH7We+9lRVvrmu4LbtbshctbX5Xz+sIq2xNmQy01xF3UHLUy3hQU1pglo9l5fLD5Nd/1xOs2hu9gaGJFI0efzJvNSHaPuXAvESvT5YBhONh6PfbjHEYuIYXL0ZVtF3cTpW29VXeyA8Uvx9PAxjSbyR/BlF1lTaCotAYCzI2keg6RTK3NCmo3co4t43hNemXPffCwykv4ShU8jdennk167W/6JTmTX7ppmseXimMP9DHnXZEomakUIZComiXxqlnTvw/Xdh9GGWA+6qgS5k68a3hdr2cD1gAKX1T53QCrXbNzpcZ9ab4CaCTv8iFtZaGXOBJjwOXAWZEf3k0I9XQZ3FCeg1Gqs8NgULwfWQTv78208kbsiLOGeu9mGEXgXNyK0yO/U4AWJb+HEfPpfeN3tpHFigzmALzt8RztCKcRv+gKm3RyVEW5'), + new CipherValue( + Base64BinaryValue::fromString('mlo++g0c4lTsVbL7ArhQh5/xu6t9EuNoRZXF8dqYIq0hARzKiZC5OhTZtHpQlwVd5f4N/lDsur2hhFAu5dxGVdWF+xN4wGMVoQDcyqipwH00w4lO5GNPD16mb1I5l3v3LJf9jKm+090Mv54BPsSOhSYvPBGbv2Uj6LzRE6z0l9zTWtyj2Z7lShrOYR6ZgG254HoltAA6veBXROEdPBBax0ezvoKmOBUcN1RX15Bfj0fVOX1FzS27SX+GCWYgCr0xPnhNBxaMhvU/2ayW6S8A5HWHWb1K2h/VVx6eumXaKzUFoEO5MxfC3Kxni3R3jyaGXmAZ4LhzcpWxJvz9LCpq5+9ovjnRNhheMrtQr/eZ6kWQ12pzKlHCfuFESB0IK2V2NbBDSe6C4n6TAS9mia9tT7CaKsRhVKlNMfkMKC+B6AOkTvlt6Rma5iz/QKL0A7t4LufQ/17YSb3eNOesmV/l3T8bEFqTRHiO8CwiT28ctfDjd0OKB4q1gh0PSidZL/yuaFTG/WXDpnpIV9qZELUgLVjFzW5+Rb/Alv2U7tE68c8oXv7xqmBUhkFQhYBy84cwHrCeKqn2iiJkh19aXYdgAZxys9Dp2+B2wX86coLU2CDJlyyCEohkXn5w8TkU0zNDZnh8J1oz5iawSx1d0aPy+uLNYVUMmx2hcrb3PlWdUApnyts38DcNwTkTy2/uxZmBU/4VGi3JzdnQ7KbW7EUXe3veExb63mRlU+cWl8LMRgP1FExg3CKT6HhW3roTu9GI51ofHpjPCPi41xQvoRrUo2VytBV/IZi4ArD4Y9d2tIcK2O0ZblUNjpRsNhPsVuCDLH23Fx42/5eGVkeTLPOt+Mr6IfY2d1NJGzqz9vJ4/h3L5PelDBQiD/o+5ZvgS5I5HL0bVbGXkT+v6k2GhHQDKNE3qJviXLRPjWv+Eaq+wJhukmcivA1z75/IydZhSPBZfhgORe6n5coiCf2mqiaZpI1YEZRR2g77NXf7I8qAuR7umkEpLC1ciLUpwZjaLNb7ojmC7cogXv8FmcWOk1xWdr7+kY3FXaWWwhUgxO4CSUYGdcOvydybcvAFTnf09+lR0RKVTGgnuukgYROyl8ulY2hoAFm+/jy9qcGqE/7JBlm6qx0B815TZY0aC3ulgwYDvUhdk9Sxq7Dp44h7BMBQezY2o4PBsY6nJNbCAkSULQ1rMY1nZViAAtZntTeHsnlFYm3pJo7MEhrGLYE/nSVcEHuP0z4WpwSb4CW2eOFBmrHcJfqBmDTnFtRwBQZfhQvcSyLy9Vyy//Hj7oDpC6GKmC3m9QTH+9T95sVxhHYkHN10YfHHQhn2pouNzo95QKVVtF98UGMEqrpIbtgGd+CE4icDjq8Qm8iQzJD/DB1YIjpwS0ftoD5+n/YlFYCbbOedN7uxsh9a3Q4NhbkYhNwYQN+/nkr90j6X9PS6uon04TS5GfxpX9gGczxMfeUKHh93in+UksVdzWqgrGxtdXGg7eataR2AcWoTIzsOTWC1sUIi/cOD1N2WR7dMBajNI1vZEsc2+DF3JgfYMigT0sa804LwZNeuopjcgP6qUxL+N+uFO+mobnMZAWK2zBmVwG60psV5zkOShGxq+l+AuobD0pKl0PH4qwhOIUbTc72F2snuKEAJvnpaW2kWymATnbuYsUrpUwoWUmAT4l9o6mD4XGAaYG6YUjD0JJDSJrHKgWy7j5Dqb6ocEMubzOAzpFT6H+BPd09ZraBDLELjX+yYow/adGsGw3sOwDZYfHwM+2f78j8xqCbWgaCME02umAfbkXGbIZ1l7cQv3w0QIDPKreePjI6vMHKJtSsOz9yMwb7RqMf53+m4e+HTlBZEV1m5Dd99qp3ESUYvUEg8rHmx+GeY1KyjZz14AXyxxvepQ4TZFPbROcNvL6EUm4gV7MV+MdkyRznA3nMro5vuGteuEAmqyFGuK/mmTGboA5FDBGnvRGzMt87eJtwWyeaPca7YZttaZJRv2Gbko9T7YNU9bdcJ41m9XC3BApUNQ3nQwWoallQrGX3r862to2Cl7z3MegrSt3GBDCI7RgmBPuEaVAFQQz0Rgr50zBtG834r7/RJ4gQtD0VksO1NoJoM/aifqWjKgRpawOnn2UkztqXEAkTwry04nNkMdLHCegDtl8cqdEAI5kzXMUf7fNxO19eOa+Yc4LYlNIPLOUIw3bGdCjZhhRuP9WR6UpQc69u6zK38e5Sxe+ff+XAdDB9OoH7We+9lRVvrmu4LbtbshctbX5Xz+sIq2xNmQy01xF3UHLUy3hQU1pglo9l5fLD5Nd/1xOs2hu9gaGJFI0efzJvNSHaPuXAvESvT5YBhONh6PfbjHEYuIYXL0ZVtF3cTpW29VXeyA8Uvx9PAxjSbyR/BlF1lTaCotAYCzI2keg6RTK3NCmo3co4t43hNemXPffCwykv4ShU8jdennk167W/6JTmTX7ppmseXimMP9DHnXZEomakUIZComiXxqlnTvw/Xdh9GGWA+6qgS5k68a3hdr2cD1gAKX1T53QCrXbNzpcZ9ab4CaCTv8iFtZaGXOBJjwOXAWZEf3k0I9XQZ3FCeg1Gqs8NgULwfWQTv78208kbsiLOGeu9mGEXgXNyK0yO/U4AWJb+HEfPpfeN3tpHFigzmALzt8RztCKcRv+gKm3RyVEW5'), + ), + ), + type: AnyURIValue::fromString(C::XMLENC_ELEMENT), + encryptionMethod: new EncryptionMethod( + AnyURIValue::fromString(C::BLOCK_ENC_AES256_GCM), ), - type: C::XMLENC_ELEMENT, - encryptionMethod: new EncryptionMethod(C::BLOCK_ENC_AES256_GCM), keyInfo: new KeyInfo([ $retrievalMethod, $ek, @@ -130,10 +156,16 @@ public function testMarshalling(): void public function testEncryption(): void { $assertion = new Assertion( - id: C::MSGID, - issueInstant: self::$clock->now(), - issuer: new Issuer('urn:x-simplesamlphp:issuer'), - subject: new Subject(new NameID('Someone')), + id: IDValue::fromString(C::MSGID), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + issuer: new Issuer( + SAMLStringValue::fromString('urn:x-simplesamlphp:issuer'), + ), + subject: new Subject( + new NameID( + SAMLStringValue::fromString('Someone'), + ), + ), ); $encryptor = (new KeyTransportAlgorithmFactory())->getAlgorithm( @@ -148,7 +180,7 @@ public function testEncryption(): void $encAssertion = EncryptedAssertion::fromXML($doc->documentElement); /** @psalm-suppress PossiblyNullArgument */ $decryptor = (new KeyTransportAlgorithmFactory())->getAlgorithm( - $encAssertion->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm(), + $encAssertion->getEncryptedKeys()[0]->getEncryptionMethod()?->getAlgorithm()->getValue(), PEMCertificatesMock::getPrivateKey(PEMCertificatesMock::SELFSIGNED_PRIVATE_KEY), ); diff --git a/tests/SAML2/XML/saml/EncryptedAttributeTest.php b/tests/SAML2/XML/saml/EncryptedAttributeTest.php index 615981d49..4c95097f4 100644 --- a/tests/SAML2/XML/saml/EncryptedAttributeTest.php +++ b/tests/SAML2/XML/saml/EncryptedAttributeTest.php @@ -9,6 +9,7 @@ use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Compat\AbstractContainer; use SimpleSAML\SAML2\Compat\ContainerSingleton; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\Attribute; use SimpleSAML\SAML2\XML\saml\AttributeValue; @@ -74,8 +75,10 @@ public static function tearDownAfterClass(): void public function testMarshalling(): void { $attribute = new Attribute( - name: 'urn:encrypted:attribute', - attributeValue: [new AttributeValue('very secret data')], + name: SAMLStringValue::fromString('urn:encrypted:attribute'), + attributeValue: [ + new AttributeValue('very secret data'), + ], ); $encryptor = (new KeyTransportAlgorithmFactory())->getAlgorithm( @@ -101,7 +104,7 @@ public function testDecryptAttribute(): void /** @psalm-suppress PossiblyNullArgument */ $decryptor = (new KeyTransportAlgorithmFactory())->getAlgorithm( - $encryptedAttribute->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm(), + $encryptedAttribute->getEncryptedKeys()[0]->getEncryptionMethod()?->getAlgorithm()->getValue(), PEMCertificatesMock::getPrivateKey(PEMCertificatesMock::PRIVATE_KEY), ); diff --git a/tests/SAML2/XML/saml/EncryptedIDTest.php b/tests/SAML2/XML/saml/EncryptedIDTest.php index d2aa5b808..311d68bbe 100644 --- a/tests/SAML2/XML/saml/EncryptedIDTest.php +++ b/tests/SAML2/XML/saml/EncryptedIDTest.php @@ -10,6 +10,8 @@ use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Compat\AbstractContainer; use SimpleSAML\SAML2\Compat\ContainerSingleton; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\Attribute; @@ -22,6 +24,10 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\AnyURIValue; +use SimpleSAML\XMLSchema\Type\Base64BinaryValue; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\StringValue; use SimpleSAML\XMLSecurity\Alg\KeyTransport\KeyTransportAlgorithmFactory; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; @@ -91,30 +97,46 @@ public function testMarshalling(): void { $ed = new EncryptedData( cipherData: new CipherData( - new CipherValue('720FAxwOXcv8ast9YvQutUoue+YA2FgLLNaD/FZrWiNexTkPyZ8CWrcf2zZj2zrOwTjQ9KJvzvCuzq4fM51sU1boOakLpz05NonDdMgeWW/eWcOJJfOZs0tYvYc5qZ/R+BzRnJsGG6w2ZmipEi88X/8uA85c'), + new CipherValue( + Base64BinaryValue::fromString('720FAxwOXcv8ast9YvQutUoue+YA2FgLLNaD/FZrWiNexTkPyZ8CWrcf2zZj2zrOwTjQ9KJvzvCuzq4fM51sU1boOakLpz05NonDdMgeWW/eWcOJJfOZs0tYvYc5qZ/R+BzRnJsGG6w2ZmipEi88X/8uA85c'), + ), + ), + type: AnyURIValue::fromString(C::XMLENC_ELEMENT), + encryptionMethod: new EncryptionMethod( + AnyURIValue::fromString('http://www.w3.org/2009xmlenc11#aes256-gcm'), ), - type: C::XMLENC_ELEMENT, - encryptionMethod: new EncryptionMethod('http://www.w3.org/2009xmlenc11#aes256-gcm'), keyInfo: new KeyInfo([ new EncryptedKey( cipherData: new CipherData( - new CipherValue('he5ZBjtfp/1/Y3PgE/CWspDPADig9vuZ7yZyYXDQ1wA/HBTPCldtL/p6UT5RCAFYUwN6kp3jnHkhK1yMjrI1SMw0n5NEc2wO9N5inQIeQOZ8XD9yD9M5fHvWz2ByNMGlB35RWMnBRHzDi1PRV7Irwcs9WoiODh3i6j2vYXP7cAo='), + new CipherValue( + Base64BinaryValue::fromString('he5ZBjtfp/1/Y3PgE/CWspDPADig9vuZ7yZyYXDQ1wA/HBTPCldtL/p6UT5RCAFYUwN6kp3jnHkhK1yMjrI1SMw0n5NEc2wO9N5inQIeQOZ8XD9yD9M5fHvWz2ByNMGlB35RWMnBRHzDi1PRV7Irwcs9WoiODh3i6j2vYXP7cAo='), + ), + ), + encryptionMethod: new EncryptionMethod( + AnyURIValue::fromString('http://www.w3.org/2009/xmlenc11#rsa-oaep'), ), - encryptionMethod: new EncryptionMethod('http://www.w3.org/2009/xmlenc11#rsa-oaep'), ), ]), ); $ek = new EncryptedKey( cipherData: new CipherData( - new CipherValue('he5ZBjtfp/1/Y3PgE/CWspDPADig9vuZ7yZyYXDQ1wA/HBTPCldtL/p6UT5RCAFYUwN6kp3jnHkhK1yMjrI1SMw0n5NEc2wO9N5inQIeQOZ8XD9yD9M5fHvWz2ByNMGlB35RWMnBRHzDi1PRV7Irwcs9WoiODh3i6j2vYXP7cAo='), + new CipherValue( + Base64BinaryValue::fromString('he5ZBjtfp/1/Y3PgE/CWspDPADig9vuZ7yZyYXDQ1wA/HBTPCldtL/p6UT5RCAFYUwN6kp3jnHkhK1yMjrI1SMw0n5NEc2wO9N5inQIeQOZ8XD9yD9M5fHvWz2ByNMGlB35RWMnBRHzDi1PRV7Irwcs9WoiODh3i6j2vYXP7cAo='), + ), + ), + id: IDValue::fromString('Encrypted_KEY_ID'), + recipient: StringValue::fromString(C::ENTITY_SP), + carriedKeyName: new CarriedKeyName( + StringValue::fromString('Name of the key'), ), - id: 'Encrypted_KEY_ID', - recipient: C::ENTITY_SP, - carriedKeyName: new CarriedKeyName('Name of the key'), - encryptionMethod: new EncryptionMethod('http://www.w3.org/2009/xmlenc11#rsa-oaep'), - referenceList: new ReferenceList( - [new DataReference('#Encrypted_DATA_ID')], + encryptionMethod: new EncryptionMethod( + AnyURIValue::fromString('http://www.w3.org/2009/xmlenc11#rsa-oaep'), ), + referenceList: new ReferenceList([ + new DataReference( + AnyURIValue::fromString('#Encrypted_DATA_ID'), + ), + ]), ); $eid = new EncryptedID($ed, [$ek]); @@ -131,29 +153,46 @@ public function testMarshallingElementOrdering(): void { $ed = new EncryptedData( cipherData: new CipherData( - new CipherValue('iFz/8KASJCLCAHqaAKhZXWOG/TPZlgTxcQ25lTGxdSdEsGYz7cg5lfZAbcN3UITCP9MkJsyjMlRsQouIqBkoPCGZz8NXibDkQ8OUeE7JdkFgKvgUMXawp+uDL4gHR8L7l6SPAmWZU3Hx/Wg9pTJBOpTjwoS0'), + new CipherValue( + Base64BinaryValue::fromString('iFz/8KASJCLCAHqaAKhZXWOG/TPZlgTxcQ25lTGxdSdEsGYz7cg5lfZAbcN3UITCP9MkJsyjMlRsQouIqBkoPCGZz8NXibDkQ8OUeE7JdkFgKvgUMXawp+uDL4gHR8L7l6SPAmWZU3Hx/Wg9pTJBOpTjwoS0'), + ), + ), + encryptionMethod: new EncryptionMethod( + AnyURIValue::fromString('http://www.w3.org/2001/04/xmlenc#aes128-cbc'), ), - encryptionMethod: new EncryptionMethod('http://www.w3.org/2001/04/xmlenc#aes128-cbc'), + type: AnyURIValue::fromString(C::XMLENC_ELEMENT), keyInfo: new KeyInfo([ new EncryptedKey( cipherData: new CipherData( - new CipherValue('GMhpk09X+quNC/SsnxcDglZU/DCLAu9bMJ5bPcgaBK4s3F1eXciU8hlOYNaskSwP86HmA704NbzSDOHAgN6ckR+iCssxA7XCBjz0hltsgfn5p9Rh8qKtKltiXvxo/xXTcSXXZXNcE0R2KTya0P4DjZvYYgbIls/AH8ZyDV07ntI='), + new CipherValue( + Base64BinaryValue::fromString('GMhpk09X+quNC/SsnxcDglZU/DCLAu9bMJ5bPcgaBK4s3F1eXciU8hlOYNaskSwP86HmA704NbzSDOHAgN6ckR+iCssxA7XCBjz0hltsgfn5p9Rh8qKtKltiXvxo/xXTcSXXZXNcE0R2KTya0P4DjZvYYgbIls/AH8ZyDV07ntI='), + ), + ), + encryptionMethod: new EncryptionMethod( + AnyURIValue::fromString('http://www.w3.org/2009/xmlenc11#rsa-oaep'), ), - encryptionMethod: new EncryptionMethod('http://www.w3.org/2009/xmlenc11#rsa-oaep'), ), ]), ); $ek = new EncryptedKey( cipherData: new CipherData( - new CipherValue('GMhpk09X+quNC/SsnxcDglZU/DCLAu9bMJ5bPcgaBK4s3F1eXciU8hlOYNaskSwP86HmA704NbzSDOHAgN6ckR+iCssxA7XCBjz0hltsgfn5p9Rh8qKtKltiXvxo/xXTcSXXZXNcE0R2KTya0P4DjZvYYgbIls/AH8ZyDV07ntI='), + new CipherValue( + Base64BinaryValue::fromString('GMhpk09X+quNC/SsnxcDglZU/DCLAu9bMJ5bPcgaBK4s3F1eXciU8hlOYNaskSwP86HmA704NbzSDOHAgN6ckR+iCssxA7XCBjz0hltsgfn5p9Rh8qKtKltiXvxo/xXTcSXXZXNcE0R2KTya0P4DjZvYYgbIls/AH8ZyDV07ntI='), + ), + ), + id: IDValue::fromString('Encrypted_KEY_ID'), + recipient: StringValue::fromString(C::ENTITY_SP), + carriedKeyName: new CarriedKeyName( + StringValue::fromString('Name of the key'), ), - id: 'Encrypted_KEY_ID', - recipient: C::ENTITY_SP, - carriedKeyName: new CarriedKeyName('Name of the key'), - encryptionMethod: new EncryptionMethod('http://www.w3.org/2001/04/xmlenc#rsa-1_5'), - referenceList: new ReferenceList( - [new DataReference('#Encrypted_DATA_ID')], + encryptionMethod: new EncryptionMethod( + AnyURIValue::fromString('http://www.w3.org/2001/04/xmlenc#rsa-1_5'), ), + referenceList: new ReferenceList([ + new DataReference( + AnyURIValue::fromString('#Encrypted_DATA_ID'), + ), + ]), ); $eid = new EncryptedID($ed, [$ek]); $eidElement = $eid->toXML(); @@ -187,7 +226,11 @@ public function testEncryption(): void ); // test with a NameID - $nameid = new NameID('value', 'urn:x-simplesamlphp:namequalifier'); + $nameid = new NameID( + SAMLStringValue::fromString('value'), + SAMLStringValue::fromString('urn:x-simplesamlphp:namequalifier'), + ); + $encid = new EncryptedID($nameid->encrypt($encryptor)); /** @psalm-suppress ArgumentTypeCoercion */ $doc = DOMDocumentFactory::fromString(strval($encid)); @@ -195,7 +238,7 @@ public function testEncryption(): void $encid = EncryptedID::fromXML($doc->documentElement); /** @psalm-suppress PossiblyNullArgument */ $decryptor = (new KeyTransportAlgorithmFactory())->getAlgorithm( - $encid->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm(), + $encid->getEncryptedKeys()[0]->getEncryptionMethod()?->getAlgorithm()->getValue(), $privKey, ); $id = $encid->decrypt($decryptor); @@ -204,9 +247,13 @@ public function testEncryption(): void // test a custom BaseID that's registered $customId = new CustomBaseID( - [new Audience('urn:some:audience')], - 'urn:x-simplesamlphp:namequalifier', - 'urn:x-simplesamlphp:spnamequalifier', + [ + new Audience( + SAMLAnyURIValue::fromString('urn:some:audience'), + ), + ], + SAMLStringValue::fromString('urn:x-simplesamlphp:namequalifier'), + SAMLStringValue::fromString('urn:x-simplesamlphp:spnamequalifier'), ); $encid = new EncryptedID($customId->encrypt($encryptor)); @@ -216,7 +263,7 @@ public function testEncryption(): void $encid = EncryptedID::fromXML($doc->documentElement); /** @psalm-suppress PossiblyNullArgument */ $decryptor = (new KeyTransportAlgorithmFactory())->getAlgorithm( - $encid->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm(), + $encid->getEncryptedKeys()[0]->getEncryptionMethod()?->getAlgorithm()->getValue(), $privKey, ); $id = $encid->decrypt($decryptor); @@ -239,7 +286,7 @@ public function testEncryption(): void $encid = EncryptedID::fromXML($doc->documentElement); /** @psalm-suppress PossiblyNullArgument */ $decryptor = (new KeyTransportAlgorithmFactory())->getAlgorithm( - $encid->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm(), + $encid->getEncryptedKeys()[0]->getEncryptionMethod()?->getAlgorithm()->getValue(), $privKey, ); $id = $encid->decrypt($decryptor); @@ -248,7 +295,9 @@ public function testEncryption(): void $this->assertEquals(strval($unknownId), strval($id)); // test with unsupported ID - $attr = new Attribute('name'); + $attr = new Attribute( + SAMLStringValue::fromString('name'), + ); $encid = new EncryptedID($attr->encrypt($encryptor)); $this->expectException(InvalidArgumentException::class); diff --git a/tests/SAML2/XML/saml/EvidenceTest.php b/tests/SAML2/XML/saml/EvidenceTest.php index d86246023..dda8fe75e 100644 --- a/tests/SAML2/XML/saml/EvidenceTest.php +++ b/tests/SAML2/XML/saml/EvidenceTest.php @@ -14,9 +14,18 @@ use SimpleSAML\SAML2\XML\saml\AssertionURIRef; use SimpleSAML\SAML2\XML\saml\EncryptedAssertion; use SimpleSAML\SAML2\XML\saml\Evidence; +use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\AnyURIValue; +use SimpleSAML\XMLSchema\Type\Base64BinaryValue; +use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; +use SimpleSAML\XMLSecurity\XML\xenc\CipherData; +use SimpleSAML\XMLSecurity\XML\xenc\CipherValue; +use SimpleSAML\XMLSecurity\XML\xenc\EncryptedData; +use SimpleSAML\XMLSecurity\XML\xenc\EncryptedKey; +use SimpleSAML\XMLSecurity\XML\xenc\EncryptionMethod; use function dirname; use function strval; @@ -44,8 +53,8 @@ final class EvidenceTest extends TestCase /** @var \DOMDocument $assertion */ private static DOMDocument $assertion; - /** @var \DOMDocument $encryptedAssertion */ - private static DOMDocument $encryptedAssertion; + /** @var \SimpleSAML\SAML2\XML\saml\EncryptedAssertion $encryptedAssertion */ + private static EncryptedAssertion $encryptedAssertion; /** @@ -70,9 +79,35 @@ protected function setUp(): void dirname(__FILE__, 4) . '/resources/xml/saml_Assertion.xml', ); - self::$encryptedAssertion = DOMDocumentFactory::fromFile( - dirname(__FILE__, 4) . '/resources/xml/saml_EncryptedAssertion.xml', + $ek = new EncryptedKey( + cipherData: new CipherData( + new CipherValue( + // phpcs:ignore Generic.Files.LineLength + Base64BinaryValue::fromString('sNLWjwyj/R0oPwSgNnqowahiOwM0YU3YaH3jsH0t2YUDcHkcgouvW5x6YbNdgvGq0ImsNrkjI//0hrL4HvrOX33+DkhCo2FX5+a7UCdftfBfSjvt0houF8z3Zq/XOm6HxBUbWt5MULYpMKMZ9iAY6+raydxk2tFWgnAyHaBfzvU='), + ), + ), + encryptionMethod: new EncryptionMethod( + AnyURIValue::fromString(C::KEY_TRANSPORT_OAEP_MGF1P), + ), ); + + $ed = new EncryptedData( + cipherData: new CipherData( + new CipherValue( + // phpcs:ignore Generic.Files.LineLength + Base64BinaryValue::fromString('mlo++g0c4lTsVbL7ArhQh5/xu6t9EuNoRZXF8dqYIq0hARzKiZC5OhTZtHpQlwVd5f4N/lDsur2hhFAu5dxGVdWF+xN4wGMVoQDcyqipwH00w4lO5GNPD16mb1I5l3v3LJf9jKm+090Mv54BPsSOhSYvPBGbv2Uj6LzRE6z0l9zTWtyj2Z7lShrOYR6ZgG254HoltAA6veBXROEdPBBax0ezvoKmOBUcN1RX15Bfj0fVOX1FzS27SX+GCWYgCr0xPnhNBxaMhvU/2ayW6S8A5HWHWb1K2h/VVx6eumXaKzUFoEO5MxfC3Kxni3R3jyaGXmAZ4LhzcpWxJvz9LCpq5+9ovjnRNhheMrtQr/eZ6kWQ12pzKlHCfuFESB0IK2V2NbBDSe6C4n6TAS9mia9tT7CaKsRhVKlNMfkMKC+B6AOkTvlt6Rma5iz/QKL0A7t4LufQ/17YSb3eNOesmV/l3T8bEFqTRHiO8CwiT28ctfDjd0OKB4q1gh0PSidZL/yuaFTG/WXDpnpIV9qZELUgLVjFzW5+Rb/Alv2U7tE68c8oXv7xqmBUhkFQhYBy84cwHrCeKqn2iiJkh19aXYdgAZxys9Dp2+B2wX86coLU2CDJlyyCEohkXn5w8TkU0zNDZnh8J1oz5iawSx1d0aPy+uLNYVUMmx2hcrb3PlWdUApnyts38DcNwTkTy2/uxZmBU/4VGi3JzdnQ7KbW7EUXe3veExb63mRlU+cWl8LMRgP1FExg3CKT6HhW3roTu9GI51ofHpjPCPi41xQvoRrUo2VytBV/IZi4ArD4Y9d2tIcK2O0ZblUNjpRsNhPsVuCDLH23Fx42/5eGVkeTLPOt+Mr6IfY2d1NJGzqz9vJ4/h3L5PelDBQiD/o+5ZvgS5I5HL0bVbGXkT+v6k2GhHQDKNE3qJviXLRPjWv+Eaq+wJhukmcivA1z75/IydZhSPBZfhgORe6n5coiCf2mqiaZpI1YEZRR2g77NXf7I8qAuR7umkEpLC1ciLUpwZjaLNb7ojmC7cogXv8FmcWOk1xWdr7+kY3FXaWWwhUgxO4CSUYGdcOvydybcvAFTnf09+lR0RKVTGgnuukgYROyl8ulY2hoAFm+/jy9qcGqE/7JBlm6qx0B815TZY0aC3ulgwYDvUhdk9Sxq7Dp44h7BMBQezY2o4PBsY6nJNbCAkSULQ1rMY1nZViAAtZntTeHsnlFYm3pJo7MEhrGLYE/nSVcEHuP0z4WpwSb4CW2eOFBmrHcJfqBmDTnFtRwBQZfhQvcSyLy9Vyy//Hj7oDpC6GKmC3m9QTH+9T95sVxhHYkHN10YfHHQhn2pouNzo95QKVVtF98UGMEqrpIbtgGd+CE4icDjq8Qm8iQzJD/DB1YIjpwS0ftoD5+n/YlFYCbbOedN7uxsh9a3Q4NhbkYhNwYQN+/nkr90j6X9PS6uon04TS5GfxpX9gGczxMfeUKHh93in+UksVdzWqgrGxtdXGg7eataR2AcWoTIzsOTWC1sUIi/cOD1N2WR7dMBajNI1vZEsc2+DF3JgfYMigT0sa804LwZNeuopjcgP6qUxL+N+uFO+mobnMZAWK2zBmVwG60psV5zkOShGxq+l+AuobD0pKl0PH4qwhOIUbTc72F2snuKEAJvnpaW2kWymATnbuYsUrpUwoWUmAT4l9o6mD4XGAaYG6YUjD0JJDSJrHKgWy7j5Dqb6ocEMubzOAzpFT6H+BPd09ZraBDLELjX+yYow/adGsGw3sOwDZYfHwM+2f78j8xqCbWgaCME02umAfbkXGbIZ1l7cQv3w0QIDPKreePjI6vMHKJtSsOz9yMwb7RqMf53+m4e+HTlBZEV1m5Dd99qp3ESUYvUEg8rHmx+GeY1KyjZz14AXyxxvepQ4TZFPbROcNvL6EUm4gV7MV+MdkyRznA3nMro5vuGteuEAmqyFGuK/mmTGboA5FDBGnvRGzMt87eJtwWyeaPca7YZttaZJRv2Gbko9T7YNU9bdcJ41m9XC3BApUNQ3nQwWoallQrGX3r862to2Cl7z3MegrSt3GBDCI7RgmBPuEaVAFQQz0Rgr50zBtG834r7/RJ4gQtD0VksO1NoJoM/aifqWjKgRpawOnn2UkztqXEAkTwry04nNkMdLHCegDtl8cqdEAI5kzXMUf7fNxO19eOa+Yc4LYlNIPLOUIw3bGdCjZhhRuP9WR6UpQc69u6zK38e5Sxe+ff+XAdDB9OoH7We+9lRVvrmu4LbtbshctbX5Xz+sIq2xNmQy01xF3UHLUy3hQU1pglo9l5fLD5Nd/1xOs2hu9gaGJFI0efzJvNSHaPuXAvESvT5YBhONh6PfbjHEYuIYXL0ZVtF3cTpW29VXeyA8Uvx9PAxjSbyR/BlF1lTaCotAYCzI2keg6RTK3NCmo3co4t43hNemXPffCwykv4ShU8jdennk167W/6JTmTX7ppmseXimMP9DHnXZEomakUIZComiXxqlnTvw/Xdh9GGWA+6qgS5k68a3hdr2cD1gAKX1T53QCrXbNzpcZ9ab4CaCTv8iFtZaGXOBJjwOXAWZEf3k0I9XQZ3FCeg1Gqs8NgULwfWQTv78208kbsiLOGeu9mGEXgXNyK0yO/U4AWJb+HEfPpfeN3tpHFigzmALzt8RztCKcRv+gKm3RyVEW5'), + ), + ), + type: AnyURIValue::fromString(C::XMLENC_ELEMENT), + encryptionMethod: new EncryptionMethod( + AnyURIValue::fromString(C::BLOCK_ENC_AES256_GCM), + ), + keyInfo: new KeyInfo([ + $ek, + ]), + ); + + self::$encryptedAssertion = new EncryptedAssertion($ed, [$ek]); } @@ -84,7 +119,7 @@ public function testMarshalling(): void [AssertionIDRef::fromXML(self::$assertionIDRef->documentElement)], [AssertionURIRef::fromXML(self::$assertionURIRef->documentElement)], [Assertion::fromXML(self::$assertion->documentElement)], - [EncryptedAssertion::fromXML(self::$encryptedAssertion->documentElement)], + [self::$encryptedAssertion], ); $this->assertFalse($evidence->isEmptyElement()); diff --git a/tests/SAML2/XML/saml/IssuerTest.php b/tests/SAML2/XML/saml/IssuerTest.php index 2baaca493..460495032 100644 --- a/tests/SAML2/XML/saml/IssuerTest.php +++ b/tests/SAML2/XML/saml/IssuerTest.php @@ -9,6 +9,8 @@ use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\saml\NameIDType; @@ -54,11 +56,11 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $issuer = new Issuer( - 'urn:x-simplesamlphp:issuer', - 'urn:x-simplesamlphp:namequalifier', - 'urn:x-simplesamlphp:spnamequalifier', - 'urn:the:format', - 'TheSPProvidedID', + SAMLStringValue::fromString('urn:x-simplesamlphp:issuer'), + SAMLStringValue::fromString('urn:x-simplesamlphp:namequalifier'), + SAMLStringValue::fromString('urn:x-simplesamlphp:spnamequalifier'), + SAMLAnyURIValue::fromString('urn:the:format'), + SAMLStringValue::fromString('TheSPProvidedID'), ); $this->assertEquals( @@ -77,11 +79,11 @@ public function testMarshallingEntityFormat(): void $this->expectExceptionMessage('Illegal combination of attributes being used'); new Issuer( - 'urn:x-simplesamlphp:issuer', - 'urn:x-simplesamlphp:namequalifier', - 'urn:x-simplesamlphp:spnamequalifier', - C::NAMEID_ENTITY, - 'TheSPProvidedID', + SAMLStringValue::fromString('urn:x-simplesamlphp:issuer'), + SAMLStringValue::fromString('urn:x-simplesamlphp:namequalifier'), + SAMLStringValue::fromString('urn:x-simplesamlphp:spnamequalifier'), + SAMLAnyURIValue::fromString(C::NAMEID_ENTITY), + SAMLStringValue::fromString('TheSPProvidedID'), ); } @@ -96,10 +98,10 @@ public function testMarshallingNoFormat(): void $this->expectExceptionMessage('Illegal combination of attributes being used'); new Issuer( - value: 'urn:x-simplesamlphp:issuer', - NameQualifier: 'urn:x-simplesamlphp:namequalifier', - SPNameQualifier: 'urn:x-simplesamlphp:spnamequalifier', - SPProvidedID: 'TheSPProvidedID', + value: SAMLStringValue::fromString('urn:x-simplesamlphp:issuer'), + NameQualifier: SAMLStringValue::fromString('urn:x-simplesamlphp:namequalifier'), + SPNameQualifier: SAMLStringValue::fromString('urn:x-simplesamlphp:spnamequalifier'), + SPProvidedID: SAMLStringValue::fromString('TheSPProvidedID'), ); } diff --git a/tests/SAML2/XML/saml/NameIDTest.php b/tests/SAML2/XML/saml/NameIDTest.php index 1ee59eb39..c80e83d87 100644 --- a/tests/SAML2/XML/saml/NameIDTest.php +++ b/tests/SAML2/XML/saml/NameIDTest.php @@ -7,6 +7,8 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\NameID; use SimpleSAML\SAML2\XML\saml\NameIDType; @@ -62,11 +64,11 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $nameId = new NameID( - 'TheNameIDValue', - 'urn:x-simplesamlphp:namequalifier', - 'urn:x-simplesamlphp:spnamequalifier', - 'urn:the:format', - 'TheSPProvidedID', + SAMLStringValue::fromString('TheNameIDValue'), + SAMLStringValue::fromString('urn:x-simplesamlphp:namequalifier'), + SAMLStringValue::fromString('urn:x-simplesamlphp:spnamequalifier'), + SAMLAnyURIValue::fromString('urn:the:format'), + SAMLStringValue::fromString('TheSPProvidedID'), ); $this->assertEquals( diff --git a/tests/SAML2/XML/saml/ProxyRestrictionTest.php b/tests/SAML2/XML/saml/ProxyRestrictionTest.php index a8bc6c168..11b10cd93 100644 --- a/tests/SAML2/XML/saml/ProxyRestrictionTest.php +++ b/tests/SAML2/XML/saml/ProxyRestrictionTest.php @@ -7,12 +7,14 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\Audience; use SimpleSAML\SAML2\XML\saml\ProxyRestriction; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\NonNegativeIntegerValue; use function dirname; use function strval; @@ -52,10 +54,14 @@ public function testMarshalling(): void { $condition = new ProxyRestriction( [ - new Audience('urn:test:audience1'), - new Audience('urn:test:audience2'), + new Audience( + SAMLAnyURIValue::fromString('urn:test:audience1'), + ), + new Audience( + SAMLAnyURIValue::fromString('urn:test:audience2'), + ), ], - 2, + NonNegativeIntegerValue::fromInteger(2), ); $this->assertEquals( diff --git a/tests/SAML2/XML/saml/StatementTest.php b/tests/SAML2/XML/saml/StatementTest.php index 643d53a03..bd2429a9f 100644 --- a/tests/SAML2/XML/saml/StatementTest.php +++ b/tests/SAML2/XML/saml/StatementTest.php @@ -9,6 +9,7 @@ use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Compat\AbstractContainer; use SimpleSAML\SAML2\Compat\ContainerSingleton; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\AbstractStatement; use SimpleSAML\SAML2\XML\saml\AbstractStatementType; @@ -19,6 +20,7 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Constants as C_XSI; use function dirname; use function strval; @@ -78,9 +80,11 @@ public static function tearDownAfterClass(): void */ public function testMarshalling(): void { - $statement = new CustomStatement( - [new Audience('urn:some:audience')], - ); + $statement = new CustomStatement([ + new Audience( + SAMLAnyURIValue::fromString('urn:some:audience'), + ), + ]); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), @@ -117,12 +121,15 @@ public function testUnmarshalling(): void public function testUnmarshallingUnregistered(): void { $element = clone self::$xmlRepresentation->documentElement; - $element->setAttributeNS(C::NS_XSI, 'xsi:type', 'ssp:UnknownStatementType'); + $element->setAttributeNS(C_XSI::NS_XSI, 'xsi:type', 'ssp:UnknownStatementType'); $statement = AbstractStatement::fromXML($element); $this->assertInstanceOf(UnknownStatement::class, $statement); - $this->assertEquals('urn:x-simplesamlphp:namespace:UnknownStatementType', $statement->getXsiType()); + $this->assertEquals( + '{urn:x-simplesamlphp:namespace}ssp:UnknownStatementType', + $statement->getXsiType()->getRawValue(), + ); $chunk = $statement->getRawStatement(); $this->assertEquals('saml', $chunk->getPrefix()); diff --git a/tests/SAML2/XML/saml/SubjectConfirmationDataTest.php b/tests/SAML2/XML/saml/SubjectConfirmationDataTest.php index d9cecf502..3084efd73 100644 --- a/tests/SAML2/XML/saml/SubjectConfirmationDataTest.php +++ b/tests/SAML2/XML/saml/SubjectConfirmationDataTest.php @@ -4,10 +4,12 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use DateTimeImmutable; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\SubjectConfirmationData; use SimpleSAML\Test\SAML2\Constants as C; @@ -16,6 +18,8 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\NCNameValue; +use SimpleSAML\XMLSchema\Type\StringValue; use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; use SimpleSAML\XMLSecurity\XML\ds\KeyName; @@ -57,17 +61,21 @@ public function testMarshalling(): void { $arbitrary = DOMDocumentFactory::fromString('Arbitrary Element'); - $attr1 = new XMLAttribute('urn:test:something', 'test', 'attr1', 'testval1'); - $attr2 = new XMLAttribute('urn:test:something', 'test', 'attr2', 'testval2'); + $attr1 = new XMLAttribute('urn:test:something', 'test', 'attr1', StringValue::fromString('testval1')); + $attr2 = new XMLAttribute('urn:test:something', 'test', 'attr2', StringValue::fromString('testval2')); $subjectConfirmationData = new SubjectConfirmationData( - new DateTimeImmutable('2001-04-19T04:25:21Z'), - new DateTimeImmutable('2009-02-13T23:31:30Z'), - C::ENTITY_SP, - 'SomeRequestID', - '127.0.0.1', + SAMLDateTimeValue::fromString('2001-04-19T04:25:21Z'), + SAMLDateTimeValue::fromString('2009-02-13T23:31:30Z'), + EntityIDValue::fromString(C::ENTITY_SP), + NCNameValue::fromString('SomeRequestID'), + SAMLStringValue::fromString('127.0.0.1'), [ - new KeyInfo([new KeyName('SomeKey')]), + new KeyInfo([ + new KeyName( + StringValue::fromString('SomeKey'), + ), + ]), new Chunk($arbitrary->documentElement), ], [$attr1, $attr2], @@ -86,17 +94,21 @@ public function testMarshallingWithNonIPAddress(): void { $arbitrary = DOMDocumentFactory::fromString('Arbitrary Element'); - $attr1 = new XMLAttribute('urn:test:something', 'test', 'attr1', 'testval1'); - $attr2 = new XMLAttribute('urn:test:something', 'test', 'attr2', 'testval2'); + $attr1 = new XMLAttribute('urn:test:something', 'test', 'attr1', StringValue::fromString('testval1')); + $attr2 = new XMLAttribute('urn:test:something', 'test', 'attr2', StringValue::fromString('testval2')); $subjectConfirmationData = new SubjectConfirmationData( - new DateTimeImmutable('2001-04-19T04:25:21Z'), - new DateTimeImmutable('2009-02-13T23:31:30Z'), - C::ENTITY_SP, - 'SomeRequestID', - 'non-IP', + SAMLDateTimeValue::fromString('2001-04-19T04:25:21Z'), + SAMLDateTimeValue::fromString('2009-02-13T23:31:30Z'), + EntityIDValue::fromString(C::ENTITY_SP), + NCNameValue::fromString('SomeRequestID'), + SAMLStringValue::fromString('non-IP'), [ - new KeyInfo([new KeyName('SomeKey')]), + new KeyInfo([ + new KeyName( + StringValue::fromString('SomeKey'), + ), + ]), new Chunk($arbitrary->documentElement), ], [$attr1, $attr2], @@ -104,15 +116,15 @@ public function testMarshallingWithNonIPAddress(): void $this->assertEquals( '2001-04-19T04:25:21Z', - $subjectConfirmationData->getNotBefore()->format(C::DATETIME_FORMAT), + $subjectConfirmationData->getNotBefore()->getValue(), ); $this->assertEquals( '2009-02-13T23:31:30Z', - $subjectConfirmationData->getNotOnOrAfter()->format(C::DATETIME_FORMAT), + $subjectConfirmationData->getNotOnOrAfter()->getValue(), ); - $this->assertEquals(C::ENTITY_SP, $subjectConfirmationData->getRecipient()); - $this->assertEquals('SomeRequestID', $subjectConfirmationData->getInResponseTo()); - $this->assertEquals('non-IP', $subjectConfirmationData->getAddress()); + $this->assertEquals(C::ENTITY_SP, $subjectConfirmationData->getRecipient()->getValue()); + $this->assertEquals('SomeRequestID', $subjectConfirmationData->getInResponseTo()->getValue()); + $this->assertEquals('non-IP', $subjectConfirmationData->getAddress()->getValue()); $attributes = $subjectConfirmationData->getAttributesNS(); $this->assertCount(2, $attributes); diff --git a/tests/SAML2/XML/saml/SubjectConfirmationTest.php b/tests/SAML2/XML/saml/SubjectConfirmationTest.php index c8ba3868e..50d09a7f3 100644 --- a/tests/SAML2/XML/saml/SubjectConfirmationTest.php +++ b/tests/SAML2/XML/saml/SubjectConfirmationTest.php @@ -4,11 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use DateTimeImmutable; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; @@ -19,10 +22,12 @@ use SimpleSAML\XML\Attribute as XMLAttribute; use SimpleSAML\XML\Chunk; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\NCNameValue; +use SimpleSAML\XMLSchema\Type\StringValue; use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; use SimpleSAML\XMLSecurity\XML\ds\KeyName; @@ -66,25 +71,29 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $attr1 = new XMLAttribute('urn:test:something', 'test', 'attr1', 'testval1'); - $attr2 = new XMLAttribute('urn:test:something', 'test', 'attr2', 'testval2'); + $attr1 = new XMLAttribute('urn:test:something', 'test', 'attr1', StringValue::fromString('testval1')); + $attr2 = new XMLAttribute('urn:test:something', 'test', 'attr2', StringValue::fromString('testval2')); $subjectConfirmation = new SubjectConfirmation( - C::CM_BEARER, + SAMLAnyURIValue::fromString(C::CM_BEARER), new NameID( - 'SomeNameIDValue', + SAMLStringValue::fromString('SomeNameIDValue'), null, - 'https://sp.example.org/authentication/sp/metadata', - C::NAMEID_TRANSIENT, + SAMLStringValue::fromString('https://sp.example.org/authentication/sp/metadata'), + SAMLAnyURIValue::fromString(C::NAMEID_TRANSIENT), ), new SubjectConfirmationData( - new DateTimeImmutable('2001-04-19T04:25:21Z'), - new DateTimeImmutable('2009-02-13T23:31:30Z'), - C::ENTITY_SP, - 'SomeRequestID', - '127.0.0.1', + SAMLDateTimeValue::fromString('2001-04-19T04:25:21Z'), + SAMLDateTimeValue::fromString('2009-02-13T23:31:30Z'), + EntityIDValue::fromString(C::ENTITY_SP), + NCNameValue::fromString('SomeRequestID'), + SAMLStringValue::fromString('127.0.0.1'), [ - new KeyInfo([new KeyName('SomeKey')]), + new KeyInfo([ + new KeyName( + StringValue::fromString('SomeKey'), + ), + ]), new Chunk(DOMDocumentFactory::fromString('Arbitrary Element')->documentElement), ], [$attr1, $attr2], @@ -103,8 +112,10 @@ public function testMarshalling(): void public function testMarshallingEmptySubjectConfirmationData(): void { $subjectConfirmation = new SubjectConfirmation( - C::CM_BEARER, - new NameID('SomeNameIDValue'), + SAMLAnyURIValue::fromString(C::CM_BEARER), + new NameID( + SAMLStringValue::fromString('SomeNameIDValue'), + ), new SubjectConfirmationData(), ); $ns_saml = C::NS_SAML; @@ -130,9 +141,13 @@ public function testMarshallingEmptySubjectConfirmationData(): void public function testMarshallingElementOrdering(): void { $subjectConfirmation = new SubjectConfirmation( - C::CM_BEARER, - new NameID('SomeNameIDValue'), - new SubjectConfirmationData(self::$clock->now()), + SAMLAnyURIValue::fromString(C::CM_BEARER), + new NameID( + SAMLStringValue::fromString('SomeNameIDValue'), + ), + new SubjectConfirmationData( + SAMLDateTimeValue::fromDateTime(self::$clock->now()), + ), ); // Marshall it to a \DOMElement @@ -203,7 +218,7 @@ public function testMultipleIdentifiers(): void $document = DOMDocumentFactory::fromString( << - SomeNameIDValue + SomeNameIDValue AnotherNameIDValue @@ -229,8 +244,8 @@ public function testManySubjectConfirmationDataThrowsException(): void << SomeNameIDValue - - + + XML , diff --git a/tests/SAML2/XML/saml/SubjectLocalityTest.php b/tests/SAML2/XML/saml/SubjectLocalityTest.php index ba886c8f8..8021d84f5 100644 --- a/tests/SAML2/XML/saml/SubjectLocalityTest.php +++ b/tests/SAML2/XML/saml/SubjectLocalityTest.php @@ -8,6 +8,8 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\DomainValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; use SimpleSAML\SAML2\XML\saml\SubjectLocality; use SimpleSAML\XML\DOMDocumentFactory; @@ -51,8 +53,8 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $subjectLocality = new SubjectLocality( - '1.1.1.1', - 'idp.example.org', + SAMLStringValue::fromString('1.1.1.1'), + DomainValue::fromString('idp.example.org'), ); $this->assertEquals( diff --git a/tests/SAML2/XML/saml/SubjectTest.php b/tests/SAML2/XML/saml/SubjectTest.php index 2faa0acfa..858c5c6f3 100644 --- a/tests/SAML2/XML/saml/SubjectTest.php +++ b/tests/SAML2/XML/saml/SubjectTest.php @@ -4,11 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use DateTimeImmutable; use DOMDocument; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\saml\AbstractBaseID; use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; @@ -22,9 +25,12 @@ use SimpleSAML\XML\Attribute as XMLAttribute; use SimpleSAML\XML\Chunk; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Constants as C_XSI; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\NCNameValue; +use SimpleSAML\XMLSchema\Type\StringValue; use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; use SimpleSAML\XMLSecurity\XML\ds\KeyName; @@ -96,17 +102,19 @@ public function testMarshalling(): void { $arbitrary = DOMDocumentFactory::fromString('Arbitrary Element'); - $attr1 = new XMLAttribute('urn:test:something', 'test', 'attr1', 'testval1'); - $attr2 = new XMLAttribute('urn:test:something', 'test', 'attr2', 'testval2'); + $attr1 = new XMLAttribute('urn:test:something', 'test', 'attr1', StringValue::fromString('testval1')); + $attr2 = new XMLAttribute('urn:test:something', 'test', 'attr2', StringValue::fromString('testval2')); $subjectConfirmationData = new SubjectConfirmationData( - new DateTimeImmutable('2001-04-19T04:25:21Z'), - new DateTimeImmutable('2009-02-13T23:31:30Z'), - C::ENTITY_SP, - 'SomeRequestID', - '127.0.0.1', + SAMLDateTimeValue::fromString('2001-04-19T04:25:21Z'), + SAMLDateTimeValue::fromString('2009-02-13T23:31:30Z'), + EntityIDValue::fromString(C::ENTITY_SP), + NCNameValue::fromString('SomeRequestID'), + SAMLStringValue::fromString('127.0.0.1'), [ - new KeyInfo([new KeyName('SomeKey')]), + new KeyInfo([ + new KeyName(StringValue::fromString('SomeKey')), + ]), new Chunk($arbitrary->documentElement), ], [$attr1, $attr2], @@ -114,17 +122,19 @@ public function testMarshalling(): void $subject = new Subject( new NameID( - value: 'SomeNameIDValue', - SPNameQualifier: 'https://sp.example.org/authentication/sp/metadata', - Format: C::NAMEID_TRANSIENT, + value: SAMLStringValue::fromString('SomeNameIDValue'), + SPNameQualifier: SAMLStringValue::fromString('https://sp.example.org/authentication/sp/metadata'), + Format: SAMLAnyURIValue::fromString(C::NAMEID_TRANSIENT), ), [ new SubjectConfirmation( - 'urn:oasis:names:tc:SAML:2.0:cm:bearer', + SAMLAnyURIValue::fromString('urn:oasis:names:tc:SAML:2.0:cm:bearer'), new NameID( - value: 'SomeOtherNameIDValue', - SPNameQualifier: 'https://sp.example.org/authentication/sp/metadata', - Format: C::NAMEID_TRANSIENT, + value: SAMLStringValue::fromString('SomeOtherNameIDValue'), + SPNameQualifier: SAMLStringValue::fromString( + 'https://sp.example.org/authentication/sp/metadata', + ), + Format: SAMLAnyURIValue::fromString(C::NAMEID_TRANSIENT), ), $subjectConfirmationData, ), @@ -144,17 +154,19 @@ public function testMarshallingElementOrdering(): void { $arbitrary = DOMDocumentFactory::fromString('Arbitrary Element'); - $attr1 = new XMLAttribute('urn:test:something', 'test', 'attr1', 'testval1'); - $attr2 = new XMLAttribute('urn:test:something', 'test', 'attr2', 'testval2'); + $attr1 = new XMLAttribute('urn:test:something', 'test', 'attr1', StringValue::fromString('testval1')); + $attr2 = new XMLAttribute('urn:test:something', 'test', 'attr2', StringValue::fromString('testval2')); $subjectConfirmationData = new SubjectConfirmationData( - new DateTimeImmutable('2001-04-19T04:25:21Z'), - new DateTimeImmutable('2009-02-13T23:31:30Z'), - C::ENTITY_SP, - 'SomeRequestID', - '127.0.0.1', + SAMLDateTimeValue::fromString('2001-04-19T04:25:21Z'), + SAMLDateTimeValue::fromString('2009-02-13T23:31:30Z'), + EntityIDValue::fromString(C::ENTITY_SP), + NCNameValue::fromString('SomeRequestID'), + SAMLStringValue::fromString('127.0.0.1'), [ - new KeyInfo([new KeyName('SomeKey')]), + new KeyInfo([ + new KeyName(StringValue::fromString('SomeKey')), + ]), new Chunk($arbitrary->documentElement), ], [$attr1, $attr2], @@ -162,17 +174,19 @@ public function testMarshallingElementOrdering(): void $subject = new Subject( new NameID( - value: 'SomeNameIDValue', - SPNameQualifier: 'https://sp.example.org/authentication/sp/metadata', - Format: C::NAMEID_TRANSIENT, + value: SAMLStringValue::fromString('SomeNameIDValue'), + SPNameQualifier: SAMLStringValue::fromString('https://sp.example.org/authentication/sp/metadata'), + Format: SAMLAnyURIValue::fromString(C::NAMEID_TRANSIENT), ), [ new SubjectConfirmation( - 'urn:oasis:names:tc:SAML:2.0:cm:bearer', + SAMLAnyURIValue::fromString('urn:oasis:names:tc:SAML:2.0:cm:bearer'), new NameID( - value: 'SomeOtherNameIDValue', - SPNameQualifier: 'https://sp.example.org/authentication/sp/metadata', - Format: C::NAMEID_TRANSIENT, + value: SAMLStringValue::fromString('SomeOtherNameIDValue'), + SPNameQualifier: SAMLStringValue::fromString( + 'https://sp.example.org/authentication/sp/metadata', + ), + Format: SAMLAnyURIValue::fromString(C::NAMEID_TRANSIENT), ), $subjectConfirmationData, ), @@ -201,17 +215,19 @@ public function testMarshallingBaseID(): void { $arbitrary = DOMDocumentFactory::fromString('Arbitrary Element'); - $attr1 = new XMLAttribute('urn:test:something', 'test', 'attr1', 'testval1'); - $attr2 = new XMLAttribute('urn:test:something', 'test', 'attr2', 'testval2'); + $attr1 = new XMLAttribute('urn:test:something', 'test', 'attr1', StringValue::fromString('testval1')); + $attr2 = new XMLAttribute('urn:test:something', 'test', 'attr2', StringValue::fromString('testval2')); $subjectConfirmationData = new SubjectConfirmationData( - new DateTimeImmutable('2001-04-19T04:25:21Z'), - new DateTimeImmutable('2009-02-13T23:31:30Z'), - C::ENTITY_SP, - 'SomeRequestID', - '127.0.0.1', + SAMLDateTimeValue::fromString('2001-04-19T04:25:21Z'), + SAMLDateTimeValue::fromString('2009-02-13T23:31:30Z'), + EntityIDValue::fromString(C::ENTITY_SP), + NCNameValue::fromString('SomeRequestID'), + SAMLStringValue::fromString('127.0.0.1'), [ - new KeyInfo([new KeyName('SomeKey')]), + new KeyInfo([ + new KeyName(StringValue::fromString('SomeKey')), + ]), new Chunk($arbitrary->documentElement), ], [$attr1, $attr2], @@ -219,17 +235,21 @@ public function testMarshallingBaseID(): void $subject = new Subject( new CustomBaseID( - [new Audience('urn:some:audience')], - 'urn:x-simplesamlphp:namequalifier', - 'urn:x-simplesamlphp:spnamequalifier', + [ + new Audience(EntityIDValue::fromString('urn:some:audience')), + ], + SAMLStringValue::fromString('urn:x-simplesamlphp:namequalifier'), + SAMLStringValue::fromString('urn:x-simplesamlphp:spnamequalifier'), ), [ new SubjectConfirmation( - 'urn:oasis:names:tc:SAML:2.0:cm:bearer', + SAMLAnyURIValue::fromString('urn:oasis:names:tc:SAML:2.0:cm:bearer'), new NameID( - value: 'SomeNameIDValue', - SPNameQualifier: 'https://sp.example.org/authentication/sp/metadata', - Format: C::NAMEID_TRANSIENT, + value: SAMLStringValue::fromString('SomeNameIDValue'), + SPNameQualifier: SAMLStringValue::fromString( + 'https://sp.example.org/authentication/sp/metadata', + ), + Format: SAMLAnyURIValue::fromString(C::NAMEID_TRANSIENT), ), $subjectConfirmationData, ), @@ -246,7 +266,12 @@ public function testMarshallingBaseID(): void AbstractBaseID::fromXML(self::$baseId->documentElement)->toXML($document->documentElement); SubjectConfirmation::fromXML(self::$subjectConfirmation->documentElement)->toXML($document->documentElement); - $this->assertXmlStringEqualsXmlString($document->saveXML(), strval($subject)); + // Normalize both documents before comparing + $expected = DOMDocumentFactory::normalizeDocument($document); + $actualDoc = DOMDocumentFactory::fromString((string) $subject); + $actual = DOMDocumentFactory::normalizeDocument($actualDoc); + + $this->assertXmlStringEqualsXmlString($expected->saveXML(), $actual->saveXML()); } @@ -310,13 +335,15 @@ public function testManyNameIDThrowsException(): void */ public function testMultipleIdentifiers(): void { + $dsNamespace = KeyInfo::NS; $samlNamespace = Subject::NS; - $xsiNamespace = C::NS_XSI; + $xsiNamespace = C_XSI::NS_XSI; $document = DOMDocumentFactory::fromString( << - + + urn:some:audience documentElement); - $this->assertEquals('2.0', $unsignedMessage->getVersion()); - $unsignedMessage->sign($signer); $signedMessage = MessageFactory::fromXML($unsignedMessage->toXML()); @@ -140,12 +142,25 @@ public function testIssuerParsedAsNameID(): void #[Group('Message')] public function testConvertIssuerToXML(): void { - $status = new Status(new StatusCode()); + $status = new Status( + new StatusCode( + SAMLAnyURIValue::fromString( + C::STATUS_SUCCESS, + ), + ), + ); // first, try with common Issuer objects (Format=entity) - $issuer = new Issuer('https://gateway.stepup.org/saml20/sp/metadata'); + $issuer = new Issuer( + SAMLStringValue::fromString('https://gateway.stepup.org/saml20/sp/metadata'), + ); - $response = new Response($status, self::$clock->now(), $issuer); + $response = new Response( + id: IDValue::fromString('SomeIDValue'), + status: $status, + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + issuer: $issuer, + ); $xml = $response->toXML(); $xpCache = XPath::getXPath($xml); $xml_issuer = XPath::xpQuery($xml, './saml_assertion:Issuer', $xpCache); @@ -156,13 +171,18 @@ public function testConvertIssuerToXML(): void // now, try an Issuer with another format and attributes $issuer = new Issuer( - 'https://gateway.stepup.org/saml20/sp/metadata', - 'urn:x-simplesamlphp:namequalifier', - 'urn:x-simplesamlphp:spnamequalifier', - C::NAMEID_UNSPECIFIED, - 'SomeSPProvidedID', + SAMLStringValue::fromString('https://gateway.stepup.org/saml20/sp/metadata'), + SAMLStringValue::fromString('urn:x-simplesamlphp:namequalifier'), + SAMLStringValue::fromString('urn:x-simplesamlphp:spnamequalifier'), + SAMLAnyURIValue::fromString(C::NAMEID_UNSPECIFIED), + SAMLStringValue::fromString('SomeSPProvidedID'), + ); + $response = new Response( + id: IDValue::fromString('SomeIDValue'), + status: $status, + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + issuer: $issuer, ); - $response = new Response($status, self::$clock->now(), $issuer); $xml = $response->toXML(); $xpCache = XPath::getXPath($xml); $xml_issuer = XPath::xpQuery($xml, './saml_assertion:Issuer', $xpCache); @@ -176,7 +196,11 @@ public function testConvertIssuerToXML(): void $this->assertEquals($issuer->getSPProvidedID(), $xml_issuer->getAttribute('SPProvidedID')); // finally, make sure we can skip the Issuer by setting it to null - $response = new Response($status, self::$clock->now()); + $response = new Response( + id: IDValue::fromString('SomeIDValue'), + status: $status, + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + ); $xml = $response->toXML(); $xpCache = XPath::getXPath($xml); diff --git a/tests/SAML2/XML/samlp/AbstractStatusResponseTest.php b/tests/SAML2/XML/samlp/AbstractStatusResponseTest.php index fe35fce08..d841db061 100644 --- a/tests/SAML2/XML/samlp/AbstractStatusResponseTest.php +++ b/tests/SAML2/XML/samlp/AbstractStatusResponseTest.php @@ -9,6 +9,10 @@ use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\DomainValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\saml\Issuer; @@ -21,9 +25,9 @@ use SimpleSAML\SAML2\XML\samlp\StatusCode; use SimpleSAML\SAML2\XML\samlp\StatusMessage; use SimpleSAML\SAML2\XML\shibmd\Scope; -use SimpleSAML\XML\Chunk; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\Alg\Signature\SignatureAlgorithmFactory; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; @@ -56,17 +60,23 @@ public function testMarshalling(): void { $status = new Status( new StatusCode( - C::STATUS_SUCCESS, + SAMLAnyURIValue::fromString(C::STATUS_SUCCESS), [ new StatusCode( - 'urn:test:OurSubStatusCode', + SAMLAnyURIValue::fromString('urn:test:OurSubStatusCode'), ), ], ), - new StatusMessage('OurMessageText'), + new StatusMessage( + SAMLStringValue::fromString('OurMessageText'), + ), ); - $response = new Response($status, self::$clock->now()); + $response = new Response( + id: IDValue::fromString('SomeIDValue'), + status: $status, + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + ); $responseElement = $response->toXML(); @@ -96,21 +106,27 @@ public function testMarshallingSignedResponseElementOrdering(): void { $status = new Status( new StatusCode( - C::STATUS_SUCCESS, + SAMLAnyURIValue::fromString(C::STATUS_SUCCESS), [ - new StatusCode('urn:test:OurSubStatusCode'), + new StatusCode( + SAMLAnyURIValue::fromString('urn:test:OurSubStatusCode'), + ), ], ), - new StatusMessage('OurMessageText'), + new StatusMessage( + SAMLStringValue::fromString('OurMessageText'), + ), ); - $issuer = new Issuer('urn:x-simplesamlphp:issuer'); + $issuer = new Issuer( + SAMLStringValue::fromString('urn:x-simplesamlphp:issuer'), + ); - $scope = new Scope("scope"); + $scope = new Scope( + DomainValue::fromString('scope.org'), + ); - $extensions = new Extensions([ - new Chunk($scope->toXML()), - ]); + $extensions = new Extensions([$scope]); $signer = (new SignatureAlgorithmFactory())->getAlgorithm( C::SIG_RSA_SHA256, @@ -118,7 +134,8 @@ public function testMarshallingSignedResponseElementOrdering(): void ); $response = new Response( - issueInstant: self::$clock->now(), + id: IDValue::fromString('SomeIDValue'), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), status: $status, issuer: $issuer, extensions: $extensions, diff --git a/tests/SAML2/XML/samlp/ArtifactResolveTest.php b/tests/SAML2/XML/samlp/ArtifactResolveTest.php index 25b30f027..9006bb310 100644 --- a/tests/SAML2/XML/samlp/ArtifactResolveTest.php +++ b/tests/SAML2/XML/samlp/ArtifactResolveTest.php @@ -4,10 +4,11 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use DateTimeImmutable; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\samlp\AbstractMessage; use SimpleSAML\SAML2\XML\samlp\AbstractRequest; @@ -17,6 +18,8 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\Base64BinaryValue; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -53,15 +56,16 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $issuer = new Issuer('https://ServiceProvider.com/SAML'); - $artifact = 'AAQAADWNEw5VT47wcO4zX/iEzMmFQvGknDfws2ZtqSGdkNSbsW1cmVR0bzU='; + $issuer = new Issuer( + SAMLStringValue::fromString('https://ServiceProvider.com/SAML'), + ); + $artifact = Base64BinaryValue::fromString('AAQAADWNEw5VT47wcO4zX/iEzMmFQvGknDfws2ZtqSGdkNSbsW1cmVR0bzU='); $artifactResolve = new ArtifactResolve( + IDValue::fromString('_6c3a4f8b9c2d'), new Artifact($artifact), - new DateTimeImmutable('2004-01-21T19:00:49Z'), + SAMLDateTimeValue::fromString('2004-01-21T19:00:49Z'), $issuer, - '_6c3a4f8b9c2d', - '2.0', ); $this->assertEquals( diff --git a/tests/SAML2/XML/samlp/ArtifactResponseTest.php b/tests/SAML2/XML/samlp/ArtifactResponseTest.php index b589aa0af..4109d1047 100644 --- a/tests/SAML2/XML/samlp/ArtifactResponseTest.php +++ b/tests/SAML2/XML/samlp/ArtifactResponseTest.php @@ -4,11 +4,13 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use DateTimeImmutable; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\samlp\AbstractMessage; use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; @@ -21,6 +23,9 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\BooleanValue; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\NCNameValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -57,20 +62,22 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $issuer2 = new Issuer('urn:example:other'); - $id = '_306f8ec5b618f361c70b6ffb1480eade'; - $issueInstant = new DateTimeImmutable('2004-12-05T09:21:59Z'); - $destination = 'https://idp.example.org/SAML2/SSO/Artifact'; - $protocolBinding = C::BINDING_HTTP_ARTIFACT; - $assertionConsumerServiceURL = 'https://sp.example.com/SAML2/SSO/Artifact'; + $issuer2 = new Issuer( + SAMLStringValue::fromString('urn:example:other'), + ); + $id = IDValue::fromString('_306f8ec5b618f361c70b6ffb1480eade'); + $issueInstant = SAMLDateTimeValue::fromString('2004-12-05T09:21:59Z'); + $destination = SAMLAnyURIValue::fromString('https://idp.example.org/SAML2/SSO/Artifact'); + $protocolBinding = SAMLAnyURIValue::fromString(C::BINDING_HTTP_ARTIFACT); + $assertionConsumerServiceURL = SAMLAnyURIValue::fromString('https://sp.example.com/SAML2/SSO/Artifact'); $nameIdPolicy = new NameIDPolicy( - Format: C::NAMEID_EMAIL_ADDRESS, - AllowCreate: false, + Format: SAMLAnyURIValue::fromString(C::NAMEID_EMAIL_ADDRESS), + AllowCreate: BooleanValue::fromBoolean(false), ); $authnRequest = new AuthnRequest( nameIdPolicy: $nameIdPolicy, - issueInstant: new DateTimeImmutable('2004-12-05T09:21:59Z'), + issueInstant: SAMLDateTimeValue::fromString('2004-12-05T09:21:59Z'), assertionConsumerServiceURL: $assertionConsumerServiceURL, protocolBinding: $protocolBinding, issuer: $issuer2, @@ -78,14 +85,20 @@ public function testMarshalling(): void destination: $destination, ); - $status = new Status(new StatusCode()); - $issuer1 = new Issuer('https://sp.example.com/SAML2'); + $status = new Status( + new StatusCode( + SAMLAnyURIValue::fromString(C::STATUS_SUCCESS), + ), + ); + $issuer1 = new Issuer( + SAMLStringValue::fromString('https://sp.example.com/SAML2'), + ); $artifactResponse = new ArtifactResponse( status: $status, issuer: $issuer1, - id: '_d84a49e5958803dedcff4c984c2b0d95', - issueInstant: new DateTimeImmutable('2004-12-05T09:21:59Z'), - inResponseTo: '_cce4ee769ed970b501d680f697989d14', + id: IDValue::fromString('_d84a49e5958803dedcff4c984c2b0d95'), + issueInstant: SAMLDateTimeValue::fromString('2004-12-05T09:21:59Z'), + inResponseTo: NCNameValue::fromString('_cce4ee769ed970b501d680f697989d14'), message: $authnRequest, ); diff --git a/tests/SAML2/XML/samlp/ArtifactTest.php b/tests/SAML2/XML/samlp/ArtifactTest.php index 0cde2283a..89fff7a7b 100644 --- a/tests/SAML2/XML/samlp/ArtifactTest.php +++ b/tests/SAML2/XML/samlp/ArtifactTest.php @@ -12,6 +12,7 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\Base64BinaryValue; use function dirname; use function strval; @@ -46,7 +47,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $artifact = new Artifact('AAQAAM0ARI+cUaUKAx19/KC3fOV/vznNj8oE0JKKPQC8nTesXxPke7uRy+8='); + $artifact = new Artifact( + Base64BinaryValue::fromString('AAQAAM0ARI+cUaUKAx19/KC3fOV/vznNj8oE0JKKPQC8nTesXxPke7uRy+8='), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/samlp/AssertionIDRequestTest.php b/tests/SAML2/XML/samlp/AssertionIDRequestTest.php index 8b91d21be..895a70bc7 100644 --- a/tests/SAML2/XML/samlp/AssertionIDRequestTest.php +++ b/tests/SAML2/XML/samlp/AssertionIDRequestTest.php @@ -4,10 +4,12 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use DateTimeImmutable; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\AssertionIDRef; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\samlp\AbstractMessage; @@ -17,6 +19,8 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\NCNameValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -59,11 +63,20 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $assertionIDRequest = new AssertionIDRequest( - assertionIDRef: [new AssertionIDRef('_abc123'), new AssertionIDRef('_def456')], - issuer: new Issuer('https://gateway.stepup.org/saml20/sp/metadata'), - id: '_2b0226190ca1c22de6f66e85f5c95158', - issueInstant: new DateTimeImmutable('2014-09-22T13:42:00Z'), - destination: 'https://tiqr.stepup.org/idp/profile/saml2/Redirect/SSO', + assertionIDRef: [ + new AssertionIDRef( + NCNameValue::fromString('_abc123'), + ), + new AssertionIDRef( + NCNameValue::fromString('_def456'), + ), + ], + issuer: new Issuer( + SAMLStringValue::fromString('https://gateway.stepup.org/saml20/sp/metadata'), + ), + id: IDValue::fromString('_2b0226190ca1c22de6f66e85f5c95158'), + issueInstant: SAMLDateTimeValue::fromString('2014-09-22T13:42:00Z'), + destination: SAMLAnyURIValue::fromString('https://tiqr.stepup.org/idp/profile/saml2/Redirect/SSO'), ); $this->assertEquals( diff --git a/tests/SAML2/XML/samlp/AttributeQueryTest.php b/tests/SAML2/XML/samlp/AttributeQueryTest.php index a706a366a..0c7afdf96 100644 --- a/tests/SAML2/XML/samlp/AttributeQueryTest.php +++ b/tests/SAML2/XML/samlp/AttributeQueryTest.php @@ -4,12 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use DateTimeImmutable; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\saml\Attribute; @@ -23,11 +25,12 @@ use SimpleSAML\SAML2\XML\samlp\AbstractSubjectQuery; use SimpleSAML\SAML2\XML\samlp\AttributeQuery; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; -use SimpleSAML\XML\Exception\MissingElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -73,20 +76,23 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $nameId = new NameID('urn:example:subject', null, null, C::NAMEID_UNSPECIFIED); + $nameId = new NameID( + value: SAMLStringValue::fromString('urn:example:subject'), + Format: SAMLAnyURIValue::fromString(C::NAMEID_UNSPECIFIED), + ); $attributeQuery = new AttributeQuery( subject: new Subject($nameId), attributes: [ new Attribute( - name: 'test1', + name: SAMLStringValue::fromString('test1'), attributeValue: [ new AttributeValue('test1_attrv1'), new AttributeValue('test1_attrv2'), ], ), new Attribute( - name: 'test2', + name: SAMLStringValue::fromString('test2'), attributeValue: [ new AttributeValue('test2_attrv1'), new AttributeValue('test2_attrv2'), @@ -94,10 +100,10 @@ public function testMarshalling(): void ], ), new Attribute( - name: 'test3', + name: SAMLStringValue::fromString('test3'), ), new Attribute( - name: 'test4', + name: SAMLStringValue::fromString('test4'), attributeValue: [ new AttributeValue(4), new AttributeValue(23), @@ -105,11 +111,11 @@ public function testMarshalling(): void ), ], issuer: new Issuer( - value: 'https://example.org/', - Format: C::NAMEID_ENTITY, + value: SAMLStringValue::fromString('https://example.org/'), + Format: SAMLAnyURIValue::fromString(C::NAMEID_ENTITY), ), - id: 'aaf23196-1773-2113-474a-fe114412ab72', - issueInstant: new DateTimeImmutable('2017-09-06T11:49:27Z'), + id: IDValue::fromString('aaf23196-1773-2113-474a-fe114412ab72'), + issueInstant: SAMLDateTimeValue::fromString('2017-09-06T11:49:27Z'), ); $this->assertEquals( @@ -121,22 +127,25 @@ public function testMarshalling(): void public function testAttributeNameFormat(): void { - $nameId = new NameID('NameIDValue'); + $nameId = new NameID( + SAMLStringValue::fromString('NameIDValue'), + ); $attributeQuery = new AttributeQuery( + id: IDValue::fromString('SomeIDValue'), subject: new Subject($nameId), - issueInstant: self::$clock->now(), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), attributes: [ new Attribute( - name: 'test1', - nameFormat: C::NAMEFORMAT_BASIC, + name: SAMLStringValue::fromString('test1'), + nameFormat: SAMLAnyURIValue::fromString(C::NAMEFORMAT_BASIC), attributeValue: [ new AttributeValue('test1_attrv1'), new AttributeValue('test1_attrv2'), ], ), new Attribute( - name: 'test2', - nameFormat: C::NAMEFORMAT_BASIC, + name: SAMLStringValue::fromString('test2'), + nameFormat: SAMLAnyURIValue::fromString(C::NAMEFORMAT_BASIC), attributeValue: [ new AttributeValue('test2_attrv1'), new AttributeValue('test2_attrv2'), @@ -144,8 +153,8 @@ public function testAttributeNameFormat(): void ], ), new Attribute( - name: 'test3', - nameFormat: C::NAMEFORMAT_BASIC, + name: SAMLStringValue::fromString('test3'), + nameFormat: SAMLAnyURIValue::fromString(C::NAMEFORMAT_BASIC), ), ], ); diff --git a/tests/SAML2/XML/samlp/AuthnQueryTest.php b/tests/SAML2/XML/samlp/AuthnQueryTest.php index 43c69598b..a8cfc46d6 100644 --- a/tests/SAML2/XML/samlp/AuthnQueryTest.php +++ b/tests/SAML2/XML/samlp/AuthnQueryTest.php @@ -4,12 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use DateTimeImmutable; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\XML\Comparison; +use SimpleSAML\SAML2\Type\AuthnContextComparisonTypeValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\AuthnContextDeclRef; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\saml\NameID; @@ -18,11 +20,13 @@ use SimpleSAML\SAML2\XML\samlp\AbstractRequest; use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; use SimpleSAML\SAML2\XML\samlp\AbstractSubjectQuery; +use SimpleSAML\SAML2\XML\samlp\AuthnContextComparisonTypeEnum; use SimpleSAML\SAML2\XML\samlp\AuthnQuery; use SimpleSAML\SAML2\XML\samlp\RequestedAuthnContext; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -62,20 +66,28 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $nameId = new NameID('urn:example:subject', null, null, C::NAMEID_UNSPECIFIED); - $authnContextDeclRef = new AuthnContextDeclRef('https://example.org/relative/path/to/document.xml'); - $requestedAuthnContext = new RequestedAuthnContext([$authnContextDeclRef], Comparison::EXACT); + $nameId = new NameID( + value: SAMLStringValue::fromString('urn:example:subject'), + Format: SAMLAnyURIValue::fromString(C::NAMEID_UNSPECIFIED), + ); + $authnContextDeclRef = new AuthnContextDeclRef( + SAMLAnyURIValue::fromString('https://example.org/relative/path/to/document.xml'), + ); + $requestedAuthnContext = new RequestedAuthnContext( + [$authnContextDeclRef], + AuthnContextComparisonTypeValue::fromEnum(AuthnContextComparisonTypeEnum::Exact), + ); $authnQuery = new AuthnQuery( + id: IDValue::fromString('aaf23196-1773-2113-474a-fe114412ab72'), subject: new Subject($nameId), requestedAuthnContext: $requestedAuthnContext, issuer: new Issuer( - value: 'https://example.org/', - Format: C::NAMEID_ENTITY, + value: SAMLStringValue::fromString('https://example.org/'), + Format: SAMLAnyURIValue::fromString(C::NAMEID_ENTITY), ), - id: 'aaf23196-1773-2113-474a-fe114412ab72', - issueInstant: new DateTimeImmutable('2017-09-06T11:49:27Z'), - sessionIndex: 'phpunit', + issueInstant: SAMLDateTimeValue::fromString('2017-09-06T11:49:27Z'), + sessionIndex: SAMLStringValue::fromString('phpunit'), ); $this->assertEquals( diff --git a/tests/SAML2/XML/samlp/AuthnRequestTest.php b/tests/SAML2/XML/samlp/AuthnRequestTest.php index 45a9761d3..e2121d518 100644 --- a/tests/SAML2/XML/samlp/AuthnRequestTest.php +++ b/tests/SAML2/XML/samlp/AuthnRequestTest.php @@ -4,16 +4,19 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use DateTimeImmutable; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Compat\ContainerSingleton; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\AuthnContextComparisonTypeValue; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\Utils\XPath; -use SimpleSAML\SAML2\XML\Comparison; use SimpleSAML\SAML2\XML\saml\Audience; use SimpleSAML\SAML2\XML\saml\AudienceRestriction; use SimpleSAML\SAML2\XML\saml\AuthnContextClassRef; @@ -26,6 +29,7 @@ use SimpleSAML\SAML2\XML\saml\Subject; use SimpleSAML\SAML2\XML\samlp\AbstractMessage; use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; +use SimpleSAML\SAML2\XML\samlp\AuthnContextComparisonTypeEnum; use SimpleSAML\SAML2\XML\samlp\AuthnRequest; use SimpleSAML\SAML2\XML\samlp\GetComplete; use SimpleSAML\SAML2\XML\samlp\IDPEntry; @@ -36,10 +40,14 @@ use SimpleSAML\SAML2\XML\samlp\Scoping; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingAttributeException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\BooleanValue; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\NonNegativeIntegerValue; +use SimpleSAML\XMLSchema\Type\UnsignedShortValue; use SimpleSAML\XMLSecurity\Alg\KeyTransport\KeyTransportAlgorithmFactory; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; @@ -88,17 +96,19 @@ public function testMarshalling(): void { $subject = new Subject( new NameID( - value: 'user@example.org', - Format: C::NAMEID_UNSPECIFIED, + value: SAMLStringValue::fromString('user@example.org'), + Format: SAMLAnyURIValue::fromString(C::NAMEID_UNSPECIFIED), ), ); $authnRequest = new AuthnRequest( subject: $subject, - issuer: new Issuer('https://gateway.stepup.org/saml20/sp/metadata'), - id: '_2b0226190ca1c22de6f66e85f5c95158', - issueInstant: new DateTimeImmutable('2014-09-22T13:42:00Z'), - destination: 'https://tiqr.stepup.org/idp/profile/saml2/Redirect/SSO', + issuer: new Issuer( + SAMLStringValue::fromString('https://gateway.stepup.org/saml20/sp/metadata'), + ), + id: IDValue::fromString('_2b0226190ca1c22de6f66e85f5c95158'), + issueInstant: SAMLDateTimeValue::fromString('2014-09-22T13:42:00Z'), + destination: SAMLAnyURIValue::fromString('https://tiqr.stepup.org/idp/profile/saml2/Redirect/SSO'), ); $this->assertEquals( @@ -113,59 +123,84 @@ public function testMarshallingElementOrdering(): void // Create RequestedAuthnContext $rac = new RequestedAuthnContext( [ - new AuthnContextClassRef('urn:test:accr1'), - new AuthnContextClassRef('urn:test:accr2'), + new AuthnContextClassRef( + SAMLAnyURIValue::fromString('urn:test:accr1'), + ), + new AuthnContextClassRef( + SAMLAnyURIValue::fromString('urn:test:accr2'), + ), ], - Comparison::BETTER, + AuthnContextComparisonTypeValue::fromEnum(AuthnContextComparisonTypeEnum::Better), ); // Create Subject $subject = new Subject( - new Issuer('urn:x-simplesamlphp:issuer'), + new Issuer( + SAMLStringValue::fromString('urn:x-simplesamlphp:issuer'), + ), ); // Create NameIDPolicy $nameIdPolicy = new NameIDPolicy( - 'urn:the:format', - 'urn:x-simplesamlphp:spnamequalifier', - true, + SAMLAnyURIValue::fromString('urn:the:format'), + SAMLStringValue::fromString('urn:x-simplesamlphp:spnamequalifier'), + BooleanValue::fromBoolean(true), ); // Create Conditions $conditions = new Conditions( - new DateTimeImmutable('1970-01-01T01:33:31Z'), - new DateTimeImmutable('1970-01-02T01:33:31Z'), + SAMLDateTimeValue::fromString('1970-01-01T01:33:31Z'), + SAMLDateTimeValue::fromString('1970-01-02T01:33:31Z'), [], [ new AudienceRestriction( [ - new Audience('http://sp.example.com/demo1/metadata.php'), + new Audience( + SAMLAnyURIValue::fromstring('http://sp.example.com/demo1/metadata.php'), + ), ], ), ], new OneTimeUse(), new ProxyRestriction( [ - new Audience('http://sp.example.com/demo2/metadata.php'), + new Audience( + SAMLAnyURIValue::fromString('http://sp.example.com/demo2/metadata.php'), + ), ], - 2, + NonNegativeIntegerValue::fromInteger(2), ), ); // Create Scoping - $entry1 = new IDPEntry('urn:some:requester1', 'testName1', 'urn:test:testLoc1'); - $getComplete = new GetComplete('https://some/location'); + $entry1 = new IDPEntry( + EntityIDValue::fromString('urn:some:requester1'), + SAMLStringValue::fromString('testName1'), + SAMLAnyURIValue::fromString('urn:test:testLoc1'), + ); + $getComplete = new GetComplete( + SAMLAnyURIValue::fromString('https://some/location'), + ); $list = new IDPList([$entry1], $getComplete); - $requesterId = new RequesterID('urn:some:requester'); - $scoping = new Scoping(2, $list, [$requesterId]); + $requesterId = new RequesterID( + EntityIDValue::fromString('urn:some:requester'), + ); + $scoping = new Scoping( + NonNegativeIntegerValue::fromInteger(2), + $list, + [$requesterId], + ); $authnRequest = new AuthnRequest( + id: IDValue::fromString('SomeIDValue'), requestedAuthnContext: $rac, - issueInstant: self::$clock->now(), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), subject: $subject, nameIdPolicy: $nameIdPolicy, conditions: $conditions, - issuer: new Issuer('https://gateway.stepup.org/saml20/sp/metadata'), + issuer: new Issuer( + SAMLStringValue::fromString('https://gateway.stepup.org/saml20/sp/metadata'), + ), scoping: $scoping, ); @@ -199,28 +234,27 @@ public function testUnmarshallingOfSimpleRequest(): void $xml = << - https://sp.example.com/SAML2 + https://sp.example.com/SAML2 AUTHNREQUEST; $authnRequest = AuthnRequest::fromXML(DOMDocumentFactory::fromString($xml)->documentElement); $issuer = $authnRequest->getIssuer(); - $this->assertEquals('2004-12-05T09:21:59Z', $authnRequest->getIssueInstant()->format(C::DATETIME_FORMAT)); - $this->assertEquals('https://idp.example.org/SAML2/SSO/Artifact', $authnRequest->getDestination()); - $this->assertEquals(C::BINDING_HTTP_ARTIFACT, $authnRequest->getProtocolBinding()); + $this->assertEquals('2004-12-05T09:21:59Z', $authnRequest->getIssueInstant()->getValue()); + $this->assertEquals('https://idp.example.org/SAML2/SSO/Artifact', $authnRequest->getDestination()->getValue()); + $this->assertEquals(C::BINDING_HTTP_ARTIFACT, $authnRequest->getProtocolBinding()->getValue()); $this->assertEquals( 'https://sp.example.com/SAML2/SSO/Artifact', - $authnRequest->getAssertionConsumerServiceURL(), + $authnRequest->getAssertionConsumerServiceURL()->getValue(), ); $this->assertInstanceOf(Issuer::class, $issuer); - $this->assertEquals('https://sp.example.com/SAML2', $issuer->getContent()); + $this->assertEquals('https://sp.example.com/SAML2', $issuer->getContent()->getValue()); } @@ -232,20 +266,19 @@ public function testExtensionOrdering(): void $xml = << - https://sp.example.com/SAML2 + https://sp.example.com/SAML2 - + user@example.org getAlgorithm( - $identifier->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm(), + $identifier->getEncryptedKeys()[0]->getEncryptionMethod()?->getAlgorithm()->getValue(), PEMCertificatesMock::getPrivateKey(PEMCertificatesMock::SELFSIGNED_PRIVATE_KEY), ); @@ -299,14 +332,13 @@ public function testScopeWithoutProviderIDThrowsException(): void $xmlRequest = << - https://sp.example.com/SAML2 + https://sp.example.com/SAML2 @@ -326,14 +358,17 @@ public function testScopeWithoutProviderIDThrowsException(): void public function testSettingProtocolBindingAndACSIndex(): void { // the Issuer - $issuer = new Issuer('https://sp.example.org/saml20/sp/metadata'); - $issueInstant = new DateTimeImmutable('2004-12-05T09:21:59Z'); - $destination = 'https://idp.example.org/idp/profile/saml2/Redirect/SSO'; - $protocolBinding = C::BINDING_HTTP_POST; - $assertionConsumerServiceIndex = 1; + $issuer = new Issuer( + SAMLStringValue::fromString('https://sp.example.org/saml20/sp/metadata'), + ); + $issueInstant = SAMLDateTimeValue::fromString('2004-12-05T09:21:59Z'); + $destination = SAMLAnyURIValue::fromString('https://idp.example.org/idp/profile/saml2/Redirect/SSO'); + $protocolBinding = SAMLAnyURIValue::fromString(C::BINDING_HTTP_POST); + $assertionConsumerServiceIndex = UnsignedShortValue::fromInteger(1); $this->expectException(ProtocolViolationException::class); new AuthnRequest( + id: IDValue::fromString('_306f8ec5b618f361c70b6ffb1480eadf'), assertionConsumerServiceIndex: $assertionConsumerServiceIndex, protocolBinding: $protocolBinding, issuer: $issuer, @@ -350,14 +385,19 @@ public function testSettingProtocolBindingAndACSIndex(): void public function testSettingACSUrlAndACSIndex(): void { // the Issuer - $issuer = new Issuer('https://sp.example.org/saml20/sp/metadata'); - $issueInstant = new DateTimeImmutable('2004-12-05T09:21:59Z'); - $destination = 'https://idp.example.org/idp/profile/saml2/Redirect/SSO'; - $assertionConsumerServiceIndex = 1; - $assertionConsumerServiceURL = "https://sp.example.org/authentication/sp/consume-assertion"; + $issuer = new Issuer( + SAMLStringValue::fromString('https://sp.example.org/saml20/sp/metadata'), + ); + $issueInstant = SAMLDateTimeValue::fromString('2004-12-05T09:21:59Z'); + $destination = SAMLAnyURIValue::fromString('https://idp.example.org/idp/profile/saml2/Redirect/SSO'); + $assertionConsumerServiceIndex = UnsignedShortValue::fromInteger(1); + $assertionConsumerServiceURL = SAMLAnyURIValue::fromString( + "https://sp.example.org/authentication/sp/consume-assertion", + ); $this->expectException(ProtocolViolationException::class); new AuthnRequest( + id: IDValue::fromString('SomeIDValue'), assertionConsumerServiceURL: $assertionConsumerServiceURL, assertionConsumerServiceIndex: $assertionConsumerServiceIndex, issuer: $issuer, @@ -375,17 +415,16 @@ public function testMultipleSubjectsThrowsException(): void $xml = << - https://gateway.example.org/saml20/sp/metadata - + https://gateway.example.org/saml20/sp/metadata + user@example.org - + aabbcc @@ -405,14 +444,13 @@ public function testMultipleNameIdsInSubjectThrowsException(): void $xml = << - https://gateway.example.org/saml20/sp/metadata - + https://gateway.example.org/saml20/sp/metadata + user@example.org aabbcc @@ -433,14 +471,13 @@ public function testEmptySubjectThrowsException(): void $xml = << - https://gateway.example.org/saml20/sp/metadata - + https://gateway.example.org/saml20/sp/metadata + AUTHNREQUEST; diff --git a/tests/SAML2/XML/samlp/AuthzDecisionQueryTest.php b/tests/SAML2/XML/samlp/AuthzDecisionQueryTest.php index 3782aca38..c45d2e66b 100644 --- a/tests/SAML2/XML/samlp/AuthzDecisionQueryTest.php +++ b/tests/SAML2/XML/samlp/AuthzDecisionQueryTest.php @@ -4,11 +4,13 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use DateTimeImmutable; use DOMDocument; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\Action; use SimpleSAML\SAML2\XML\saml\Assertion; use SimpleSAML\SAML2\XML\saml\Evidence; @@ -24,6 +26,7 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -71,25 +74,36 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $nameId = new NameID('urn:example:subject', null, null, C::NAMEID_UNSPECIFIED); + $nameId = new NameID( + value: SAMLStringValue::fromString('urn:example:subject'), + Format: SAMLAnyURIValue::fromString(C::NAMEID_UNSPECIFIED), + ); $evidence = new Evidence( - assertion: [Assertion::fromXML(self::$assertion->documentElement)], + assertion: [ + Assertion::fromXML(self::$assertion->documentElement), + ], ); $authzDecisionQuery = new AuthzDecisionQuery( + id: IDValue::fromString('aaf23196-1773-2113-474a-fe114412ab72'), subject: new Subject($nameId), - resource: 'urn:x-simplesamlphp:resource', + resource: SAMLAnyURIValue::fromString('urn:x-simplesamlphp:resource'), action: [ - new Action(C::NAMESPACE, 'SomeAction'), - new Action('urn:x-simplesamlphp:alt-namespace', 'SomeOtherAction'), + new Action( + SAMLAnyURIValue::fromString(C::NAMESPACE), + SAMLStringValue::fromString('SomeAction'), + ), + new Action( + SAMLAnyURIValue::fromString('urn:x-simplesamlphp:alt-namespace'), + SAMLStringValue::fromString('SomeOtherAction'), + ), ], evidence: $evidence, issuer: new Issuer( - value: 'https://example.org/', - Format: C::NAMEID_ENTITY, + value: SAMLStringValue::fromString('https://example.org/'), + Format: SAMLAnyURIValue::fromString(C::NAMEID_ENTITY), ), - id: 'aaf23196-1773-2113-474a-fe114412ab72', - issueInstant: new DateTimeImmutable('2017-09-06T11:49:27Z'), + issueInstant: SAMLDateTimeValue::fromString('2017-09-06T11:49:27Z'), ); $this->assertEquals( diff --git a/tests/SAML2/XML/samlp/GetCompleteTest.php b/tests/SAML2/XML/samlp/GetCompleteTest.php index e821efaf3..29a059df2 100644 --- a/tests/SAML2/XML/samlp/GetCompleteTest.php +++ b/tests/SAML2/XML/samlp/GetCompleteTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; use SimpleSAML\SAML2\XML\samlp\GetComplete; use SimpleSAML\XML\DOMDocumentFactory; @@ -50,10 +51,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $getComplete = new GetComplete('https://some/location'); - - $getCompleteElement = $getComplete->toXML(); - $this->assertEquals('https://some/location', $getCompleteElement->textContent); + $getComplete = new GetComplete( + SAMLAnyURIValue::fromString('https://some/location'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/samlp/IDPEntryTest.php b/tests/SAML2/XML/samlp/IDPEntryTest.php index 3e062a07c..f396b4c05 100644 --- a/tests/SAML2/XML/samlp/IDPEntryTest.php +++ b/tests/SAML2/XML/samlp/IDPEntryTest.php @@ -7,6 +7,9 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; use SimpleSAML\SAML2\XML\samlp\IDPEntry; use SimpleSAML\XML\DOMDocumentFactory; @@ -54,7 +57,11 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $entry = new IDPEntry('urn:some:requester', 'testName', 'urn:test:testLoc'); + $entry = new IDPEntry( + EntityIDValue::fromString('urn:some:requester'), + SAMLStringValue::fromString('testName'), + SAMLAnyURIValue::fromString('urn:test:testLoc'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), @@ -71,9 +78,11 @@ public function testMarshallingNullables(): void $document->documentElement->removeAttribute('Name'); $document->documentElement->removeAttribute('Loc'); - $entry = new IDPEntry('urn:some:requester'); + $entry = new IDPEntry( + EntityIDValue::fromString('urn:some:requester'), + ); - $this->assertEquals('urn:some:requester', $entry->getProviderID()); + $this->assertEquals('urn:some:requester', $entry->getProviderID()->getValue()); $this->assertNull($entry->getName()); $this->assertNull($entry->getLoc()); diff --git a/tests/SAML2/XML/samlp/IDPListTest.php b/tests/SAML2/XML/samlp/IDPListTest.php index 11699a9f5..6ce56a9a5 100644 --- a/tests/SAML2/XML/samlp/IDPListTest.php +++ b/tests/SAML2/XML/samlp/IDPListTest.php @@ -7,16 +7,19 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; use SimpleSAML\SAML2\XML\samlp\GetComplete; use SimpleSAML\SAML2\XML\samlp\IDPEntry; use SimpleSAML\SAML2\XML\samlp\IDPList; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingElementException; use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingElementException; use function dirname; use function strval; @@ -60,9 +63,19 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $entry1 = new IDPEntry('urn:some:requester1', 'testName1', 'urn:test:testLoc1'); - $entry2 = new IDPEntry('urn:some:requester2', 'testName2', 'urn:test:testLoc2'); - $getComplete = new GetComplete('https://some/location'); + $entry1 = new IDPEntry( + EntityIDValue::fromString('urn:some:requester1'), + SAMLStringValue::fromString('testName1'), + SAMLAnyURIValue::fromString('urn:test:testLoc1'), + ); + $entry2 = new IDPEntry( + EntityIDValue::fromString('urn:some:requester2'), + SAMLStringValue::fromString('testName2'), + SAMLAnyURIValue::fromString('urn:test:testLoc2'), + ); + $getComplete = new GetComplete( + SAMLAnyURIValue::fromString('https://some/location'), + ); $list = new IDPList([$entry1, $entry2], $getComplete); $this->assertEquals( @@ -76,9 +89,19 @@ public function testMarshalling(): void */ public function testMarshallingElementOrdering(): void { - $entry1 = new IDPEntry('urn:some:requester1', 'testName1', 'urn:test:testLoc1'); - $entry2 = new IDPEntry('urn:some:requester2', 'testName2', 'urn:test:testLoc2'); - $getComplete = new GetComplete('https://some/location'); + $entry1 = new IDPEntry( + EntityIDValue::fromString('urn:some:requester1'), + SAMLStringValue::fromString('testName1'), + SAMLAnyURIValue::fromString('urn:test:testLoc1'), + ); + $entry2 = new IDPEntry( + EntityIDValue::fromString('urn:some:requester2'), + SAMLStringValue::fromString('testName2'), + SAMLAnyURIValue::fromString('urn:test:testLoc2'), + ); + $getComplete = new GetComplete( + SAMLAnyURIValue::fromString('https://some/location'), + ); $list = new IDPList([$entry1, $entry2], $getComplete); $listElement = $list->toXML(); @@ -109,7 +132,11 @@ public function testMarshallingNullables(): void XML ; - $entry1 = new IDPEntry('urn:some:requester1', 'testName1', 'urn:test:testLoc1'); + $entry1 = new IDPEntry( + EntityIDValue::fromString('urn:some:requester1'), + SAMLStringValue::fromString('testName1'), + SAMLAnyURIValue::fromString('urn:test:testLoc1'), + ); $list = new IDPList([$entry1]); $entries = $list->getIdpEntry(); diff --git a/tests/SAML2/XML/samlp/LogoutRequestTest.php b/tests/SAML2/XML/samlp/LogoutRequestTest.php index 7ba2a57be..e14966899 100644 --- a/tests/SAML2/XML/samlp/LogoutRequestTest.php +++ b/tests/SAML2/XML/samlp/LogoutRequestTest.php @@ -10,6 +10,8 @@ use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Compat\ContainerSingleton; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\saml\EncryptedID; @@ -21,10 +23,11 @@ use SimpleSAML\SAML2\XML\samlp\LogoutRequest; use SimpleSAML\SAML2\XML\samlp\SessionIndex; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingElementException; -use SimpleSAML\XML\Exception\TooManyElementsException; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\MissingElementException; +use SimpleSAML\XMLSchema\Exception\TooManyElementsException; +use SimpleSAML\XMLSchema\Type\IDValue; use SimpleSAML\XMLSecurity\Alg\KeyTransport\KeyTransportAlgorithmFactory; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; @@ -71,12 +74,17 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $nameId = new NameID('NameIDValue'); + $nameId = new NameID( + SAMLStringValue::fromString('NameIDValue'), + ); $logoutRequest = new LogoutRequest( + id: IDValue::fromString('SomeIDValue'), identifier: $nameId, - issueInstant: self::$clock->now(), - sessionIndexes: [new SessionIndex('SessionIndexValue')], + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + sessionIndexes: [ + new SessionIndex(SAMLStringValue::fromString('SessionIndexValue')), + ], ); $logoutRequestElement = $logoutRequest->toXML(); @@ -93,11 +101,17 @@ public function testMarshalling(): void $this->assertCount(1, $sessionIndexElements); $this->assertEquals('SessionIndexValue', $sessionIndexElements[0]->textContent); - $nameId = new NameID('NameIDValue'); + $nameId = new NameID( + SAMLStringValue::fromString('NameIDValue'), + ); $logoutRequest = new LogoutRequest( + id: IDValue::fromString('SomeIDValue'), identifier: $nameId, - issueInstant: self::$clock->now(), - sessionIndexes: [new SessionIndex('SessionIndexValue1'), new SessionIndex('SessionIndexValue2')], + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + sessionIndexes: [ + new SessionIndex(SAMLStringValue::fromString('SessionIndexValue1')), + new SessionIndex(SAMLStringValue::fromString('SessionIndexValue2')), + ], ); $logoutRequestElement = $logoutRequest->toXML(); @@ -113,12 +127,17 @@ public function testMarshalling(): void */ public function testMarshallingElementOrdering(): void { - $nameId = new NameID('NameIDValue'); + $nameId = new NameID( + SAMLStringValue::fromString('NameIDValue'), + ); $logoutRequest = new LogoutRequest( + id: IDValue::fromString('SomeIDValue'), identifier: $nameId, - issueInstant: self::$clock->now(), - sessionIndexes: [new SessionIndex('SessionIndexValue')], + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + sessionIndexes: [ + new SessionIndex(SAMLStringValue::fromString('SessionIndexValue')), + ], ); $logoutRequestElement = $logoutRequest->toXML(); @@ -159,12 +178,12 @@ public function testUnmarshalling(): void $sessionIndexes = $logoutRequest->getSessionIndexes(); $this->assertCount(2, $sessionIndexes); - $this->assertEquals('SomeSessionIndex1', $sessionIndexes[0]->getContent()); - $this->assertEquals('SomeSessionIndex2', $sessionIndexes[1]->getContent()); + $this->assertEquals('SomeSessionIndex1', $sessionIndexes[0]->getContent()->getValue()); + $this->assertEquals('SomeSessionIndex2', $sessionIndexes[1]->getContent()->getValue()); /** @psalm-suppress PossiblyNullArgument */ $decryptor = (new KeyTransportAlgorithmFactory())->getAlgorithm( - $encid->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm(), + $encid->getEncryptedKeys()[0]->getEncryptionMethod()?->getAlgorithm()->getValue(), PEMCertificatesMock::getPrivateKey(PEMCertificatesMock::SELFSIGNED_PRIVATE_KEY), ); $identifier = $encid->decrypt($decryptor); @@ -181,7 +200,11 @@ public function testEncryptedNameId(): void dirname(__FILE__, 4) . '/resources/xml/saml_EncryptedID.xml', )->documentElement); - $logoutRequest = new LogoutRequest($eid, self::$clock->now()); + $logoutRequest = new LogoutRequest( + identifier: $eid, + id: IDValue::fromString('SomeIDValue'), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + ); $logoutRequestElement = $logoutRequest->toXML(); $this->assertCount( 1, @@ -291,7 +314,7 @@ public function testGetNotOnOrAfter(): void $logoutRequestElement = $document->documentElement; $logoutRequest = LogoutRequest::fromXML($logoutRequestElement); - $this->assertEquals('2018-11-28T19:33:12Z', $logoutRequest->getNotOnOrAfter()->format(C::DATETIME_FORMAT)); + $this->assertEquals('2018-11-28T19:33:12Z', $logoutRequest->getNotOnOrAfter()->getValue()); } @@ -299,15 +322,22 @@ public function testGetNotOnOrAfter(): void */ public function testSetNotOnOrAfter(): void { - $nameId = new NameID('NameIDValue'); + $nameId = new NameID( + SAMLStringValue::fromString('NameIDValue'), + ); - $logoutRequest = new LogoutRequest($nameId, self::$clock->now(), self::$clock->now()); + $logoutRequest = new LogoutRequest( + IDValue::fromString('SomeIDValue'), + $nameId, + SAMLDateTimeValue::fromDateTime(self::$clock->now()), + SAMLDateTimeValue::fromDateTime(self::$clock->now()), + ); $logoutRequestElement = $logoutRequest->toXML(); $logoutRequest2 = LogoutRequest::fromXML($logoutRequestElement); $this->assertEquals( - self::$clock->now()->format(C::DATETIME_FORMAT), - $logoutRequest2->getNotOnOrAfter()->format(C::DATETIME_FORMAT), + SAMLDateTimeValue::fromDateTime(self::$clock->now())->getValue(), + $logoutRequest2->getNotOnOrAfter()->getValue(), ); } @@ -342,10 +372,18 @@ public function testGetReason(): void */ public function testSetReason(): void { - $reason = "urn:simplesamlphp:reason-test"; - $nameId = new NameID('NameIDValue'); + $reason = SAMLStringValue::fromString("urn:simplesamlphp:reason-test"); + $nameId = new NameID( + SAMLStringValue::fromString('NameIDValue'), + ); - $logoutRequest = new LogoutRequest($nameId, self::$clock->now(), null, $reason); + $logoutRequest = new LogoutRequest( + id: IDValue::fromString('SomeIDValue'), + identifier: $nameId, + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), + notOnOrAfter: null, + reason: $reason, + ); $logoutRequestElement = $logoutRequest->toXML(); $logoutRequest2 = LogoutRequest::fromXML($logoutRequestElement); @@ -380,21 +418,25 @@ public function testWithOutSessionIndices(): void */ public function testSetSessionIndicesVariants(): void { - $nameId = new NameID('test'); + $nameId = new NameID( + SAMLStringValue::fromString('test'), + ); + $sessionIndexes = [ - new SessionIndex('SessionIndexValue1'), - new SessionIndex('SessionIndexValue2'), + new SessionIndex(SAMLStringValue::fromString('SessionIndexValue1')), + new SessionIndex(SAMLStringValue::fromString('SessionIndexValue2')), ]; $logoutRequest = new LogoutRequest( - issueInstant: self::$clock->now(), + id: IDValue::fromString('SomeIDValue'), + issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()), identifier: $nameId, sessionIndexes: $sessionIndexes, ); $sessionIndexes = $logoutRequest->getSessionIndexes(); $this->assertCount(2, $sessionIndexes); - $this->assertEquals('SessionIndexValue1', $sessionIndexes[0]->getContent()); - $this->assertEquals('SessionIndexValue2', $sessionIndexes[1]->getContent()); + $this->assertEquals('SessionIndexValue1', $sessionIndexes[0]->getContent()->getValue()); + $this->assertEquals('SessionIndexValue2', $sessionIndexes[1]->getContent()->getValue()); } } diff --git a/tests/SAML2/XML/samlp/LogoutResponseTest.php b/tests/SAML2/XML/samlp/LogoutResponseTest.php index d2affd040..8905e0adc 100644 --- a/tests/SAML2/XML/samlp/LogoutResponseTest.php +++ b/tests/SAML2/XML/samlp/LogoutResponseTest.php @@ -4,11 +4,13 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use DateTimeImmutable; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\samlp\AbstractMessage; use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; @@ -19,6 +21,8 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\NCNameValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -57,14 +61,22 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $issuer = new Issuer('urn:x-simplesamlphp:issuer'); - $status = new Status(new StatusCode(C::STATUS_SUCCESS)); + $issuer = new Issuer( + SAMLStringValue::fromString('urn:x-simplesamlphp:issuer'), + ); + $status = new Status( + new StatusCode( + SAMLAnyURIValue::fromString(C::STATUS_SUCCESS), + ), + ); $logoutResponse = new LogoutResponse( - id: 's2a0da3504aff978b0f8c80f6a62c713c4a2f64c5b', - issueInstant: new DateTimeImmutable('2007-12-10T11:39:48Z'), - destination: 'http://somewhere.example.org/simplesaml/saml2/sp/AssertionConsumerService.php', - inResponseTo: '_bec424fa5103428909a30ff1e31168327f79474984', + id: IDValue::fromString('s2a0da3504aff978b0f8c80f6a62c713c4a2f64c5b'), + issueInstant: SAMLDateTimeValue::fromString('2007-12-10T11:39:48Z'), + destination: SAMLAnyURIValue::fromString( + 'http://somewhere.example.org/simplesaml/saml2/sp/AssertionConsumerService.php', + ), + inResponseTo: NCNameValue::fromString('_bec424fa5103428909a30ff1e31168327f79474984'), issuer: $issuer, status: $status, ); diff --git a/tests/SAML2/XML/samlp/MessageFactoryTest.php b/tests/SAML2/XML/samlp/MessageFactoryTest.php index d62f82277..3c835100a 100644 --- a/tests/SAML2/XML/samlp/MessageFactoryTest.php +++ b/tests/SAML2/XML/samlp/MessageFactoryTest.php @@ -18,7 +18,7 @@ use SimpleSAML\SAML2\XML\samlp\MessageFactory; use SimpleSAML\SAML2\XML\samlp\Response; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\InvalidDOMElementException; +use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException; use function dirname; diff --git a/tests/SAML2/XML/samlp/NameIDPolicyTest.php b/tests/SAML2/XML/samlp/NameIDPolicyTest.php index 398762249..5c3150c5d 100644 --- a/tests/SAML2/XML/samlp/NameIDPolicyTest.php +++ b/tests/SAML2/XML/samlp/NameIDPolicyTest.php @@ -8,12 +8,15 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; use SimpleSAML\SAML2\XML\samlp\NameIDPolicy; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\BooleanValue; use function dirname; use function strval; @@ -56,9 +59,9 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $nameIdPolicy = new NameIDPolicy( - 'urn:the:format', - 'urn:x-simplesamlphp:spnamequalifier', - true, + SAMLAnyURIValue::fromString('urn:the:format'), + SAMLStringValue::fromString('urn:x-simplesamlphp:spnamequalifier'), + BooleanValue::fromBoolean(true), ); $this->assertEquals( @@ -77,7 +80,7 @@ public function testMarshallingFormatOnly(): void ); $nameIdPolicy = new NameIDPolicy( - 'urn:the:format', + SAMLAnyURIValue::fromString('urn:the:format'), ); $this->assertEquals( diff --git a/tests/SAML2/XML/samlp/RequestedAuthnContextTest.php b/tests/SAML2/XML/samlp/RequestedAuthnContextTest.php index a22e493fd..c4ead4dff 100644 --- a/tests/SAML2/XML/samlp/RequestedAuthnContextTest.php +++ b/tests/SAML2/XML/samlp/RequestedAuthnContextTest.php @@ -7,16 +7,19 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\XML\Comparison; +use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\AuthnContextComparisonTypeValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\saml\AuthnContextClassRef; use SimpleSAML\SAML2\XML\saml\AuthnContextDeclRef; use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; +use SimpleSAML\SAML2\XML\samlp\AuthnContextComparisonTypeEnum; use SimpleSAML\SAML2\XML\samlp\RequestedAuthnContext; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Exception\SchemaViolationException; use function dirname; use function strval; @@ -51,9 +54,14 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $authnContextDeclRef = new AuthnContextDeclRef('https://example.org/relative/path/to/document.xml'); + $authnContextDeclRef = new AuthnContextDeclRef( + SAMLAnyURIValue::fromString('https://example.org/relative/path/to/document.xml'), + ); - $requestedAuthnContext = new RequestedAuthnContext([$authnContextDeclRef], Comparison::EXACT); + $requestedAuthnContext = new RequestedAuthnContext( + [$authnContextDeclRef], + AuthnContextComparisonTypeValue::fromEnum(AuthnContextComparisonTypeEnum::Exact), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), @@ -66,13 +74,20 @@ public function testMarshalling(): void */ public function testMarshallingWithMixedContextsFails(): void { - $authnContextDeclRef = new AuthnContextDeclRef('https://example.org/relative/path/to/document.xml'); - $authnContextClassRef = new AuthnContextClassRef(C::AC_PASSWORD_PROTECTED_TRANSPORT); + $authnContextDeclRef = new AuthnContextDeclRef( + SAMLAnyURIValue::fromString('https://example.org/relative/path/to/document.xml'), + ); + $authnContextClassRef = new AuthnContextClassRef( + SAMLAnyURIValue::fromString(C::AC_PASSWORD_PROTECTED_TRANSPORT), + ); - $this->expectException(AssertionFailedException::class); + $this->expectException(ProtocolViolationException::class); $this->expectExceptionMessage('You need either AuthnContextClassRef or AuthnContextDeclRef, not both.'); - new RequestedAuthnContext([$authnContextClassRef, $authnContextDeclRef], Comparison::EXACT); + new RequestedAuthnContext( + [$authnContextClassRef, $authnContextDeclRef], + AuthnContextComparisonTypeValue::fromEnum(AuthnContextComparisonTypeEnum::Exact), + ); } @@ -80,20 +95,23 @@ public function testMarshallingWithMixedContextsFails(): void */ public function testMarshallingWithInvalidContentFails(): void { - $authnContextDeclRef = new AuthnContextDeclRef('https://example.org/relative/path/to/document.xml'); + $authnContextDeclRef = new AuthnContextDeclRef( + SAMLAnyURIValue::fromString('https://example.org/relative/path/to/document.xml'), + ); - $this->expectException(AssertionFailedException::class); + $this->expectException(SchemaViolationException::class); $this->expectExceptionMessage( 'Expected an instance of any of "' . AuthnContextClassRef::class . '", "' . AuthnContextDeclRef::class . '". Got: DOMDocument', ); new RequestedAuthnContext( + /** @phpstan-ignore argument.type */ [ DOMDocumentFactory::fromString(''), $authnContextDeclRef, ], - Comparison::EXACT, + AuthnContextComparisonTypeValue::fromEnum(AuthnContextComparisonTypeEnum::Exact), ); } @@ -115,7 +133,7 @@ public function testUnmarshallingWithMixedContextsFails(): void , ); - $this->expectException(AssertionFailedException::class); + $this->expectException(ProtocolViolationException::class); $this->expectExceptionMessage('You need either AuthnContextClassRef or AuthnContextDeclRef, not both.'); RequestedAuthnContext::fromXML($document->documentElement); diff --git a/tests/SAML2/XML/samlp/RequesterIDTest.php b/tests/SAML2/XML/samlp/RequesterIDTest.php index dd2ae47dc..c3a3f442d 100644 --- a/tests/SAML2/XML/samlp/RequesterIDTest.php +++ b/tests/SAML2/XML/samlp/RequesterIDTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\EntityIDValue; use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; use SimpleSAML\SAML2\XML\samlp\RequesterID; use SimpleSAML\XML\DOMDocumentFactory; @@ -50,7 +51,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $requesterId = new RequesterID('urn:some:requester'); + $requesterId = new RequesterID( + EntityIDValue::fromString('urn:some:requester'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/samlp/ResponseTest.php b/tests/SAML2/XML/samlp/ResponseTest.php index f0a59c9a4..240a74d9d 100644 --- a/tests/SAML2/XML/samlp/ResponseTest.php +++ b/tests/SAML2/XML/samlp/ResponseTest.php @@ -4,11 +4,13 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use DateTimeImmutable; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\Assertion; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\samlp\AbstractMessage; @@ -20,6 +22,8 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\NCNameValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -58,21 +62,29 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $status = new Status(new StatusCode()); - $issuer = new Issuer('https://IdentityProvider.com'); + $status = new Status( + new StatusCode( + SAMLAnyURIValue::fromString(C::STATUS_SUCCESS), + ), + ); + $issuer = new Issuer( + SAMLStringValue::fromString('https://IdentityProvider.com'), + ); $assertion = DOMDocumentFactory::fromFile( dirname(__FILE__, 4) . '/resources/xml/saml_Assertion.xml', ); $response = new Response( - id: 'abc123', + id: IDValue::fromString('abc123'), status: $status, issuer: $issuer, - destination: 'https://example.org/metadata', - consent: C::CONSENT_EXPLICIT, - inResponseTo: 'PHPUnit', - issueInstant: new DateTimeImmutable('2021-03-25T16:53:26Z'), - assertions: [Assertion::fromXML($assertion->documentElement)], + destination: SAMLAnyURIValue::fromString('https://example.org/metadata'), + consent: SAMLAnyURIValue::fromString(C::CONSENT_EXPLICIT), + inResponseTo: NCNameValue::fromString('PHPUnit'), + issueInstant: SAMLDateTimeValue::fromString('2021-03-25T16:53:26Z'), + assertions: [ + Assertion::fromXML($assertion->documentElement), + ], ); $this->assertEquals( diff --git a/tests/SAML2/XML/samlp/ScopingTest.php b/tests/SAML2/XML/samlp/ScopingTest.php index 069cd9ef5..4021a2180 100644 --- a/tests/SAML2/XML/samlp/ScopingTest.php +++ b/tests/SAML2/XML/samlp/ScopingTest.php @@ -8,6 +8,9 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; use SimpleSAML\SAML2\XML\samlp\GetComplete; @@ -18,6 +21,7 @@ use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\NonNegativeIntegerValue; use function dirname; use function strval; @@ -52,12 +56,24 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $entry1 = new IDPEntry('urn:some:requester1', 'testName1', 'urn:test:testLoc1'); - $getComplete = new GetComplete('https://some/location'); + $entry1 = new IDPEntry( + EntityIDValue::fromString('urn:some:requester1'), + SAMLStringValue::fromString('testName1'), + EntityIDValue::fromString('urn:test:testLoc1'), + ); + $getComplete = new GetComplete( + SAMLAnyURIValue::fromString('https://some/location'), + ); $list = new IDPList([$entry1], $getComplete); - $requesterId = 'urn:some:requester'; - - $scoping = new Scoping(2, $list, [new RequesterID($requesterId)]); + $requesterId = EntityIDValue::fromString('urn:some:requester'); + + $scoping = new Scoping( + NonNegativeIntegerValue::fromInteger(2), + $list, + [ + new RequesterID($requesterId), + ], + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), @@ -70,12 +86,24 @@ public function testMarshalling(): void */ public function testMarshallingElementOrdering(): void { - $entry1 = new IDPEntry('urn:some:requester1', 'testName1', 'urn:test:testLoc1'); - $getComplete = new GetComplete('https://some/location'); + $entry1 = new IDPEntry( + EntityIDValue::fromString('urn:some:requester1'), + SAMLStringValue::fromString('testName1'), + EntityIDValue::fromString('urn:test:testLoc1'), + ); + $getComplete = new GetComplete( + SAMLAnyURIValue::fromString('https://some/location'), + ); $list = new IDPList([$entry1], $getComplete); - $requesterId = 'urn:some:requester'; - - $scoping = new Scoping(2, $list, [new RequesterID($requesterId)]); + $requesterId = EntityIDValue::fromString('urn:some:requester'); + + $scoping = new Scoping( + NonNegativeIntegerValue::fromInteger(2), + $list, + [ + new RequesterID($requesterId), + ], + ); $scopingElement = $scoping->toXML(); diff --git a/tests/SAML2/XML/samlp/SessionIndexTest.php b/tests/SAML2/XML/samlp/SessionIndexTest.php index 8227b40f6..ac68b4948 100644 --- a/tests/SAML2/XML/samlp/SessionIndexTest.php +++ b/tests/SAML2/XML/samlp/SessionIndexTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; use SimpleSAML\SAML2\XML\samlp\SessionIndex; use SimpleSAML\XML\DOMDocumentFactory; @@ -46,7 +47,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $sessionIndex = new SessionIndex('SomeSessionIndex1'); + $sessionIndex = new SessionIndex( + SAMLStringValue::fromString('SomeSessionIndex1'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/samlp/StatusCodeTest.php b/tests/SAML2/XML/samlp/StatusCodeTest.php index aae2f8d07..34bf3c8d4 100644 --- a/tests/SAML2/XML/samlp/StatusCodeTest.php +++ b/tests/SAML2/XML/samlp/StatusCodeTest.php @@ -8,6 +8,7 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; use SimpleSAML\SAML2\XML\samlp\StatusCode; use SimpleSAML\XML\DOMDocumentFactory; @@ -49,9 +50,11 @@ public function testMarshalling(): void { $statusCode = new StatusCode( - C::STATUS_RESPONDER, + SAMLAnyURIValue::fromString(C::STATUS_RESPONDER), [ - new StatusCode(C::STATUS_REQUEST_DENIED), + new StatusCode( + SAMLAnyURIValue::fromString(C::STATUS_REQUEST_DENIED), + ), ], ); diff --git a/tests/SAML2/XML/samlp/StatusMessageTest.php b/tests/SAML2/XML/samlp/StatusMessageTest.php index 0f1e57ec3..3cbea9b06 100644 --- a/tests/SAML2/XML/samlp/StatusMessageTest.php +++ b/tests/SAML2/XML/samlp/StatusMessageTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; use SimpleSAML\SAML2\XML\samlp\StatusMessage; use SimpleSAML\XML\DOMDocumentFactory; @@ -46,7 +47,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $statusMessage = new StatusMessage('Something went wrong'); + $statusMessage = new StatusMessage( + SAMLStringValue::fromString('Something went wrong'), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/samlp/StatusTest.php b/tests/SAML2/XML/samlp/StatusTest.php index 34f2e170e..d57a99ab6 100644 --- a/tests/SAML2/XML/samlp/StatusTest.php +++ b/tests/SAML2/XML/samlp/StatusTest.php @@ -9,6 +9,8 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; use SimpleSAML\SAML2\XML\samlp\Status; @@ -63,14 +65,16 @@ public function testMarshalling(): void { $status = new Status( new StatusCode( - C::STATUS_RESPONDER, + SAMLAnyURIValue::fromString(C::STATUS_RESPONDER), [ new StatusCode( - C::STATUS_REQUEST_DENIED, + SAMLAnyURIValue::fromString(C::STATUS_REQUEST_DENIED), ), ], ), - new StatusMessage('Something went wrong'), + new StatusMessage( + SAMLStringValue::fromString('Something went wrong'), + ), [ StatusDetail::fromXML( DOMDocumentFactory::fromFile( @@ -93,14 +97,16 @@ public function testMarshallingElementOrdering(): void { $status = new Status( new StatusCode( - C::STATUS_RESPONDER, + SAMLAnyURIValue::fromString(C::STATUS_RESPONDER), [ new StatusCode( - C::STATUS_REQUEST_DENIED, + SAMLAnyURIValue::fromString(C::STATUS_REQUEST_DENIED), ), ], ), - new StatusMessage('Something went wrong'), + new StatusMessage( + SAMLStringValue::fromString('Something went wrong'), + ), [ new StatusDetail([new Chunk(self::$detail->documentElement)]), ], diff --git a/tests/SAML2/XML/shibmd/KeyAuthorityTest.php b/tests/SAML2/XML/shibmd/KeyAuthorityTest.php index 817663bc3..b92736089 100644 --- a/tests/SAML2/XML/shibmd/KeyAuthorityTest.php +++ b/tests/SAML2/XML/shibmd/KeyAuthorityTest.php @@ -7,12 +7,16 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\shibmd\AbstractShibmdElement; use SimpleSAML\SAML2\XML\shibmd\KeyAuthority; use SimpleSAML\XML\Attribute as XMLAttribute; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\Base64BinaryValue; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\UnsignedByteValue; use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; use SimpleSAML\XMLSecurity\XML\ds\X509Certificate; use SimpleSAML\XMLSecurity\XML\ds\X509Data; @@ -56,25 +60,29 @@ public function testMarshalling(): void [ new X509Data( [ - new X509Certificate('MIIG/DCCBOSgAwIBAgIIU2w5U7TnvlwwDQYJKoZIhvcNAQELBQAwZjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjE3MDUGA1UEAwwuU3RhYXQgZGVyIE5lZGVybGFuZGVuIFByaXZhdGUgU2VydmljZXMgQ0EgLSBHMTAeFw0xNjExMDMxMDM2MTFaFw0yODExMTIwMDAwMDBaMIGAMQswCQYDVQQGEwJOTDEgMB4GA1UECgwXUXVvVmFkaXMgVHJ1c3RsaW5rIEIuVi4xFzAVBgNVBGEMDk5UUk5MLTMwMjM3NDU5MTYwNAYDVQQDDC1RdW9WYWRpcyBQS0lvdmVyaGVpZCBQcml2YXRlIFNlcnZpY2VzIENBIC0gRzEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCo9ep1FEPp6FQIgMT8wD5UoTDQoqkE43vWFx2ur6cxYQFpWXefd0dpdaugwOJ5igIilAoIrd+FdYxbJxQOkrbmkFX1mdW2mAf10+9BW5rn1HvwHG/nvZ8kyaeZuEyEUmVZ+EEFw+7hOru7YPkxA5U7N3IY409xAjiYS3Cti388bLPfE3Ci0Rt2WQlL3jbnSlAty2ZdJ5aCRkL3Cm8wERlwZ0lsLsTIQo1TCw6WfrDgEk+41MvP3eh+0wL3lWPnSPzwvI13Dd5PjT7Pte73oVpqRwgWl+2ZjGD7vwNf14rma3Khuwv74lWWJIr9EHu4miseqVlhk4mFpPC4zsKM6AeXfhZwKLmGAwM54yHw7hjvSPoBilpGiKdIdELMfFzWToSOjMXPQZyHSF5F13sj/hD+YLRBx95QsDa+1xWJq4hv+/t/WPuw1E+s8JYQ/5HKArYfGNMou20skdJyvYW5H+NcZ0guCaF6zdrUDkFv+uI+MkWQMxGw/mwqZX/cW4EC4PPG1j3NEK6/gfU7LT4W/M/GIBC6kJ+L5AJtDIvW8719oIp0UBmhF1nZyQSX6WdaplsM6CNYZ7SSq+kUC4k6Oalzsnv4kNy7ru6yzHoI33V6VXQcs2BevJjbf09YIHoh2cPKPB0nIvRNq9Lvpek0mi5lGzmDj+/DxRySLdPJbzzdCQIDAQABo4IBkTCCAY0wUgYIKwYBBQUHAQEERjBEMEIGCCsGAQUFBzAChjZodHRwOi8vY2VydC5wa2lvdmVyaGVpZC5ubC9Eb21Qcml2YXRlU2VydmljZXNDQS1HMS5jZXIwHQYDVR0OBBYEFLlsphO6uy80Y4MxLvl+SR3fAPVjMBIGA1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0jBBgwFoAUPq+oD4eiLEF7FGwb89to05KnRKgwJQYIKwYBBQUHAQMEGTAXMBUGCCsGAQUFBwsCMAkGBwQAi+xJAQIwXQYDVR0gBFYwVDAMBgpghBABh2sBAggEMAwGCmCEEAGHawECCAUwNgYKYIQQAYdrAQIIBjAoMCYGCCsGAQUFBwIBFhpodHRwczovL2Nwcy5wa2lvdmVyaGVpZC5ubDBNBgNVHR8ERjBEMEKgQKA+hjxodHRwOi8vY3JsLnBraW92ZXJoZWlkLm5sL0RvbVByaXZhdGVTZXJ2aWNlc0xhdGVzdENSTC1HMS5jcmwwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQCM9aEWB9EutS4/TKJ0hSrJljJSt0sAFxkoi6upCv7+C9Pjp+R5woGAwiBctbM5PyT+KpOKlDZKL3mrXSUc/71qNxsPlZR703c+HhlkvDCHbk9afrAXWtXz0sKVs8KaNS2W4k7O8xGNZVMjMwpanQdBcsTnFPu12OTj8BCv4aOFxIYnPqPHkl8VTAi2pTArCtTQk9vi6QaXPzSmfi/rDINCJUAOnA3BEeZZI+BD8yCzE2x9M1N0AIn3UZRfVMfLJdI68a67lt3fLh2ZbLcjE0Pi4arBqxzFyKa1LyVsnA1Yg5UCZQh8U9l+5DS5dNS9lDVSBcd9iUio+lg8LvAQ7biz+FFiLSqxVcWDuUg079d8JjPakm4JllmORlnSfWlcTHmgKmQOR0TgtXUL/7EDW2qbmRb5hUttT6ixBKnjtllnXmpOkx8hZn0F0hqjnIUsw8E0SdpYlrvIKszmowoKtZpszL/REVZybhfki5zj22GBMNBBP5MWTkltAZ8x2qu8iUw7MAUkBJy14cWmbqxue95JtT3a2/BnSMofYQNALQM4Ay9iZZyCUJIF/EYxg1OXmv65UthXpc4DdApICObyxY+/OABPJWHtxuG27SmMBx/MT3ZEs6vswVqGIsbPZydVSqerDskkP1AOl4iFEwmGOtfLB+VGn3werrg7IVfbCWEqdA=='), + new X509Certificate( + Base64BinaryValue::fromString('MIIG/DCCBOSgAwIBAgIIU2w5U7TnvlwwDQYJKoZIhvcNAQELBQAwZjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjE3MDUGA1UEAwwuU3RhYXQgZGVyIE5lZGVybGFuZGVuIFByaXZhdGUgU2VydmljZXMgQ0EgLSBHMTAeFw0xNjExMDMxMDM2MTFaFw0yODExMTIwMDAwMDBaMIGAMQswCQYDVQQGEwJOTDEgMB4GA1UECgwXUXVvVmFkaXMgVHJ1c3RsaW5rIEIuVi4xFzAVBgNVBGEMDk5UUk5MLTMwMjM3NDU5MTYwNAYDVQQDDC1RdW9WYWRpcyBQS0lvdmVyaGVpZCBQcml2YXRlIFNlcnZpY2VzIENBIC0gRzEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCo9ep1FEPp6FQIgMT8wD5UoTDQoqkE43vWFx2ur6cxYQFpWXefd0dpdaugwOJ5igIilAoIrd+FdYxbJxQOkrbmkFX1mdW2mAf10+9BW5rn1HvwHG/nvZ8kyaeZuEyEUmVZ+EEFw+7hOru7YPkxA5U7N3IY409xAjiYS3Cti388bLPfE3Ci0Rt2WQlL3jbnSlAty2ZdJ5aCRkL3Cm8wERlwZ0lsLsTIQo1TCw6WfrDgEk+41MvP3eh+0wL3lWPnSPzwvI13Dd5PjT7Pte73oVpqRwgWl+2ZjGD7vwNf14rma3Khuwv74lWWJIr9EHu4miseqVlhk4mFpPC4zsKM6AeXfhZwKLmGAwM54yHw7hjvSPoBilpGiKdIdELMfFzWToSOjMXPQZyHSF5F13sj/hD+YLRBx95QsDa+1xWJq4hv+/t/WPuw1E+s8JYQ/5HKArYfGNMou20skdJyvYW5H+NcZ0guCaF6zdrUDkFv+uI+MkWQMxGw/mwqZX/cW4EC4PPG1j3NEK6/gfU7LT4W/M/GIBC6kJ+L5AJtDIvW8719oIp0UBmhF1nZyQSX6WdaplsM6CNYZ7SSq+kUC4k6Oalzsnv4kNy7ru6yzHoI33V6VXQcs2BevJjbf09YIHoh2cPKPB0nIvRNq9Lvpek0mi5lGzmDj+/DxRySLdPJbzzdCQIDAQABo4IBkTCCAY0wUgYIKwYBBQUHAQEERjBEMEIGCCsGAQUFBzAChjZodHRwOi8vY2VydC5wa2lvdmVyaGVpZC5ubC9Eb21Qcml2YXRlU2VydmljZXNDQS1HMS5jZXIwHQYDVR0OBBYEFLlsphO6uy80Y4MxLvl+SR3fAPVjMBIGA1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0jBBgwFoAUPq+oD4eiLEF7FGwb89to05KnRKgwJQYIKwYBBQUHAQMEGTAXMBUGCCsGAQUFBwsCMAkGBwQAi+xJAQIwXQYDVR0gBFYwVDAMBgpghBABh2sBAggEMAwGCmCEEAGHawECCAUwNgYKYIQQAYdrAQIIBjAoMCYGCCsGAQUFBwIBFhpodHRwczovL2Nwcy5wa2lvdmVyaGVpZC5ubDBNBgNVHR8ERjBEMEKgQKA+hjxodHRwOi8vY3JsLnBraW92ZXJoZWlkLm5sL0RvbVByaXZhdGVTZXJ2aWNlc0xhdGVzdENSTC1HMS5jcmwwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQCM9aEWB9EutS4/TKJ0hSrJljJSt0sAFxkoi6upCv7+C9Pjp+R5woGAwiBctbM5PyT+KpOKlDZKL3mrXSUc/71qNxsPlZR703c+HhlkvDCHbk9afrAXWtXz0sKVs8KaNS2W4k7O8xGNZVMjMwpanQdBcsTnFPu12OTj8BCv4aOFxIYnPqPHkl8VTAi2pTArCtTQk9vi6QaXPzSmfi/rDINCJUAOnA3BEeZZI+BD8yCzE2x9M1N0AIn3UZRfVMfLJdI68a67lt3fLh2ZbLcjE0Pi4arBqxzFyKa1LyVsnA1Yg5UCZQh8U9l+5DS5dNS9lDVSBcd9iUio+lg8LvAQ7biz+FFiLSqxVcWDuUg079d8JjPakm4JllmORlnSfWlcTHmgKmQOR0TgtXUL/7EDW2qbmRb5hUttT6ixBKnjtllnXmpOkx8hZn0F0hqjnIUsw8E0SdpYlrvIKszmowoKtZpszL/REVZybhfki5zj22GBMNBBP5MWTkltAZ8x2qu8iUw7MAUkBJy14cWmbqxue95JtT3a2/BnSMofYQNALQM4Ay9iZZyCUJIF/EYxg1OXmv65UthXpc4DdApICObyxY+/OABPJWHtxuG27SmMBx/MT3ZEs6vswVqGIsbPZydVSqerDskkP1AOl4iFEwmGOtfLB+VGn3werrg7IVfbCWEqdA=='), + ), ], ), ], - 'abc123', + IDValue::fromString('abc123'), ), new KeyInfo( [ new X509Data( [ - new X509Certificate('MIIFhDCCA2ygAwIBAgIEAJimITANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQGEwJOTDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMTMwMQYDVQQDDCpTdGFhdCBkZXIgTmVkZXJsYW5kZW4gUHJpdmF0ZSBSb290IENBIC0gRzEwHhcNMTMxMTE0MTM0ODU1WhcNMjgxMTEzMjMwMDAwWjBiMQswCQYDVQQGEwJOTDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMTMwMQYDVQQDDCpTdGFhdCBkZXIgTmVkZXJsYW5kZW4gUHJpdmF0ZSBSb290IENBIC0gRzEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDaIMh56ynwnEhE7Ey54KpX5j1XDoxbHDCgXctute55RjmG2hy6fuq++q/dCSsj38Pi/KYn/PN13EF05k39IRvakb0AQNVyHifNKXfta6Tzi5QcM4BK09DB4Ckb6TdZTNUtWyEcAtRblYaVSQ4Xr5QODNqu2FGQucraVXqCIx81azlOE2JbZli9AZKn94pP57A11dUYhxMsh70YosJEKVB8Ue4ROksHhb/nnOISG+2y9FD5M8u8jYhp00TGZGVu5z0IFgtqX0i8GmrH0ub9AWjf/iU4MWjGVRSq0cwUHEeKRj/UD9a8xIEn9TxIfYj+6+s4tn9dW/4PV5jc6iGJx6ExTPfOR7VHpxS4XujrZb5Ba/+oj/ONdOfR0JSm2itCytbtjQBBL0oocIIqaqOna1cufHkcn9VleF7Zvz/8njQIpAU4J4nJ4pE5pQ3k4ORAGNnq5R9hAqqUQGDlo3Uj8PBou0nPzQ7JNgGkN+my/lGr4rceUNK/8CoGnYFUH+UyFtJkvlLlEkb688/IdNdGgY+vuXCAB6xfKlJjAGChFUBb6swbNeNctVEdUj7Weg4Jt5gXu78C2mjs9x5lcHOgMO4ZmvYJ3Ejp4k3nNa45HOIVkYrfQrrBHzBhR0BuReAagurcbtUjJFd7BtufGVLfU3CUn1l6u3/9eG4DGH6pq+dSKQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUKv25Kx76w4SHBtuB/4aXdQ3rAYswDQYJKoZIhvcNAQELBQADggIBAEvpmXMOOKdQwUPysrsdIkGJUFF+dvmsJDiOuAqV0A1nNTooL3esvDLEZAWZwKTOwRomnHzeCfS/QxRKTkVX21pfrHf9ufDKykpzjl9uAILTS76FJ6//R0RTIPMrzknQpG2fCLR5DFEbHWU/jWAxGmncfx6HQYl/azHaWbv0dhZOUjPdkGAQ6EPvHcyNU9yMkETdw0X6ioxqzMwkGM893oBrMmtduiqIf3/H6HTXoRKAc+/DXZIq/pAc6eVMa6x43kokluaam9L78yDrlHbGd2VYAr/HZ0TjDZTtI2t2/ySTb7JjC8wL8rSqxYmLpNrnhZzPW87sl2OCFC3re3ZhtJkIHNP85jj1gqewTC7DCW6llZdB3hBzfHWby0EX2RlcwgaMfNBEV5U0IogccdXV+S6zWK4F+yBr0sXUrdbdMFu+g3I9CbXxt0q4eVJtoaun4M2Z+bZMqZvy9FryBdSfhpgmJqwFz2luOhPOVCblCPhLrUeewrvuBXoZQWt1ZjuHfwJZ1dgjszVEqwY9S0SdqCg2ZlL9s3vDIrrd3wLWrcHLQMd9gwsppNv9c7JfIJdlcZLTmF9EuL6eCvVVrqBVqLHjva4erqYol6K/jbSfUtRCy8IlFU7LYu1KLehZKYvj3vekj3Cn08Aqljr/Q8Pw+OfUZTzKg4PVDQVfFqKtyosv'), + new X509Certificate( + Base64BinaryValue::fromString('MIIFhDCCA2ygAwIBAgIEAJimITANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQGEwJOTDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMTMwMQYDVQQDDCpTdGFhdCBkZXIgTmVkZXJsYW5kZW4gUHJpdmF0ZSBSb290IENBIC0gRzEwHhcNMTMxMTE0MTM0ODU1WhcNMjgxMTEzMjMwMDAwWjBiMQswCQYDVQQGEwJOTDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMTMwMQYDVQQDDCpTdGFhdCBkZXIgTmVkZXJsYW5kZW4gUHJpdmF0ZSBSb290IENBIC0gRzEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDaIMh56ynwnEhE7Ey54KpX5j1XDoxbHDCgXctute55RjmG2hy6fuq++q/dCSsj38Pi/KYn/PN13EF05k39IRvakb0AQNVyHifNKXfta6Tzi5QcM4BK09DB4Ckb6TdZTNUtWyEcAtRblYaVSQ4Xr5QODNqu2FGQucraVXqCIx81azlOE2JbZli9AZKn94pP57A11dUYhxMsh70YosJEKVB8Ue4ROksHhb/nnOISG+2y9FD5M8u8jYhp00TGZGVu5z0IFgtqX0i8GmrH0ub9AWjf/iU4MWjGVRSq0cwUHEeKRj/UD9a8xIEn9TxIfYj+6+s4tn9dW/4PV5jc6iGJx6ExTPfOR7VHpxS4XujrZb5Ba/+oj/ONdOfR0JSm2itCytbtjQBBL0oocIIqaqOna1cufHkcn9VleF7Zvz/8njQIpAU4J4nJ4pE5pQ3k4ORAGNnq5R9hAqqUQGDlo3Uj8PBou0nPzQ7JNgGkN+my/lGr4rceUNK/8CoGnYFUH+UyFtJkvlLlEkb688/IdNdGgY+vuXCAB6xfKlJjAGChFUBb6swbNeNctVEdUj7Weg4Jt5gXu78C2mjs9x5lcHOgMO4ZmvYJ3Ejp4k3nNa45HOIVkYrfQrrBHzBhR0BuReAagurcbtUjJFd7BtufGVLfU3CUn1l6u3/9eG4DGH6pq+dSKQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUKv25Kx76w4SHBtuB/4aXdQ3rAYswDQYJKoZIhvcNAQELBQADggIBAEvpmXMOOKdQwUPysrsdIkGJUFF+dvmsJDiOuAqV0A1nNTooL3esvDLEZAWZwKTOwRomnHzeCfS/QxRKTkVX21pfrHf9ufDKykpzjl9uAILTS76FJ6//R0RTIPMrzknQpG2fCLR5DFEbHWU/jWAxGmncfx6HQYl/azHaWbv0dhZOUjPdkGAQ6EPvHcyNU9yMkETdw0X6ioxqzMwkGM893oBrMmtduiqIf3/H6HTXoRKAc+/DXZIq/pAc6eVMa6x43kokluaam9L78yDrlHbGd2VYAr/HZ0TjDZTtI2t2/ySTb7JjC8wL8rSqxYmLpNrnhZzPW87sl2OCFC3re3ZhtJkIHNP85jj1gqewTC7DCW6llZdB3hBzfHWby0EX2RlcwgaMfNBEV5U0IogccdXV+S6zWK4F+yBr0sXUrdbdMFu+g3I9CbXxt0q4eVJtoaun4M2Z+bZMqZvy9FryBdSfhpgmJqwFz2luOhPOVCblCPhLrUeewrvuBXoZQWt1ZjuHfwJZ1dgjszVEqwY9S0SdqCg2ZlL9s3vDIrrd3wLWrcHLQMd9gwsppNv9c7JfIJdlcZLTmF9EuL6eCvVVrqBVqLHjva4erqYol6K/jbSfUtRCy8IlFU7LYu1KLehZKYvj3vekj3Cn08Aqljr/Q8Pw+OfUZTzKg4PVDQVfFqKtyosv'), + ), ], ), ], - 'def456', + IDValue::fromString('def456'), ), ]; - $attr1 = new XMLAttribute('urn:test:something', 'test', 'attr1', 'testval1'); - $keyAuthority = new KeyAuthority($keys, 2, [$attr1]); + $attr1 = new XMLAttribute('urn:test:something', 'test', 'attr1', SAMLStringValue::fromString('testval1')); + $keyAuthority = new KeyAuthority($keys, UnsignedByteValue::fromInteger(2), [$attr1]); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/shibmd/ScopeTest.php b/tests/SAML2/XML/shibmd/ScopeTest.php index 84ef04f5d..e85f34a4f 100644 --- a/tests/SAML2/XML/shibmd/ScopeTest.php +++ b/tests/SAML2/XML/shibmd/ScopeTest.php @@ -7,12 +7,14 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\shibmd\AbstractShibmdElement; use SimpleSAML\SAML2\XML\shibmd\Scope; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XMLSchema\Type\BooleanValue; use function dirname; use function strval; @@ -48,7 +50,10 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $scope = new Scope("example.org", false); + $scope = new Scope( + SAMLStringValue::fromString('example.org'), + BooleanValue::fromBoolean(false), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), @@ -57,35 +62,15 @@ public function testMarshalling(): void } - /** - * Marshalling a scope which does not specificy the value for - * regexp explicitly (expect it to default to 'false'). - */ - public function testMarshallingImplicitRegexpValue(): void - { - $scope = new Scope("example.org"); - - $document = DOMDocumentFactory::fromString(''); - $scopeElement = $scope->toXML($document->documentElement); - - $xpCache = XPath::getXPath($scopeElement); - /** @var \DOMElement[] $scopeElements */ - $scopeElements = XPath::xpQuery($scopeElement, '/root/shibmd:Scope', $xpCache); - $this->assertCount(1, $scopeElements); - $scopeElement = $scopeElements[0]; - - $this->assertEquals('example.org', $scopeElement->nodeValue); - $this->assertEquals('urn:mace:shibboleth:metadata:1.0', $scopeElement->namespaceURI); - $this->assertEquals('false', $scopeElement->getAttribute('regexp')); - } - - /** * Marshalling a scope which is in regexp form. */ public function testMarshallingRegexp(): void { - $scope = new Scope("^(.*\.)?example\.edu$", true); + $scope = new Scope( + SAMLStringValue::fromString('^(.*\.)?example\.edu$'), + BooleanValue::fromBoolean(true), + ); $document = DOMDocumentFactory::fromString(''); $scopeElement = $scope->toXML($document->documentElement); @@ -111,7 +96,7 @@ public function testUnmarshallingWithoutRegexpValue(): void $scope = Scope::fromXML(self::$xmlRepresentation->documentElement); $this->assertEquals('example.org', $scope->getContent()); - $this->assertFalse($scope->isRegexpScope()); + $this->assertFalse($scope->isRegexpScope()->toBoolean()); } @@ -126,6 +111,6 @@ public function testUnmarshallingRegexp(): void $scope = Scope::fromXML($document->documentElement); $this->assertEquals('^(.*|)example.edu$', $scope->getContent()); - $this->assertTrue($scope->isRegexpScope()); + $this->assertTrue($scope->isRegexpScope()->toBoolean()); } } diff --git a/tests/bin/authnrequest.php b/tests/bin/authnrequest.php index 8e936dc1d..9ed20cc05 100644 --- a/tests/bin/authnrequest.php +++ b/tests/bin/authnrequest.php @@ -7,11 +7,15 @@ use DateTimeZone; use SimpleSAML\SAML2\Compat\ContainerSingleton; use SimpleSAML\SAML2\Compat\MockContainer; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\EncryptedID; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\saml\NameID; use SimpleSAML\SAML2\XML\saml\Subject; use SimpleSAML\SAML2\XML\samlp\AuthnRequest; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\Alg\KeyTransport\KeyTransportAlgorithmFactory; use SimpleSAML\XMLSecurity\Constants as C; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; @@ -25,18 +29,18 @@ PEMCertificatesMock::getPublicKey(PEMCertificatesMock::SELFSIGNED_PUBLIC_KEY), ); -$nid = new NameID('very secret'); +$nid = new NameID(SAMLStringValue::fromString('very secret')); $eid = new EncryptedID($nid->encrypt($encryptor)); -$issuer = new Issuer('https://gateway.example.org/saml20/sp/metadata'); +$issuer = new Issuer(SAMLStringValue::fromString('https://gateway.example.org/saml20/sp/metadata')); $subject = new Subject($eid); $authnRequest = new AuthnRequest( subject: $subject, - issueInstant: new DateTimeImmutable('now', new DateTimeZone('Z')), + issueInstant: SAMLDateTimeValue::fromDateTime(new DateTimeImmutable('now', new DateTimeZone('Z'))), issuer: $issuer, - id: '123', - destination: 'https://tiqr.example.org/idp/profile/saml2/Redirect/SSO', + id: IDValue::fromString('123'), + destination: SAMLAnyURIValue::fromString('https://tiqr.example.org/idp/profile/saml2/Redirect/SSO'), ); $authnRequest = $authnRequest->toXML(); diff --git a/tests/bin/encryptedattribute.php b/tests/bin/encryptedattribute.php index 05cbadc2a..bedbfc537 100644 --- a/tests/bin/encryptedattribute.php +++ b/tests/bin/encryptedattribute.php @@ -5,6 +5,7 @@ use SimpleSAML\SAML2\Compat\ContainerSingleton; use SimpleSAML\SAML2\Compat\MockContainer; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\Attribute; use SimpleSAML\SAML2\XML\saml\AttributeValue; use SimpleSAML\SAML2\XML\saml\EncryptedAttribute; @@ -21,8 +22,10 @@ PEMCertificatesMock::getPublicKey(PEMCertificatesMock::PUBLIC_KEY), ); $attribute = new Attribute( - name: 'urn:encrypted:attribute', - attributeValue: [new AttributeValue('very secret data')], + name: SAMLStringValue::fromString('urn:encrypted:attribute'), + attributeValue: [ + new AttributeValue(SAMLStringValue::fromString('very secret data')), + ], ); $encAttribute = new EncryptedAttribute($attribute->encrypt($encryptor)); diff --git a/tests/bin/encryptedid.php b/tests/bin/encryptedid.php index e4060f818..e009b49e0 100644 --- a/tests/bin/encryptedid.php +++ b/tests/bin/encryptedid.php @@ -5,6 +5,7 @@ use SimpleSAML\SAML2\Compat\ContainerSingleton; use SimpleSAML\SAML2\Compat\MockContainer; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\EncryptedID; use SimpleSAML\SAML2\XML\saml\NameID; use SimpleSAML\XMLSecurity\Alg\KeyTransport\KeyTransportAlgorithmFactory; @@ -19,7 +20,7 @@ C::KEY_TRANSPORT_OAEP, PEMCertificatesMock::getPublicKey(PEMCertificatesMock::SELFSIGNED_PUBLIC_KEY), ); -$nid = new NameID('very secret'); +$nid = new NameID(SAMLStringValue::fromString('very secret')); $eid = new EncryptedID($nid->encrypt($encryptor)); echo $eid->toXML()->ownerDocument->saveXML(); diff --git a/tests/bin/entityattributes.php b/tests/bin/entityattributes.php index 3ee164ca5..af7640079 100644 --- a/tests/bin/entityattributes.php +++ b/tests/bin/entityattributes.php @@ -6,6 +6,9 @@ use DateTimeImmutable; use DateTimeZone; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\mdattr\EntityAttributes; use SimpleSAML\SAML2\XML\saml\Assertion; use SimpleSAML\SAML2\XML\saml\Attribute; @@ -17,6 +20,7 @@ use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\saml\NameID; use SimpleSAML\SAML2\XML\saml\Subject; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\Alg\Signature\SignatureAlgorithmFactory; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; @@ -28,45 +32,57 @@ ); $unsignedAssertion = new Assertion( - issuer: new Issuer('urn:x-simplesamlphp:issuer'), - issueInstant: new DateTimeImmutable('now', new DateTimeZone('Z')), - id: '_93af655219464fb403b34436cfb0c5cb1d9a5502', + issuer: new Issuer(SAMLStringValue::fromString('urn:x-simplesamlphp:issuer')), + issueInstant: SAMLDateTimeValue::fromDateTime(new DateTimeImmutable('now', new DateTimeZone('Z'))), + id: IDValue::fromString('_93af655219464fb403b34436cfb0c5cb1d9a5502'), subject: new Subject(new NameID( - value: 'some:entity', - Format: C::NAMEID_ENTITY, + value: SAMLStringValue::fromString('some:entity'), + Format: SAMLAnyURIValue::fromString(C::NAMEID_ENTITY), )), conditions: new Conditions( condition: [], audienceRestriction: [ new AudienceRestriction([ - new Audience('https://simplesamlphp.org/idp/metadata'), - new Audience('urn:x-simplesamlphp:phpunit:entity'), + new Audience(SAMLAnyURIValue::fromString('https://simplesamlphp.org/idp/metadata')), + new Audience(SAMLAnyURIValue::fromString('urn:x-simplesamlphp:phpunit:entity')), ]), ], ), statements: [new AttributeStatement([ new Attribute( - name: 'urn:mace:dir:attribute-def:uid', - nameFormat: C::NAMEFORMAT_URI, - attributeValue: [new AttributeValue('student2')], + name: SAMLStringValue::fromString('urn:mace:dir:attribute-def:uid'), + nameFormat: SAMLAnyURIValue::fromString(C::NAMEFORMAT_URI), + attributeValue: [ + new AttributeValue(SAMLStringValue::fromString('student2')), + ], ), new Attribute( - name: 'urn:mace:terena.org:attribute-def:schacHomeOrganization', - nameFormat: C::NAMEFORMAT_URI, - attributeValue: [new AttributeValue('university.example.org'), new AttributeValue('bbb.cc')], + name: SAMLStringValue::fromString('urn:mace:terena.org:attribute-def:schacHomeOrganization'), + nameFormat: SAMLAnyURIValue::fromString(C::NAMEFORMAT_URI), + attributeValue: [ + new AttributeValue(SAMLStringValue::fromString('university.example.org')), + new AttributeValue(SAMLStringValue::fromString('bbb.cc')), + ], ), new Attribute( - name: 'urn:schac:attribute-def:schacPersonalUniqueCode', - nameFormat: C::NAMEFORMAT_URI, + name: SAMLStringValue::fromString('urn:schac:attribute-def:schacPersonalUniqueCode'), + nameFormat: SAMLAnyURIValue::fromString(C::NAMEFORMAT_URI), attributeValue: [ - new AttributeValue('urn:schac:personalUniqueCode:nl:local:uvt.nl:memberid:524020'), - new AttributeValue('urn:schac:personalUniqueCode:nl:local:surfnet.nl:studentid:12345'), + new AttributeValue( + SAMLStringValue::fromString('urn:schac:personalUniqueCode:nl:local:uvt.nl:memberid:524020'), + ), + new AttributeValue( + SAMLStringValue::fromString('urn:schac:personalUniqueCode:nl:local:surfnet.nl:studentid:12345'), + ), ], ), new Attribute( - name: 'urn:mace:dir:attribute-def:eduPersonAffiliation', - nameFormat: C::NAMEFORMAT_URI, - attributeValue: [new AttributeValue('member'), new AttributeValue('student')], + name: SAMLStringValue::fromString('urn:mace:dir:attribute-def:eduPersonAffiliation'), + nameFormat: SAMLAnyURIValue::fromString(C::NAMEFORMAT_URI), + attributeValue: [ + new AttributeValue(SAMLStringValue::fromString('member')), + new AttributeValue(SAMLStringValue::fromString('student')), + ], ), ])], ); @@ -74,15 +90,23 @@ $signedAssertion = Assertion::fromXML($unsignedAssertion->toXML()); $entityAttributes = new EntityAttributes([ new Attribute( - name: 'attrib1', - nameFormat: C::NAMEFORMAT_BASIC, - attributeValue: [new AttributeValue('is'), new AttributeValue('really'), new AttributeValue('cool')], + name: SAMLStringValue::fromString('attrib1'), + nameFormat: SAMLAnyURIValue::fromString(C::NAMEFORMAT_BASIC), + attributeValue: [ + new AttributeValue(SAMLStringValue::fromString('is')), + new AttributeValue(SAMLStringValue::fromString('really')), + new AttributeValue(SAMLStringValue::fromString('cool')), + ], ), $signedAssertion, new Attribute( - name: 'foo', - nameFormat: 'urn:simplesamlphp:v1:simplesamlphp', - attributeValue: [new AttributeValue('is'), new AttributeValue('really'), new AttributeValue('cool')], + name: SAMLStringValue::fromString('foo'), + nameFormat: SAMLAnyURIValue::fromString('urn:simplesamlphp:v1:simplesamlphp'), + attributeValue: [ + new AttributeValue(SAMLStringValue::fromString('is')), + new AttributeValue(SAMLStringValue::fromString('really')), + new AttributeValue(SAMLStringValue::fromString('cool')), + ], ), ]); diff --git a/tests/bin/logoutrequest.php b/tests/bin/logoutrequest.php index addb3c341..8823ec8d3 100644 --- a/tests/bin/logoutrequest.php +++ b/tests/bin/logoutrequest.php @@ -7,11 +7,14 @@ use DateTimeZone; use SimpleSAML\SAML2\Compat\ContainerSingleton; use SimpleSAML\SAML2\Compat\MockContainer; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\EncryptedID; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\saml\NameID; use SimpleSAML\SAML2\XML\samlp\LogoutRequest; use SimpleSAML\SAML2\XML\samlp\SessionIndex; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\Alg\KeyTransport\KeyTransportAlgorithmFactory; use SimpleSAML\XMLSecurity\Constants as C; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; @@ -24,14 +27,18 @@ C::KEY_TRANSPORT_OAEP, PEMCertificatesMock::getPublicKey(PEMCertificatesMock::SELFSIGNED_PUBLIC_KEY), ); -$nid = new NameID('very secret'); +$nid = new NameID(SAMLStringValue::fromString('very secret')); $eid = new EncryptedID($nid->encrypt($encryptor)); $logoutRequest = new LogoutRequest( + id: IDValue::fromString('abc123'), identifier: $eid, - issueInstant: new DateTimeImmutable('now', new DateTimeZone('Z')), - sessionIndexes: [new SessionIndex('SomeSessionIndex1'), new SessionIndex('SomeSessionIndex2')], - issuer: new Issuer('urn:test:TheIssuer'), + issueInstant: SAMLDateTimeValue::fromDateTime(new DateTimeImmutable('now', new DateTimeZone('Z'))), + sessionIndexes: [ + new SessionIndex(SAMLStringValue::fromString('SomeSessionIndex1')), + new SessionIndex(SAMLStringValue::fromString('SomeSessionIndex2')), + ], + issuer: new Issuer(SAMLStringValue::fromString('urn:test:TheIssuer')), ); $logoutRequest = $logoutRequest->toXML(); diff --git a/tests/bin/signedresponse_with_signedassertion.php b/tests/bin/signedresponse_with_signedassertion.php index 4fe8b0044..51e5bacba 100644 --- a/tests/bin/signedresponse_with_signedassertion.php +++ b/tests/bin/signedresponse_with_signedassertion.php @@ -3,6 +3,9 @@ require_once(dirname(__FILE__, 3) . '/vendor/autoload.php'); +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\Assertion; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\samlp\Response; @@ -10,6 +13,8 @@ use SimpleSAML\SAML2\XML\samlp\StatusCode; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\NCNameValue; use SimpleSAML\XMLSecurity\Alg\Signature\SignatureAlgorithmFactory; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; @@ -24,13 +29,15 @@ $signedAssertion = Assertion::fromXML($unsignedAssertion->toXML()); $unsignedResponse = new Response( - status: new Status(new StatusCode(C::STATUS_SUCCESS)), - issuer: new Issuer('https://IdentityProvider.com'), - issueInstant: new DateTimeImmutable('now', new DateTimeZone('Z')), - id: 'abc123', - inResponseTo: 'PHPUnit', - destination: C::ENTITY_OTHER, - consent: C::ENTITY_SP, + status: new Status( + new StatusCode(SAMLAnyURIValue::fromString(C::STATUS_SUCCESS)), + ), + issuer: new Issuer(SAMLStringValue::fromString('https://IdentityProvider.com')), + issueInstant: SAMLDateTimeValue::fromDateTime(new DateTimeImmutable('now', new DateTimeZone('Z'))), + id: IDValue::fromString('abc123'), + inResponseTo: NCNameValue::fromString('PHPUnit'), + destination: SAMLAnyURIValue::fromString(C::ENTITY_OTHER), + consent: SAMLAnyURIValue::fromString(C::ENTITY_SP), assertions: [$signedAssertion], ); diff --git a/tests/bin/signedresponse_with_unsignedassertion.php b/tests/bin/signedresponse_with_unsignedassertion.php index 344247ee3..d183eb039 100644 --- a/tests/bin/signedresponse_with_unsignedassertion.php +++ b/tests/bin/signedresponse_with_unsignedassertion.php @@ -3,6 +3,9 @@ require_once(dirname(__FILE__, 3) . '/vendor/autoload.php'); +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\Assertion; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\samlp\Response; @@ -10,6 +13,8 @@ use SimpleSAML\SAML2\XML\samlp\StatusCode; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\NCNameValue; use SimpleSAML\XMLSecurity\Alg\Signature\SignatureAlgorithmFactory; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; @@ -17,13 +22,15 @@ $unsignedAssertion = Assertion::fromXML($document->documentElement); $unsignedResponse = new Response( - status: new Status(new StatusCode(C::STATUS_SUCCESS)), - issuer: new Issuer('https://IdentityProvider.com'), - issueInstant: new DateTimeImmutable('now', new DateTimeZone('Z')), - id: 'abc123', - inResponseTo: 'PHPUnit', - destination: C::ENTITY_OTHER, - consent: C::ENTITY_SP, + status: new Status( + new StatusCode(SAMLAnyURIValue::fromString(C::STATUS_SUCCESS)), + ), + issuer: new Issuer(SAMLStringValue::fromString('https://IdentityProvider.com')), + issueInstant: SAMLDateTimeValue::fromDateTime(new DateTimeImmutable('now', new DateTimeZone('Z'))), + id: IDValue::fromString('abc123'), + inResponseTo: NCNameValue::fromString('PHPUnit'), + destination: SAMLAnyURIValue::fromString(C::ENTITY_OTHER), + consent: SAMLAnyURIValue::fromString(C::ENTITY_SP), assertions: [$unsignedAssertion], ); diff --git a/tests/bin/unsignedresponse_with_signedassertion.php b/tests/bin/unsignedresponse_with_signedassertion.php index c1e471559..eacbc51c1 100644 --- a/tests/bin/unsignedresponse_with_signedassertion.php +++ b/tests/bin/unsignedresponse_with_signedassertion.php @@ -3,6 +3,9 @@ require_once(dirname(__FILE__, 3) . '/vendor/autoload.php'); +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\SAML2\XML\saml\Assertion; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\samlp\Response; @@ -10,6 +13,8 @@ use SimpleSAML\SAML2\XML\samlp\StatusCode; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; +use SimpleSAML\XMLSchema\Type\IDValue; +use SimpleSAML\XMLSchema\Type\NCNameValue; use SimpleSAML\XMLSecurity\Alg\Signature\SignatureAlgorithmFactory; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; @@ -26,13 +31,15 @@ $signedAssertion = Assertion::fromXML($unsignedAssertion->toXML()); $unsignedResponse = new Response( - issueInstant: new DateTimeImmutable('now', new DateTimeZone('Z')), - status: new Status(new StatusCode(C::STATUS_SUCCESS)), - issuer: new Issuer('https://IdentityProvider.com'), - id: 'abc123', - inResponseTo: 'PHPUnit', - destination: C::ENTITY_OTHER, - consent: C::ENTITY_SP, + issueInstant: SAMLDateTimeValue::fromDateTime(new DateTimeImmutable('now', new DateTimeZone('Z'))), + status: new Status( + new StatusCode(SAMLAnyURIValue::fromString(C::STATUS_SUCCESS)), + ), + issuer: new Issuer(SAMLStringValue::fromString('https://IdentityProvider.com')), + id: IDValue::fromString('abc123'), + inResponseTo: NCNameValue::fromString('PHPUnit'), + destination: SAMLAnyURIValue::fromString(C::ENTITY_OTHER), + consent: SAMLAnyURIValue::fromString(C::ENTITY_SP), assertions: [$signedAssertion], ); diff --git a/tests/resources/xml/alg_DigestMethod.xml b/tests/resources/xml/alg_DigestMethod.xml index 79d821629..dadda9a23 100644 --- a/tests/resources/xml/alg_DigestMethod.xml +++ b/tests/resources/xml/alg_DigestMethod.xml @@ -1,3 +1,3 @@ - - Some + + Some diff --git a/tests/resources/xml/alg_SigningMethod.xml b/tests/resources/xml/alg_SigningMethod.xml index 484374460..99370b9e2 100644 --- a/tests/resources/xml/alg_SigningMethod.xml +++ b/tests/resources/xml/alg_SigningMethod.xml @@ -1,3 +1,3 @@ - - Some + + Some diff --git a/tests/resources/xml/ecp_RelayState.xml b/tests/resources/xml/ecp_RelayState.xml index d008c399a..f8a04412a 100644 --- a/tests/resources/xml/ecp_RelayState.xml +++ b/tests/resources/xml/ecp_RelayState.xml @@ -1 +1 @@ -AGDY854379dskssda +AGDY854379dskssda diff --git a/tests/resources/xml/ecp_Request.xml b/tests/resources/xml/ecp_Request.xml index 086c06a1d..ad6d79f45 100644 --- a/tests/resources/xml/ecp_Request.xml +++ b/tests/resources/xml/ecp_Request.xml @@ -1,6 +1,6 @@ - - urn:x-simplesamlphp:issuer - + + urn:x-simplesamlphp:issuer + https://some/location diff --git a/tests/resources/xml/ecp_RequestAuthenticated.xml b/tests/resources/xml/ecp_RequestAuthenticated.xml index f42183454..3452e6ec4 100644 --- a/tests/resources/xml/ecp_RequestAuthenticated.xml +++ b/tests/resources/xml/ecp_RequestAuthenticated.xml @@ -1 +1 @@ - + diff --git a/tests/resources/xml/ecp_Response.xml b/tests/resources/xml/ecp_Response.xml index 8fa9a60a2..f2909ce16 100644 --- a/tests/resources/xml/ecp_Response.xml +++ b/tests/resources/xml/ecp_Response.xml @@ -1 +1 @@ - + diff --git a/tests/resources/xml/ecp_SubjectConfirmation.xml b/tests/resources/xml/ecp_SubjectConfirmation.xml index aa3465f75..2fd654bb2 100644 --- a/tests/resources/xml/ecp_SubjectConfirmation.xml +++ b/tests/resources/xml/ecp_SubjectConfirmation.xml @@ -1,6 +1,6 @@ - - - + + + SomeKey Arbitrary Element diff --git a/tests/resources/xml/idpdisc_DiscoveryResponse.xml b/tests/resources/xml/idpdisc_DiscoveryResponse.xml index 7c71dd9c9..643c30045 100644 --- a/tests/resources/xml/idpdisc_DiscoveryResponse.xml +++ b/tests/resources/xml/idpdisc_DiscoveryResponse.xml @@ -1,3 +1,3 @@ - - SomeExtension + + SomeExtension diff --git a/tests/resources/xml/init_RequestInitiator.xml b/tests/resources/xml/init_RequestInitiator.xml index ec1ab8794..c8751ae79 100644 --- a/tests/resources/xml/init_RequestInitiator.xml +++ b/tests/resources/xml/init_RequestInitiator.xml @@ -1,3 +1,3 @@ - - SomeExtension + + SomeExtension diff --git a/tests/resources/xml/md_AffiliationDescriptor.xml b/tests/resources/xml/md_AffiliationDescriptor.xml index f25e01a6b..e8c9e4fb7 100644 --- a/tests/resources/xml/md_AffiliationDescriptor.xml +++ b/tests/resources/xml/md_AffiliationDescriptor.xml @@ -1,8 +1,8 @@ - + https://simplesamlphp.org/sp/metadata https://example.org/metadata - + IdentityProvider.com SSO Key diff --git a/tests/resources/xml/md_ArtifactResolutionService.xml b/tests/resources/xml/md_ArtifactResolutionService.xml index 37b4dbad1..b0e8b7eab 100644 --- a/tests/resources/xml/md_ArtifactResolutionService.xml +++ b/tests/resources/xml/md_ArtifactResolutionService.xml @@ -1,3 +1,3 @@ - - SomeExtension + + SomeExtension diff --git a/tests/resources/xml/md_AssertionConsumerService.xml b/tests/resources/xml/md_AssertionConsumerService.xml index b0551bf00..04c9dc5b3 100644 --- a/tests/resources/xml/md_AssertionConsumerService.xml +++ b/tests/resources/xml/md_AssertionConsumerService.xml @@ -1,3 +1,3 @@ - - SomeExtension + + SomeExtension diff --git a/tests/resources/xml/md_AttributeAuthorityDescriptor.xml b/tests/resources/xml/md_AttributeAuthorityDescriptor.xml index a8e353873..4fb4857b8 100644 --- a/tests/resources/xml/md_AttributeAuthorityDescriptor.xml +++ b/tests/resources/xml/md_AttributeAuthorityDescriptor.xml @@ -1,4 +1,4 @@ - + urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName @@ -6,8 +6,8 @@ urn:oasis:names:tc:SAML:2.0:nameid-format:transient urn:x-simplesamlphp:profile:one urn:x-simplesamlphp:profile:two - - + + member student faculty diff --git a/tests/resources/xml/md_AttributeConsumingService.xml b/tests/resources/xml/md_AttributeConsumingService.xml index d5a8fbfaa..ec7a09cc5 100644 --- a/tests/resources/xml/md_AttributeConsumingService.xml +++ b/tests/resources/xml/md_AttributeConsumingService.xml @@ -1,7 +1,7 @@ - + Academic Journals R US Academic Journals R US and only us - https://ServiceProvider.com/entitlements/123456789 + https://ServiceProvider.com/entitlements/123456789 diff --git a/tests/resources/xml/md_AttributeService.xml b/tests/resources/xml/md_AttributeService.xml index a6851c5ec..e7a2282e6 100644 --- a/tests/resources/xml/md_AttributeService.xml +++ b/tests/resources/xml/md_AttributeService.xml @@ -1,3 +1,3 @@ - - Some + + Some diff --git a/tests/resources/xml/md_ContactPerson.xml b/tests/resources/xml/md_ContactPerson.xml index ec6577916..a541ac018 100644 --- a/tests/resources/xml/md_ContactPerson.xml +++ b/tests/resources/xml/md_ContactPerson.xml @@ -1,6 +1,6 @@ - + - SomeExtension + SomeExtension Test Company John diff --git a/tests/resources/xml/md_EncryptionMethod.xml b/tests/resources/xml/md_EncryptionMethod.xml index 8cfc49077..460b1eb5a 100644 --- a/tests/resources/xml/md_EncryptionMethod.xml +++ b/tests/resources/xml/md_EncryptionMethod.xml @@ -1,5 +1,5 @@ - - 10 - 9lWu3Q== - Value + + 10 + 9lWu3Q== + Value diff --git a/tests/resources/xml/md_EntitiesDescriptor.xml b/tests/resources/xml/md_EntitiesDescriptor.xml index 739531bd9..ff2e9a5e1 100644 --- a/tests/resources/xml/md_EntitiesDescriptor.xml +++ b/tests/resources/xml/md_EntitiesDescriptor.xml @@ -1,6 +1,6 @@ - + - + http://publisher.ra/policy.txt @@ -19,7 +19,7 @@ - + IdentityProvider.com SSO Key @@ -30,8 +30,8 @@ urn:oasis:names:tc:SAML:2.0:nameid-format:transient - - + + member student faculty diff --git a/tests/resources/xml/md_EntityDescriptor.xml b/tests/resources/xml/md_EntityDescriptor.xml index 5e70b5ea6..2049a2743 100644 --- a/tests/resources/xml/md_EntityDescriptor.xml +++ b/tests/resources/xml/md_EntityDescriptor.xml @@ -1,6 +1,6 @@ - + http://publisher.ra/policy.txt diff --git a/tests/resources/xml/md_Extensions.xml b/tests/resources/xml/md_Extensions.xml index 9052cccbd..7086d4d8b 100644 --- a/tests/resources/xml/md_Extensions.xml +++ b/tests/resources/xml/md_Extensions.xml @@ -1,20 +1,20 @@ - - SomeScope - - - + + SomeScope + + + - + Example - - 127.0.0.1 + + 127.0.0.0/8 - + - - + + http://edugain.org/ diff --git a/tests/resources/xml/md_IDPSSODescriptor.xml b/tests/resources/xml/md_IDPSSODescriptor.xml index 2f2338d91..73d13f3bc 100644 --- a/tests/resources/xml/md_IDPSSODescriptor.xml +++ b/tests/resources/xml/md_IDPSSODescriptor.xml @@ -1,6 +1,6 @@ - + - + IdentityProvider.com SSO Key @@ -19,8 +19,8 @@ urn:attribute:profile1 urn:attribute:profile2 - - + + member student faculty diff --git a/tests/resources/xml/md_KeyDescriptor.xml b/tests/resources/xml/md_KeyDescriptor.xml index 4f1f72cdc..ebf656596 100644 --- a/tests/resources/xml/md_KeyDescriptor.xml +++ b/tests/resources/xml/md_KeyDescriptor.xml @@ -1,5 +1,5 @@ - - + + IdentityProvider.com SSO Key diff --git a/tests/resources/xml/md_Organization.xml b/tests/resources/xml/md_Organization.xml index eee992c91..0a83838fb 100644 --- a/tests/resources/xml/md_Organization.xml +++ b/tests/resources/xml/md_Organization.xml @@ -1,6 +1,6 @@ - + - SomeExtension + SomeExtension Identity Providers R US Identity Providers R US, a Division of Lerxst Corp. diff --git a/tests/resources/xml/md_RequestedAttribute.xml b/tests/resources/xml/md_RequestedAttribute.xml index 2cc410a3d..fbbf95ecb 100644 --- a/tests/resources/xml/md_RequestedAttribute.xml +++ b/tests/resources/xml/md_RequestedAttribute.xml @@ -1,3 +1,3 @@ - - value1 + + value1 diff --git a/tests/resources/xml/md_RoleDescriptor.xml b/tests/resources/xml/md_RoleDescriptor.xml index 946c7f5a2..2963a0981 100644 --- a/tests/resources/xml/md_RoleDescriptor.xml +++ b/tests/resources/xml/md_RoleDescriptor.xml @@ -1,14 +1,14 @@ - + Some - + IdentityProvider.com SSO Signing Key - + IdentityProvider.com SSO Encryption Key @@ -18,7 +18,7 @@ Identity Providers R US, a Division of Lerxst Corp. https://IdentityProvider.com - + Test Company John Doe diff --git a/tests/resources/xml/md_SPSSODescriptor.xml b/tests/resources/xml/md_SPSSODescriptor.xml index 81d09f4bb..cc341af21 100644 --- a/tests/resources/xml/md_SPSSODescriptor.xml +++ b/tests/resources/xml/md_SPSSODescriptor.xml @@ -1,11 +1,11 @@ - + - + http://publisher.ra/policy.txt - + ServiceProvider.com SSO Key @@ -27,13 +27,13 @@ Academic Journals R US - https://ServiceProvider.com/entitlements/123456789 + https://ServiceProvider.com/entitlements/123456789 Academic Journals R US - https://ServiceProvider.com/entitlements/123456789 + https://ServiceProvider.com/entitlements/123456789 diff --git a/tests/resources/xml/mdattr_EntityAttributes.xml b/tests/resources/xml/mdattr_EntityAttributes.xml index 10a46f549..5f7ec2d89 100644 --- a/tests/resources/xml/mdattr_EntityAttributes.xml +++ b/tests/resources/xml/mdattr_EntityAttributes.xml @@ -1,10 +1,10 @@ - - + + is really cool - + urn:x-simplesamlphp:issuer diff --git a/tests/resources/xml/mdui_Keywords.xml b/tests/resources/xml/mdui_Keywords.xml index 71e11d66f..482778ac9 100644 --- a/tests/resources/xml/mdui_Keywords.xml +++ b/tests/resources/xml/mdui_Keywords.xml @@ -1 +1 @@ -KLM+koninklijke luchtvaart+maatschappij +KLM koninklijke+luchtvaart+maatschappij diff --git a/tests/resources/xml/mdui_UIInfo.xml b/tests/resources/xml/mdui_UIInfo.xml index bc77554f8..9c90fe3d3 100644 --- a/tests/resources/xml/mdui_UIInfo.xml +++ b/tests/resources/xml/mdui_UIInfo.xml @@ -1,4 +1,4 @@ - + University of Examples Univërsitä øf Exåmpleß Just an example @@ -8,6 +8,6 @@ University Fictional Université Fictif https://example.org/idp/images/logo_87x88.png - - + + diff --git a/tests/resources/xml/saml_Advice.xml b/tests/resources/xml/saml_Advice.xml index 8985f7ad2..739d62886 100644 --- a/tests/resources/xml/saml_Advice.xml +++ b/tests/resources/xml/saml_Advice.xml @@ -1,4 +1,4 @@ - + _Test urn:x-simplesamlphp:reference @@ -23,44 +23,15 @@ - 1 + 1 - 1 + 1 - 1 + 1 - - - - - - - - self::xenc:CipherValue[@Id="example1"] - - - - - - - sNLWjwyj/R0oPwSgNnqowahiOwM0YU3YaH3jsH0t2YUDcHkcgouvW5x6YbNdgvGq0ImsNrkjI//0hrL4HvrOX33+DkhCo2FX5+a7UCdftfBfSjvt0houF8z3Zq/XOm6HxBUbWt5MULYpMKMZ9iAY6+raydxk2tFWgnAyHaBfzvU= - - - - - mlo++g0c4lTsVbL7ArhQh5/xu6t9EuNoRZXF8dqYIq0hARzKiZC5OhTZtHpQlwVd5f4N/lDsur2hhFAu5dxGVdWF+xN4wGMVoQDcyqipwH00w4lO5GNPD16mb1I5l3v3LJf9jKm+090Mv54BPsSOhSYvPBGbv2Uj6LzRE6z0l9zTWtyj2Z7lShrOYR6ZgG254HoltAA6veBXROEdPBBax0ezvoKmOBUcN1RX15Bfj0fVOX1FzS27SX+GCWYgCr0xPnhNBxaMhvU/2ayW6S8A5HWHWb1K2h/VVx6eumXaKzUFoEO5MxfC3Kxni3R3jyaGXmAZ4LhzcpWxJvz9LCpq5+9ovjnRNhheMrtQr/eZ6kWQ12pzKlHCfuFESB0IK2V2NbBDSe6C4n6TAS9mia9tT7CaKsRhVKlNMfkMKC+B6AOkTvlt6Rma5iz/QKL0A7t4LufQ/17YSb3eNOesmV/l3T8bEFqTRHiO8CwiT28ctfDjd0OKB4q1gh0PSidZL/yuaFTG/WXDpnpIV9qZELUgLVjFzW5+Rb/Alv2U7tE68c8oXv7xqmBUhkFQhYBy84cwHrCeKqn2iiJkh19aXYdgAZxys9Dp2+B2wX86coLU2CDJlyyCEohkXn5w8TkU0zNDZnh8J1oz5iawSx1d0aPy+uLNYVUMmx2hcrb3PlWdUApnyts38DcNwTkTy2/uxZmBU/4VGi3JzdnQ7KbW7EUXe3veExb63mRlU+cWl8LMRgP1FExg3CKT6HhW3roTu9GI51ofHpjPCPi41xQvoRrUo2VytBV/IZi4ArD4Y9d2tIcK2O0ZblUNjpRsNhPsVuCDLH23Fx42/5eGVkeTLPOt+Mr6IfY2d1NJGzqz9vJ4/h3L5PelDBQiD/o+5ZvgS5I5HL0bVbGXkT+v6k2GhHQDKNE3qJviXLRPjWv+Eaq+wJhukmcivA1z75/IydZhSPBZfhgORe6n5coiCf2mqiaZpI1YEZRR2g77NXf7I8qAuR7umkEpLC1ciLUpwZjaLNb7ojmC7cogXv8FmcWOk1xWdr7+kY3FXaWWwhUgxO4CSUYGdcOvydybcvAFTnf09+lR0RKVTGgnuukgYROyl8ulY2hoAFm+/jy9qcGqE/7JBlm6qx0B815TZY0aC3ulgwYDvUhdk9Sxq7Dp44h7BMBQezY2o4PBsY6nJNbCAkSULQ1rMY1nZViAAtZntTeHsnlFYm3pJo7MEhrGLYE/nSVcEHuP0z4WpwSb4CW2eOFBmrHcJfqBmDTnFtRwBQZfhQvcSyLy9Vyy//Hj7oDpC6GKmC3m9QTH+9T95sVxhHYkHN10YfHHQhn2pouNzo95QKVVtF98UGMEqrpIbtgGd+CE4icDjq8Qm8iQzJD/DB1YIjpwS0ftoD5+n/YlFYCbbOedN7uxsh9a3Q4NhbkYhNwYQN+/nkr90j6X9PS6uon04TS5GfxpX9gGczxMfeUKHh93in+UksVdzWqgrGxtdXGg7eataR2AcWoTIzsOTWC1sUIi/cOD1N2WR7dMBajNI1vZEsc2+DF3JgfYMigT0sa804LwZNeuopjcgP6qUxL+N+uFO+mobnMZAWK2zBmVwG60psV5zkOShGxq+l+AuobD0pKl0PH4qwhOIUbTc72F2snuKEAJvnpaW2kWymATnbuYsUrpUwoWUmAT4l9o6mD4XGAaYG6YUjD0JJDSJrHKgWy7j5Dqb6ocEMubzOAzpFT6H+BPd09ZraBDLELjX+yYow/adGsGw3sOwDZYfHwM+2f78j8xqCbWgaCME02umAfbkXGbIZ1l7cQv3w0QIDPKreePjI6vMHKJtSsOz9yMwb7RqMf53+m4e+HTlBZEV1m5Dd99qp3ESUYvUEg8rHmx+GeY1KyjZz14AXyxxvepQ4TZFPbROcNvL6EUm4gV7MV+MdkyRznA3nMro5vuGteuEAmqyFGuK/mmTGboA5FDBGnvRGzMt87eJtwWyeaPca7YZttaZJRv2Gbko9T7YNU9bdcJ41m9XC3BApUNQ3nQwWoallQrGX3r862to2Cl7z3MegrSt3GBDCI7RgmBPuEaVAFQQz0Rgr50zBtG834r7/RJ4gQtD0VksO1NoJoM/aifqWjKgRpawOnn2UkztqXEAkTwry04nNkMdLHCegDtl8cqdEAI5kzXMUf7fNxO19eOa+Yc4LYlNIPLOUIw3bGdCjZhhRuP9WR6UpQc69u6zK38e5Sxe+ff+XAdDB9OoH7We+9lRVvrmu4LbtbshctbX5Xz+sIq2xNmQy01xF3UHLUy3hQU1pglo9l5fLD5Nd/1xOs2hu9gaGJFI0efzJvNSHaPuXAvESvT5YBhONh6PfbjHEYuIYXL0ZVtF3cTpW29VXeyA8Uvx9PAxjSbyR/BlF1lTaCotAYCzI2keg6RTK3NCmo3co4t43hNemXPffCwykv4ShU8jdennk167W/6JTmTX7ppmseXimMP9DHnXZEomakUIZComiXxqlnTvw/Xdh9GGWA+6qgS5k68a3hdr2cD1gAKX1T53QCrXbNzpcZ9ab4CaCTv8iFtZaGXOBJjwOXAWZEf3k0I9XQZ3FCeg1Gqs8NgULwfWQTv78208kbsiLOGeu9mGEXgXNyK0yO/U4AWJb+HEfPpfeN3tpHFigzmALzt8RztCKcRv+gKm3RyVEW5 - - - - - - sNLWjwyj/R0oPwSgNnqowahiOwM0YU3YaH3jsH0t2YUDcHkcgouvW5x6YbNdgvGq0ImsNrkjI//0hrL4HvrOX33+DkhCo2FX5+a7UCdftfBfSjvt0houF8z3Zq/XOm6HxBUbWt5MULYpMKMZ9iAY6+raydxk2tFWgnAyHaBfzvU= - - - - Value + Value diff --git a/tests/resources/xml/saml_Assertion.xml b/tests/resources/xml/saml_Assertion.xml index 0f37ccf40..09bacd9f6 100644 --- a/tests/resources/xml/saml_Assertion.xml +++ b/tests/resources/xml/saml_Assertion.xml @@ -1,4 +1,4 @@ - + urn:x-simplesamlphp:issuer SomeNameIDValue @@ -20,13 +20,13 @@ - 1 + 1 - 1 + 1 - 1 + 1 diff --git a/tests/resources/xml/saml_Attribute.xml b/tests/resources/xml/saml_Attribute.xml index 0731d136a..24a90ee6c 100644 --- a/tests/resources/xml/saml_Attribute.xml +++ b/tests/resources/xml/saml_Attribute.xml @@ -1,7 +1,7 @@ - + FirstValue SecondValue - 3 - 2024-04-04T04:44:44Z - + 3 + 2024-04-04T04:44:44Z + diff --git a/tests/resources/xml/saml_AttributeStatement.xml b/tests/resources/xml/saml_AttributeStatement.xml index 30dae3999..070edbbbf 100644 --- a/tests/resources/xml/saml_AttributeStatement.xml +++ b/tests/resources/xml/saml_AttributeStatement.xml @@ -1,11 +1,11 @@ - + - 1 + 1 - 1 + 1 - 1 + 1 diff --git a/tests/resources/xml/saml_AuthnContextWithClassRefAndDecl.xml b/tests/resources/xml/saml_AuthnContextWithClassRefAndDecl.xml index e22eae239..56e11797e 100644 --- a/tests/resources/xml/saml_AuthnContextWithClassRefAndDecl.xml +++ b/tests/resources/xml/saml_AuthnContextWithClassRefAndDecl.xml @@ -1,6 +1,6 @@ - + urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport - + diff --git a/tests/resources/xml/saml_AuthnContextWithDecl.xml b/tests/resources/xml/saml_AuthnContextWithDecl.xml index 42a34fd03..984ed7fd2 100644 --- a/tests/resources/xml/saml_AuthnContextWithDecl.xml +++ b/tests/resources/xml/saml_AuthnContextWithDecl.xml @@ -1,5 +1,5 @@ - - + + diff --git a/tests/resources/xml/saml_AuthzDecisionStatement.xml b/tests/resources/xml/saml_AuthzDecisionStatement.xml index 452810e2d..4f13a8f1f 100644 --- a/tests/resources/xml/saml_AuthzDecisionStatement.xml +++ b/tests/resources/xml/saml_AuthzDecisionStatement.xml @@ -1,4 +1,4 @@ - + SomeAction OtherAction @@ -26,44 +26,15 @@ - 1 + 1 - 1 + 1 - 1 + 1 - - - - - - - - self::xenc:CipherValue[@Id="example1"] - - - - - - - sNLWjwyj/R0oPwSgNnqowahiOwM0YU3YaH3jsH0t2YUDcHkcgouvW5x6YbNdgvGq0ImsNrkjI//0hrL4HvrOX33+DkhCo2FX5+a7UCdftfBfSjvt0houF8z3Zq/XOm6HxBUbWt5MULYpMKMZ9iAY6+raydxk2tFWgnAyHaBfzvU= - - - - - mlo++g0c4lTsVbL7ArhQh5/xu6t9EuNoRZXF8dqYIq0hARzKiZC5OhTZtHpQlwVd5f4N/lDsur2hhFAu5dxGVdWF+xN4wGMVoQDcyqipwH00w4lO5GNPD16mb1I5l3v3LJf9jKm+090Mv54BPsSOhSYvPBGbv2Uj6LzRE6z0l9zTWtyj2Z7lShrOYR6ZgG254HoltAA6veBXROEdPBBax0ezvoKmOBUcN1RX15Bfj0fVOX1FzS27SX+GCWYgCr0xPnhNBxaMhvU/2ayW6S8A5HWHWb1K2h/VVx6eumXaKzUFoEO5MxfC3Kxni3R3jyaGXmAZ4LhzcpWxJvz9LCpq5+9ovjnRNhheMrtQr/eZ6kWQ12pzKlHCfuFESB0IK2V2NbBDSe6C4n6TAS9mia9tT7CaKsRhVKlNMfkMKC+B6AOkTvlt6Rma5iz/QKL0A7t4LufQ/17YSb3eNOesmV/l3T8bEFqTRHiO8CwiT28ctfDjd0OKB4q1gh0PSidZL/yuaFTG/WXDpnpIV9qZELUgLVjFzW5+Rb/Alv2U7tE68c8oXv7xqmBUhkFQhYBy84cwHrCeKqn2iiJkh19aXYdgAZxys9Dp2+B2wX86coLU2CDJlyyCEohkXn5w8TkU0zNDZnh8J1oz5iawSx1d0aPy+uLNYVUMmx2hcrb3PlWdUApnyts38DcNwTkTy2/uxZmBU/4VGi3JzdnQ7KbW7EUXe3veExb63mRlU+cWl8LMRgP1FExg3CKT6HhW3roTu9GI51ofHpjPCPi41xQvoRrUo2VytBV/IZi4ArD4Y9d2tIcK2O0ZblUNjpRsNhPsVuCDLH23Fx42/5eGVkeTLPOt+Mr6IfY2d1NJGzqz9vJ4/h3L5PelDBQiD/o+5ZvgS5I5HL0bVbGXkT+v6k2GhHQDKNE3qJviXLRPjWv+Eaq+wJhukmcivA1z75/IydZhSPBZfhgORe6n5coiCf2mqiaZpI1YEZRR2g77NXf7I8qAuR7umkEpLC1ciLUpwZjaLNb7ojmC7cogXv8FmcWOk1xWdr7+kY3FXaWWwhUgxO4CSUYGdcOvydybcvAFTnf09+lR0RKVTGgnuukgYROyl8ulY2hoAFm+/jy9qcGqE/7JBlm6qx0B815TZY0aC3ulgwYDvUhdk9Sxq7Dp44h7BMBQezY2o4PBsY6nJNbCAkSULQ1rMY1nZViAAtZntTeHsnlFYm3pJo7MEhrGLYE/nSVcEHuP0z4WpwSb4CW2eOFBmrHcJfqBmDTnFtRwBQZfhQvcSyLy9Vyy//Hj7oDpC6GKmC3m9QTH+9T95sVxhHYkHN10YfHHQhn2pouNzo95QKVVtF98UGMEqrpIbtgGd+CE4icDjq8Qm8iQzJD/DB1YIjpwS0ftoD5+n/YlFYCbbOedN7uxsh9a3Q4NhbkYhNwYQN+/nkr90j6X9PS6uon04TS5GfxpX9gGczxMfeUKHh93in+UksVdzWqgrGxtdXGg7eataR2AcWoTIzsOTWC1sUIi/cOD1N2WR7dMBajNI1vZEsc2+DF3JgfYMigT0sa804LwZNeuopjcgP6qUxL+N+uFO+mobnMZAWK2zBmVwG60psV5zkOShGxq+l+AuobD0pKl0PH4qwhOIUbTc72F2snuKEAJvnpaW2kWymATnbuYsUrpUwoWUmAT4l9o6mD4XGAaYG6YUjD0JJDSJrHKgWy7j5Dqb6ocEMubzOAzpFT6H+BPd09ZraBDLELjX+yYow/adGsGw3sOwDZYfHwM+2f78j8xqCbWgaCME02umAfbkXGbIZ1l7cQv3w0QIDPKreePjI6vMHKJtSsOz9yMwb7RqMf53+m4e+HTlBZEV1m5Dd99qp3ESUYvUEg8rHmx+GeY1KyjZz14AXyxxvepQ4TZFPbROcNvL6EUm4gV7MV+MdkyRznA3nMro5vuGteuEAmqyFGuK/mmTGboA5FDBGnvRGzMt87eJtwWyeaPca7YZttaZJRv2Gbko9T7YNU9bdcJ41m9XC3BApUNQ3nQwWoallQrGX3r862to2Cl7z3MegrSt3GBDCI7RgmBPuEaVAFQQz0Rgr50zBtG834r7/RJ4gQtD0VksO1NoJoM/aifqWjKgRpawOnn2UkztqXEAkTwry04nNkMdLHCegDtl8cqdEAI5kzXMUf7fNxO19eOa+Yc4LYlNIPLOUIw3bGdCjZhhRuP9WR6UpQc69u6zK38e5Sxe+ff+XAdDB9OoH7We+9lRVvrmu4LbtbshctbX5Xz+sIq2xNmQy01xF3UHLUy3hQU1pglo9l5fLD5Nd/1xOs2hu9gaGJFI0efzJvNSHaPuXAvESvT5YBhONh6PfbjHEYuIYXL0ZVtF3cTpW29VXeyA8Uvx9PAxjSbyR/BlF1lTaCotAYCzI2keg6RTK3NCmo3co4t43hNemXPffCwykv4ShU8jdennk167W/6JTmTX7ppmseXimMP9DHnXZEomakUIZComiXxqlnTvw/Xdh9GGWA+6qgS5k68a3hdr2cD1gAKX1T53QCrXbNzpcZ9ab4CaCTv8iFtZaGXOBJjwOXAWZEf3k0I9XQZ3FCeg1Gqs8NgULwfWQTv78208kbsiLOGeu9mGEXgXNyK0yO/U4AWJb+HEfPpfeN3tpHFigzmALzt8RztCKcRv+gKm3RyVEW5 - - - - - - sNLWjwyj/R0oPwSgNnqowahiOwM0YU3YaH3jsH0t2YUDcHkcgouvW5x6YbNdgvGq0ImsNrkjI//0hrL4HvrOX33+DkhCo2FX5+a7UCdftfBfSjvt0houF8z3Zq/XOm6HxBUbWt5MULYpMKMZ9iAY6+raydxk2tFWgnAyHaBfzvU= - - - diff --git a/tests/resources/xml/saml_EncryptedAssertion.xml b/tests/resources/xml/saml_EncryptedAssertion.xml index eaa7c7d88..474ecb67f 100644 --- a/tests/resources/xml/saml_EncryptedAssertion.xml +++ b/tests/resources/xml/saml_EncryptedAssertion.xml @@ -1,11 +1,11 @@ - - + + - + - self::xenc:CipherValue[@Id="example1"] + self::xenc:CipherValue[@Id="example1"] @@ -20,7 +20,7 @@ mlo++g0c4lTsVbL7ArhQh5/xu6t9EuNoRZXF8dqYIq0hARzKiZC5OhTZtHpQlwVd5f4N/lDsur2hhFAu5dxGVdWF+xN4wGMVoQDcyqipwH00w4lO5GNPD16mb1I5l3v3LJf9jKm+090Mv54BPsSOhSYvPBGbv2Uj6LzRE6z0l9zTWtyj2Z7lShrOYR6ZgG254HoltAA6veBXROEdPBBax0ezvoKmOBUcN1RX15Bfj0fVOX1FzS27SX+GCWYgCr0xPnhNBxaMhvU/2ayW6S8A5HWHWb1K2h/VVx6eumXaKzUFoEO5MxfC3Kxni3R3jyaGXmAZ4LhzcpWxJvz9LCpq5+9ovjnRNhheMrtQr/eZ6kWQ12pzKlHCfuFESB0IK2V2NbBDSe6C4n6TAS9mia9tT7CaKsRhVKlNMfkMKC+B6AOkTvlt6Rma5iz/QKL0A7t4LufQ/17YSb3eNOesmV/l3T8bEFqTRHiO8CwiT28ctfDjd0OKB4q1gh0PSidZL/yuaFTG/WXDpnpIV9qZELUgLVjFzW5+Rb/Alv2U7tE68c8oXv7xqmBUhkFQhYBy84cwHrCeKqn2iiJkh19aXYdgAZxys9Dp2+B2wX86coLU2CDJlyyCEohkXn5w8TkU0zNDZnh8J1oz5iawSx1d0aPy+uLNYVUMmx2hcrb3PlWdUApnyts38DcNwTkTy2/uxZmBU/4VGi3JzdnQ7KbW7EUXe3veExb63mRlU+cWl8LMRgP1FExg3CKT6HhW3roTu9GI51ofHpjPCPi41xQvoRrUo2VytBV/IZi4ArD4Y9d2tIcK2O0ZblUNjpRsNhPsVuCDLH23Fx42/5eGVkeTLPOt+Mr6IfY2d1NJGzqz9vJ4/h3L5PelDBQiD/o+5ZvgS5I5HL0bVbGXkT+v6k2GhHQDKNE3qJviXLRPjWv+Eaq+wJhukmcivA1z75/IydZhSPBZfhgORe6n5coiCf2mqiaZpI1YEZRR2g77NXf7I8qAuR7umkEpLC1ciLUpwZjaLNb7ojmC7cogXv8FmcWOk1xWdr7+kY3FXaWWwhUgxO4CSUYGdcOvydybcvAFTnf09+lR0RKVTGgnuukgYROyl8ulY2hoAFm+/jy9qcGqE/7JBlm6qx0B815TZY0aC3ulgwYDvUhdk9Sxq7Dp44h7BMBQezY2o4PBsY6nJNbCAkSULQ1rMY1nZViAAtZntTeHsnlFYm3pJo7MEhrGLYE/nSVcEHuP0z4WpwSb4CW2eOFBmrHcJfqBmDTnFtRwBQZfhQvcSyLy9Vyy//Hj7oDpC6GKmC3m9QTH+9T95sVxhHYkHN10YfHHQhn2pouNzo95QKVVtF98UGMEqrpIbtgGd+CE4icDjq8Qm8iQzJD/DB1YIjpwS0ftoD5+n/YlFYCbbOedN7uxsh9a3Q4NhbkYhNwYQN+/nkr90j6X9PS6uon04TS5GfxpX9gGczxMfeUKHh93in+UksVdzWqgrGxtdXGg7eataR2AcWoTIzsOTWC1sUIi/cOD1N2WR7dMBajNI1vZEsc2+DF3JgfYMigT0sa804LwZNeuopjcgP6qUxL+N+uFO+mobnMZAWK2zBmVwG60psV5zkOShGxq+l+AuobD0pKl0PH4qwhOIUbTc72F2snuKEAJvnpaW2kWymATnbuYsUrpUwoWUmAT4l9o6mD4XGAaYG6YUjD0JJDSJrHKgWy7j5Dqb6ocEMubzOAzpFT6H+BPd09ZraBDLELjX+yYow/adGsGw3sOwDZYfHwM+2f78j8xqCbWgaCME02umAfbkXGbIZ1l7cQv3w0QIDPKreePjI6vMHKJtSsOz9yMwb7RqMf53+m4e+HTlBZEV1m5Dd99qp3ESUYvUEg8rHmx+GeY1KyjZz14AXyxxvepQ4TZFPbROcNvL6EUm4gV7MV+MdkyRznA3nMro5vuGteuEAmqyFGuK/mmTGboA5FDBGnvRGzMt87eJtwWyeaPca7YZttaZJRv2Gbko9T7YNU9bdcJ41m9XC3BApUNQ3nQwWoallQrGX3r862to2Cl7z3MegrSt3GBDCI7RgmBPuEaVAFQQz0Rgr50zBtG834r7/RJ4gQtD0VksO1NoJoM/aifqWjKgRpawOnn2UkztqXEAkTwry04nNkMdLHCegDtl8cqdEAI5kzXMUf7fNxO19eOa+Yc4LYlNIPLOUIw3bGdCjZhhRuP9WR6UpQc69u6zK38e5Sxe+ff+XAdDB9OoH7We+9lRVvrmu4LbtbshctbX5Xz+sIq2xNmQy01xF3UHLUy3hQU1pglo9l5fLD5Nd/1xOs2hu9gaGJFI0efzJvNSHaPuXAvESvT5YBhONh6PfbjHEYuIYXL0ZVtF3cTpW29VXeyA8Uvx9PAxjSbyR/BlF1lTaCotAYCzI2keg6RTK3NCmo3co4t43hNemXPffCwykv4ShU8jdennk167W/6JTmTX7ppmseXimMP9DHnXZEomakUIZComiXxqlnTvw/Xdh9GGWA+6qgS5k68a3hdr2cD1gAKX1T53QCrXbNzpcZ9ab4CaCTv8iFtZaGXOBJjwOXAWZEf3k0I9XQZ3FCeg1Gqs8NgULwfWQTv78208kbsiLOGeu9mGEXgXNyK0yO/U4AWJb+HEfPpfeN3tpHFigzmALzt8RztCKcRv+gKm3RyVEW5 - + sNLWjwyj/R0oPwSgNnqowahiOwM0YU3YaH3jsH0t2YUDcHkcgouvW5x6YbNdgvGq0ImsNrkjI//0hrL4HvrOX33+DkhCo2FX5+a7UCdftfBfSjvt0houF8z3Zq/XOm6HxBUbWt5MULYpMKMZ9iAY6+raydxk2tFWgnAyHaBfzvU= diff --git a/tests/resources/xml/saml_EncryptedAttribute.xml b/tests/resources/xml/saml_EncryptedAttribute.xml index 9832ff775..a6cd45e55 100644 --- a/tests/resources/xml/saml_EncryptedAttribute.xml +++ b/tests/resources/xml/saml_EncryptedAttribute.xml @@ -1,7 +1,7 @@ - - + + - + @@ -13,7 +13,7 @@ 1XgQwRaembYBgx/L+EtbKy8L/C09Jyp6RMPkuMNddV6PP2+ZeX+brAftzEB1j9BbjqmSHIQU85E6Up37Naeh1VNn6KTyv1r4S1oa8AJu6P4++MdRGkifWUhgqsfLdUZFiMAF5tnLor4dU/Iqr3+iWYUIbsCUkZh2uSfuYqCsVgZlJsXY2tlDgdMtbWTMGWl+Z6oP0Y83+ygo8k05uVkhYctbAThfi7daSclsna5F4PzIycdtowyzpmjVrO5t3qmUzPOiljJx1sMJFOdDcbM= - + OrBjuSpU4nnUeh4p3iBW82E0W7xVQEdELUi+PpHkpH6LcPQJBj4sLOSuzBNTmbo4cGouP3H5oyBcbILKFA2fYEAc8r17WHFD5NbWjTesWJWoH2E2vYmIdqi31109tiI55mDNGbWm02YHbz3opgmyZB6ABoj/1vHshZaWtDlDIbY= diff --git a/tests/resources/xml/saml_EncryptedID.xml b/tests/resources/xml/saml_EncryptedID.xml index 5dba50768..1a1e95e47 100644 --- a/tests/resources/xml/saml_EncryptedID.xml +++ b/tests/resources/xml/saml_EncryptedID.xml @@ -1,7 +1,7 @@ - - + + - + @@ -13,7 +13,7 @@ 720FAxwOXcv8ast9YvQutUoue+YA2FgLLNaD/FZrWiNexTkPyZ8CWrcf2zZj2zrOwTjQ9KJvzvCuzq4fM51sU1boOakLpz05NonDdMgeWW/eWcOJJfOZs0tYvYc5qZ/R+BzRnJsGG6w2ZmipEi88X/8uA85c - + he5ZBjtfp/1/Y3PgE/CWspDPADig9vuZ7yZyYXDQ1wA/HBTPCldtL/p6UT5RCAFYUwN6kp3jnHkhK1yMjrI1SMw0n5NEc2wO9N5inQIeQOZ8XD9yD9M5fHvWz2ByNMGlB35RWMnBRHzDi1PRV7Irwcs9WoiODh3i6j2vYXP7cAo= diff --git a/tests/resources/xml/saml_Evidence.xml b/tests/resources/xml/saml_Evidence.xml index 60c25c4c9..0b87c4fd4 100644 --- a/tests/resources/xml/saml_Evidence.xml +++ b/tests/resources/xml/saml_Evidence.xml @@ -1,4 +1,4 @@ - + _Test urn:x-simplesamlphp:reference @@ -23,27 +23,20 @@ - 1 + 1 - 1 + 1 - 1 + 1 - + - - - - - self::xenc:CipherValue[@Id="example1"] - - - + @@ -55,7 +48,7 @@ mlo++g0c4lTsVbL7ArhQh5/xu6t9EuNoRZXF8dqYIq0hARzKiZC5OhTZtHpQlwVd5f4N/lDsur2hhFAu5dxGVdWF+xN4wGMVoQDcyqipwH00w4lO5GNPD16mb1I5l3v3LJf9jKm+090Mv54BPsSOhSYvPBGbv2Uj6LzRE6z0l9zTWtyj2Z7lShrOYR6ZgG254HoltAA6veBXROEdPBBax0ezvoKmOBUcN1RX15Bfj0fVOX1FzS27SX+GCWYgCr0xPnhNBxaMhvU/2ayW6S8A5HWHWb1K2h/VVx6eumXaKzUFoEO5MxfC3Kxni3R3jyaGXmAZ4LhzcpWxJvz9LCpq5+9ovjnRNhheMrtQr/eZ6kWQ12pzKlHCfuFESB0IK2V2NbBDSe6C4n6TAS9mia9tT7CaKsRhVKlNMfkMKC+B6AOkTvlt6Rma5iz/QKL0A7t4LufQ/17YSb3eNOesmV/l3T8bEFqTRHiO8CwiT28ctfDjd0OKB4q1gh0PSidZL/yuaFTG/WXDpnpIV9qZELUgLVjFzW5+Rb/Alv2U7tE68c8oXv7xqmBUhkFQhYBy84cwHrCeKqn2iiJkh19aXYdgAZxys9Dp2+B2wX86coLU2CDJlyyCEohkXn5w8TkU0zNDZnh8J1oz5iawSx1d0aPy+uLNYVUMmx2hcrb3PlWdUApnyts38DcNwTkTy2/uxZmBU/4VGi3JzdnQ7KbW7EUXe3veExb63mRlU+cWl8LMRgP1FExg3CKT6HhW3roTu9GI51ofHpjPCPi41xQvoRrUo2VytBV/IZi4ArD4Y9d2tIcK2O0ZblUNjpRsNhPsVuCDLH23Fx42/5eGVkeTLPOt+Mr6IfY2d1NJGzqz9vJ4/h3L5PelDBQiD/o+5ZvgS5I5HL0bVbGXkT+v6k2GhHQDKNE3qJviXLRPjWv+Eaq+wJhukmcivA1z75/IydZhSPBZfhgORe6n5coiCf2mqiaZpI1YEZRR2g77NXf7I8qAuR7umkEpLC1ciLUpwZjaLNb7ojmC7cogXv8FmcWOk1xWdr7+kY3FXaWWwhUgxO4CSUYGdcOvydybcvAFTnf09+lR0RKVTGgnuukgYROyl8ulY2hoAFm+/jy9qcGqE/7JBlm6qx0B815TZY0aC3ulgwYDvUhdk9Sxq7Dp44h7BMBQezY2o4PBsY6nJNbCAkSULQ1rMY1nZViAAtZntTeHsnlFYm3pJo7MEhrGLYE/nSVcEHuP0z4WpwSb4CW2eOFBmrHcJfqBmDTnFtRwBQZfhQvcSyLy9Vyy//Hj7oDpC6GKmC3m9QTH+9T95sVxhHYkHN10YfHHQhn2pouNzo95QKVVtF98UGMEqrpIbtgGd+CE4icDjq8Qm8iQzJD/DB1YIjpwS0ftoD5+n/YlFYCbbOedN7uxsh9a3Q4NhbkYhNwYQN+/nkr90j6X9PS6uon04TS5GfxpX9gGczxMfeUKHh93in+UksVdzWqgrGxtdXGg7eataR2AcWoTIzsOTWC1sUIi/cOD1N2WR7dMBajNI1vZEsc2+DF3JgfYMigT0sa804LwZNeuopjcgP6qUxL+N+uFO+mobnMZAWK2zBmVwG60psV5zkOShGxq+l+AuobD0pKl0PH4qwhOIUbTc72F2snuKEAJvnpaW2kWymATnbuYsUrpUwoWUmAT4l9o6mD4XGAaYG6YUjD0JJDSJrHKgWy7j5Dqb6ocEMubzOAzpFT6H+BPd09ZraBDLELjX+yYow/adGsGw3sOwDZYfHwM+2f78j8xqCbWgaCME02umAfbkXGbIZ1l7cQv3w0QIDPKreePjI6vMHKJtSsOz9yMwb7RqMf53+m4e+HTlBZEV1m5Dd99qp3ESUYvUEg8rHmx+GeY1KyjZz14AXyxxvepQ4TZFPbROcNvL6EUm4gV7MV+MdkyRznA3nMro5vuGteuEAmqyFGuK/mmTGboA5FDBGnvRGzMt87eJtwWyeaPca7YZttaZJRv2Gbko9T7YNU9bdcJ41m9XC3BApUNQ3nQwWoallQrGX3r862to2Cl7z3MegrSt3GBDCI7RgmBPuEaVAFQQz0Rgr50zBtG834r7/RJ4gQtD0VksO1NoJoM/aifqWjKgRpawOnn2UkztqXEAkTwry04nNkMdLHCegDtl8cqdEAI5kzXMUf7fNxO19eOa+Yc4LYlNIPLOUIw3bGdCjZhhRuP9WR6UpQc69u6zK38e5Sxe+ff+XAdDB9OoH7We+9lRVvrmu4LbtbshctbX5Xz+sIq2xNmQy01xF3UHLUy3hQU1pglo9l5fLD5Nd/1xOs2hu9gaGJFI0efzJvNSHaPuXAvESvT5YBhONh6PfbjHEYuIYXL0ZVtF3cTpW29VXeyA8Uvx9PAxjSbyR/BlF1lTaCotAYCzI2keg6RTK3NCmo3co4t43hNemXPffCwykv4ShU8jdennk167W/6JTmTX7ppmseXimMP9DHnXZEomakUIZComiXxqlnTvw/Xdh9GGWA+6qgS5k68a3hdr2cD1gAKX1T53QCrXbNzpcZ9ab4CaCTv8iFtZaGXOBJjwOXAWZEf3k0I9XQZ3FCeg1Gqs8NgULwfWQTv78208kbsiLOGeu9mGEXgXNyK0yO/U4AWJb+HEfPpfeN3tpHFigzmALzt8RztCKcRv+gKm3RyVEW5 - + sNLWjwyj/R0oPwSgNnqowahiOwM0YU3YaH3jsH0t2YUDcHkcgouvW5x6YbNdgvGq0ImsNrkjI//0hrL4HvrOX33+DkhCo2FX5+a7UCdftfBfSjvt0houF8z3Zq/XOm6HxBUbWt5MULYpMKMZ9iAY6+raydxk2tFWgnAyHaBfzvU= diff --git a/tests/resources/xml/saml_Subject.xml b/tests/resources/xml/saml_Subject.xml index 531c54991..afde1cb41 100644 --- a/tests/resources/xml/saml_Subject.xml +++ b/tests/resources/xml/saml_Subject.xml @@ -1,9 +1,9 @@ - + SomeNameIDValue SomeOtherNameIDValue - - + + SomeKey Arbitrary Element diff --git a/tests/resources/xml/saml_SubjectConfirmation.xml b/tests/resources/xml/saml_SubjectConfirmation.xml index 0e1c7c8ae..4851272cb 100644 --- a/tests/resources/xml/saml_SubjectConfirmation.xml +++ b/tests/resources/xml/saml_SubjectConfirmation.xml @@ -1,7 +1,7 @@ - + SomeNameIDValue - + SomeKey Arbitrary Element diff --git a/tests/resources/xml/saml_SubjectConfirmationData.xml b/tests/resources/xml/saml_SubjectConfirmationData.xml index 198fb2b26..c8e7400da 100644 --- a/tests/resources/xml/saml_SubjectConfirmationData.xml +++ b/tests/resources/xml/saml_SubjectConfirmationData.xml @@ -1,5 +1,5 @@ - - + + SomeKey Arbitrary Element diff --git a/tests/resources/xml/samlp_AttributeQuery.xml b/tests/resources/xml/samlp_AttributeQuery.xml index af91a1b96..724a74db8 100644 --- a/tests/resources/xml/samlp_AttributeQuery.xml +++ b/tests/resources/xml/samlp_AttributeQuery.xml @@ -1,4 +1,4 @@ - + https://example.org/ urn:example:subject @@ -14,7 +14,7 @@ - 4 - 23 + 4 + 23 diff --git a/tests/resources/xml/samlp_AuthzDecisionQuery.xml b/tests/resources/xml/samlp_AuthzDecisionQuery.xml index 54bdd11e4..1be1cd0bd 100644 --- a/tests/resources/xml/samlp_AuthzDecisionQuery.xml +++ b/tests/resources/xml/samlp_AuthzDecisionQuery.xml @@ -1,4 +1,4 @@ - + https://example.org/ urn:example:subject @@ -28,13 +28,13 @@ - 1 + 1 - 1 + 1 - 1 + 1 diff --git a/tests/resources/xml/samlp_Extensions.xml b/tests/resources/xml/samlp_Extensions.xml index 17fd9c9d5..e47a70f44 100644 --- a/tests/resources/xml/samlp_Extensions.xml +++ b/tests/resources/xml/samlp_Extensions.xml @@ -1,6 +1,6 @@ - - + + - + diff --git a/tests/resources/xml/samlp_LogoutRequest.xml b/tests/resources/xml/samlp_LogoutRequest.xml index 2b4345bed..cba9fe6ad 100644 --- a/tests/resources/xml/samlp_LogoutRequest.xml +++ b/tests/resources/xml/samlp_LogoutRequest.xml @@ -1,9 +1,9 @@ - + urn:x-simplesamlphp:issuer - + - + @@ -15,7 +15,7 @@ MN9qX/dEA1oXIS9Dowjhax2cWTZ88ADKpnZ7zI/okqlqpu7okUf/HACkh+hwo5r+BZSyE06RITOAhFBczwjJsZVBwbf/cUb7JjD0pMvywWkEhNoak4OTA5RVXo96bqoRL6co6Bz3GOJBmTUEnXUZATyWcazf - + grf3DVcVDV8EVCbfl9+jf6XX6gNjGSTenPqCAQhztFP6YJ3o6BS3XVbilA08CEBx0ci9PDfAsQKDl6fyBMgVSoL17zvJhNpyC7XCniIyCskUv0WmT9xCuIDNzEMZy5InunKf3KRtCRJGQzdjkoxRY3Q8Qczm2x2UoEVfzlpj2n8= diff --git a/tests/resources/xml/samlp_RequestedAuthnContext.xml b/tests/resources/xml/samlp_RequestedAuthnContext.xml index 8f0640f44..254a54c2a 100644 --- a/tests/resources/xml/samlp_RequestedAuthnContext.xml +++ b/tests/resources/xml/samlp_RequestedAuthnContext.xml @@ -1,3 +1,3 @@ - - https://example.org/relative/path/to/document.xml + + https://example.org/relative/path/to/document.xml diff --git a/tests/resources/xml/samlp_Response.xml b/tests/resources/xml/samlp_Response.xml index 6bbfab336..5e9ee8968 100644 --- a/tests/resources/xml/samlp_Response.xml +++ b/tests/resources/xml/samlp_Response.xml @@ -1,9 +1,9 @@ - + https://IdentityProvider.com - + urn:x-simplesamlphp:issuer SomeNameIDValue @@ -25,13 +25,13 @@ - 1 + 1 - 1 + 1 - 1 + 1 diff --git a/tests/resources/xml/samlp_Status.xml b/tests/resources/xml/samlp_Status.xml index 0ac60c75d..67cbdb82e 100644 --- a/tests/resources/xml/samlp_Status.xml +++ b/tests/resources/xml/samlp_Status.xml @@ -1,9 +1,9 @@ - + Something went wrong - org.sourceid.websso.profiles.idp.FailedAuthnSsoException + org.sourceid.websso.profiles.idp.FailedAuthnSsoException diff --git a/tests/resources/xml/samlp_StatusDetail.xml b/tests/resources/xml/samlp_StatusDetail.xml index 5654a3454..5ed94b7ac 100644 --- a/tests/resources/xml/samlp_StatusDetail.xml +++ b/tests/resources/xml/samlp_StatusDetail.xml @@ -1,3 +1,3 @@ - - org.sourceid.websso.profiles.idp.FailedAuthnSsoException + + org.sourceid.websso.profiles.idp.FailedAuthnSsoException diff --git a/tests/resources/xml/shibmd_KeyAuthority.xml b/tests/resources/xml/shibmd_KeyAuthority.xml index 941a29696..52efbfa3f 100644 --- a/tests/resources/xml/shibmd_KeyAuthority.xml +++ b/tests/resources/xml/shibmd_KeyAuthority.xml @@ -1,10 +1,10 @@ - - + + MIIG/DCCBOSgAwIBAgIIU2w5U7TnvlwwDQYJKoZIhvcNAQELBQAwZjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjE3MDUGA1UEAwwuU3RhYXQgZGVyIE5lZGVybGFuZGVuIFByaXZhdGUgU2VydmljZXMgQ0EgLSBHMTAeFw0xNjExMDMxMDM2MTFaFw0yODExMTIwMDAwMDBaMIGAMQswCQYDVQQGEwJOTDEgMB4GA1UECgwXUXVvVmFkaXMgVHJ1c3RsaW5rIEIuVi4xFzAVBgNVBGEMDk5UUk5MLTMwMjM3NDU5MTYwNAYDVQQDDC1RdW9WYWRpcyBQS0lvdmVyaGVpZCBQcml2YXRlIFNlcnZpY2VzIENBIC0gRzEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCo9ep1FEPp6FQIgMT8wD5UoTDQoqkE43vWFx2ur6cxYQFpWXefd0dpdaugwOJ5igIilAoIrd+FdYxbJxQOkrbmkFX1mdW2mAf10+9BW5rn1HvwHG/nvZ8kyaeZuEyEUmVZ+EEFw+7hOru7YPkxA5U7N3IY409xAjiYS3Cti388bLPfE3Ci0Rt2WQlL3jbnSlAty2ZdJ5aCRkL3Cm8wERlwZ0lsLsTIQo1TCw6WfrDgEk+41MvP3eh+0wL3lWPnSPzwvI13Dd5PjT7Pte73oVpqRwgWl+2ZjGD7vwNf14rma3Khuwv74lWWJIr9EHu4miseqVlhk4mFpPC4zsKM6AeXfhZwKLmGAwM54yHw7hjvSPoBilpGiKdIdELMfFzWToSOjMXPQZyHSF5F13sj/hD+YLRBx95QsDa+1xWJq4hv+/t/WPuw1E+s8JYQ/5HKArYfGNMou20skdJyvYW5H+NcZ0guCaF6zdrUDkFv+uI+MkWQMxGw/mwqZX/cW4EC4PPG1j3NEK6/gfU7LT4W/M/GIBC6kJ+L5AJtDIvW8719oIp0UBmhF1nZyQSX6WdaplsM6CNYZ7SSq+kUC4k6Oalzsnv4kNy7ru6yzHoI33V6VXQcs2BevJjbf09YIHoh2cPKPB0nIvRNq9Lvpek0mi5lGzmDj+/DxRySLdPJbzzdCQIDAQABo4IBkTCCAY0wUgYIKwYBBQUHAQEERjBEMEIGCCsGAQUFBzAChjZodHRwOi8vY2VydC5wa2lvdmVyaGVpZC5ubC9Eb21Qcml2YXRlU2VydmljZXNDQS1HMS5jZXIwHQYDVR0OBBYEFLlsphO6uy80Y4MxLvl+SR3fAPVjMBIGA1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0jBBgwFoAUPq+oD4eiLEF7FGwb89to05KnRKgwJQYIKwYBBQUHAQMEGTAXMBUGCCsGAQUFBwsCMAkGBwQAi+xJAQIwXQYDVR0gBFYwVDAMBgpghBABh2sBAggEMAwGCmCEEAGHawECCAUwNgYKYIQQAYdrAQIIBjAoMCYGCCsGAQUFBwIBFhpodHRwczovL2Nwcy5wa2lvdmVyaGVpZC5ubDBNBgNVHR8ERjBEMEKgQKA+hjxodHRwOi8vY3JsLnBraW92ZXJoZWlkLm5sL0RvbVByaXZhdGVTZXJ2aWNlc0xhdGVzdENSTC1HMS5jcmwwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQCM9aEWB9EutS4/TKJ0hSrJljJSt0sAFxkoi6upCv7+C9Pjp+R5woGAwiBctbM5PyT+KpOKlDZKL3mrXSUc/71qNxsPlZR703c+HhlkvDCHbk9afrAXWtXz0sKVs8KaNS2W4k7O8xGNZVMjMwpanQdBcsTnFPu12OTj8BCv4aOFxIYnPqPHkl8VTAi2pTArCtTQk9vi6QaXPzSmfi/rDINCJUAOnA3BEeZZI+BD8yCzE2x9M1N0AIn3UZRfVMfLJdI68a67lt3fLh2ZbLcjE0Pi4arBqxzFyKa1LyVsnA1Yg5UCZQh8U9l+5DS5dNS9lDVSBcd9iUio+lg8LvAQ7biz+FFiLSqxVcWDuUg079d8JjPakm4JllmORlnSfWlcTHmgKmQOR0TgtXUL/7EDW2qbmRb5hUttT6ixBKnjtllnXmpOkx8hZn0F0hqjnIUsw8E0SdpYlrvIKszmowoKtZpszL/REVZybhfki5zj22GBMNBBP5MWTkltAZ8x2qu8iUw7MAUkBJy14cWmbqxue95JtT3a2/BnSMofYQNALQM4Ay9iZZyCUJIF/EYxg1OXmv65UthXpc4DdApICObyxY+/OABPJWHtxuG27SmMBx/MT3ZEs6vswVqGIsbPZydVSqerDskkP1AOl4iFEwmGOtfLB+VGn3werrg7IVfbCWEqdA== - + MIIFhDCCA2ygAwIBAgIEAJimITANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQGEwJOTDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMTMwMQYDVQQDDCpTdGFhdCBkZXIgTmVkZXJsYW5kZW4gUHJpdmF0ZSBSb290IENBIC0gRzEwHhcNMTMxMTE0MTM0ODU1WhcNMjgxMTEzMjMwMDAwWjBiMQswCQYDVQQGEwJOTDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMTMwMQYDVQQDDCpTdGFhdCBkZXIgTmVkZXJsYW5kZW4gUHJpdmF0ZSBSb290IENBIC0gRzEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDaIMh56ynwnEhE7Ey54KpX5j1XDoxbHDCgXctute55RjmG2hy6fuq++q/dCSsj38Pi/KYn/PN13EF05k39IRvakb0AQNVyHifNKXfta6Tzi5QcM4BK09DB4Ckb6TdZTNUtWyEcAtRblYaVSQ4Xr5QODNqu2FGQucraVXqCIx81azlOE2JbZli9AZKn94pP57A11dUYhxMsh70YosJEKVB8Ue4ROksHhb/nnOISG+2y9FD5M8u8jYhp00TGZGVu5z0IFgtqX0i8GmrH0ub9AWjf/iU4MWjGVRSq0cwUHEeKRj/UD9a8xIEn9TxIfYj+6+s4tn9dW/4PV5jc6iGJx6ExTPfOR7VHpxS4XujrZb5Ba/+oj/ONdOfR0JSm2itCytbtjQBBL0oocIIqaqOna1cufHkcn9VleF7Zvz/8njQIpAU4J4nJ4pE5pQ3k4ORAGNnq5R9hAqqUQGDlo3Uj8PBou0nPzQ7JNgGkN+my/lGr4rceUNK/8CoGnYFUH+UyFtJkvlLlEkb688/IdNdGgY+vuXCAB6xfKlJjAGChFUBb6swbNeNctVEdUj7Weg4Jt5gXu78C2mjs9x5lcHOgMO4ZmvYJ3Ejp4k3nNa45HOIVkYrfQrrBHzBhR0BuReAagurcbtUjJFd7BtufGVLfU3CUn1l6u3/9eG4DGH6pq+dSKQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUKv25Kx76w4SHBtuB/4aXdQ3rAYswDQYJKoZIhvcNAQELBQADggIBAEvpmXMOOKdQwUPysrsdIkGJUFF+dvmsJDiOuAqV0A1nNTooL3esvDLEZAWZwKTOwRomnHzeCfS/QxRKTkVX21pfrHf9ufDKykpzjl9uAILTS76FJ6//R0RTIPMrzknQpG2fCLR5DFEbHWU/jWAxGmncfx6HQYl/azHaWbv0dhZOUjPdkGAQ6EPvHcyNU9yMkETdw0X6ioxqzMwkGM893oBrMmtduiqIf3/H6HTXoRKAc+/DXZIq/pAc6eVMa6x43kokluaam9L78yDrlHbGd2VYAr/HZ0TjDZTtI2t2/ySTb7JjC8wL8rSqxYmLpNrnhZzPW87sl2OCFC3re3ZhtJkIHNP85jj1gqewTC7DCW6llZdB3hBzfHWby0EX2RlcwgaMfNBEV5U0IogccdXV+S6zWK4F+yBr0sXUrdbdMFu+g3I9CbXxt0q4eVJtoaun4M2Z+bZMqZvy9FryBdSfhpgmJqwFz2luOhPOVCblCPhLrUeewrvuBXoZQWt1ZjuHfwJZ1dgjszVEqwY9S0SdqCg2ZlL9s3vDIrrd3wLWrcHLQMd9gwsppNv9c7JfIJdlcZLTmF9EuL6eCvVVrqBVqLHjva4erqYol6K/jbSfUtRCy8IlFU7LYu1KLehZKYvj3vekj3Cn08Aqljr/Q8Pw+OfUZTzKg4PVDQVfFqKtyosv