diff --git a/.github/workflows/interoperability.yml b/.github/workflows/interoperability.yml index d229ed4c1..39312adac 100644 --- a/.github/workflows/interoperability.yml +++ b/.github/workflows/interoperability.yml @@ -23,7 +23,7 @@ jobs: fail-fast: false matrix: operating-system: [ubuntu-latest] - php-versions: ['8.2'] + php-versions: ['8.4'] steps: - name: Setup PHP, with composer and extensions @@ -80,8 +80,14 @@ jobs: run: | mkdir -p /tmp/metadata wget https://mds.edugain.org/edugain-v2.xml -O /tmp/metadata/edugain.xml - wget https://technical.edugain.org/mds-v2.cer -O /tmp/metadataedugain-pub.crt + 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 GRNET metadata if: steps.cache-metadata.outputs.cache-hit != 'true' diff --git a/composer.json b/composer.json index a030cc04a..f5c7f6508 100644 --- a/composer.json +++ b/composer.json @@ -32,9 +32,9 @@ "psr/http-message": "^2.0", "psr/log": "^2.0 || ^3.0", "simplesamlphp/assert": "~1.8.0", - "simplesamlphp/xml-common": "~1.24.0", - "simplesamlphp/xml-security": "~1.13.0", - "simplesamlphp/xml-soap": "~1.7.0" + "simplesamlphp/xml-common": "dev-feature/xsd-types", + "simplesamlphp/xml-security": "dev-feature/xsd-types", + "simplesamlphp/xml-soap": "dev-feature/xsd-types" }, "require-dev": { "ext-intl": "*", 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 97a8b17f6..7b9a538c9 100644 --- a/phpstan-baseline-dev.neon +++ b/phpstan-baseline-dev.neon @@ -1,5 +1,10 @@ parameters: ignoreErrors: + - + message: "#^Dead catch \\- SimpleSAML\\\\Assert\\\\AssertionFailedException is never thrown in the try block\\.$#" + count: 1 + path: tests/InterOperability/EntityDescriptorTest.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\\.$#" count: 1 diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 82a9b5cb2..8b17eb89c 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,5 +1,25 @@ parameters: ignoreErrors: + - + message: "#^Call to an undefined method SimpleSAML\\\\SAML2\\\\XML\\\\samlp\\\\AbstractMessage\\:\\:addValidator\\(\\)\\.$#" + count: 1 + path: src/Binding/HTTPArtifact.php + + - + message: "#^Call to an undefined method SimpleSAML\\\\SAML2\\\\XML\\\\samlp\\\\ArtifactResponse\\:\\:validate\\(\\)\\.$#" + count: 1 + path: src/Binding/HTTPArtifact.php + + - + message: "#^Call to method addURLparameters\\(\\) on an unknown class SimpleSAML\\\\Utils\\\\HTTP\\.$#" + count: 1 + path: src/Binding/HTTPArtifact.php + + - + message: "#^Call to method getString\\(\\) on an unknown class SimpleSAML\\\\Configuration\\.$#" + count: 1 + path: src/Binding/HTTPArtifact.php + - message: "#^Call to static method addSign\\(\\) on an unknown class SimpleSAML\\\\Module\\\\saml\\\\Message\\.$#" count: 1 @@ -27,29 +47,39 @@ parameters: - message: "#^Parameter \\$key of method SimpleSAML\\\\SAML2\\\\Binding\\\\HTTPArtifact\\:\\:validateSignature\\(\\) has invalid type SimpleSAML\\\\XMLSecurity\\\\XMLSecurityKey\\.$#" - count: 1 + count: 2 path: src/Binding/HTTPArtifact.php - message: "#^Parameter \\$sp of method SimpleSAML\\\\SAML2\\\\Binding\\\\HTTPArtifact\\:\\:setSPMetadata\\(\\) has invalid type SimpleSAML\\\\Configuration\\.$#" - count: 1 + count: 2 path: src/Binding/HTTPArtifact.php - message: "#^Property SimpleSAML\\\\SAML2\\\\Binding\\\\HTTPArtifact\\:\\:\\$spMetadata has unknown class SimpleSAML\\\\Configuration as its type\\.$#" - count: 1 + count: 2 path: src/Binding/HTTPArtifact.php - - message: "#^Access to constant AES128_CBC on an unknown class SimpleSAML\\\\XMLSecurity\\\\XMLSecurityKey\\.$#" + message: "#^Call to an undefined method SimpleSAML\\\\XMLSecurity\\\\XML\\\\ds\\\\SignatureValue\\:\\:getContent\\(\\)\\.$#" count: 1 - path: src/Certificate/PrivateKeyLoader.php + path: src/Binding/HTTPRedirect.php - message: "#^Access to constant RSA_1_5 on an unknown class SimpleSAML\\\\XMLSecurity\\\\XMLSecurityKey\\.$#" count: 1 path: src/Certificate/PrivateKeyLoader.php + - + message: "#^Access to property \\$passphrase on an unknown class SimpleSAML\\\\XMLSecurity\\\\XMLSecurityKey\\.$#" + count: 2 + path: src/Certificate/PrivateKeyLoader.php + + - + message: "#^Call to method loadKey\\(\\) on an unknown class SimpleSAML\\\\XMLSecurity\\\\XMLSecurityKey\\.$#" + count: 2 + path: src/Certificate/PrivateKeyLoader.php + - message: "#^Instantiated class SimpleSAML\\\\XMLSecurity\\\\XMLSecurityKey not found\\.$#" count: 2 @@ -57,138 +87,183 @@ parameters: - message: "#^Method SimpleSAML\\\\SAML2\\\\Certificate\\\\PrivateKeyLoader\\:\\:convertPrivateKeyToRsaKey\\(\\) has invalid return type SimpleSAML\\\\XMLSecurity\\\\XMLSecurityKey\\.$#" - count: 1 + count: 2 path: src/Certificate/PrivateKeyLoader.php - - message: "#^Parameter \\$configuration of method SimpleSAML\\\\SAML2\\\\Configuration\\\\SimpleSAMLConverter\\:\\:convertToIdentityProvider\\(\\) has invalid type SimpleSAML\\\\Configuration\\.$#" + message: "#^PHPDoc tag @param for parameter \\$qName with type SimpleSAML\\\\XML\\\\Type\\\\QNameValue\\|null is not subtype of native type SimpleSAML\\\\XML\\\\Type\\\\QNameValue\\.$#" + count: 1 + path: src/Compat/AbstractContainer.php + + - + message: "#^Call to method getArray\\(\\) on an unknown class SimpleSAML\\\\Configuration\\.$#" count: 1 path: src/Configuration/SimpleSAMLConverter.php - - message: "#^Parameter \\$configuration of method SimpleSAML\\\\SAML2\\\\Configuration\\\\SimpleSAMLConverter\\:\\:convertToServiceProvider\\(\\) has invalid type SimpleSAML\\\\Configuration\\.$#" + message: "#^Call to method getBoolean\\(\\) on an unknown class SimpleSAML\\\\Configuration\\.$#" + count: 2 + path: src/Configuration/SimpleSAMLConverter.php + + - + message: "#^Call to method getString\\(\\) on an unknown class SimpleSAML\\\\Configuration\\.$#" + count: 10 + path: src/Configuration/SimpleSAMLConverter.php + + - + message: "#^Call to method getValue\\(\\) on an unknown class SimpleSAML\\\\Configuration\\.$#" count: 1 path: src/Configuration/SimpleSAMLConverter.php + - + message: "#^Call to method hasValue\\(\\) on an unknown class SimpleSAML\\\\Configuration\\.$#" + count: 7 + path: src/Configuration/SimpleSAMLConverter.php + + - + message: "#^Parameter \\$configuration of method SimpleSAML\\\\SAML2\\\\Configuration\\\\SimpleSAMLConverter\\:\\:convertToIdentityProvider\\(\\) has invalid type SimpleSAML\\\\Configuration\\.$#" + count: 2 + path: src/Configuration/SimpleSAMLConverter.php + + - + message: "#^Parameter \\$configuration of method SimpleSAML\\\\SAML2\\\\Configuration\\\\SimpleSAMLConverter\\:\\:convertToServiceProvider\\(\\) has invalid type SimpleSAML\\\\Configuration\\.$#" + count: 2 + path: src/Configuration/SimpleSAMLConverter.php + - message: "#^Parameter \\$configuration of method SimpleSAML\\\\SAML2\\\\Configuration\\\\SimpleSAMLConverter\\:\\:enrichForDecryptionProvider\\(\\) has invalid type SimpleSAML\\\\Configuration\\.$#" - count: 1 + count: 2 path: src/Configuration/SimpleSAMLConverter.php - message: "#^Parameter \\$configuration of method SimpleSAML\\\\SAML2\\\\Configuration\\\\SimpleSAMLConverter\\:\\:enrichForIdentityProvider\\(\\) has invalid type SimpleSAML\\\\Configuration\\.$#" - count: 1 + count: 2 path: src/Configuration/SimpleSAMLConverter.php - message: "#^Parameter \\$configuration of method SimpleSAML\\\\SAML2\\\\Configuration\\\\SimpleSAMLConverter\\:\\:enrichForServiceProvider\\(\\) has invalid type SimpleSAML\\\\Configuration\\.$#" - count: 1 + count: 2 path: src/Configuration/SimpleSAMLConverter.php - message: "#^Parameter \\$configuration of method SimpleSAML\\\\SAML2\\\\Configuration\\\\SimpleSAMLConverter\\:\\:pluckConfiguration\\(\\) has invalid type SimpleSAML\\\\Configuration\\.$#" - count: 1 + count: 2 path: src/Configuration/SimpleSAMLConverter.php - - message: "#^Instantiated class SimpleSAML\\\\Utils\\\\Config not found\\.$#" + message: "#^Access to property \\$key on an unknown class SimpleSAML\\\\XMLSecurity\\\\XMLSecurityKey\\.$#" count: 1 path: src/SOAPClient.php - - message: "#^Instantiated class SimpleSAML\\\\Utils\\\\Crypto not found\\.$#" + message: "#^Call to an undefined method SimpleSAML\\\\SAML2\\\\XML\\\\samlp\\\\AbstractMessage\\:\\:addValidator\\(\\)\\.$#" count: 1 path: src/SOAPClient.php - - message: "#^Parameter \\$dstMetadata of method SimpleSAML\\\\SAML2\\\\SOAPClient\\:\\:send\\(\\) has invalid type SimpleSAML\\\\Configuration\\.$#" + message: "#^Call to method getCertPath\\(\\) on an unknown class SimpleSAML\\\\Utils\\\\Config\\.$#" count: 1 path: src/SOAPClient.php - - message: "#^Parameter \\$key of method SimpleSAML\\\\SAML2\\\\SOAPClient\\:\\:validateSSL\\(\\) has invalid type SimpleSAML\\\\XMLSecurity\\\\XMLSecurityKey\\.$#" + message: "#^Call to method getPublicKeys\\(\\) on an unknown class SimpleSAML\\\\Configuration\\.$#" count: 1 path: src/SOAPClient.php - - message: "#^Parameter \\$srcMetadata of method SimpleSAML\\\\SAML2\\\\SOAPClient\\:\\:send\\(\\) has invalid type SimpleSAML\\\\Configuration\\.$#" - count: 1 + message: "#^Call to method getString\\(\\) on an unknown class SimpleSAML\\\\Configuration\\.$#" + count: 3 path: src/SOAPClient.php - - message: "#^Unsafe usage of new static\\(\\)\\.$#" - count: 2 - path: src/XML/md/AbstractEndpointType.php + message: "#^Call to method getValue\\(\\) on an unknown class SimpleSAML\\\\Configuration\\.$#" + count: 3 + path: src/SOAPClient.php - - message: "#^Unsafe usage of new static\\(\\)\\.$#" - count: 2 - path: src/XML/md/AbstractIndexedEndpointType.php + message: "#^Call to method hasValue\\(\\) on an unknown class SimpleSAML\\\\Configuration\\.$#" + count: 5 + path: src/SOAPClient.php - - message: "#^Access to undefined constant static\\(SimpleSAML\\\\SAML2\\\\XML\\\\md\\\\AbstractRoleDescriptor\\)\\:\\:XSI_TYPE_NAME\\.$#" - count: 2 - path: src/XML/md/AbstractRoleDescriptor.php + message: "#^Call to method loadPrivateKey\\(\\) on an unknown class SimpleSAML\\\\Utils\\\\Crypto\\.$#" + count: 1 + path: src/SOAPClient.php - - message: "#^Access to undefined constant static\\(SimpleSAML\\\\SAML2\\\\XML\\\\md\\\\AbstractRoleDescriptor\\)\\:\\:XSI_TYPE_NAMESPACE\\.$#" - count: 2 - path: src/XML/md/AbstractRoleDescriptor.php + message: "#^Call to method loadPublicKey\\(\\) on an unknown class SimpleSAML\\\\Utils\\\\Crypto\\.$#" + count: 1 + path: src/SOAPClient.php - - message: "#^Access to undefined constant static\\(SimpleSAML\\\\SAML2\\\\XML\\\\md\\\\AbstractRoleDescriptor\\)\\:\\:XSI_TYPE_PREFIX\\.$#" - count: 2 - path: src/XML/md/AbstractRoleDescriptor.php + message: "#^Instantiated class SimpleSAML\\\\Utils\\\\Config not found\\.$#" + count: 1 + path: src/SOAPClient.php - - message: "#^Call to an undefined static method SimpleSAML\\\\SAML2\\\\XML\\\\md\\\\AbstractSignedMdElement\\:\\:getXsiTypeNamespaceURI\\(\\)\\.$#" + message: "#^Instantiated class SimpleSAML\\\\Utils\\\\Crypto not found\\.$#" count: 1 - path: src/XML/md/AbstractSignedMdElement.php + path: src/SOAPClient.php - - message: "#^Access to undefined constant static\\(SimpleSAML\\\\SAML2\\\\XML\\\\saml\\\\AbstractBaseID\\)\\:\\:XSI_TYPE_NAME\\.$#" + message: "#^Parameter \\$dstMetadata of method SimpleSAML\\\\SAML2\\\\SOAPClient\\:\\:send\\(\\) has invalid type SimpleSAML\\\\Configuration\\.$#" count: 2 - path: src/XML/saml/AbstractBaseID.php + path: src/SOAPClient.php - - message: "#^Access to undefined constant static\\(SimpleSAML\\\\SAML2\\\\XML\\\\saml\\\\AbstractBaseID\\)\\:\\:XSI_TYPE_NAMESPACE\\.$#" + message: "#^Parameter \\$key of method SimpleSAML\\\\SAML2\\\\SOAPClient\\:\\:validateSSL\\(\\) has invalid type SimpleSAML\\\\XMLSecurity\\\\XMLSecurityKey\\.$#" count: 2 - path: src/XML/saml/AbstractBaseID.php + path: src/SOAPClient.php - - message: "#^Access to undefined constant static\\(SimpleSAML\\\\SAML2\\\\XML\\\\saml\\\\AbstractBaseID\\)\\:\\:XSI_TYPE_PREFIX\\.$#" + message: "#^Parameter \\$srcMetadata of method SimpleSAML\\\\SAML2\\\\SOAPClient\\:\\:send\\(\\) has invalid type SimpleSAML\\\\Configuration\\.$#" count: 2 - path: src/XML/saml/AbstractBaseID.php + path: src/SOAPClient.php - - message: "#^Access to undefined constant static\\(SimpleSAML\\\\SAML2\\\\XML\\\\saml\\\\AbstractCondition\\)\\:\\:XSI_TYPE_NAME\\.$#" + message: "#^Unsafe usage of new static\\(\\)\\.$#" count: 2 - path: src/XML/saml/AbstractCondition.php + path: src/XML/md/AbstractEndpointType.php - - message: "#^Access to undefined constant static\\(SimpleSAML\\\\SAML2\\\\XML\\\\saml\\\\AbstractCondition\\)\\:\\:XSI_TYPE_NAMESPACE\\.$#" + message: "#^Unsafe usage of new static\\(\\)\\.$#" count: 2 - path: src/XML/saml/AbstractCondition.php + path: src/XML/md/AbstractIndexedEndpointType.php - - message: "#^Access to undefined constant static\\(SimpleSAML\\\\SAML2\\\\XML\\\\saml\\\\AbstractCondition\\)\\:\\:XSI_TYPE_PREFIX\\.$#" + message: "#^Unsafe usage of new static\\(\\)\\.$#" count: 2 - path: src/XML/saml/AbstractCondition.php + path: src/XML/md/AbstractLocalizedName.php - - message: "#^Access to undefined constant static\\(SimpleSAML\\\\SAML2\\\\XML\\\\saml\\\\AbstractStatement\\)\\:\\:XSI_TYPE_NAME\\.$#" - count: 2 - path: src/XML/saml/AbstractStatement.php + message: "#^Call to an undefined static method SimpleSAML\\\\SAML2\\\\XML\\\\md\\\\AbstractSignedMdElement\\:\\:getXsiTypeNamespaceURI\\(\\)\\.$#" + count: 1 + path: src/XML/md/AbstractSignedMdElement.php - - message: "#^Access to undefined constant static\\(SimpleSAML\\\\SAML2\\\\XML\\\\saml\\\\AbstractStatement\\)\\:\\:XSI_TYPE_NAMESPACE\\.$#" - count: 2 - path: src/XML/saml/AbstractStatement.php + message: "#^Call to an undefined method SimpleSAML\\\\XML\\\\AbstractElement\\:\\:getList\\(\\)\\.$#" + count: 1 + path: src/XML/md/ContactPerson.php - - message: "#^Access to undefined constant static\\(SimpleSAML\\\\SAML2\\\\XML\\\\saml\\\\AbstractStatement\\)\\:\\:XSI_TYPE_PREFIX\\.$#" - count: 2 - path: src/XML/saml/AbstractStatement.php + message: "#^Call to an undefined method SimpleSAML\\\\XML\\\\AbstractElement\\:\\:getList\\(\\)\\.$#" + count: 1 + path: src/XML/md/EntitiesDescriptor.php + + - + message: "#^Call to an undefined method SimpleSAML\\\\XML\\\\AbstractElement\\:\\:getList\\(\\)\\.$#" + count: 1 + path: src/XML/md/Organization.php + + - + message: "#^Call to an undefined method DOMDocument\\:\\:setAttribute\\(\\)\\.$#" + count: 1 + path: src/XML/mdui/Keywords.php + + - + message: "#^Call to an undefined method SimpleSAML\\\\XML\\\\Type\\\\ValueTypeInterface\\:\\:toArray\\(\\)\\.$#" + count: 1 + path: src/XML/mdui/Keywords.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 5ea636604..000000000 --- a/src/Assert/CustomAssertionTrait.php +++ /dev/null @@ -1,83 +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..4f6d39d57 --- /dev/null +++ b/src/Assert/SAMLAnyURITrait.php @@ -0,0 +1,32 @@ +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..7c68e1b11 --- /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..5a74a2551 100644 --- a/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationRecipientMatches.php +++ b/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationRecipientMatches.php @@ -4,14 +4,11 @@ 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\Assertion\Validation\{Result, SubjectConfirmationConstraintValidator}; use SimpleSAML\SAML2\Configuration\Destination; use SimpleSAML\SAML2\XML\saml\SubjectConfirmation; use function sprintf; -use function strval; class SubjectConfirmationRecipientMatches implements SubjectConfirmationConstraintValidator { @@ -33,16 +30,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..cf794a031 100644 --- a/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationResponseToMatches.php +++ b/src/Assertion/Validation/ConstraintValidator/SubjectConfirmationResponseToMatches.php @@ -4,14 +4,11 @@ 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\Assertion\Validation\{Result, 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 +31,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.php b/src/Binding.php index 4e8c3f2d3..7fab65b6e 100644 --- a/src/Binding.php +++ b/src/Binding.php @@ -5,7 +5,6 @@ namespace SimpleSAML\SAML2; use Psr\Http\Message\{ResponseInterface, ServerRequestInterface}; -use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Binding\{HTTPArtifact, HTTPPost, HTTPRedirect, SOAP}; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Exception\Protocol\UnsupportedBindingException; diff --git a/src/Binding/HTTPArtifact.php b/src/Binding/HTTPArtifact.php index bbd22e9f4..63caf96a8 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 bd8352701..9d44c1d2c 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; @@ -40,7 +40,7 @@ class HTTPPost extends Binding 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 c0b9beeaf..f9e3a8bfd 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; @@ -54,6 +54,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; @@ -83,8 +85,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->getContent()->getValue()); } if (str_contains($destination, '?')) { diff --git a/src/Binding/SOAP.php b/src/Binding/SOAP.php index 9b0b35ec1..770451654 100644 --- a/src/Binding/SOAP.php +++ b/src/Binding/SOAP.php @@ -6,21 +6,19 @@ use Exception; use Nyholm\Psr7\Response; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Message\{ResponseInterface, 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\ecp\{RequestAuthenticated, 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\SOAP\XML\env_200106\{Body, Envelope, Header}; use SimpleSAML\XML\DOMDocumentFactory; +use SimpleSAML\XML\Type\BooleanValue; use function file_get_contents; @@ -44,13 +42,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( + BooleanValue::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 1bd2d9838..1921a274a 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/Certificate/PrivateKeyLoader.php b/src/Certificate/PrivateKeyLoader.php index f8c990eb4..16af413f0 100644 --- a/src/Certificate/PrivateKeyLoader.php +++ b/src/Certificate/PrivateKeyLoader.php @@ -7,6 +7,7 @@ use SimpleSAML\SAML2\Certificate\PrivateKey; use SimpleSAML\SAML2\Configuration\DecryptionProvider; use SimpleSAML\SAML2\Configuration\PrivateKey as PrivateKeyConfiguration; +use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Utilities\ArrayCollection; use SimpleSAML\SAML2\Utilities\File; use SimpleSAML\XMLSecurity\XMLSecurityKey; @@ -45,7 +46,7 @@ public function loadDecryptionKeys( $senderSharedKey = $identityProvider->getSharedKey(); if ($senderSharedKey !== null) { - $key = new XMLSecurityKey(XMLSecurityKey::AES128_CBC); + $key = new XMLSecurityKey(C::BLOCK_ENC_AES128); $key->loadKey($senderSharedKey); $decryptionKeys->add($key); diff --git a/src/Compat/AbstractContainer.php b/src/Compat/AbstractContainer.php index 700ca79c0..ef939af55 100644 --- a/src/Compat/AbstractContainer.php +++ b/src/Compat/AbstractContainer.php @@ -8,24 +8,23 @@ use Psr\Log\LoggerInterface; use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\XML\ExtensionPointInterface; -use SimpleSAML\XML\AbstractElement; -use SimpleSAML\XML\Exception\SchemaViolationException; +use SimpleSAML\XML\{AbstractElement, ElementInterface}; +use SimpleSAML\XML\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, @@ -46,6 +45,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. * @@ -54,37 +67,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\XML\Type\QNameValue|null $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]; } @@ -96,23 +101,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\XML\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 f92105b5e..df7f5e262 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/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/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/CIDRValue.php b/src/Type/CIDRValue.php new file mode 100644 index 000000000..1e726b03b --- /dev/null +++ b/src/Type/CIDRValue.php @@ -0,0 +1,25 @@ +sanitizeValue($value)); + } +} 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..1d38808fb --- /dev/null +++ b/src/Type/EntityIDValue.php @@ -0,0 +1,37 @@ +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..85f346043 --- /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..47dfe9e6e --- /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..0c41e987e --- /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..b4aea4405 --- /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..26e83d84d --- /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 2f07b21ad..f72f7fc3e 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 ArrayCollection */ diff --git a/src/XML/EncryptedElementTrait.php b/src/XML/EncryptedElementTrait.php index 4b582b9d2..46ef7798b 100644 --- a/src/XML/EncryptedElementTrait.php +++ b/src/XML/EncryptedElementTrait.php @@ -5,7 +5,7 @@ namespace SimpleSAML\SAML2\XML; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Compat\ContainerSingleton; use SimpleSAML\SAML2\Exception\ProtocolViolationException; use SimpleSAML\XML\AbstractElement; @@ -43,7 +43,7 @@ public function __construct( * 6.2: The 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) { diff --git a/src/XML/ExtensionPointInterface.php b/src/XML/ExtensionPointInterface.php index b7945f2d3..01a6299b7 100644 --- a/src/XML/ExtensionPointInterface.php +++ b/src/XML/ExtensionPointInterface.php @@ -4,6 +4,8 @@ namespace SimpleSAML\SAML2\XML; +use SimpleSAML\XML\Type\{AnyURIValue, NCNameValue, QNameValue}; + /** * Interface for several extension points objects. * @@ -14,31 +16,31 @@ interface ExtensionPointInterface /** * Get the local name for the element's xsi:type. * - * @return string + * @return \SimpleSAML\XML\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\XML\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\XML\Type\NCNameValue */ - public static function getXsiTypePrefix(): string; + public static function getXsiTypePrefix(): NCNameValue; /** * Return the xsi:type value corresponding this element. * - * @return string + * @return \SimpleSAML\XML\Type\QNameValue */ - public function getXsiType(): string; + public function getXsiType(): QNameValue; } diff --git a/src/XML/ExtensionPointTrait.php b/src/XML/ExtensionPointTrait.php index 3602fb67d..edd2bdca1 100644 --- a/src/XML/ExtensionPointTrait.php +++ b/src/XML/ExtensionPointTrait.php @@ -6,7 +6,11 @@ use RuntimeException; use SimpleSAML\SAML2\Assert\Assert; -use SimpleSAML\XML\Exception\SchemaViolationException; +use SimpleSAML\XML\Type\{AnyURIValue, NCNameValue}; + +use function constant; +use function defined; +use function sprintf; /** * Trait for several extension points objects. @@ -18,9 +22,9 @@ trait ExtensionPointTrait /** * Get the local name for the element's xsi:type. * - * @return string + * @return \SimpleSAML\XML\Type\NCNameValue */ - public static function getXsiTypeName(): string + public static function getXsiTypeName(): NCNameValue { Assert::true( defined('static::XSI_TYPE_NAME'), @@ -29,17 +33,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\XML\Type\AnyURIValue */ - public static function getXsiTypeNamespaceURI(): string + public static function getXsiTypeNamespaceURI(): AnyURIValue { Assert::true( defined('static::XSI_TYPE_NAMESPACE'), @@ -48,17 +51,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\XML\Type\NCNameValue */ - public static function getXsiTypePrefix(): string + public static function getXsiTypePrefix(): NCNameValue { Assert::true( defined('static::XSI_TYPE_PREFIX'), @@ -69,7 +71,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..26d60eadf 100644 --- a/src/XML/IdentifierTrait.php +++ b/src/XML/IdentifierTrait.php @@ -5,11 +5,8 @@ namespace SimpleSAML\SAML2\XML; use DOMElement; -use SimpleSAML\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\SAML2\Assert\Assert; +use SimpleSAML\SAML2\XML\saml\{AbstractBaseID, EncryptedID, IdentifierInterface, NameID}; use SimpleSAML\XML\Exception\TooManyElementsException; use function array_pop; diff --git a/src/XML/SignableElementTrait.php b/src/XML/SignableElementTrait.php index 00fda83f0..98ea8b87d 100644 --- a/src/XML/SignableElementTrait.php +++ b/src/XML/SignableElementTrait.php @@ -5,22 +5,24 @@ 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\XML\Type\{AnyURIValue, Base64BinaryValue}; use SimpleSAML\XMLSecurity\Alg\Signature\SignatureAlgorithmInterface; use SimpleSAML\XMLSecurity\Constants as C; -use SimpleSAML\XMLSecurity\Exception\RuntimeException; -use SimpleSAML\XMLSecurity\Exception\UnsupportedAlgorithmException; +use SimpleSAML\XMLSecurity\Exception\{RuntimeException, UnsupportedAlgorithmException}; use SimpleSAML\XMLSecurity\Utils\XML; -use SimpleSAML\XMLSecurity\XML\ds\CanonicalizationMethod; -use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; -use SimpleSAML\XMLSecurity\XML\ds\Signature; -use SimpleSAML\XMLSecurity\XML\ds\SignatureMethod; -use SimpleSAML\XMLSecurity\XML\ds\SignatureValue; -use SimpleSAML\XMLSecurity\XML\ds\SignedInfo; -use SimpleSAML\XMLSecurity\XML\ds\Transform; -use SimpleSAML\XMLSecurity\XML\ds\Transforms; +use SimpleSAML\XMLSecurity\XML\ds\{ + CanonicalizationMethod, + KeyInfo, + Signature, + SignatureMethod, + SignatureValue, + SignedInfo, + Transform, + Transforms, +}; use SimpleSAML\XMLSecurity\XML\SignableElementTrait as BaseSignableElementTrait; use function base64_encode; @@ -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 216adea3d..5e7a696c6 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\XMLSecurity\Exception\ReferenceValidationFailedException; use SimpleSAML\XMLSecurity\XML\ds\Signature; @@ -38,9 +38,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 c2d6fcb0d..000000000 --- a/src/XML/StringElementTrait.php +++ /dev/null @@ -1,39 +0,0 @@ -setElements($elements); } @@ -46,9 +45,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; } @@ -71,7 +70,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), ); } @@ -86,7 +85,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 443bcd4ce..059c9fce7 100644 --- a/src/XML/alg/SigningMethod.php +++ b/src/XML/alg/SigningMethod.php @@ -5,16 +5,14 @@ namespace SimpleSAML\SAML2\XML\alg; 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\XML\Exception\InvalidDOMElementException; use SimpleSAML\XML\ExtendableElementTrait; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\PositiveIntegerValue; use SimpleSAML\XML\XsNamespace as NS; -use function strval; - /** * Class for handling the alg:SigningMethod element. * @@ -33,21 +31,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\XML\Type\PositiveIntegerValue|null $minKeySize + * @param \SimpleSAML\XML\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); } @@ -55,9 +49,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; } @@ -66,9 +60,9 @@ public function getAlgorithm(): string /** * Collect the value of the MinKeySize-property * - * @return int|null + * @return \SimpleSAML\XML\Type\PositiveIntegerValue|null */ - public function getMinKeySize(): ?int + public function getMinKeySize(): ?PositiveIntegerValue { return $this->minKeySize; } @@ -77,9 +71,9 @@ public function getMinKeySize(): ?int /** * Collect the value of the MaxKeySize-property * - * @return int|null + * @return \SimpleSAML\XML\Type\PositiveIntegerValue|null */ - public function getMaxKeySize(): ?int + public function getMaxKeySize(): ?PositiveIntegerValue { return $this->maxKeySize; } @@ -102,9 +96,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), ); } @@ -120,14 +114,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 c694e9992..daae01402 100644 --- a/src/XML/ecp/RelayState.php +++ b/src/XML/ecp/RelayState.php @@ -5,14 +5,13 @@ 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\SAML2\Type\SAMLStringValue; use SimpleSAML\SOAP\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingAttributeException; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\Exception\{InvalidDOMElementException, MissingAttributeException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class representing the ECP RelayState element. @@ -22,18 +21,10 @@ 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; /** @@ -64,23 +55,23 @@ public static function fromXML(DOMElement $xml): static MissingAttributeException::class, ); - $mustUnderstand = $xml->getAttributeNS(C::NS_SOAP_ENV_11, 'mustUnderstand'); Assert::same( - $mustUnderstand, + $xml->getAttributeNS(C::NS_SOAP_ENV_11, 'mustUnderstand'), '1', '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_11, '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), + ); } @@ -93,9 +84,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->textContent = $this->getContent()->getValue(); return $e; } diff --git a/src/XML/ecp/Request.php b/src/XML/ecp/Request.php index 8e9d17f3b..2666f5c93 100644 --- a/src/XML/ecp/Request.php +++ b/src/XML/ecp/Request.php @@ -5,16 +5,15 @@ 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\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\Exception\{InvalidDOMElementException, MissingAttributeException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\BooleanValue; use function intval; use function strval; @@ -33,14 +32,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\XML\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, ) { } @@ -48,9 +47,9 @@ public function __construct( /** * Collect the value of the isPassive-property * - * @return bool|null + * @return \SimpleSAML\XML\Type\BooleanValue|null */ - public function getIsPassive(): ?bool + public function getIsPassive(): ?BooleanValue { return $this->isPassive; } @@ -59,9 +58,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; } @@ -76,6 +75,8 @@ public function getIssuer(): Issuer { return $this->issuer; } + + /** * Collect the value of the idpList-property * @@ -115,17 +116,15 @@ public static function fromXML(DOMElement $xml): static MissingAttributeException::class, ); - $mustUnderstand = $xml->getAttributeNS(C::NS_SOAP_ENV_11, 'mustUnderstand'); Assert::same( - $mustUnderstand, + $xml->getAttributeNS(C::NS_SOAP_ENV_11, 'mustUnderstand'), '1', '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_11, 'actor'), C::SOAP_ACTOR_NEXT, 'Invalid value of env:actor attribute in .', ProtocolViolationException::class, @@ -144,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), ); } @@ -163,11 +162,11 @@ public function toXML(?DOMElement $parent = null): DOMElement $e->setAttributeNS(C::NS_SOAP_ENV_11, '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 c4dbaf66b..0df358181 100644 --- a/src/XML/ecp/RequestAuthenticated.php +++ b/src/XML/ecp/RequestAuthenticated.php @@ -5,15 +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\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\Exception\{InvalidDOMElementException, MissingAttributeException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\BooleanValue; -use function boolval; +use function intval; use function strval; /** @@ -28,10 +27,10 @@ final class RequestAuthenticated extends AbstractEcpElement implements SchemaVal /** * Create a ECP RequestAuthenticated element. * - * @param bool|null $mustUnderstand + * @param \SimpleSAML\XML\Type\BooleanValue|null $mustUnderstand */ public function __construct( - protected ?bool $mustUnderstand = false, + protected ?BooleanValue $mustUnderstand, ) { } @@ -39,9 +38,9 @@ public function __construct( /** * Collect the value of the mustUnderstand-property * - * @return bool|null + * @return \SimpleSAML\XML\Type\BooleanValue|null */ - public function getMustUnderstand(): ?bool + public function getMustUnderstand(): ?BooleanValue { return $this->mustUnderstand; } @@ -72,22 +71,12 @@ public static function fromXML(DOMElement $xml): static $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); + $mustUnderstand = BooleanValue::fromString($xml->getAttributeNS(C::NS_SOAP_ENV_11, '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_11, 'actor'), + C::SOAP_ACTOR_NEXT, 'Invalid value of env:actor attribute in .', ProtocolViolationException::class, ); @@ -107,7 +96,11 @@ 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()))); + $e->setAttributeNS( + C::NS_SOAP_ENV_11, + 'env:mustUnderstand', + strval(intval($this->getMustUnderstand()->getValue())), + ); } $e->setAttributeNS(C::NS_SOAP_ENV_11, 'env:actor', C::SOAP_ACTOR_NEXT); diff --git a/src/XML/ecp/Response.php b/src/XML/ecp/Response.php index 4b1608e1e..5613c327a 100644 --- a/src/XML/ecp/Response.php +++ b/src/XML/ecp/Response.php @@ -5,14 +5,12 @@ 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\SOAP\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingAttributeException; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\Exception\{InvalidDOMElementException, MissingAttributeException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * Class representing the ECP Response element. @@ -26,21 +24,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; } @@ -79,23 +76,21 @@ 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'); - Assert::same( - $mustUnderstand, + $xml->getAttributeNS(C::NS_SOAP_ENV_11, '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_11, '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,8 +105,8 @@ 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_11, '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 052c0c61f..a69ef33cc 100644 --- a/src/XML/ecp/SubjectConfirmation.php +++ b/src/XML/ecp/SubjectConfirmation.php @@ -5,16 +5,13 @@ 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\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\Exception\{InvalidDOMElementException, MissingAttributeException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * Class representing the ECP SubjectConfirmation element. @@ -28,23 +25,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; } @@ -89,17 +85,15 @@ public static function fromXML(DOMElement $xml): static MissingAttributeException::class, ); - $mustUnderstand = $xml->getAttributeNS(C::NS_SOAP_ENV_11, 'mustUnderstand'); - Assert::same( - $mustUnderstand, - '1', + Assert::oneOf( + $xml->getAttributeNS(C::NS_SOAP_ENV_11, 'mustUnderstand'), + ['1', 'true'], '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_11, 'actor'), C::SOAP_ACTOR_NEXT, 'Invalid value of env:actor attribute in .', ProtocolViolationException::class, @@ -114,7 +108,7 @@ public static function fromXML(DOMElement $xml): static ); return new static( - self::getAttribute($xml, 'Method'), + self::getAttribute($xml, 'Method', SAMLAnyURIValue::class), array_pop($subjectConfirmationData), ); } @@ -131,7 +125,7 @@ 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->setAttribute('Method', $this->getMethod()->getValue()); $this->getSubjectConfirmationData()?->toXML($e); diff --git a/src/XML/emd/RepublishRequest.php b/src/XML/emd/RepublishRequest.php index aa1e4df2a..c791ee895 100644 --- a/src/XML/emd/RepublishRequest.php +++ b/src/XML/emd/RepublishRequest.php @@ -5,13 +5,12 @@ 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\XML\Exception\{InvalidDOMElementException, SchemaViolationException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use function array_pop; @@ -101,7 +100,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']), + ), + ); } @@ -112,6 +115,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..d2726223e 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,19 @@ */ 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 299487c2c..8cecb5fe0 100644 --- a/src/XML/idpdisc/DiscoveryResponse.php +++ b/src/XML/idpdisc/DiscoveryResponse.php @@ -4,12 +4,13 @@ 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\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\{BooleanValue, UnsignedShortValue}; /** * Abstract class to be implemented by all the classes in this namespace @@ -36,30 +37,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\XML\Type\UnsignedShortValue $index + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $binding + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $location + * @param \SimpleSAML\XML\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 8e930d0e9..bf4981296 100644 --- a/src/XML/init/RequestInitiator.php +++ b/src/XML/init/RequestInitiator.php @@ -5,12 +5,12 @@ 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\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * Class for handling the init:RequestInitiator element. @@ -35,20 +35,26 @@ final class RequestInitiator extends AbstractEndpointType implements SchemaValid /** * EndpointType constructor. * - * @param string $location - * @param string|null $responseLocation + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $location + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $responseLocation * @param array $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, + ); } @@ -79,8 +85,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 0bb22e6d8..e70c14bf0 100644 --- a/src/XML/md/AbstractEndpointType.php +++ b/src/XML/md/AbstractEndpointType.php @@ -5,14 +5,13 @@ 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\{ExtendableAttributesTrait, ExtendableElementTrait}; use SimpleSAML\XML\SerializableElementInterface; use SimpleSAML\XML\XsNamespace as NS; @@ -51,25 +50,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); } @@ -78,9 +73,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; } @@ -89,9 +84,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; } @@ -100,9 +95,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; } @@ -132,9 +127,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), ); @@ -151,11 +146,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) { @@ -184,9 +179,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'] ?? [], ); @@ -259,9 +254,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..c520f85a8 100644 --- a/src/XML/md/AbstractIndexedEndpointType.php +++ b/src/XML/md/AbstractIndexedEndpointType.php @@ -5,18 +5,18 @@ 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\XML\Type\{BooleanValue, 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 +36,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\XML\Type\UnsignedShortValue $index + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $binding + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $location + * @param \SimpleSAML\XML\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 = [], ) { @@ -82,11 +82,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 +102,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 +141,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 +226,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..820d71c32 100644 --- a/src/XML/md/AbstractLocalizedName.php +++ b/src/XML/md/AbstractLocalizedName.php @@ -5,14 +5,14 @@ namespace SimpleSAML\SAML2\XML\md; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Exception\ArrayValidationException; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\StringElementTrait; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Exception\{ArrayValidationException, ProtocolViolationException}; +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\Exception\{InvalidDOMElementException, MissingAttributeException}; +use SimpleSAML\XML\Type\LanguageValue; +use SimpleSAML\XML\TypedTextContentTrait; use function array_key_first; @@ -23,31 +23,32 @@ */ 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\XML\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\XML\Type\LanguageValue */ - public function getLanguage(): string + public function getLanguage(): LanguageValue { return $this->language; } @@ -72,7 +73,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 +87,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 +104,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 +118,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..ab2170c85 100644 --- a/src/XML/md/AbstractLocalizedURI.php +++ b/src/XML/md/AbstractLocalizedURI.php @@ -4,8 +4,14 @@ 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, SAMLStringValue}; +use SimpleSAML\XML\Exception\{InvalidDOMElementException, MissingAttributeException}; +use SimpleSAML\XML\Type\LanguageValue; + +use function array_key_first; /** * Abstract class implementing LocalizedURIType. @@ -14,64 +20,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\XML\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\XML\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 +76,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..98ded978e 100644 --- a/src/XML/md/AbstractMetadataDocument.php +++ b/src/XML/md/AbstractMetadataDocument.php @@ -4,12 +4,14 @@ namespace SimpleSAML\SAML2\XML\md; -use DateTimeImmutable; use DOMElement; use SimpleSAML\SAML2\Assert\Assert; -use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\SAMLDateTimeValue; +use SimpleSAML\SAML2\Exception\ProtocolViolationException; use SimpleSAML\SAML2\XML\ExtendableElementTrait; -use SimpleSAML\XML\Exception\SchemaViolationException; +use SimpleSAML\SAML2\XML\mdrpi\{PublicationInfo, PublicationPath, RegistrationInfo}; +use SimpleSAML\SAML2\XML\mdui\{DiscoHints, UIInfo}; +use SimpleSAML\XML\Type\{DurationValue, IDValue}; /** * Class to represent a metadata document @@ -24,20 +26,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\XML\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\XML\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 +91,9 @@ public function __construct( /** * Collect the value of the id property. * - * @return string|null + * @return \SimpleSAML\XML\Type\IDValue|null */ - public function getId(): ?string + public function getId(): ?IDValue { return $this->id; } @@ -57,9 +102,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 +113,9 @@ public function getValidUntil(): ?DateTimeImmutable /** * Collect the value of the cacheDuration property. * - * @return string|null + * @return \SimpleSAML\XML\Type\DurationValue|null */ - public function getCacheDuration(): ?string + public function getCacheDuration(): ?DurationValue { return $this->cacheDuration; } @@ -95,15 +140,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 d88227e23..7fcd0e451 100644 --- a/src/XML/md/AbstractRoleDescriptor.php +++ b/src/XML/md/AbstractRoleDescriptor.php @@ -4,24 +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\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; use SimpleSAML\SAML2\Utils; -use SimpleSAML\SAML2\XML\ExtensionPointInterface; -use SimpleSAML\SAML2\XML\ExtensionPointTrait; -use SimpleSAML\XML\Attribute as XMLAttribute; +use SimpleSAML\SAML2\XML\{ExtensionPointInterface, ExtensionPointTrait}; 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\XML\Exception\{InvalidDOMElementException, SchemaViolationException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\{DurationValue, IDValue, QNameValue, StringValue}; use function array_pop; -use function count; -use function implode; /** * Class representing a SAML2 RoleDescriptor element. @@ -42,13 +36,16 @@ abstract class AbstractRoleDescriptor extends AbstractRoleDescriptorType impleme /** * Initialize a md:RoleDescriptor from scratch. * - * @param string $type + * @param \SimpleSAML\XML\Type\QNameValue $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\XML\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\XML\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 @@ -58,13 +55,13 @@ abstract class AbstractRoleDescriptor extends AbstractRoleDescriptorType impleme * @param list<\SimpleSAML\XML\Attribute> $namespacedAttributes */ public function __construct( - protected string $type, + protected QNameValue $type, array $protocolSupportEnumeration, - ?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 $contactPerson = [], @@ -88,9 +85,9 @@ public function __construct( /** * Return the xsi:type value corresponding this element. * - * @return string + * @return \SimpleSAML\XML\Type\QNameValue */ - public function getXsiType(): string + public function getXsiType(): QNameValue { return $this->type; } @@ -110,32 +107,17 @@ public static function fromXML(DOMElement $xml): static Assert::same($xml->namespaceURI, C::NS_MD, InvalidDOMElementException::class); Assert::true( $xml->hasAttributeNS(C::NS_XSI, 'type'), - 'Missing required xsi:type in element.', + '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::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); + $protocols = self::getAttribute($xml, 'protocolSupportEnumeration', SAMLStringValue::class); $orgs = Organization::getChildrenOfClass($xml); Assert::maxCount( @@ -156,12 +138,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), + preg_split('/[\s]+/', trim($protocols->getValue())), + 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), @@ -177,21 +159,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 1d751a2ea..d5a0b25cd 100644 --- a/src/XML/md/AbstractRoleDescriptorType.php +++ b/src/XML/md/AbstractRoleDescriptorType.php @@ -4,13 +4,14 @@ namespace SimpleSAML\SAML2\XML\md; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue}; use SimpleSAML\XML\Exception\SchemaViolationException; use SimpleSAML\XML\ExtendableAttributesTrait; +use SimpleSAML\XML\Type\{DurationValue, IDValue}; use SimpleSAML\XML\XsNamespace as NS; use function implode; @@ -32,11 +33,14 @@ 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\XML\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\XML\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,11 +51,11 @@ abstract class AbstractRoleDescriptorType extends AbstractMetadataDocument */ public function __construct( protected array $protocolSupportEnumeration, - ?string $ID = null, - ?DateTimeImmutable $validUntil = null, - ?string $cacheDuration = null, + ?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 = [], @@ -64,7 +68,6 @@ public function __construct( '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, @@ -87,9 +90,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; } @@ -151,7 +154,7 @@ public function toUnsignedXML(?DOMElement $parent = null): DOMElement $e->setAttribute('protocolSupportEnumeration', implode(' ', $this->getProtocolSupportEnumeration())); if ($this->getErrorURL() !== null) { - $e->setAttribute('errorURL', $this->getErrorURL()); + $e->setAttribute('errorURL', $this->getErrorURL()->getValue()); } foreach ($this->getKeyDescriptor() as $kd) { diff --git a/src/XML/md/AbstractSSODescriptor.php b/src/XML/md/AbstractSSODescriptor.php index 19196fdfb..44fe7ca6b 100644 --- a/src/XML/md/AbstractSSODescriptor.php +++ b/src/XML/md/AbstractSSODescriptor.php @@ -4,11 +4,12 @@ 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\{SAMLAnyURIValue, SAMLDateTimeValue}; use SimpleSAML\XML\Constants as C; +use SimpleSAML\XML\Type\{IDValue, DurationValue}; /** * Class representing SAML 2 SSODescriptorType. @@ -21,11 +22,14 @@ 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\XML\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\XML\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 @@ -43,11 +47,11 @@ abstract class AbstractSSODescriptor extends AbstractRoleDescriptorType */ public function __construct( array $protocolSupportEnumeration, - ?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 = [], diff --git a/src/XML/md/AbstractSignedMdElement.php b/src/XML/md/AbstractSignedMdElement.php index 378877d11..a413e96cf 100644 --- a/src/XML/md/AbstractSignedMdElement.php +++ b/src/XML/md/AbstractSignedMdElement.php @@ -5,10 +5,8 @@ namespace SimpleSAML\SAML2\XML\md; use DOMElement; -use SimpleSAML\SAML2\XML\SignableElementTrait; -use SimpleSAML\SAML2\XML\SignedElementTrait; -use SimpleSAML\XMLSecurity\XML\SignableElementInterface; -use SimpleSAML\XMLSecurity\XML\SignedElementInterface; +use SimpleSAML\SAML2\XML\{SignableElementTrait, SignedElementTrait}; +use SimpleSAML\XMLSecurity\XML\{SignableElementInterface, SignedElementInterface}; use function method_exists; @@ -75,6 +73,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. @@ -82,7 +81,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..0db99da22 100644 --- a/src/XML/md/AdditionalMetadataLocation.php +++ b/src/XML/md/AdditionalMetadataLocation.php @@ -5,14 +5,10 @@ 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\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; - -use function trim; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * Class representing SAML 2 metadata AdditionalMetadataLocation element. @@ -22,35 +18,43 @@ 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. * @@ -67,9 +71,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 +87,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..af960d327 100644 --- a/src/XML/md/AffiliateMember.php +++ b/src/XML/md/AffiliateMember.php @@ -4,10 +4,9 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; -use SimpleSAML\SAML2\XML\StringElementTrait; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class implementing AffiliateMember. @@ -17,27 +16,8 @@ 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 66ea21796..a4789e8bb 100644 --- a/src/XML/md/AffiliationDescriptor.php +++ b/src/XML/md/AffiliationDescriptor.php @@ -4,16 +4,13 @@ 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\XML\ExtendableAttributesTrait; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Type\{SAMLDateTimeValue, EntityIDValue}; +use SimpleSAML\XML\Exception\{InvalidDOMElementException, TooManyElementsException}; +use SimpleSAML\XML\{ExtendableAttributesTrait, SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\{DurationValue, IDValue}; use SimpleSAML\XML\XsNamespace as NS; use SimpleSAML\XMLSecurity\XML\ds\Signature; @@ -34,28 +31,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\XML\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\XML\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); @@ -71,9 +69,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; } @@ -119,13 +117,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, @@ -153,9 +148,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), @@ -179,7 +174,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 8af0579ae..35af9603d 100644 --- a/src/XML/md/ArtifactResolutionService.php +++ b/src/XML/md/ArtifactResolutionService.php @@ -4,9 +4,10 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\Assert\Assert; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\{BooleanValue, UnsignedShortValue}; /** * A class implementing the md:ArtifactResolutionService element. @@ -22,22 +23,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\XML\Type\UnsignedShortValue $index + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $binding + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $location + * @param \SimpleSAML\XML\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/AssertionConsumerService.php b/src/XML/md/AssertionConsumerService.php index b234a0b3a..090f34745 100644 --- a/src/XML/md/AssertionConsumerService.php +++ b/src/XML/md/AssertionConsumerService.php @@ -4,8 +4,7 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * Class implementing the md:AssertionConsumerService element. diff --git a/src/XML/md/AttributeAuthorityDescriptor.php b/src/XML/md/AttributeAuthorityDescriptor.php index 21cb2fa0e..025476070 100644 --- a/src/XML/md/AttributeAuthorityDescriptor.php +++ b/src/XML/md/AttributeAuthorityDescriptor.php @@ -4,17 +4,14 @@ 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\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; 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\XML\Exception\{InvalidDOMElementException, MissingElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\{DurationValue, IDValue}; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function preg_split; @@ -38,11 +35,11 @@ final class AttributeAuthorityDescriptor extends AbstractRoleDescriptorType impl * @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\XML\Type\IDValue|null $ID + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil + * @param \SimpleSAML\XML\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 @@ -55,11 +52,11 @@ public function __construct( 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 = [], @@ -177,9 +174,7 @@ 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); + $protocols = self::getAttribute($xml, 'protocolSupportEnumeration', SAMLStringValue::class); $attrServices = AttributeService::getChildrenOfClass($xml); Assert::notEmpty( @@ -219,16 +214,16 @@ public static function fromXML(DOMElement $xml): static $authority = new static( $attrServices, - preg_split('/[\s]+/', trim($protocols)), + preg_split('/[\s]+/', $protocols->getValue()), $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 0c8f8712a..2863d82a3 100644 --- a/src/XML/md/AttributeConsumingService.php +++ b/src/XML/md/AttributeConsumingService.php @@ -5,14 +5,13 @@ 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\XML\Exception\{InvalidDOMElementException, MissingElementException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\{BooleanValue, UnsignedShortValue}; -use function strval; +use function var_export; /** * Class representing SAML 2 Metadata AttributeConsumingService element. @@ -27,17 +26,17 @@ final class AttributeConsumingService extends AbstractMdElement implements Schem /** * AttributeConsumingService constructor. * - * @param int $index + * @param \SimpleSAML\XML\Type\UnsignedShortValue $index * @param \SimpleSAML\SAML2\XML\md\ServiceName[] $serviceName * @param \SimpleSAML\SAML2\XML\md\RequestedAttribute[] $requestedAttribute - * @param bool|null $isDefault + * @param \SimpleSAML\XML\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); @@ -92,7 +91,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, @@ -106,10 +104,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, ); } @@ -157,12 +155,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..85cb0409d 100644 --- a/src/XML/md/AttributeProfile.php +++ b/src/XML/md/AttributeProfile.php @@ -4,9 +4,9 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\SAML2\XML\StringElementTrait; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class implementing AttributeProfile. @@ -16,14 +16,8 @@ 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/AttributeService.php b/src/XML/md/AttributeService.php index c0626f728..43d60cafe 100644 --- a/src/XML/md/AttributeService.php +++ b/src/XML/md/AttributeService.php @@ -4,8 +4,7 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * AttributeService elements of type EndpointType diff --git a/src/XML/md/AuthnAuthorityDescriptor.php b/src/XML/md/AuthnAuthorityDescriptor.php index d9f420a3d..8258033d5 100644 --- a/src/XML/md/AuthnAuthorityDescriptor.php +++ b/src/XML/md/AuthnAuthorityDescriptor.php @@ -4,15 +4,13 @@ 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\{SAMLAnyURIValue, 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\XML\Exception\{InvalidDOMElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\{DurationValue, IDValue}; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function preg_split; @@ -33,11 +31,11 @@ final class AuthnAuthorityDescriptor extends AbstractRoleDescriptorType implemen * @param array $protocolSupportEnumeration * @param array $assertionIDRequestService * @param array $nameIDFormat - * @param string|null $ID - * @param \DateTimeImmutable|null $validUntil - * @param string|null $cacheDuration + * @param \SimpleSAML\XML\Type\IDValue|null $ID + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil + * @param \SimpleSAML\XML\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 @@ -48,11 +46,11 @@ public function __construct( array $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 = [], @@ -146,9 +144,6 @@ public static function fromXML(DOMElement $xml): static $assertionIDRequestServices = AssertionIDRequestService::getChildrenOfClass($xml); $nameIDFormats = NameIDFormat::getChildrenOfClass($xml); - $validUntil = self::getOptionalAttribute($xml, 'validUntil', null); - SAMLAssert::nullOrValidDateTime($validUntil); - $orgs = Organization::getChildrenOfClass($xml); Assert::maxCount( $orgs, @@ -175,14 +170,14 @@ public static function fromXML(DOMElement $xml): static $authority = new static( $authnQueryServices, - preg_split('/[\s]+/', trim($protocols)), + preg_split('/[\s]+/', trim($protocols->getValue())), $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..97ade90bf 100644 --- a/src/XML/md/Company.php +++ b/src/XML/md/Company.php @@ -4,9 +4,9 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\SAML2\XML\StringElementTrait; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class implementing Company. @@ -16,14 +16,8 @@ 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 f2a6f4bda..f1f48dbad 100644 --- a/src/XML/md/ContactPerson.php +++ b/src/XML/md/ContactPerson.php @@ -5,23 +5,22 @@ 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\{EmailAddressValue, 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\Exception\{InvalidDOMElementException, TooManyElementsException}; +use SimpleSAML\XML\{ExtendableAttributesTrait, SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use SimpleSAML\XML\XsNamespace as 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 +56,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 +66,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 +75,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 +89,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; } @@ -171,7 +170,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 +211,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 +245,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 +295,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 +320,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 +349,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..0b651b33c 100644 --- a/src/XML/md/EmailAddress.php +++ b/src/XML/md/EmailAddress.php @@ -4,17 +4,18 @@ 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\XML\ArrayizableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Type\EmailAddressValue; +use SimpleSAML\XML\{ + ArrayizableElementInterface, + SchemaValidatableElementInterface, + SchemaValidatableElementTrait, + TypedTextContentTrait, +}; use function array_key_first; use function preg_filter; -use function preg_replace; -use function trim; /** * Class implementing EmailAddress. @@ -26,60 +27,10 @@ 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 +40,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 +55,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/EncryptionMethod.php b/src/XML/md/EncryptionMethod.php index e76b61f16..c1d5c7902 100644 --- a/src/XML/md/EncryptionMethod.php +++ b/src/XML/md/EncryptionMethod.php @@ -4,8 +4,7 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use SimpleSAML\XMLSecurity\XML\xenc\AbstractEncryptionMethod; /** diff --git a/src/XML/md/EntitiesDescriptor.php b/src/XML/md/EntitiesDescriptor.php index 5c3d817f4..52f178fd9 100644 --- a/src/XML/md/EntitiesDescriptor.php +++ b/src/XML/md/EntitiesDescriptor.php @@ -4,18 +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\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\{SAMLDateTimeValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\mdrpi\{PublicationInfo, PublicationPath, 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\XML\Exception\{InvalidDOMElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\{DurationValue, IDValue}; use SimpleSAML\XMLSecurity\XML\ds\Signature; +use function count; +use function array_filter; +use function array_merge; +use function array_values; + /** * Class representing SAML 2 EntitiesDescriptor element. * @@ -30,19 +34,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\XML\Type\IDValue|null $ID + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil + * @param \SimpleSAML\XML\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( @@ -55,10 +59,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 * @@ -84,9 +188,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; } @@ -108,9 +212,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, @@ -138,10 +239,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, ); @@ -164,8 +265,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 c59a167db..b774fc969 100644 --- a/src/XML/md/EntityDescriptor.php +++ b/src/XML/md/EntityDescriptor.php @@ -4,17 +4,14 @@ 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\XML\ExtendableAttributesTrait; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Type\{SAMLDateTimeValue, EntityIDValue}; +use SimpleSAML\XML\Exception\{InvalidDOMElementException, TooManyElementsException}; +use SimpleSAML\XML\{ExtendableAttributesTrait, SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\{DurationValue, IDValue}; use SimpleSAML\XML\XsNamespace as NS; use SimpleSAML\XMLSecurity\XML\ds\Signature; @@ -37,10 +34,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\XML\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\XML\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 @@ -54,10 +53,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, @@ -71,7 +70,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, @@ -115,16 +113,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; @@ -191,10 +185,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, @@ -216,10 +210,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; } @@ -289,7 +282,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 54731410b..f371431a0 100644 --- a/src/XML/md/Extensions.php +++ b/src/XML/md/Extensions.php @@ -5,28 +5,33 @@ 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; -use SimpleSAML\SAML2\XML\alg\SigningMethod; +use SimpleSAML\SAML2\XML\alg\{ + AbstractAlgElement as ALG, + DigestMethod, + SigningMethod, +}; use SimpleSAML\SAML2\XML\emd\RepublishRequest; use SimpleSAML\SAML2\XML\ExtensionsTrait; use SimpleSAML\SAML2\XML\idpdisc\DiscoveryResponse; use SimpleSAML\SAML2\XML\init\RequestInitiator; use SimpleSAML\SAML2\XML\mdattr\EntityAttributes; -use SimpleSAML\SAML2\XML\mdrpi\AbstractMdrpiElement as MDRPI; -use SimpleSAML\SAML2\XML\mdrpi\PublicationInfo; -use SimpleSAML\SAML2\XML\mdrpi\PublicationPath; -use SimpleSAML\SAML2\XML\mdrpi\RegistrationInfo; -use SimpleSAML\SAML2\XML\mdui\AbstractMduiElement as MDUI; -use SimpleSAML\SAML2\XML\mdui\DiscoHints; -use SimpleSAML\SAML2\XML\mdui\UIInfo; +use SimpleSAML\SAML2\XML\mdrpi\{ + AbstractMdrpiElement as MDRPI, + PublicationInfo, + PublicationPath, + RegistrationInfo, +}; +use SimpleSAML\SAML2\XML\mdui\{ + AbstractMduiElement as MDUI, + DiscoHints, + 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\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use function array_key_exists; diff --git a/src/XML/md/GivenName.php b/src/XML/md/GivenName.php index 8d9e606ef..8be023402 100644 --- a/src/XML/md/GivenName.php +++ b/src/XML/md/GivenName.php @@ -4,9 +4,9 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\SAML2\XML\StringElementTrait; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class implementing GivenName. @@ -16,14 +16,8 @@ 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 e6cada20e..2cd2e73d0 100644 --- a/src/XML/md/IDPSSODescriptor.php +++ b/src/XML/md/IDPSSODescriptor.php @@ -4,19 +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\Type\{SAMLAnyURIValue, 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\XML\Exception\{InvalidDOMElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\{BooleanValue, DurationValue, IDValue}; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function preg_split; +use function var_export; /** * Class representing SAML 2 IDPSSODescriptor. @@ -32,16 +31,16 @@ final class IDPSSODescriptor extends AbstractSSODescriptor implements SchemaVali * * @param \SimpleSAML\SAML2\XML\md\SingleSignOnService[] $singleSignOnService * @param string[] $protocolSupportEnumeration - * @param bool|null $wantAuthnRequestsSigned + * @param \SimpleSAML\XML\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\XML\Type\IDValue|null $ID + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil + * @param \SimpleSAML\XML\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,16 +52,16 @@ final class IDPSSODescriptor extends AbstractSSODescriptor implements SchemaVali public function __construct( protected array $singleSignOnService, array $protocolSupportEnumeration, - protected ?bool $wantAuthnRequestsSigned = null, + 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 = [], @@ -120,9 +119,9 @@ public function __construct( /** * Collect the value of the WantAuthnRequestsSigned-property * - * @return bool|null + * @return \SimpleSAML\XML\Type\BooleanValue|null */ - public function wantAuthnRequestsSigned(): ?bool + public function wantAuthnRequestsSigned(): ?BooleanValue { return $this->wantAuthnRequestsSigned; } @@ -202,8 +201,6 @@ public static function fromXML(DOMElement $xml): static 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( @@ -231,17 +228,17 @@ public static function fromXML(DOMElement $xml): static $idpssod = new static( SingleSignOnService::getChildrenOfClass($xml), - preg_split('/[\s]+/', trim($protocols)), - self::getOptionalBooleanAttribute($xml, 'WantAuthnRequestsSigned', null), + preg_split('/[\s]+/', trim($protocols->getValue())), + 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), @@ -269,8 +266,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..ba2d8c6a4 100644 --- a/src/XML/md/IndexedElementTrait.php +++ b/src/XML/md/IndexedElementTrait.php @@ -4,7 +4,7 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\Assert\Assert; +use SimpleSAML\XML\Type\{BooleanValue, UnsignedShortValue}; /** * Trait adding methods to handle elements that can be indexed. @@ -16,24 +16,24 @@ trait IndexedElementTrait /** * The index for this endpoint. * - * @var int + * @var \SimpleSAML\XML\Type\UnsignedShortValue */ - protected int $index; + protected UnsignedShortValue $index; /** * Whether this endpoint is the default. * - * @var bool|null + * @var \SimpleSAML\XML\Type\BooleanValue|null */ - protected ?bool $isDefault = null; + protected ?BooleanValue $isDefault = null; /** * Collect the value of the index property. * - * @return int + * @return \SimpleSAML\XML\Type\UnsignedShortValue */ - public function getIndex(): int + public function getIndex(): UnsignedShortValue { return $this->index; } @@ -42,12 +42,10 @@ public function getIndex(): int /** * Set the value of the index property. * - * @param int $index - * @throws \SimpleSAML\Assert\AssertionFailedException + * @param \SimpleSAML\XML\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 +53,9 @@ protected function setIndex(int $index): void /** * Collect the value of the isDefault property. * - * @return bool|null + * @return \SimpleSAML\XML\Type\BooleanValue|null */ - public function getIsDefault(): ?bool + public function getIsDefault(): ?BooleanValue { return $this->isDefault; } @@ -66,9 +64,9 @@ public function getIsDefault(): ?bool /** * Set the value of the isDefault property. * - * @param bool|null $flag + * @param \SimpleSAML\XML\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 c96473da5..e4b1ac3a2 100644 --- a/src/XML/md/KeyDescriptor.php +++ b/src/XML/md/KeyDescriptor.php @@ -5,15 +5,15 @@ 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\XML\Exception\{InvalidDOMElementException, MissingElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; +use function array_pop; + /** * Class representing a KeyDescriptor element. * @@ -27,19 +27,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); } @@ -48,9 +43,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; } @@ -96,23 +91,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), ); } @@ -129,7 +114,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 91b62e356..ddb2ce1b8 100644 --- a/src/XML/md/NameIDMappingService.php +++ b/src/XML/md/NameIDMappingService.php @@ -4,9 +4,9 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\Assert\Assert; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * Class representing an md:NameIDMappingService element. @@ -22,22 +22,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 7c75dce34..e9c3d748e 100644 --- a/src/XML/md/Organization.php +++ b/src/XML/md/Organization.php @@ -5,19 +5,14 @@ namespace SimpleSAML\SAML2\XML\md; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Exception\ArrayValidationException; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Exception\{ArrayValidationException, 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\Exception\{InvalidDOMElementException, MissingElementException, TooManyElementsException}; +use SimpleSAML\XML\{ExtendableAttributesTrait, SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use SimpleSAML\XML\XsNamespace as NS; use function array_change_key_case; diff --git a/src/XML/md/OrganizationDisplayName.php b/src/XML/md/OrganizationDisplayName.php index a30e05700..0c3084762 100644 --- a/src/XML/md/OrganizationDisplayName.php +++ b/src/XML/md/OrganizationDisplayName.php @@ -4,8 +4,7 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * A localized name representing an organization's name for display purposes. diff --git a/src/XML/md/OrganizationName.php b/src/XML/md/OrganizationName.php index 7891505fd..bd1d7e530 100644 --- a/src/XML/md/OrganizationName.php +++ b/src/XML/md/OrganizationName.php @@ -4,8 +4,7 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * A localized name representing an organization's name. diff --git a/src/XML/md/OrganizationURL.php b/src/XML/md/OrganizationURL.php index fd0210313..17db0c491 100644 --- a/src/XML/md/OrganizationURL.php +++ b/src/XML/md/OrganizationURL.php @@ -4,8 +4,7 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * A localized name representing an organization's url. diff --git a/src/XML/md/PDPDescriptor.php b/src/XML/md/PDPDescriptor.php index 6f150cee2..a7b538e7b 100644 --- a/src/XML/md/PDPDescriptor.php +++ b/src/XML/md/PDPDescriptor.php @@ -4,15 +4,13 @@ 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\{SAMLAnyURIValue, 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\XML\Exception\{InvalidDOMElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\{DurationValue, IDValue}; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function preg_split; @@ -33,11 +31,11 @@ final class PDPDescriptor extends AbstractRoleDescriptorType implements SchemaVa * @param string[] $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\XML\Type\IDValue|null $ID + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil + * @param \SimpleSAML\XML\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 @@ -48,11 +46,11 @@ public function __construct( array $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 = [], @@ -141,8 +139,6 @@ public static function fromXML(DOMElement $xml): static 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( @@ -165,14 +161,14 @@ public static function fromXML(DOMElement $xml): static $pdp = new static( AuthzService::getChildrenOfClass($xml), - preg_split('/[\s]+/', trim($protocols)), + preg_split('/[\s]+/', trim($protocols->getValue())), 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..40df3d685 100644 --- a/src/XML/md/RequestedAttribute.php +++ b/src/XML/md/RequestedAttribute.php @@ -5,12 +5,12 @@ namespace SimpleSAML\SAML2\XML\md; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLStringValue}; use SimpleSAML\SAML2\XML\saml\Attribute; use SimpleSAML\SAML2\XML\saml\AttributeValue; use SimpleSAML\XML\Exception\InvalidDOMElementException; - -use function is_bool; +use SimpleSAML\XML\Type\BooleanValue; /** * Class representing SAML 2 metadata RequestedAttribute. @@ -32,17 +32,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\XML\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 +52,9 @@ public function __construct( /** * Collect the value of the isRequired-property * - * @return bool|null + * @return \SimpleSAML\XML\Type\BooleanValue|null */ - public function getIsRequired(): ?bool + public function getIsRequired(): ?BooleanValue { return $this->isRequired; } @@ -77,10 +77,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 +96,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 ec6e20521..d423623e5 100644 --- a/src/XML/md/SPSSODescriptor.php +++ b/src/XML/md/SPSSODescriptor.php @@ -4,20 +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\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; 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\XML\Exception\{InvalidDOMElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\{BooleanValue, DurationValue, 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,14 +31,14 @@ final class SPSSODescriptor extends AbstractSSODescriptor implements SchemaValid * * @param array<\SimpleSAML\SAML2\XML\md\AssertionConsumerService> $assertionConsumerService * @param string[] $protocolSupportEnumeration - * @param bool|null $authnRequestsSigned - * @param bool|null $wantAssertionsSigned + * @param \SimpleSAML\XML\Type\BooleanValue|null $authnRequestsSigned + * @param \SimpleSAML\XML\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\XML\Type\IDValue|null $ID + * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil + * @param \SimpleSAML\XML\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,14 +50,14 @@ final class SPSSODescriptor extends AbstractSSODescriptor implements SchemaValid public function __construct( protected array $assertionConsumerService, array $protocolSupportEnumeration, - protected ?bool $authnRequestsSigned = null, - protected ?bool $wantAssertionsSigned = null, + 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 = [], @@ -103,7 +101,7 @@ public function __construct( array_filter( $attributeConsumingService, function (AttributeConsumingService $acs) { - return $acs->getIsDefault() === true; + return $acs->getIsDefault()?->toBoolean() === true; }, ), 1, @@ -115,9 +113,9 @@ function (AttributeConsumingService $acs) { /** * Collect the value of the AuthnRequestsSigned-property * - * @return bool|null + * @return \SimpleSAML\XML\Type\BooleanValue|null */ - public function getAuthnRequestsSigned(): ?bool + public function getAuthnRequestsSigned(): ?BooleanValue { return $this->authnRequestsSigned; } @@ -126,9 +124,9 @@ public function getAuthnRequestsSigned(): ?bool /** * Collect the value of the WantAssertionsSigned-property * - * @return bool|null + * @return \SimpleSAML\XML\Type\BooleanValue|null */ - public function getWantAssertionsSigned(): ?bool + public function getWantAssertionsSigned(): ?BooleanValue { return $this->wantAssertionsSigned; } @@ -174,9 +172,7 @@ 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); + $protocols = self::getAttribute($xml, 'protocolSupportEnumeration', SAMLStringValue::class); $orgs = Organization::getChildrenOfClass($xml); Assert::maxCount( @@ -204,15 +200,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), + preg_split('/[\s]+/', trim($protocols->getValue())), + 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), @@ -241,12 +237,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/ServiceDescription.php b/src/XML/md/ServiceDescription.php index f749c6ac9..f10807683 100644 --- a/src/XML/md/ServiceDescription.php +++ b/src/XML/md/ServiceDescription.php @@ -4,8 +4,7 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * A localized name representing a service's description. diff --git a/src/XML/md/ServiceName.php b/src/XML/md/ServiceName.php index 58f0cf3fd..6c3f98e3b 100644 --- a/src/XML/md/ServiceName.php +++ b/src/XML/md/ServiceName.php @@ -4,8 +4,7 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * A localized name representing a service's name. diff --git a/src/XML/md/SingleSignOnService.php b/src/XML/md/SingleSignOnService.php index 2e749d92b..e00e3e3f0 100644 --- a/src/XML/md/SingleSignOnService.php +++ b/src/XML/md/SingleSignOnService.php @@ -4,9 +4,10 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\Assert\Assert; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * Class representing an md:SingleSignOnService element. @@ -22,21 +23,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..f2a3143a7 100644 --- a/src/XML/md/SurName.php +++ b/src/XML/md/SurName.php @@ -4,9 +4,9 @@ namespace SimpleSAML\SAML2\XML\md; -use SimpleSAML\SAML2\XML\StringElementTrait; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class implementing SurName. @@ -16,14 +16,8 @@ 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..9734d09c2 100644 --- a/src/XML/md/TelephoneNumber.php +++ b/src/XML/md/TelephoneNumber.php @@ -4,12 +4,15 @@ 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\XML\ArrayizableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\XML\{ + ArrayizableElementInterface, + SchemaValidatableElementInterface, + SchemaValidatableElementTrait, + TypedTextContentTrait, +}; use function array_key_first; @@ -23,16 +26,10 @@ 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 +43,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 +56,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..47518534d 100644 --- a/src/XML/md/UnknownRoleDescriptor.php +++ b/src/XML/md/UnknownRoleDescriptor.php @@ -4,9 +4,10 @@ namespace SimpleSAML\SAML2\XML\md; -use DateTimeImmutable; use DOMElement; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue}; use SimpleSAML\XML\Chunk; +use SimpleSAML\XML\Type\{DurationValue, IDValue, QNameValue}; /** * Class representing unknown RoleDescriptors. @@ -19,13 +20,16 @@ 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 \SimpleSAML\XML\Type\QNameValue $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\XML\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\XML\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 +40,13 @@ final class UnknownRoleDescriptor extends AbstractRoleDescriptor */ protected function __construct( protected Chunk $chunk, - string $type, + QNameValue $type, array $protocolSupportEnumeration, - ?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 = [], diff --git a/src/XML/mdattr/EntityAttributes.php b/src/XML/mdattr/EntityAttributes.php index 2b8c62ccc..fba14d13d 100644 --- a/src/XML/mdattr/EntityAttributes.php +++ b/src/XML/mdattr/EntityAttributes.php @@ -5,16 +5,12 @@ 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\SAML2\XML\saml\{Assertion, Attribute, AttributeStatement, NameID}; use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use function array_filter; use function array_merge; @@ -79,7 +75,7 @@ public function __construct( ); Assert::isEmpty( - $subject?->getSubjectConfirmation(), + $subject->getSubjectConfirmation(), 'Every inside a must NOT contain any SubjectConfirmation', ProtocolViolationException::class, ); @@ -93,7 +89,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, diff --git a/src/XML/mdrpi/Publication.php b/src/XML/mdrpi/Publication.php index 8427855c7..b2dc55fbc 100644 --- a/src/XML/mdrpi/Publication.php +++ b/src/XML/mdrpi/Publication.php @@ -4,19 +4,13 @@ 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\Exception\ArrayValidationException; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Exception\{ArrayValidationException, ProtocolViolationException}; +use SimpleSAML\SAML2\Type\{SAMLDateTimeValue, SAMLStringValue}; use SimpleSAML\XML\ArrayizableElementInterface; use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; - -use function preg_replace; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * Class for handling the mdrpi:Publication element. @@ -33,25 +27,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; } @@ -60,9 +53,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; } @@ -71,9 +64,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; } @@ -95,19 +88,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); } @@ -122,14 +105,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; @@ -147,9 +130,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, ); } @@ -177,8 +160,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)) { @@ -198,14 +181,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 9cac21319..3382d3d53 100644 --- a/src/XML/mdrpi/PublicationInfo.php +++ b/src/XML/mdrpi/PublicationInfo.php @@ -4,21 +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\Exception\{ArrayValidationException, ProtocolViolationException}; +use SimpleSAML\SAML2\Type\{SAMLDateTimeValue, SAMLStringValue}; use SimpleSAML\XML\ArrayizableElementInterface; use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use function array_change_key_case; use function array_keys; -use function preg_replace; /** * Class for handling the mdrpi:PublicationInfo element. @@ -35,18 +31,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); @@ -72,9 +67,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; } @@ -83,9 +78,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; } @@ -94,9 +89,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; } @@ -129,19 +124,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); @@ -157,14 +142,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) { @@ -186,9 +171,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'] ?? [], ); } @@ -217,8 +202,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)) { @@ -245,14 +230,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 9bc2ce4cc..4d87ac625 100644 --- a/src/XML/mdrpi/PublicationPath.php +++ b/src/XML/mdrpi/PublicationPath.php @@ -5,13 +5,12 @@ 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\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * Class for handling the mdrpi:PublicationPath element. diff --git a/src/XML/mdrpi/RegistrationInfo.php b/src/XML/mdrpi/RegistrationInfo.php index d2ffaaee4..4c033eb8f 100644 --- a/src/XML/mdrpi/RegistrationInfo.php +++ b/src/XML/mdrpi/RegistrationInfo.php @@ -4,19 +4,14 @@ 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\Exception\{ArrayValidationException, ProtocolViolationException}; +use SimpleSAML\SAML2\Type\{SAMLDateTimeValue, SAMLStringValue}; use SimpleSAML\XML\ArrayizableElementInterface; use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; - -use function preg_replace; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * Class for handling the mdrpi:RegistrationInfo element. @@ -33,16 +28,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); @@ -68,9 +62,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; } @@ -79,9 +73,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; } @@ -114,17 +108,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); @@ -140,10 +125,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) { @@ -165,8 +150,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'] ?? [], ); } @@ -195,8 +180,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)) { @@ -218,10 +203,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 937b72876..bf6220a8c 100644 --- a/src/XML/mdui/DiscoHints.php +++ b/src/XML/mdui/DiscoHints.php @@ -5,17 +5,15 @@ 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, DomainValue, 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\{SchemaValidatableElementInterface, SchemaValidatableElementTrait, SerializableElementInterface}; use SimpleSAML\XML\XsNamespace as NS; use function array_filter; @@ -115,10 +113,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()); } @@ -139,13 +137,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); } @@ -230,7 +222,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), + ); } } @@ -238,7 +232,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), + ); } } @@ -246,7 +242,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..a488ddf57 100644 --- a/src/XML/mdui/DomainHint.php +++ b/src/XML/mdui/DomainHint.php @@ -4,17 +4,9 @@ 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\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; - -use function filter_var; -use function preg_replace; -use function rtrim; -use function sprintf; +use SimpleSAML\SAML2\Type\DomainValue; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class implementing DomainHint. @@ -24,46 +16,8 @@ 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/"); - } - - - /** - * 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); + use TypedTextContentTrait; - 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..684fcd00c 100644 --- a/src/XML/mdui/GeolocationHint.php +++ b/src/XML/mdui/GeolocationHint.php @@ -4,12 +4,9 @@ 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\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Type\GeolocationValue; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class implementing GeolocationHint. @@ -19,62 +16,8 @@ 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..eb8a17d54 100644 --- a/src/XML/mdui/IPHint.php +++ b/src/XML/mdui/IPHint.php @@ -4,9 +4,9 @@ namespace SimpleSAML\SAML2\XML\mdui; -use SimpleSAML\SAML2\XML\StringElementTrait; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Type\CIDRValue; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class implementing IPHint. @@ -16,14 +16,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 58a2aaf15..c57db4960 100644 --- a/src/XML/mdui/Keywords.php +++ b/src/XML/mdui/Keywords.php @@ -5,18 +5,16 @@ namespace SimpleSAML\SAML2\XML\mdui; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Exception\ArrayValidationException; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Exception\{ArrayValidationException, 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\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\LanguageValue; +use SimpleSAML\XML\TypedTextContentTrait; 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,58 +27,37 @@ 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\XML\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\XML\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 * @@ -98,8 +75,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); } @@ -116,8 +93,8 @@ 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; } @@ -134,10 +111,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()]; + + Assert::allNotContains($keywords, '+', ProtocolViolationException::class); - return new static($lang, $keywords); + return new static($lang, ListOfStringsValue::fromArray($keywords)); } @@ -148,6 +127,6 @@ public static function fromArray(array $data): static */ public function toArray(): array { - return [$this->getLanguage() => $this->getKeywords()]; + return [$this->getLanguage()->getValue() => $this->getContent()->toArray()]; } } diff --git a/src/XML/mdui/Logo.php b/src/XML/mdui/Logo.php index 2c553d356..c73129a41 100644 --- a/src/XML/mdui/Logo.php +++ b/src/XML/mdui/Logo.php @@ -5,21 +5,14 @@ namespace SimpleSAML\SAML2\XML\mdui; use DOMElement; -use InvalidArgumentException; -use SimpleSAML\Assert\Assert; -//use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; -use SimpleSAML\SAML2\Exception\ArrayValidationException; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\StringElementTrait; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Exception\{ArrayValidationException, ProtocolViolationException}; +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\Exception\{InvalidDOMElementException, SchemaViolationException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\{LanguageValue, PositiveIntegerValue}; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class for handling the Logo metadata extensions for login and discovery user interface @@ -32,22 +25,28 @@ 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\XML\Type\PositiveIntegerValue $height + * @param \SimpleSAML\XML\Type\PositiveIntegerValue $width + * @param \SimpleSAML\XML\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 +61,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\XML\Type\LanguageValue|null */ - public function getLanguage(): ?string + public function getLanguage(): ?LanguageValue { return $this->lang; } @@ -85,9 +80,9 @@ public function getLanguage(): ?string /** * Collect the value of the height-property * - * @return int + * @return \SimpleSAML\XML\Type\PositiveIntegerValue */ - public function getHeight(): int + public function getHeight(): PositiveIntegerValue { return $this->height; } @@ -96,9 +91,9 @@ public function getHeight(): int /** * Collect the value of the width-property * - * @return int + * @return \SimpleSAML\XML\Type\PositiveIntegerValue */ - public function getWidth(): int + public function getWidth(): PositiveIntegerValue { return $this->width; } @@ -121,10 +116,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 +134,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 +156,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 +217,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 8e493b4b7..5e671e2e7 100644 --- a/src/XML/mdui/UIInfo.php +++ b/src/XML/mdui/UIInfo.php @@ -5,18 +5,14 @@ namespace SimpleSAML\SAML2\XML\mdui; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Exception\ArrayValidationException; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\Utils\XPath; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Exception\{ArrayValidationException, ProtocolViolationException}; 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\{SchemaValidatableElementInterface, SchemaValidatableElementTrait, SerializableElementInterface}; use SimpleSAML\XML\XsNamespace as NS; use function array_filter; @@ -220,20 +216,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 @@ -280,14 +276,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 330c06e4b..c56f961ca 100644 --- a/src/XML/saml/AbstractBaseID.php +++ b/src/XML/saml/AbstractBaseID.php @@ -8,21 +8,16 @@ use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Utils; -use SimpleSAML\SAML2\XML\EncryptableElementTrait; -use SimpleSAML\SAML2\XML\ExtensionPointInterface; -use SimpleSAML\SAML2\XML\ExtensionPointTrait; +use SimpleSAML\SAML2\XML\{EncryptableElementTrait, ExtensionPointInterface, ExtensionPointTrait}; +use SimpleSAML\SAML2\Type\SAMLStringValue; 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\XML\Exception\{InvalidDOMElementException, SchemaViolationException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\QNameValue; use SimpleSAML\XMLSecurity\Backend\EncryptionBackend; use SimpleSAML\XMLSecurity\XML\EncryptableElementInterface; -use function count; -use function explode; - /** * SAML BaseID data type. * @@ -44,23 +39,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\XML\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\XML\Type\QNameValue */ - public function getXsiType(): string + public function getXsiType(): QNameValue { return $this->type; } @@ -85,19 +80,7 @@ public static function fromXML(DOMElement $xml): static 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::NS_XSI, 'type'), $xml); // now check if we have a handler registered for it $handler = Utils::getContainer()->getExtensionHandler($type); @@ -106,8 +89,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), ); } @@ -132,18 +115,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->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 d35320834..4031b3acf 100644 --- a/src/XML/saml/AbstractCondition.php +++ b/src/XML/saml/AbstractCondition.php @@ -8,17 +8,12 @@ use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Utils; -use SimpleSAML\SAML2\XML\ExtensionPointInterface; -use SimpleSAML\SAML2\XML\ExtensionPointTrait; +use SimpleSAML\SAML2\XML\{ExtensionPointInterface, 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\XML\Exception\{InvalidDOMElementException, SchemaViolationException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\QNameValue; /** * SAML Condition data type. @@ -39,18 +34,18 @@ abstract class AbstractCondition extends AbstractConditionType implements /** * Initialize a custom saml:Condition element. * - * @param string $type + * @param \SimpleSAML\XML\Type\QNameValue $type */ protected function __construct( - protected string $type, + protected QNameValue $type, ) { } /** - * @inheritDoc + * @return \SimpleSAML\XML\Type\QNameValue */ - public function getXsiType(): string + public function getXsiType(): QNameValue { return $this->type; } @@ -75,19 +70,7 @@ public static function fromXML(DOMElement $xml): static 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::NS_XSI, 'type'), $xml); // now check if we have a handler registered for it $handler = Utils::getContainer()->getExtensionHandler($type); @@ -117,7 +100,7 @@ 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()); diff --git a/src/XML/saml/AbstractStatement.php b/src/XML/saml/AbstractStatement.php index 61d427b9e..f387208a4 100644 --- a/src/XML/saml/AbstractStatement.php +++ b/src/XML/saml/AbstractStatement.php @@ -8,17 +8,12 @@ use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Utils; -use SimpleSAML\SAML2\XML\ExtensionPointInterface; -use SimpleSAML\SAML2\XML\ExtensionPointTrait; +use SimpleSAML\SAML2\XML\{ExtensionPointInterface, 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\XML\Exception\{InvalidDOMElementException, SchemaViolationException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\QNameValue; /** * Class implementing the extension point. @@ -39,18 +34,18 @@ abstract class AbstractStatement extends AbstractStatementType implements /** * Initialize a custom saml:Statement element. * - * @param string $type + * @param \SimpleSAML\XML\Type\QNameValue $type */ protected function __construct( - protected string $type, + protected QNameValue $type, ) { } /** - * @inheritDoc + * @return \SimpleSAML\XML\Type\QNameValue */ - public function getXsiType(): string + public function getXsiType(): QNameValue { return $this->type; } @@ -75,19 +70,7 @@ public static function fromXML(DOMElement $xml): static 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::NS_XSI, 'type'), $xml); // now check if we have a handler registered for it $handler = Utils::getContainer()->getExtensionHandler($type); @@ -117,7 +100,7 @@ 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()); diff --git a/src/XML/saml/Action.php b/src/XML/saml/Action.php index 7621ad65a..69cae0aae 100644 --- a/src/XML/saml/Action.php +++ b/src/XML/saml/Action.php @@ -5,10 +5,12 @@ 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\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLStringValue}; use SimpleSAML\XML\Exception\InvalidDOMElementException; +use SimpleSAML\XML\TypedTextContentTrait; + +use function strval; /** * Class representing SAML2 Action @@ -17,21 +19,23 @@ */ 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: This 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 +43,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; } @@ -62,8 +66,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 +82,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 f5e2df2c3..32a52d4ec 100644 --- a/src/XML/saml/Advice.php +++ b/src/XML/saml/Advice.php @@ -5,13 +5,10 @@ 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\Exception\{InvalidDOMElementException, SchemaViolationException}; +use SimpleSAML\XML\{ExtendableElementTrait, SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use SimpleSAML\XML\XsNamespace as NS; /** diff --git a/src/XML/saml/Assertion.php b/src/XML/saml/Assertion.php index 224a27b5f..a3f320ba8 100644 --- a/src/XML/saml/Assertion.php +++ b/src/XML/saml/Assertion.php @@ -4,31 +4,26 @@ 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, RequestVersionTooLowException}; +use SimpleSAML\SAML2\Type\{SAMLDateTimeValue, 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\SAML2\XML\{EncryptableElementTrait, SignableElementTrait, SignedElementTrait}; +use SimpleSAML\XML\Exception\{InvalidDOMElementException, MissingElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\Backend\EncryptionBackend; use SimpleSAML\XMLSecurity\XML\ds\Signature; use SimpleSAML\XMLSecurity\XML\EncryptableElementInterface; -use SimpleSAML\XMLSecurity\XML\SignableElementInterface; -use SimpleSAML\XMLSecurity\XML\SignedElementInterface; +use SimpleSAML\XMLSecurity\XML\{SignableElementInterface, SignedElementInterface}; use function array_filter; use function array_merge; use function array_pop; use function array_values; +use function strval; /** * Class representing a SAML 2 assertion. @@ -67,29 +62,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\XML\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 +143,10 @@ public function getStatements(): array /** * Retrieve the identifier of this assertion. * - * @return string The identifier of this assertion. + * @return \SimpleSAML\XML\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 +154,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; } @@ -252,17 +240,10 @@ 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 +274,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 +302,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..77d1fbd73 100644 --- a/src/XML/saml/AssertionIDRef.php +++ b/src/XML/saml/AssertionIDRef.php @@ -4,11 +4,9 @@ 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\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\NCNameValue; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class representing a saml:AssertionIDRef element. @@ -18,30 +16,8 @@ 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..1afa94808 100644 --- a/src/XML/saml/AssertionURIRef.php +++ b/src/XML/saml/AssertionURIRef.php @@ -4,9 +4,9 @@ namespace SimpleSAML\SAML2\XML\saml; -use SimpleSAML\SAML2\XML\URIElementTrait; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class representing a saml:AssertionURIRef element. @@ -16,14 +16,8 @@ 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 0873c9139..efbd83632 100644 --- a/src/XML/saml/Attribute.php +++ b/src/XML/saml/Attribute.php @@ -7,15 +7,17 @@ use DOMElement; use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, 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\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use SimpleSAML\XML\XsNamespace as NS; use SimpleSAML\XMLSecurity\Backend\EncryptionBackend; use SimpleSAML\XMLSecurity\XML\EncryptableElementInterface; +use function strval; + /** * Class representing SAML 2 Attribute. * @@ -36,35 +38,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); @@ -74,9 +76,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; } @@ -85,9 +87,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; } @@ -96,9 +98,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; } @@ -140,9 +142,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), ); @@ -158,14 +160,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 b1f6bdee8..9a9d02442 100644 --- a/src/XML/saml/AttributeStatement.php +++ b/src/XML/saml/AttributeStatement.php @@ -5,11 +5,10 @@ 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\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * Class representing a SAML2 AttributeStatement diff --git a/src/XML/saml/AttributeValue.php b/src/XML/saml/AttributeValue.php index b17fdf934..c1cf29610 100644 --- a/src/XML/saml/AttributeValue.php +++ b/src/XML/saml/AttributeValue.php @@ -12,8 +12,7 @@ use SimpleSAML\XML\AbstractElement; use SimpleSAML\XML\Chunk; use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use function class_exists; use function explode; diff --git a/src/XML/saml/Audience.php b/src/XML/saml/Audience.php index 30b56494f..713066a7d 100644 --- a/src/XML/saml/Audience.php +++ b/src/XML/saml/Audience.php @@ -4,10 +4,9 @@ namespace SimpleSAML\SAML2\XML\saml; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; -use SimpleSAML\SAML2\XML\URIElementTrait; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class representing a saml:Audience element. @@ -17,27 +16,8 @@ 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 b7e172980..0098b4603 100644 --- a/src/XML/saml/AudienceRestriction.php +++ b/src/XML/saml/AudienceRestriction.php @@ -5,12 +5,10 @@ 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\XML\Exception\{InvalidDOMElementException, SchemaViolationException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * SAML AudienceRestriction data type. diff --git a/src/XML/saml/AuthenticatingAuthority.php b/src/XML/saml/AuthenticatingAuthority.php index 2fabef427..1f2d52ed2 100644 --- a/src/XML/saml/AuthenticatingAuthority.php +++ b/src/XML/saml/AuthenticatingAuthority.php @@ -4,10 +4,9 @@ namespace SimpleSAML\SAML2\XML\saml; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; -use SimpleSAML\SAML2\XML\URIElementTrait; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class representing a saml:AuthenticatingAuthority element. @@ -17,27 +16,8 @@ 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 a13c8471b..594727165 100644 --- a/src/XML/saml/AuthnContext.php +++ b/src/XML/saml/AuthnContext.php @@ -5,15 +5,11 @@ namespace SimpleSAML\SAML2\XML\saml; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\XML\saml\AuthnContextClassRef; -use SimpleSAML\SAML2\XML\saml\AuthnContextDecl; -use SimpleSAML\SAML2\XML\saml\AuthnContextDeclRef; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\XML\saml\{AuthnContextClassRef, AuthnContextDecl, 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\XML\Exception\{InvalidDOMElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use function array_pop; use function is_null; diff --git a/src/XML/saml/AuthnContextClassRef.php b/src/XML/saml/AuthnContextClassRef.php index 7f8720756..ecebd4600 100644 --- a/src/XML/saml/AuthnContextClassRef.php +++ b/src/XML/saml/AuthnContextClassRef.php @@ -4,9 +4,9 @@ namespace SimpleSAML\SAML2\XML\saml; -use SimpleSAML\SAML2\XML\URIElementTrait; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class representing SAML2 AuthnContextClassRef @@ -16,14 +16,8 @@ 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 46f14c715..da757f6ae 100644 --- a/src/XML/saml/AuthnContextDecl.php +++ b/src/XML/saml/AuthnContextDecl.php @@ -5,13 +5,15 @@ namespace SimpleSAML\SAML2\XML\saml; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; 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\XML\{ + ExtendableAttributesTrait, + ExtendableElementTrait, + SchemaValidatableElementInterface, + SchemaValidatableElementTrait, + XsNamespace as NS, +}; /** * Class representing SAML2 AuthnContextDecl diff --git a/src/XML/saml/AuthnContextDeclRef.php b/src/XML/saml/AuthnContextDeclRef.php index a8983b35b..4f1728380 100644 --- a/src/XML/saml/AuthnContextDeclRef.php +++ b/src/XML/saml/AuthnContextDeclRef.php @@ -4,9 +4,8 @@ namespace SimpleSAML\SAML2\XML\saml; -use SimpleSAML\SAML2\XML\URIElementTrait; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait, TypedTextContentTrait}; /** * Class representing SAML2 AuthnContextDeclRef @@ -16,14 +15,8 @@ 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 1aa9cdef1..b1d4708ba 100644 --- a/src/XML/saml/AuthnStatement.php +++ b/src/XML/saml/AuthnStatement.php @@ -4,20 +4,13 @@ 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\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\{SAMLDateTimeValue, SAMLStringValue}; +use SimpleSAML\XML\Exception\{InvalidDOMElementException, MissingElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use function array_pop; -use function preg_replace; /** * Class representing a SAML2 AuthnStatement @@ -32,20 +25,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); } @@ -64,9 +55,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; } @@ -75,9 +66,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; } @@ -86,9 +77,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; } @@ -136,29 +127,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), ); } @@ -180,14 +155,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 467bc7334..d11359842 100644 --- a/src/XML/saml/AuthzDecisionStatement.php +++ b/src/XML/saml/AuthzDecisionStatement.php @@ -5,17 +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\Type\SAMLStringValue; 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\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\Exception\{ + InvalidDOMElementException, + MissingElementException, + SchemaViolationException, + TooManyElementsException, +}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\AnyURIValue; use ValueError; use function array_pop; @@ -33,18 +35,18 @@ final class AuthzDecisionStatement extends AbstractStatementType implements Sche /** * Initialize an AuthzDecisionStatement. * - * @param string $resource + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $resource * @param \SimpleSAML\SAML2\XML\Decision $decision * @param \SimpleSAML\SAML2\XML\saml\Action[] $action * @param \SimpleSAML\SAML2\XML\saml\Evidence|null $evidence */ public function __construct( - protected string $resource, + // Uses the base AnyURIValue because the SAML-specification allows this attribute to be an empty string + protected AnyURIValue $resource, protected Decision $decision, protected array $action, protected ?Evidence $evidence = null, ) { - SAMLAssert::validURI($resource); Assert::maxCount($action, C::UNBOUNDED_LIMIT); Assert::allIsInstanceOf($action, Action::class, SchemaViolationException::class); } @@ -53,9 +55,9 @@ public function __construct( /** * Collect the value of the resource-property * - * @return string + * @return \SimpleSAML\XML\Type\AnyURIValue */ - public function getResource(): string + public function getResource(): AnyURIValue { return $this->resource; } @@ -127,15 +129,15 @@ public static function fromXML(DOMElement $xml): static TooManyElementsException::class, ); - $decision = self::getAttribute($xml, 'Decision'); + $decision = self::getAttribute($xml, 'Decision', SAMLStringValue::class); try { - $decision = Decision::from($decision); + $decision = Decision::from($decision->getValue()); } catch (ValueError) { throw new ProtocolViolationException(sprintf('Unknown value \'%s\' for Decision attribute.', $decision)); } return new static( - self::getAttribute($xml, 'Resource'), + self::getAttribute($xml, 'Resource', AnyURIValue::class), $decision, $action, array_pop($evidence), @@ -153,7 +155,7 @@ public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); - $e->setAttribute('Resource', $this->getResource()); + $e->setAttribute('Resource', $this->getResource()->getValue()); $e->setAttribute('Decision', $this->getDecision()->value); foreach ($this->getAction() as $action) { 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 800e1c15e..bfd751b80 100644 --- a/src/XML/saml/Conditions.php +++ b/src/XML/saml/Conditions.php @@ -4,15 +4,13 @@ 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\SAML2\Type\SAMLDateTimeValue; use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use function array_pop; @@ -28,23 +26,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); @@ -55,9 +51,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; } @@ -66,9 +62,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; } @@ -125,12 +121,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()); } @@ -148,22 +144,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); @@ -183,8 +163,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), @@ -204,11 +184,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/EncryptedAssertion.php b/src/XML/saml/EncryptedAssertion.php index bee518f44..db17b84fd 100644 --- a/src/XML/saml/EncryptedAssertion.php +++ b/src/XML/saml/EncryptedAssertion.php @@ -5,9 +5,7 @@ namespace SimpleSAML\SAML2\XML\saml; use SimpleSAML\SAML2\XML\EncryptedElementTrait; -use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{DOMDocumentFactory, SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use SimpleSAML\XMLSecurity\Alg\Encryption\EncryptionAlgorithmInterface; use SimpleSAML\XMLSecurity\XML\EncryptedElementInterface; diff --git a/src/XML/saml/EncryptedAttribute.php b/src/XML/saml/EncryptedAttribute.php index dfa6c84c2..fda37fa72 100644 --- a/src/XML/saml/EncryptedAttribute.php +++ b/src/XML/saml/EncryptedAttribute.php @@ -5,9 +5,7 @@ namespace SimpleSAML\SAML2\XML\saml; use SimpleSAML\SAML2\XML\EncryptedElementTrait; -use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{DOMDocumentFactory, SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use SimpleSAML\XMLSecurity\Alg\Encryption\EncryptionAlgorithmInterface; use SimpleSAML\XMLSecurity\XML\EncryptedElementInterface; diff --git a/src/XML/saml/EncryptedID.php b/src/XML/saml/EncryptedID.php index 4641cfd05..7f68e4ea7 100644 --- a/src/XML/saml/EncryptedID.php +++ b/src/XML/saml/EncryptedID.php @@ -6,10 +6,12 @@ use InvalidArgumentException; use SimpleSAML\SAML2\XML\EncryptedElementTrait; -use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; -use SimpleSAML\XML\SerializableElementInterface; +use SimpleSAML\XML\{ + DOMDocumentFactory, + SchemaValidatableElementInterface, + SchemaValidatableElementTrait, + SerializableElementInterface, +}; use SimpleSAML\XMLSecurity\Alg\Encryption\EncryptionAlgorithmInterface; use SimpleSAML\XMLSecurity\XML\EncryptedElementInterface; diff --git a/src/XML/saml/Evidence.php b/src/XML/saml/Evidence.php index 58c2783c4..5f9ec1b3c 100644 --- a/src/XML/saml/Evidence.php +++ b/src/XML/saml/Evidence.php @@ -5,12 +5,10 @@ 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\XML\Exception\{InvalidDOMElementException, SchemaViolationException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * Class representing a saml:Evidence element. 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 7112663d7..5b5597c23 100644 --- a/src/XML/saml/Issuer.php +++ b/src/XML/saml/Issuer.php @@ -4,11 +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\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLStringValue}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * Class representing the saml:Issuer element. @@ -22,18 +22,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. @@ -56,13 +56,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 812afec52..b0531e5e0 100644 --- a/src/XML/saml/NameID.php +++ b/src/XML/saml/NameID.php @@ -4,12 +4,12 @@ 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\XML\EncryptableElementTrait; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLStringValue}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use SimpleSAML\XMLSecurity\Backend\EncryptionBackend; use SimpleSAML\XMLSecurity\XML\EncryptableElementInterface; @@ -33,48 +33,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); @@ -100,11 +105,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, ); } @@ -169,11 +174,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..b108bd844 100644 --- a/src/XML/saml/NameIDType.php +++ b/src/XML/saml/NameIDType.php @@ -5,10 +5,12 @@ 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\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLStringValue}; use SimpleSAML\XML\Exception\InvalidDOMElementException; +use SimpleSAML\XML\TypedTextContentTrait; + +use function strval; /** * SAML NameIDType abstract data type. @@ -19,30 +21,28 @@ 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 +50,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,27 +61,14 @@ 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 * @@ -96,12 +83,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 +102,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 bbecfcd92..2f2c48c9a 100644 --- a/src/XML/saml/OneTimeUse.php +++ b/src/XML/saml/OneTimeUse.php @@ -5,10 +5,9 @@ namespace SimpleSAML\SAML2\XML\saml; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * Class representing a saml:OneTimeUse element. diff --git a/src/XML/saml/ProxyRestriction.php b/src/XML/saml/ProxyRestriction.php index 99f6370b8..fbbf0335c 100644 --- a/src/XML/saml/ProxyRestriction.php +++ b/src/XML/saml/ProxyRestriction.php @@ -5,13 +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 function strval; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\NonNegativeIntegerValue; /** * @package simplesamlphp/saml2 @@ -24,13 +22,12 @@ final class ProxyRestriction extends AbstractConditionType implements SchemaVali * ProxyRestriction constructor. * * @param \SimpleSAML\SAML2\XML\saml\Audience[] $audience - * @param int|null $count + * @param \SimpleSAML\XML\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); } @@ -39,9 +36,9 @@ public function __construct( /** * Get the value of the count-attribute. * - * @return int|null + * @return \SimpleSAML\XML\Type\NonNegativeIntegerValue|null */ - public function getCount(): ?int + public function getCount(): ?NonNegativeIntegerValue { return $this->count; } @@ -70,7 +67,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); @@ -88,7 +85,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 6ed9f7478..359d769ba 100644 --- a/src/XML/saml/Subject.php +++ b/src/XML/saml/Subject.php @@ -5,13 +5,11 @@ 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\XML\Exception\{InvalidDOMElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * Class representing SAML 2 Subject element. diff --git a/src/XML/saml/SubjectConfirmation.php b/src/XML/saml/SubjectConfirmation.php index 4b6af1c29..5d1a4293b 100644 --- a/src/XML/saml/SubjectConfirmation.php +++ b/src/XML/saml/SubjectConfirmation.php @@ -5,13 +5,11 @@ 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\XML\Exception\{InvalidDOMElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use function array_pop; @@ -28,16 +26,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); } @@ -45,9 +42,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; } @@ -82,10 +79,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, @@ -94,8 +88,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), ); } @@ -110,7 +104,7 @@ 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 */ $identifier = $this->getIdentifier(); diff --git a/src/XML/saml/SubjectConfirmationData.php b/src/XML/saml/SubjectConfirmationData.php index e8522141b..36628e8ed 100644 --- a/src/XML/saml/SubjectConfirmationData.php +++ b/src/XML/saml/SubjectConfirmationData.php @@ -4,22 +4,18 @@ 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\{SAMLDateTimeValue, EntityIDValue, 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\{ExtendableAttributesTrait, ExtendableElementTrait}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\NCNameValue; use SimpleSAML\XML\XsNamespace as NS; -use function filter_var; -use function is_null; +use function strval; /** * Class representing SAML 2 SubjectConfirmationData element. @@ -42,32 +38,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\XML\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); @@ -78,9 +78,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; } @@ -89,9 +89,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; } @@ -100,9 +100,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; } @@ -111,9 +111,9 @@ public function getRecipient(): ?string /** * Collect the value of the InResponseTo-property * - * @return string|null + * @return \SimpleSAML\XML\Type\NCNameValue|null */ - public function getInResponseTo(): ?string + public function getInResponseTo(): ?NCNameValue { return $this->inResponseTo; } @@ -122,9 +122,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; } @@ -137,13 +137,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()); } @@ -165,34 +165,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), ); @@ -210,19 +188,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 5481b9f2e..7b4908848 100644 --- a/src/XML/saml/SubjectLocality.php +++ b/src/XML/saml/SubjectLocality.php @@ -5,10 +5,10 @@ namespace SimpleSAML\SAML2\XML\saml; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\{DomainValue, SAMLStringValue}; use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * Class representing SAML2 SubjectLocality @@ -22,24 +22,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; } @@ -48,9 +47,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; } @@ -63,8 +62,8 @@ public function getDnsName(): ?string */ public function isEmptyElement(): bool { - return empty($this->address) - && empty($this->dnsName); + return empty($this->getAddress()) + && empty($this->getDnsName()); } @@ -83,8 +82,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), ); } @@ -100,11 +99,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..a06b737f3 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\XML\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\XML\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..667889704 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\XML\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\XML\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..b7bf5913f 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\XML\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\XML\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..fd5c88354 100644 --- a/src/XML/samlp/AbstractMessage.php +++ b/src/XML/samlp/AbstractMessage.php @@ -4,20 +4,15 @@ 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, 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\XMLSecurity\XML\SignableElementInterface; -use SimpleSAML\XMLSecurity\XML\SignedElementInterface; +use SimpleSAML\SAML2\XML\{SignableElementTrait, SignedElementTrait}; +use SimpleSAML\XML\Type\IDValue; +use SimpleSAML\XMLSecurity\XML\{SignableElementInterface, SignedElementInterface}; use function array_pop; @@ -54,29 +49,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\XML\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 +72,21 @@ protected function __construct( /** * Retrieve the identifier of this message. * - * @return string The identifier of this message + * @return \SimpleSAML\XML\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 +94,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 +108,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 +180,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..52b17c5cb 100644 --- a/src/XML/samlp/AbstractStatusResponse.php +++ b/src/XML/samlp/AbstractStatusResponse.php @@ -4,17 +4,17 @@ 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, SAMLDateTimeValue}; use SimpleSAML\SAML2\XML\saml\Issuer; +use SimpleSAML\XML\Type\{IDValue, 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 +25,28 @@ abstract class AbstractStatusResponse extends AbstractMessage /** * Constructor for SAML 2 response messages. * + * @param \SimpleSAML\XML\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\XML\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 +57,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\XML\Type\NCNameValue|null The ID of the request. */ - public function getInResponseTo(): ?string + public function getInResponseTo(): ?NCNameValue { return $this->inResponseTo; } @@ -98,7 +94,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..689f0b536 100644 --- a/src/XML/samlp/AbstractSubjectQuery.php +++ b/src/XML/samlp/AbstractSubjectQuery.php @@ -4,11 +4,11 @@ namespace SimpleSAML\SAML2\XML\samlp; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\XML\saml\Issuer; -use SimpleSAML\SAML2\XML\saml\Subject; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue}; +use SimpleSAML\SAML2\XML\saml\{Issuer, Subject}; +use SimpleSAML\XML\Type\IDValue; /** * Base class for SAML 2 subject query messages. @@ -26,26 +26,24 @@ abstract class AbstractSubjectQuery extends AbstractRequest /** * Constructor for SAML 2 response messages. * + * @param \SimpleSAML\XML\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 559611363..309ab54af 100644 --- a/src/XML/samlp/Artifact.php +++ b/src/XML/samlp/Artifact.php @@ -4,12 +4,9 @@ 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\Type\Base64BinaryValue; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class for SAML artifacts. @@ -18,35 +15,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 91c626044..df2e60a08 100644 --- a/src/XML/samlp/ArtifactResolve.php +++ b/src/XML/samlp/ArtifactResolve.php @@ -4,22 +4,17 @@ 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\Exception\Protocol\{RequestVersionTooHighException, RequestVersionTooLowException}; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, 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\XML\Exception\{InvalidDOMElementException, MissingElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\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. @@ -35,28 +30,26 @@ class ArtifactResolve extends AbstractRequest implements SchemaValidatableElemen /** * Initialize an ArtifactResolve. * + * @param \SimpleSAML\XML\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); } @@ -87,19 +80,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); @@ -120,13 +103,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 f928505bc..1756ae663 100644 --- a/src/XML/samlp/ArtifactResponse.php +++ b/src/XML/samlp/ArtifactResponse.php @@ -4,22 +4,18 @@ 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\Exception\Protocol\{RequestVersionTooHighException, RequestVersionTooLowException}; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, 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\XML\Exception\{InvalidDOMElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\{IDValue, NCNameValue}; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function array_pop; -use function preg_replace; use function version_compare; /** @@ -35,35 +31,32 @@ class ArtifactResponse extends AbstractStatusResponse implements SchemaValidatab /** * Constructor for SAML 2 ArtifactResponse. * + * @param \SimpleSAML\XML\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\XML\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, @@ -99,23 +92,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); @@ -154,14 +133,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 d994a8345..aa21a4a4c 100644 --- a/src/XML/samlp/AssertionIDRequest.php +++ b/src/XML/samlp/AssertionIDRequest.php @@ -4,23 +4,18 @@ 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\XML\saml\AssertionIDRef; -use SimpleSAML\SAML2\XML\saml\Issuer; +use SimpleSAML\SAML2\Exception\Protocol\{RequestVersionTooHighException, RequestVersionTooLowException}; +use SimpleSAML\SAML2\XML\saml\{AssertionIDRef, Issuer}; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; 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\XML\Exception\{InvalidDOMElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function array_pop; -use function preg_replace; use function version_compare; /** @@ -33,34 +28,31 @@ final class AssertionIDRequest extends AbstractRequest implements SchemaValidata /** * Initialize an AssertionIDRequest. * + * @param \SimpleSAML\XML\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 */ 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, @@ -104,19 +96,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 +117,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 07334e3dc..23776b32a 100644 --- a/src/XML/samlp/AttributeQuery.php +++ b/src/XML/samlp/AttributeQuery.php @@ -4,21 +4,16 @@ 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\Constants as C; +use SimpleSAML\SAML2\Exception\Protocol\{RequestVersionTooHighException, RequestVersionTooLowException}; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -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\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\saml\{Attribute, Issuer, Subject}; +use SimpleSAML\XML\Exception\{InvalidDOMElementException, MissingElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function array_pop; @@ -46,25 +41,23 @@ class AttributeQuery extends AbstractSubjectQuery implements SchemaValidatableEl /** * Constructor for SAML 2 AttributeQuery. * + * @param \SimpleSAML\XML\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); @@ -73,7 +66,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( @@ -86,7 +79,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); } @@ -121,22 +114,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); @@ -162,14 +142,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/samlp/AuthnQuery.php b/src/XML/samlp/AuthnQuery.php index 543f33b94..a2b265faa 100644 --- a/src/XML/samlp/AuthnQuery.php +++ b/src/XML/samlp/AuthnQuery.php @@ -4,24 +4,18 @@ 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\XML\saml\Issuer; -use SimpleSAML\SAML2\XML\saml\Subject; +use SimpleSAML\SAML2\Exception\Protocol\{RequestVersionTooHighException, RequestVersionTooLowException}; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\saml\{Issuer, 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\XML\Exception\{InvalidDOMElementException, MissingElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function array_pop; -use function preg_replace; use function version_compare; /** @@ -36,30 +30,28 @@ final class AuthnQuery extends AbstractSubjectQuery implements SchemaValidatable /** * Constructor for SAML 2 AuthnQuery. * + * @param \SimpleSAML\XML\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); } @@ -77,9 +69,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; } @@ -106,22 +98,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); @@ -149,15 +127,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), ); @@ -182,7 +159,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 71d3ae32b..9cb44ff90 100644 --- a/src/XML/samlp/AuthnRequest.php +++ b/src/XML/samlp/AuthnRequest.php @@ -4,19 +4,15 @@ 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\Protocol\{RequestVersionTooHighException, RequestVersionTooLowException}; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -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\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\saml\{Conditions, Issuer, Subject}; +use SimpleSAML\XML\Exception\{InvalidDOMElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\{BooleanValue, IDValue, UnsignedShortValue}; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function array_pop; @@ -34,49 +30,46 @@ class AuthnRequest extends AbstractRequest implements SchemaValidatableElementIn /** * Constructor for SAML 2 AuthnRequest * - * @param \DateTimeImmutable $issueInstant + * @param \SimpleSAML\XML\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\XML\Type\BooleanValue|null $forceAuthn + * @param \SimpleSAML\XML\Type\BooleanValue|null $isPassive + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $assertionConsumerServiceURL + * @param \SimpleSAML\XML\Type\UnsignedShortValue|null $assertionConsumerServiceIndex + * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $protocolBinding + * @param \SimpleSAML\XML\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], @@ -91,12 +84,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); } @@ -142,9 +131,9 @@ public function getNameIdPolicy(): ?NameIDPolicy /** * Retrieve the value of the ForceAuthn attribute. * - * @return bool|null The ForceAuthn attribute. + * @return \SimpleSAML\XML\Type\BooleanValue|null The ForceAuthn attribute. */ - public function getForceAuthn(): ?bool + public function getForceAuthn(): ?BooleanValue { return $this->forceAuthn; } @@ -153,9 +142,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; } @@ -164,9 +153,9 @@ public function getProviderName(): ?string /** * Retrieve the value of the IsPassive attribute. * - * @return bool|null The IsPassive attribute. + * @return \SimpleSAML\XML\Type\BooleanValue|null The IsPassive attribute. */ - public function getIsPassive(): ?bool + public function getIsPassive(): ?BooleanValue { return $this->isPassive; } @@ -175,9 +164,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; } @@ -186,9 +175,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; } @@ -197,9 +186,9 @@ public function getProtocolBinding(): ?string /** * Retrieve the value of the AttributeConsumingServiceIndex attribute. * - * @return int|null The AttributeConsumingServiceIndex attribute. + * @return \SimpleSAML\XML\Type\UnsignedShortValue|null The AttributeConsumingServiceIndex attribute. */ - public function getAttributeConsumingServiceIndex(): ?int + public function getAttributeConsumingServiceIndex(): ?UnsignedShortValue { return $this->attributeConsumingServiceIndex; } @@ -208,9 +197,9 @@ public function getAttributeConsumingServiceIndex(): ?int /** * Retrieve the value of the AssertionConsumerServiceIndex attribute. * - * @return int|null The AssertionConsumerServiceIndex attribute. + * @return \SimpleSAML\XML\Type\UnsignedShortValue|null The AssertionConsumerServiceIndex attribute. */ - public function getAssertionConsumerServiceIndex(): ?int + public function getAssertionConsumerServiceIndex(): ?UnsignedShortValue { return $this->assertionConsumerServiceIndex; } @@ -245,30 +234,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( @@ -320,23 +288,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), ); @@ -362,25 +329,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 6f23b3ee6..e590740dc 100644 --- a/src/XML/samlp/AuthzDecisionQuery.php +++ b/src/XML/samlp/AuthzDecisionQuery.php @@ -4,23 +4,20 @@ 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\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\SAML2\Exception\Protocol\{RequestVersionTooHighException, RequestVersionTooLowException}; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\saml\{Action, Evidence, Issuer, Subject}; +use SimpleSAML\XML\Exception\{ + InvalidDOMElementException, + MissingElementException, + SchemaViolationException, + TooManyElementsException, +}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function version_compare; @@ -37,45 +34,42 @@ final class AuthzDecisionQuery extends AbstractSubjectQuery implements SchemaVal /** * Constructor for SAML 2 AuthzDecisionQuery. * + * @param \SimpleSAML\XML\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; } @@ -120,22 +114,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); @@ -177,16 +158,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), ); @@ -208,7 +188,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 5ab0f9041..52c96ebe2 100644 --- a/src/XML/samlp/Extensions.php +++ b/src/XML/samlp/Extensions.php @@ -5,13 +5,12 @@ 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\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; /** * Class for handling SAML2 extensions. diff --git a/src/XML/samlp/GetComplete.php b/src/XML/samlp/GetComplete.php index 4e7ea7514..d89ceb5f0 100644 --- a/src/XML/samlp/GetComplete.php +++ b/src/XML/samlp/GetComplete.php @@ -4,13 +4,14 @@ 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\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\TypedTextContentTrait; use function array_key_first; +use function strval; /** * Class representing a samlp:GetComplete element. @@ -20,16 +21,10 @@ 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 +38,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 +51,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 34d1f993c..3eacd9a50 100644 --- a/src/XML/samlp/IDPEntry.php +++ b/src/XML/samlp/IDPEntry.php @@ -5,12 +5,11 @@ 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, EntityIDValue, SAMLStringValue}; use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use function array_change_key_case; use function array_filter; @@ -29,43 +28,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; } @@ -87,11 +83,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), + ); } @@ -104,14 +100,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; @@ -129,9 +125,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, ); } @@ -185,9 +181,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 df698b8e6..6698e0e8d 100644 --- a/src/XML/samlp/IDPList.php +++ b/src/XML/samlp/IDPList.php @@ -5,14 +5,11 @@ 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\XML\Exception\{InvalidDOMElementException, MissingElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use function array_change_key_case; use function array_filter; diff --git a/src/XML/samlp/LogoutRequest.php b/src/XML/samlp/LogoutRequest.php index dbdca29a3..8264f2b37 100644 --- a/src/XML/samlp/LogoutRequest.php +++ b/src/XML/samlp/LogoutRequest.php @@ -4,24 +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\Protocol\RequestVersionTooHighException; -use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Exception\Protocol\{RequestVersionTooHighException, RequestVersionTooLowException}; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, 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\SAML2\XML\saml\{AbstractBaseID, EncryptedID, IdentifierInterface, Issuer, NameID}; +use SimpleSAML\XML\Exception\{InvalidDOMElementException, MissingElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function array_pop; @@ -39,36 +31,34 @@ final class LogoutRequest extends AbstractRequest implements SchemaValidatableEl /** * Constructor for SAML 2 AttributeQuery. * + * @param \SimpleSAML\XML\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); } @@ -77,9 +67,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; } @@ -88,9 +78,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; } @@ -128,28 +118,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); @@ -176,16 +152,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), ); @@ -210,11 +185,11 @@ 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 */ diff --git a/src/XML/samlp/LogoutResponse.php b/src/XML/samlp/LogoutResponse.php index 8a5233dc2..da5085ab9 100644 --- a/src/XML/samlp/LogoutResponse.php +++ b/src/XML/samlp/LogoutResponse.php @@ -4,20 +4,18 @@ 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\Exception\Protocol\{RequestVersionTooHighException, RequestVersionTooLowException}; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\{IDValue, NCNameValue}; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function array_pop; -use function preg_replace; +use function strval; /** * Class for SAML 2 LogoutResponse messages. @@ -31,35 +29,32 @@ final class LogoutResponse extends AbstractStatusResponse implements SchemaValid /** * Constructor for SAML 2 LogoutResponse. * + * @param \SimpleSAML\XML\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\XML\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, @@ -84,19 +79,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); @@ -111,14 +96,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..d173528a7 100644 --- a/src/XML/samlp/MessageFactory.php +++ b/src/XML/samlp/MessageFactory.php @@ -5,7 +5,7 @@ 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; diff --git a/src/XML/samlp/NameIDPolicy.php b/src/XML/samlp/NameIDPolicy.php index 9d817ed46..857e0a260 100644 --- a/src/XML/samlp/NameIDPolicy.php +++ b/src/XML/samlp/NameIDPolicy.php @@ -5,13 +5,13 @@ 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, SAMLStringValue}; use SimpleSAML\XML\ArrayizableElementInterface; use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\BooleanValue; use function array_change_key_case; use function array_filter; @@ -33,42 +33,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\XML\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\XML\Type\BooleanValue|null */ - public function getAllowCreate(): ?bool + public function getAllowCreate(): ?BooleanValue { return $this->AllowCreate; } @@ -81,9 +79,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()); } @@ -101,9 +99,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,15 +122,15 @@ public function toXML(?DOMElement $parent = null): DOMElement $e = $this->instantiateParentElement($parent); if ($this->getFormat()) { - $e->setAttribute('Format', $this->getFormat()); + $e->setAttribute('Format', $this->getFormat()->getValue()); } if ($this->getSPNameQualifier()) { - $e->setAttribute('SPNameQualifier', $this->getSPNameQualifier()); + $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; @@ -150,9 +148,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, ); } @@ -205,9 +203,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 4ef9b688c..80491b6df 100644 --- a/src/XML/samlp/RequestedAuthnContext.php +++ b/src/XML/samlp/RequestedAuthnContext.php @@ -5,15 +5,14 @@ namespace SimpleSAML\SAML2\XML\samlp; 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\Comparison; -use SimpleSAML\SAML2\XML\saml\AuthnContextClassRef; -use SimpleSAML\SAML2\XML\saml\AuthnContextDeclRef; +use SimpleSAML\SAML2\XML\saml\{AuthnContextClassRef, 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\XML\Exception\{InvalidDOMElementException, SchemaViolationException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use function array_merge; @@ -52,12 +51,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, ); } } @@ -99,13 +100,19 @@ 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'); + $Comparison = self::getOptionalAttribute( + $xml, + 'Comparison', + SAMLStringValue::class, + SAMLStringValue::fromString('unknown'), + ); + return new static( array_merge( AuthnContextClassRef::getChildrenOfClass($xml), AuthnContextDeclRef::getChildrenOfClass($xml), ), - Comparison::tryFrom($Comparison), + Comparison::tryFrom($Comparison->getValue()), ); } diff --git a/src/XML/samlp/RequesterID.php b/src/XML/samlp/RequesterID.php index 741037d8e..d31622328 100644 --- a/src/XML/samlp/RequesterID.php +++ b/src/XML/samlp/RequesterID.php @@ -4,11 +4,11 @@ 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\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\TypedTextContentTrait; use function array_key_first; @@ -20,16 +20,10 @@ 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 +37,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 +50,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 e3f9884e8..f6b1867f9 100644 --- a/src/XML/samlp/Response.php +++ b/src/XML/samlp/Response.php @@ -4,25 +4,20 @@ 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\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\SAML2\Exception\Protocol\{RequestVersionTooHighException, RequestVersionTooLowException}; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\saml\{Assertion, EncryptedAssertion, Issuer}; +use SimpleSAML\XML\Exception\{InvalidDOMElementException, MissingElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\{IDValue, NCNameValue}; use SimpleSAML\XMLSecurity\XML\ds\Signature; use function array_merge; use function array_pop; +use function strval; /** * Class for SAML 2 Response messages. @@ -36,26 +31,24 @@ class Response extends AbstractStatusResponse implements SchemaValidatableElemen /** * Constructor for SAML 2 response messages. * + * @param \SimpleSAML\XML\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\XML\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 = [], ) { @@ -63,11 +56,10 @@ final public function __construct( Assert::allIsInstanceOfAny($assertions, [Assertion::class, EncryptedAssertion::class]); parent::__construct( + $id, $status, $issueInstant, $issuer, - $id, - $version, $inResponseTo, $destination, $consent, @@ -105,27 +97,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); @@ -142,14 +120,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 7a536019d..2d8bcfa3c 100644 --- a/src/XML/samlp/Scoping.php +++ b/src/XML/samlp/Scoping.php @@ -5,13 +5,14 @@ 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\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\NonNegativeIntegerValue; use function array_pop; +use function strval; /** * Class for handling SAML2 Scoping. @@ -25,18 +26,17 @@ final class Scoping extends AbstractSamlpElement implements SchemaValidatableEle /** * Initialize a Scoping element. * - * @param int|null $proxyCount + * @param \SimpleSAML\XML\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); } @@ -59,9 +59,9 @@ public function getRequesterId(): array /** - * @return int|null + * @return \SimpleSAML\XML\Type\NonNegativeIntegerValue|null */ - public function getProxyCount(): ?int + public function getProxyCount(): ?NonNegativeIntegerValue { return $this->proxyCount; } @@ -74,9 +74,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()); } @@ -94,12 +94,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..286f00d93 100644 --- a/src/XML/samlp/SessionIndex.php +++ b/src/XML/samlp/SessionIndex.php @@ -4,9 +4,9 @@ namespace SimpleSAML\SAML2\XML\samlp; -use SimpleSAML\SAML2\XML\StringElementTrait; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class representing a samlp:SessionIndex element. @@ -16,14 +16,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 6d7cfaa10..e381405ff 100644 --- a/src/XML/samlp/Status.php +++ b/src/XML/samlp/Status.php @@ -5,16 +5,14 @@ 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\XML\Exception\{InvalidDOMElementException, MissingElementException, TooManyElementsException}; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use function array_pop; +use function strval; /** * SAML Status data type. @@ -38,7 +36,7 @@ public function __construct( protected array $statusDetails = [], ) { Assert::oneOf( - $statusCode->getValue(), + strval($statusCode->getValue()), [ C::STATUS_SUCCESS, C::STATUS_REQUESTER, diff --git a/src/XML/samlp/StatusCode.php b/src/XML/samlp/StatusCode.php index d77cc8190..d55209762 100644 --- a/src/XML/samlp/StatusCode.php +++ b/src/XML/samlp/StatusCode.php @@ -5,12 +5,13 @@ 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\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; + +use function strval; /** * SAML StatusCode data type. @@ -24,14 +25,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); } @@ -40,9 +40,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; } @@ -75,12 +75,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), ); } @@ -94,7 +91,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 a21059f04..574b9afaa 100644 --- a/src/XML/samlp/StatusDetail.php +++ b/src/XML/samlp/StatusDetail.php @@ -5,11 +5,9 @@ namespace SimpleSAML\SAML2\XML\samlp; use DOMElement; -use SimpleSAML\Assert\Assert; +use SimpleSAML\SAML2\Assert\Assert; use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\ExtendableElementTrait; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{ExtendableElementTrait, SchemaValidatableElementInterface, SchemaValidatableElementTrait}; use SimpleSAML\XML\XsNamespace as NS; /** diff --git a/src/XML/samlp/StatusMessage.php b/src/XML/samlp/StatusMessage.php index 00ee4b4f9..e7351505f 100644 --- a/src/XML/samlp/StatusMessage.php +++ b/src/XML/samlp/StatusMessage.php @@ -4,9 +4,9 @@ namespace SimpleSAML\SAML2\XML\samlp; -use SimpleSAML\SAML2\XML\StringElementTrait; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class representing a samlp:StatusMessage element. @@ -16,14 +16,8 @@ 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 d9ca6248a..ce097fcad 100644 --- a/src/XML/shibmd/KeyAuthority.php +++ b/src/XML/shibmd/KeyAuthority.php @@ -5,12 +5,11 @@ 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\{ExtendableAttributesTrait, SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\UnsignedByteValue; use SimpleSAML\XML\XsNamespace as NS; use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; @@ -35,16 +34,15 @@ final class KeyAuthority extends AbstractShibmdElement implements SchemaValidata * Create a KeyAuthority. * * @param \SimpleSAML\XMLSecurity\XML\ds\KeyInfo[] $keys - * @param int|null $VerifyDepth + * @param \SimpleSAML\XML\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); } @@ -53,9 +51,9 @@ public function __construct( /** * Collect the value of the VerifyDepth-property * - * @return int|null + * @return \SimpleSAML\XML\Type\UnsignedByteValue|null */ - public function getVerifyDepth(): ?int + public function getVerifyDepth(): UnsignedByteValue|null { return $this->VerifyDepth; } @@ -86,8 +84,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); @@ -97,9 +94,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..2d7a28730 100644 --- a/src/XML/shibmd/Scope.php +++ b/src/XML/shibmd/Scope.php @@ -5,11 +5,12 @@ namespace SimpleSAML\SAML2\XML\shibmd; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\XML\StringElementTrait; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\SAMLStringValue; use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\SchemaValidatableElementInterface; -use SimpleSAML\XML\SchemaValidatableElementTrait; +use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait}; +use SimpleSAML\XML\Type\BooleanValue; +use SimpleSAML\XML\TypedTextContentTrait; /** * Class which represents the Scope element found in Shibboleth metadata. @@ -20,18 +21,21 @@ 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\XML\Type\BooleanValue|null $regexp */ public function __construct( - string $scope, - protected ?bool $regexp = false, + SAMLStringValue $scope, + protected ?BooleanValue $regexp = null, ) { $this->setContent($scope); } @@ -40,9 +44,9 @@ public function __construct( /** * Collect the value of the regexp-property * - * @return bool|null + * @return \SimpleSAML\XML\Type\BooleanValue|null */ - public function isRegexpScope(): ?bool + public function isRegexpScope(): ?BooleanValue { return $this->regexp; } @@ -62,10 +66,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 +82,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 46a3cb849..981e8d54a 100644 --- a/tests/InterOperability/EntitiesDescriptorTest.php +++ b/tests/InterOperability/EntitiesDescriptorTest.php @@ -89,6 +89,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..f6ff14c50 --- /dev/null +++ b/tests/SAML2/Assert/CIDRTest.php @@ -0,0 +1,58 @@ +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..cf07c635e --- /dev/null +++ b/tests/SAML2/Assert/DomainTest.php @@ -0,0 +1,52 @@ +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..1ceb4c94c 100644 --- a/tests/SAML2/Assert/EntityIDTest.php +++ b/tests/SAML2/Assert/EntityIDTest.php @@ -4,10 +4,9 @@ namespace SimpleSAML\Test\SAML2\Assert; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\{CoversClass, DataProvider, 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; @@ -19,7 +18,8 @@ * * @package simplesamlphp/saml2 */ -#[CoversClass(SAML2Assert::class)] +#[Group('assert')] +#[CoversClass(Assert::class)] final class EntityIDTest extends TestCase { /** @@ -30,7 +30,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 8926e84e0..455ec9e81 100644 --- a/tests/SAML2/Assert/URITest.php +++ b/tests/SAML2/Assert/SAMLAnyURITest.php @@ -4,30 +4,30 @@ namespace SimpleSAML\Test\SAML2\Assert; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\{CoversClass, DataProvider, 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; /** - * 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..44b976830 100644 --- a/tests/SAML2/Assert/DateTimeTest.php +++ b/tests/SAML2/Assert/SAMLDateTimeTest.php @@ -4,31 +4,31 @@ namespace SimpleSAML\SAML2\Test\Assert; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\{CoversClass, DataProvider, 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; /** - * 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..8e5af044c --- /dev/null +++ b/tests/SAML2/Assert/SAMLStringTest.php @@ -0,0 +1,50 @@ +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 75ccd5518..0a509d684 100644 --- a/tests/SAML2/Assertion/Transformer/NameIdDecryptionTransformerTest.php +++ b/tests/SAML2/Assertion/Transformer/NameIdDecryptionTransformerTest.php @@ -4,36 +4,31 @@ namespace SimpleSAML\Test\SAML2\Assertion\Transformer; -use DateTimeImmutable; use DOMDocument; -use PHPUnit\Framework\Attributes\PreserveGlobalState; -use PHPUnit\Framework\Attributes\RunInSeparateProcess; +use PHPUnit\Framework\Attributes\{PreserveGlobalState, RunInSeparateProcess}; use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; -use Psr\Log\LoggerInterface; -use Psr\Log\NullLogger; -use SimpleSAML\SAML2\Assertion\Processor; -use SimpleSAML\SAML2\Assertion\ProcessorBuilder; +use Psr\Log\{LoggerInterface, NullLogger}; +use SimpleSAML\SAML2\Assertion\{Processor, ProcessorBuilder}; use SimpleSAML\SAML2\Compat\ContainerSingleton; -use SimpleSAML\SAML2\Configuration\Destination; -use SimpleSAML\SAML2\Configuration\IdentityProvider; -use SimpleSAML\SAML2\Configuration\PrivateKey; -use SimpleSAML\SAML2\Configuration\ServiceProvider; +use SimpleSAML\SAML2\Configuration\{Destination, IdentityProvider, PrivateKey, ServiceProvider}; use SimpleSAML\SAML2\Signature\Validator; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; use SimpleSAML\SAML2\Utilities\ArrayCollection; use SimpleSAML\SAML2\Utils; -use SimpleSAML\SAML2\XML\saml\Assertion; -use SimpleSAML\SAML2\XML\saml\AuthnContext; -use SimpleSAML\SAML2\XML\saml\AuthnContextClassRef; -use SimpleSAML\SAML2\XML\saml\AuthnStatement; -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\Response; -use SimpleSAML\SAML2\XML\samlp\Status; -use SimpleSAML\SAML2\XML\samlp\StatusCode; +use SimpleSAML\SAML2\XML\saml\{ + Assertion, + AuthnContext, + AuthnContextClassRef, + AuthnStatement, + EncryptedID, + Issuer, + NameID, + Subject, +}; +use SimpleSAML\SAML2\XML\samlp\{Response, Status, StatusCode}; use SimpleSAML\Test\SAML2\Constants as C; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\Alg\KeyTransport\KeyTransportAlgorithmFactory; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; @@ -90,7 +85,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; @@ -123,22 +124,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'), ), ], ); @@ -162,8 +170,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()); } @@ -186,7 +194,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 6fa85f2c1..52514636e 100644 --- a/tests/SAML2/Assertion/Validation/AssertionValidatorTest.php +++ b/tests/SAML2/Assertion/Validation/AssertionValidatorTest.php @@ -5,28 +5,22 @@ namespace SimpleSAML\Test\SAML2\Assertion\Validation; use DOMDocument; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\PreserveGlobalState; -use PHPUnit\Framework\Attributes\RunInSeparateProcess; +use PHPUnit\Framework\Attributes\{CoversClass, PreserveGlobalState, RunInSeparateProcess}; use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; -use Psr\Log\LoggerInterface; -use Psr\Log\NullLogger; +use Psr\Log\{LoggerInterface, NullLogger}; use SimpleSAML\SAML2\Assertion\Exception\InvalidAssertionException; -use SimpleSAML\SAML2\Assertion\Processor; -use SimpleSAML\SAML2\Assertion\ProcessorBuilder; +use SimpleSAML\SAML2\Assertion\{Processor, ProcessorBuilder}; use SimpleSAML\SAML2\Assertion\Validation\AssertionValidator; -use SimpleSAML\SAML2\Configuration\Destination; -use SimpleSAML\SAML2\Configuration\IdentityProvider; -use SimpleSAML\SAML2\Configuration\ServiceProvider; +use SimpleSAML\SAML2\Configuration\{Destination, IdentityProvider, ServiceProvider}; use SimpleSAML\SAML2\Signature\Validator; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue}; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\XML\saml\Assertion; -use SimpleSAML\SAML2\XML\samlp\Response; -use SimpleSAML\SAML2\XML\samlp\Status; -use SimpleSAML\SAML2\XML\samlp\StatusCode; +use SimpleSAML\SAML2\XML\samlp\{Response, Status, StatusCode}; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; +use SimpleSAML\XML\Type\IDValue; /** * Tests for the Assertion validators @@ -77,7 +71,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..25c8c7543 100644 --- a/tests/SAML2/Assertion/Validation/ConstraintValidator/NotBeforeTest.php +++ b/tests/SAML2/Assertion/Validation/ConstraintValidator/NotBeforeTest.php @@ -5,20 +5,23 @@ namespace SimpleSAML\Test\SAML2\Assertion\Validation\ConstraintValidator; use DateInterval; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator\NotBefore; use SimpleSAML\SAML2\Assertion\Validation\Result; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; use SimpleSAML\SAML2\Utils; -use SimpleSAML\SAML2\XML\saml\Assertion; -use SimpleSAML\SAML2\XML\saml\AuthnContext; -use SimpleSAML\SAML2\XML\saml\AuthnContextClassRef; -use SimpleSAML\SAML2\XML\saml\AuthnStatement; -use SimpleSAML\SAML2\XML\saml\Conditions; -use SimpleSAML\SAML2\XML\saml\Issuer; +use SimpleSAML\SAML2\XML\saml\{ + Assertion, + AuthnContext, + AuthnContextClassRef, + AuthnStatement, + Conditions, + Issuer, +}; use SimpleSAML\Test\SAML2\Constants as C; +use SimpleSAML\XML\Type\IDValue; /** * @package simplesamlphp/saml2 @@ -43,16 +46,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 +70,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 +101,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 +131,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..af81ef79d 100644 --- a/tests/SAML2/Assertion/Validation/ConstraintValidator/NotOnOrAfterTest.php +++ b/tests/SAML2/Assertion/Validation/ConstraintValidator/NotOnOrAfterTest.php @@ -5,20 +5,23 @@ namespace SimpleSAML\Test\SAML2\Assertion\Validation\ConstraintValidator; use DateInterval; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator\NotOnOrAfter; use SimpleSAML\SAML2\Assertion\Validation\Result; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; use SimpleSAML\SAML2\Utils; -use SimpleSAML\SAML2\XML\saml\Assertion; -use SimpleSAML\SAML2\XML\saml\AuthnContext; -use SimpleSAML\SAML2\XML\saml\AuthnContextClassRef; -use SimpleSAML\SAML2\XML\saml\AuthnStatement; -use SimpleSAML\SAML2\XML\saml\Conditions; -use SimpleSAML\SAML2\XML\saml\Issuer; +use SimpleSAML\SAML2\XML\saml\{ + Assertion, + AuthnContext, + AuthnContextClassRef, + AuthnStatement, + Conditions, + Issuer, +}; use SimpleSAML\Test\SAML2\Constants as C; +use SimpleSAML\XML\Type\IDValue; /** * @package simplesamlphp/saml2 @@ -43,16 +46,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 +70,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 +102,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 +133,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..a3a01071a 100644 --- a/tests/SAML2/Assertion/Validation/ConstraintValidator/SessionNotOnOrAfterTest.php +++ b/tests/SAML2/Assertion/Validation/ConstraintValidator/SessionNotOnOrAfterTest.php @@ -5,19 +5,16 @@ namespace SimpleSAML\Test\SAML2\Assertion\Validation\ConstraintValidator; use DateInterval; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator\SessionNotOnOrAfter; use SimpleSAML\SAML2\Assertion\Validation\Result; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; use SimpleSAML\SAML2\Utils; -use SimpleSAML\SAML2\XML\saml\Assertion; -use SimpleSAML\SAML2\XML\saml\AuthnContext; -use SimpleSAML\SAML2\XML\saml\AuthnContextClassRef; -use SimpleSAML\SAML2\XML\saml\AuthnStatement; -use SimpleSAML\SAML2\XML\saml\Issuer; +use SimpleSAML\SAML2\XML\saml\{Assertion, AuthnContext, AuthnContextClassRef, AuthnStatement, Issuer}; use SimpleSAML\Test\SAML2\Constants as C; +use SimpleSAML\XML\Type\IDValue; /** * @package simplesamlphp/saml2 @@ -39,7 +36,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 +50,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 +88,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 +125,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..7cc606bb0 100644 --- a/tests/SAML2/Assertion/Validation/ConstraintValidator/SpIsValidAudienceTest.php +++ b/tests/SAML2/Assertion/Validation/ConstraintValidator/SpIsValidAudienceTest.php @@ -7,22 +7,25 @@ use Mockery; use Mockery\Adapter\Phpunit\MockeryTestCase; use Mockery\MockInterface; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator\SpIsValidAudience; use SimpleSAML\SAML2\Assertion\Validation\Result; use SimpleSAML\SAML2\Configuration\ServiceProvider; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; use SimpleSAML\SAML2\Utils; -use SimpleSAML\SAML2\XML\saml\Assertion; -use SimpleSAML\SAML2\XML\saml\Audience; -use SimpleSAML\SAML2\XML\saml\AudienceRestriction; -use SimpleSAML\SAML2\XML\saml\AuthnContext; -use SimpleSAML\SAML2\XML\saml\AuthnContextClassRef; -use SimpleSAML\SAML2\XML\saml\AuthnStatement; -use SimpleSAML\SAML2\XML\saml\Conditions; -use SimpleSAML\SAML2\XML\saml\Issuer; +use SimpleSAML\SAML2\XML\saml\{ + Assertion, + Audience, + AudienceRestriction, + AuthnContext, + AuthnContextClassRef, + AuthnStatement, + Conditions, + 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 +59,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 +105,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 +130,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 +157,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..5003d50d2 100644 --- a/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationMethodTest.php +++ b/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationMethodTest.php @@ -4,12 +4,12 @@ namespace SimpleSAML\Test\SAML2\Assertion\Validation\ConstraintValidator; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; 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 +23,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 +41,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..95d5c9cfc 100644 --- a/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotBeforeTest.php +++ b/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotBeforeTest.php @@ -5,16 +5,15 @@ namespace SimpleSAML\Test\SAML2\Assertion\Validation\ConstraintValidator; use DateInterval; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator\SubjectConfirmationNotBefore; use SimpleSAML\SAML2\Assertion\Validation\Result; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue}; use SimpleSAML\SAML2\Utils; -use SimpleSAML\SAML2\XML\saml\SubjectConfirmation; -use SimpleSAML\SAML2\XML\saml\SubjectConfirmationData; +use SimpleSAML\SAML2\XML\saml\{SubjectConfirmation, SubjectConfirmationData}; /** * @package simplesamlphp/saml2 @@ -39,8 +38,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 +66,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 +90,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..2a7cf420b 100644 --- a/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotOnOrAfterTest.php +++ b/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotOnOrAfterTest.php @@ -5,17 +5,18 @@ namespace SimpleSAML\Test\SAML2\Assertion\Validation\ConstraintValidator; use DateInterval; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; -use SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator\SubjectConfirmationNotBefore; -use SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator\SubjectConfirmationNotOnOrAfter; +use SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator\{ + SubjectConfirmationNotBefore, + SubjectConfirmationNotOnOrAfter, +}; use SimpleSAML\SAML2\Assertion\Validation\Result; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue}; use SimpleSAML\SAML2\Utils; -use SimpleSAML\SAML2\XML\saml\SubjectConfirmation; -use SimpleSAML\SAML2\XML\saml\SubjectConfirmationData; +use SimpleSAML\SAML2\XML\saml\{SubjectConfirmation, SubjectConfirmationData}; /** * @package simplesamlphp/saml2 @@ -42,9 +43,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 +70,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 +94,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..1ca56814a 100644 --- a/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationRecipientMatchesTest.php +++ b/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationRecipientMatchesTest.php @@ -4,15 +4,14 @@ namespace SimpleSAML\Test\SAML2\Assertion\Validation\ConstraintValidator; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator\SubjectConfirmationRecipientMatches; use SimpleSAML\SAML2\Assertion\Validation\Result; use SimpleSAML\SAML2\Configuration\Destination; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\XML\saml\SubjectConfirmation; -use SimpleSAML\SAML2\XML\saml\SubjectConfirmationData; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, EntityIDValue}; +use SimpleSAML\SAML2\XML\saml\{SubjectConfirmation, SubjectConfirmationData}; /** * @package simplesamlphp/saml2 @@ -25,11 +24,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 +52,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..74227605b 100644 --- a/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationResponseToMatchesTest.php +++ b/tests/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationResponseToMatchesTest.php @@ -7,14 +7,14 @@ use Mockery; use Mockery\Adapter\Phpunit\MockeryTestCase; use Mockery\MockInterface; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use SimpleSAML\SAML2\Assertion\Validation\ConstraintValidator\SubjectConfirmationResponseToMatches; use SimpleSAML\SAML2\Assertion\Validation\Result; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\XML\saml\SubjectConfirmation; -use SimpleSAML\SAML2\XML\saml\SubjectConfirmationData; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, EntityIDValue}; +use SimpleSAML\SAML2\XML\saml\{SubjectConfirmation, SubjectConfirmationData}; use SimpleSAML\SAML2\XML\samlp\Response; +use SimpleSAML\XML\Type\NCNameValue; /** * @package simplesamlphp/saml2 @@ -40,8 +40,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 +63,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 +87,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 +105,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 +131,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 37412199c..fe3783628 100644 --- a/tests/SAML2/Assertion/Validation/SubjectConfirmationValidatorTest.php +++ b/tests/SAML2/Assertion/Validation/SubjectConfirmationValidatorTest.php @@ -8,23 +8,19 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; -use Psr\Log\LoggerInterface; -use Psr\Log\NullLogger; +use Psr\Log\{LoggerInterface, NullLogger}; use SimpleSAML\SAML2\Assertion\Exception\InvalidSubjectConfirmationException; -use SimpleSAML\SAML2\Assertion\Processor; -use SimpleSAML\SAML2\Assertion\ProcessorBuilder; +use SimpleSAML\SAML2\Assertion\{Processor, ProcessorBuilder}; use SimpleSAML\SAML2\Assertion\Validation\SubjectConfirmationValidator; -use SimpleSAML\SAML2\Configuration\Destination; -use SimpleSAML\SAML2\Configuration\IdentityProvider; -use SimpleSAML\SAML2\Configuration\ServiceProvider; +use SimpleSAML\SAML2\Configuration\{Destination, IdentityProvider, ServiceProvider}; use SimpleSAML\SAML2\Signature\Validator; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue}; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\XML\saml\Assertion; -use SimpleSAML\SAML2\XML\samlp\Response; -use SimpleSAML\SAML2\XML\samlp\Status; -use SimpleSAML\SAML2\XML\samlp\StatusCode; +use SimpleSAML\SAML2\XML\samlp\{Response, Status, StatusCode}; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; +use SimpleSAML\XML\Type\IDValue; /** * Tests for the SubjectConfirmation validators @@ -70,7 +66,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]); diff --git a/tests/SAML2/Binding/HTTPArtifactTest.php b/tests/SAML2/Binding/HTTPArtifactTest.php index d62b3cab6..05b0c553b 100644 --- a/tests/SAML2/Binding/HTTPArtifactTest.php +++ b/tests/SAML2/Binding/HTTPArtifactTest.php @@ -6,13 +6,14 @@ use Exception; use Nyholm\Psr7\ServerRequest; -use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\{CoversClass, 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..ffb3b679f 100644 --- a/tests/SAML2/Binding/HTTPPostTest.php +++ b/tests/SAML2/Binding/HTTPPostTest.php @@ -6,24 +6,23 @@ use Exception; use Nyholm\Psr7\ServerRequest; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; +use PHPUnit\Framework\Attributes\{CoversClass, DoesNotPerformAssertions, 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, SAMLDateTimeValue, 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\SAML2\XML\samlp\{AuthnRequest, Response, Status, 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 +105,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 +122,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 +138,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 +154,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 7865c3553..7d05786c5 100644 --- a/tests/SAML2/Binding/HTTPRedirectTest.php +++ b/tests/SAML2/Binding/HTTPRedirectTest.php @@ -6,23 +6,21 @@ use Exception; use Nyholm\Psr7\ServerRequest; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; +use PHPUnit\Framework\Attributes\{CoversClass, DoesNotPerformAssertions, 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\Compat\{AbstractContainer, ContainerSingleton}; +use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, 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\SAML2\XML\samlp\{AbstractRequest, AuthnRequest, Response, Status, StatusCode}; +use SimpleSAML\XML\Type\IDValue; /** * @package simplesamlphp\saml2 */ +#[Group('bindings')] #[CoversClass(HTTPRedirect::class)] final class HTTPRedirectTest extends TestCase { @@ -182,6 +180,7 @@ public function testInvalidEncodingSpecified(): void $this->expectException(Exception::class); $this->expectExceptionMessage('Unknown SAMLEncoding:'); + $hr = new HTTPRedirect(); $hr->receive($request); } @@ -201,6 +200,7 @@ public function testNoSigAlgSpecified(): void $this->expectException(Exception::class); $this->expectExceptionMessage('Missing signature algorithm'); + $hr = new HTTPRedirect(); $hr->receive($request); } @@ -217,6 +217,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 +234,7 @@ public function testNoRequestOrResponse(): void $this->expectException(Exception::class); $this->expectExceptionMessage('Missing SAMLRequest or SAMLResponse parameter.'); + $hr = new HTTPRedirect(); $hr->receive($request); } @@ -243,7 +245,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 +263,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 +280,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 +309,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); @@ -309,8 +337,8 @@ public function testSendAuthnResponseBespokeDestination(): void */ public function testDuplicateQueryParameters(): void { - /* @phpstan-ignore array.duplicateKey */ $q = [ + /* @phpstan-ignore array.duplicateKey */ 'SAMLRequest' => 'nVLBauMwEP0Vo7sjW7FpKpJA2rBsoNuGOruHXhZFHm8EsuRqxtv27yvbWWgvYelFgjfvzbx5zBJVazu56enkHuG5B6TktbUO5VhYsT446RUalE61gJK0rDY/7qSYZbILnrz2ln2QXFYoRAhkvGPJbrtiv7VoygJEoTJ9LOusXDSFuJ4vdH6cxwoIEGUjsrqoFUt+QcCoXLHYKMoRe9g5JOUoQlleprlI8/yQz6W4ksXiiSXbuI1xikbViahDyfkRSM2wD40DmjnL0bSdhcE6Hx7BTd3xqnqoIPw1GmbdqWPJNx80jCGtGIUeWLL5t8mtd9i3EM78n493/zWr9XVvx+58mj39IlUaR/QmKOPq4Dtkyf4c9E1EjPtzOePjREL5/XDYp/uH6sDWy6G3HDML66+5ayO7VlHx2dySf2y9nM7pPprabffeGv02ZNcquux5QEydNiNVUlAODTiKMVvrX24DKIJz8nw9jfx8tOt3', 'SAMLRequest' => 'hVLLbttADPwVYe+ylJXsyAvbgBujqIG0MWK3h1wCVkvFC+xDXVJp+/ddywmS9uCeCJAznOGACwJne7Ue+Ojv8ceAxNkvZz2pcbAUQ/QqABlSHhyS4lbt159vlZyUqo+BQxuseEe5zAAijGyCF9l2sxSPjZ41jW5npZxjpWvsrisoZ9ddV8NU6is5nTczXTfTeS2ybxgpMZciLUp0ogG3nhg8p1Ypq7y8ymV1kJUqa1XJB5Ft0jXGA4+sI3NPqiiM7icuhBxiezTPOPG2cEEPFif9sS9OJ5wgBRn/ZHFvnvyd32N8Ni2KbP1q/yZ4GhzGl8nX+9s3AY0u/E+BzlXm0NLY1djBYDmnXmS7l1g/GK+Ti8uJfj+DSH06HHb57m5/EKvFabcaE4qrV1v/OEoOHDJoYFgU7/GL80d8SUrbzS5Y0/7OPobogC8bOXWMzrsRqjiCJ4OeU2jWhp83EYFxKTgOKIrVWfLvv1v9AQ==', 'RelayState' => 'https://demo.moo-archive.nl/module.php/admin/test/default-sp', @@ -324,8 +352,8 @@ public function testDuplicateQueryParameters(): void $hr = new HTTPRedirect(); $hr->receive($request); - /* @phpstan-ignore array.duplicateKey */ $q = [ + /* @phpstan-ignore array.duplicateKey */ 'SAMLRequest' => 'hVLLbttADPwVYe+ylJXsyAvbgBujqIG0MWK3h1wCVkvFC+xDXVJp+/ddywmS9uCeCJAznOGACwJne7Ue+Ojv8ceAxNkvZz2pcbAUQ/QqABlSHhyS4lbt159vlZyUqo+BQxuseEe5zAAijGyCF9l2sxSPjZ41jW5npZxjpWvsrisoZ9ddV8NU6is5nTczXTfTeS2ybxgpMZciLUp0ogG3nhg8p1Ypq7y8ymV1kJUqa1XJB5Ft0jXGA4+sI3NPqiiM7icuhBxiezTPOPG2cEEPFif9sS9OJ5wgBRn/ZHFvnvyd32N8Ni2KbP1q/yZ4GhzGl8nX+9s3AY0u/E+BzlXm0NLY1djBYDmnXmS7l1g/GK+Ti8uJfj+DSH06HHb57m5/EKvFabcaE4qrV1v/OEoOHDJoYFgU7/GL80d8SUrbzS5Y0/7OPobogC8bOXWMzrsRqjiCJ4OeU2jWhp83EYFxKTgOKIrVWfLvv1v9AQ==', 'SAMLRequest' => 'nVLBauMwEP0Vo7sjW7FpKpJA2rBsoNuGOruHXhZFHm8EsuRqxtv27yvbWWgvYelFgjfvzbx5zBJVazu56enkHuG5B6TktbUO5VhYsT446RUalE61gJK0rDY/7qSYZbILnrz2ln2QXFYoRAhkvGPJbrtiv7VoygJEoTJ9LOusXDSFuJ4vdH6cxwoIEGUjsrqoFUt+QcCoXLHYKMoRe9g5JOUoQlleprlI8/yQz6W4ksXiiSXbuI1xikbViahDyfkRSM2wD40DmjnL0bSdhcE6Hx7BTd3xqnqoIPw1GmbdqWPJNx80jCGtGIUeWLL5t8mtd9i3EM78n493/zWr9XVvx+58mj39IlUaR/QmKOPq4Dtkyf4c9E1EjPtzOePjREL5/XDYp/uH6sDWy6G3HDML66+5ayO7VlHx2dySf2y9nM7pPprabffeGv02ZNcquux5QEydNiNVUlAODTiKMVvrX24DKIJz8nw9jfx8tOt3', 'RelayState' => 'https://demo.moo-archive.nl/module.php/admin/test/default-sp', diff --git a/tests/SAML2/Binding/SOAPTest.php b/tests/SAML2/Binding/SOAPTest.php index 135611191..ba202d93f 100644 --- a/tests/SAML2/Binding/SOAPTest.php +++ b/tests/SAML2/Binding/SOAPTest.php @@ -6,21 +6,22 @@ use Mockery\Adapter\Phpunit\MockeryTestCase; use Nyholm\Psr7\ServerRequest; -use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use SimpleSAML\SAML2\Binding\SOAP; use SimpleSAML\SAML2\Exception\Protocol\UnsupportedBindingException; -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\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\ecp\{RequestAuthenticated, Response}; +use SimpleSAML\SAML2\XML\samlp\{ArtifactResolve, MessageFactory}; use SimpleSAML\SOAP\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; +use SimpleSAML\XML\Type\BooleanValue; use function dirname; /** * @package simplesamlphp\saml2 */ +#[Group('bindings')] #[CoversClass(SOAP::class)] final class SOAPTest extends MockeryTestCase { @@ -109,8 +110,12 @@ public function testSendResponse(): void SOAP); - $requestAuthenticated = new RequestAuthenticated(true); - $ecpResponse = new Response('https://example.org/metadata'); + $requestAuthenticated = new RequestAuthenticated( + BooleanValue::fromBoolean(true), + ); + $ecpResponse = new Response( + SAMLAnyURIValue::fromString('https://example.org/metadata'), + ); /** @var \DOMElement $header */ diff --git a/tests/SAML2/BindingTest.php b/tests/SAML2/BindingTest.php index ddd287a69..ce59c1d5c 100644 --- a/tests/SAML2/BindingTest.php +++ b/tests/SAML2/BindingTest.php @@ -5,7 +5,7 @@ namespace SimpleSAML\Test\SAML2; use Nyholm\Psr7\ServerRequest; -use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Binding; use SimpleSAML\SAML2\Constants as C; @@ -15,6 +15,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..7ecd4937b 100644 --- a/tests/SAML2/CustomBaseID.php +++ b/tests/SAML2/CustomBaseID.php @@ -5,12 +5,12 @@ namespace SimpleSAML\Test\SAML2; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\XML\saml\AbstractBaseID; -use SimpleSAML\SAML2\XML\saml\Audience; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\SAML2\XML\saml\{AbstractBaseID, Audience}; use SimpleSAML\Test\SAML2\Constants as C; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\SchemaViolationException; +use SimpleSAML\XML\Exception\{InvalidDOMElementException, SchemaViolationException}; +use SimpleSAML\XML\Type\QNameValue; /** * Example class to demonstrate how BaseID can be extended. @@ -33,17 +33,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, + ); } @@ -75,10 +81,11 @@ public static function fromXML(DOMElement $xml): static $type = $xml->getAttributeNS(C::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..1c4736b39 100644 --- a/tests/SAML2/CustomCondition.php +++ b/tests/SAML2/CustomCondition.php @@ -5,11 +5,11 @@ namespace SimpleSAML\Test\SAML2; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\XML\saml\AbstractCondition; -use SimpleSAML\SAML2\XML\saml\Audience; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\XML\saml\{AbstractCondition, Audience}; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\Exception\InvalidDOMElementException; +use SimpleSAML\XML\Type\QNameValue; /** * Example class to demonstrate how Condition can be extended. @@ -38,7 +38,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, + ), + ); } diff --git a/tests/SAML2/CustomRoleDescriptor.php b/tests/SAML2/CustomRoleDescriptor.php index fba5d7403..42028f19a 100644 --- a/tests/SAML2/CustomRoleDescriptor.php +++ b/tests/SAML2/CustomRoleDescriptor.php @@ -4,20 +4,23 @@ namespace SimpleSAML\Test\SAML2; -use DateTimeImmutable; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\Assert\Assert as SAMLAssert; -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\SAML2\Assert\Assert; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\md\{ + AbstractRoleDescriptor, + ContactPerson, + Extensions, + KeyDescriptor, + 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\XML\Exception\{InvalidDOMElementException, MissingElementException, TooManyElementsException}; +use SimpleSAML\XML\Type\{DurationValue, IDValue, QNameValue}; +use SimpleSAML\XML\XsNamespace as NS; /** * Example class to demonstrate how RoleDescriptor can be extended. @@ -26,6 +29,8 @@ */ final class CustomRoleDescriptor extends AbstractRoleDescriptor { + use ExtendableElementTrait; + /** @var string */ protected const XSI_TYPE_NAME = 'CustomRoleDescriptorType'; @@ -35,17 +40,22 @@ 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 \SimpleSAML\XML\SerializableElementInterface[] $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\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\XML\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 @@ -57,20 +67,23 @@ final class CustomRoleDescriptor extends AbstractRoleDescriptor public function __construct( protected array $chunk, array $protocolSupportEnumeration, - ?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 = [], 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 +101,7 @@ public function __construct( /** * Get the value of the chunk-attribute. * - * @return \SimpleSAML\XML\Chunk[] + * @return \SimpleSAML\XML\SerializableElementInterface[] */ public function getChunk(): array { @@ -119,10 +132,7 @@ public static function fromXML(DOMElement $xml): static $type = $xml->getAttributeNS(C::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); + $protocols = self::getAttribute($xml, 'protocolSupportEnumeration', SAMLStringValue::class); $orgs = Organization::getChildrenOfClass($xml); Assert::maxCount( @@ -140,26 +150,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), + preg_split('/[\s]+/', trim($protocols->getValue())), + 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 +176,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::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..a60ba31ed 100644 --- a/tests/SAML2/CustomStatement.php +++ b/tests/SAML2/CustomStatement.php @@ -5,11 +5,11 @@ namespace SimpleSAML\Test\SAML2; use DOMElement; -use SimpleSAML\Assert\Assert; -use SimpleSAML\SAML2\XML\saml\AbstractStatement; -use SimpleSAML\SAML2\XML\saml\Audience; +use SimpleSAML\SAML2\Assert\Assert; +use SimpleSAML\SAML2\XML\saml\{AbstractStatement, Audience}; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\Exception\InvalidDOMElementException; +use SimpleSAML\XML\Type\QNameValue; /** * Example class to demonstrate how Statement can be extended. @@ -38,7 +38,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, + ), + ); } diff --git a/tests/SAML2/Response/Validation/ConstraintValidator/DestinationMatchesTest.php b/tests/SAML2/Response/Validation/ConstraintValidator/DestinationMatchesTest.php index 6e3631452..645014142 100644 --- a/tests/SAML2/Response/Validation/ConstraintValidator/DestinationMatchesTest.php +++ b/tests/SAML2/Response/Validation/ConstraintValidator/DestinationMatchesTest.php @@ -7,11 +7,11 @@ use Mockery; use Mockery\Adapter\Phpunit\MockeryTestCase; use Mockery\MockInterface; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; 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 +37,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 +55,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 +68,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..c314ce6d8 100644 --- a/tests/SAML2/Response/Validation/ConstraintValidator/IsSuccessfulTest.php +++ b/tests/SAML2/Response/Validation/ConstraintValidator/IsSuccessfulTest.php @@ -7,15 +7,12 @@ use Mockery; use Mockery\Adapter\Phpunit\MockeryTestCase; use Mockery\MockInterface; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Response\Validation\ConstraintValidator\IsSuccessful; use SimpleSAML\SAML2\Response\Validation\Result; -use SimpleSAML\SAML2\XML\samlp\Response; -use SimpleSAML\SAML2\XML\samlp\Status; -use SimpleSAML\SAML2\XML\samlp\StatusCode; -use SimpleSAML\SAML2\XML\samlp\StatusMessage; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\samlp\{Response, Status, StatusCode, StatusMessage}; /** * @package simplesamlphp/saml2 @@ -58,14 +55,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/Signature/ValidatorChainTest.php b/tests/SAML2/Signature/ValidatorChainTest.php index 441e02a2b..9449df7b9 100644 --- a/tests/SAML2/Signature/ValidatorChainTest.php +++ b/tests/SAML2/Signature/ValidatorChainTest.php @@ -4,18 +4,17 @@ namespace SimpleSAML\Test\SAML2\Signature; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; use Psr\Log\NullLogger; use SimpleSAML\SAML2\Configuration\IdentityProvider; -use SimpleSAML\SAML2\Signature\MissingConfigurationException; -use SimpleSAML\SAML2\Signature\ValidatorChain; +use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Signature\{MissingConfigurationException, ValidatorChain}; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, 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\SAML2\XML\samlp\{Response, Status, StatusCode}; +use SimpleSAML\XML\Type\IDValue; /** * @package simplesamlphp/saml2 @@ -23,6 +22,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 +38,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 +60,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 +76,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 +93,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/EntityIDValueTest.php b/tests/SAML2/Type/EntityIDValueTest.php new file mode 100644 index 000000000..7a44cd38c --- /dev/null +++ b/tests/SAML2/Type/EntityIDValueTest.php @@ -0,0 +1,57 @@ +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..41122e8c6 --- /dev/null +++ b/tests/SAML2/Type/ListOfStringsValueTest.php @@ -0,0 +1,57 @@ +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..217d457df --- /dev/null +++ b/tests/SAML2/Type/SAMLAnyURIValueTest.php @@ -0,0 +1,55 @@ +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..5bfb5ab1e --- /dev/null +++ b/tests/SAML2/Type/SAMLDateTimeValueTest.php @@ -0,0 +1,63 @@ +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..90727d989 --- /dev/null +++ b/tests/SAML2/Type/SAMLStringValueTest.php @@ -0,0 +1,48 @@ +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 e2c6313aa..c1c8b662b 100644 --- a/tests/SAML2/UtilsTest.php +++ b/tests/SAML2/UtilsTest.php @@ -8,11 +8,12 @@ use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, 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\saml\{NameID, Subject}; use SimpleSAML\SAML2\XML\samlp\AttributeQuery; +use SimpleSAML\XML\Type\IDValue; use function count; @@ -42,13 +43,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..962fbbb7b 100644 --- a/tests/SAML2/XML/alg/DigestMethodTest.php +++ b/tests/SAML2/XML/alg/DigestMethodTest.php @@ -4,17 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\alg; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\alg\AbstractAlgElement; -use SimpleSAML\SAML2\XML\alg\DigestMethod; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\alg\{AbstractAlgElement, DigestMethod}; use SimpleSAML\Test\SAML2\Constants as C; -use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; use SimpleSAML\XML\Exception\MissingAttributeException; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -50,7 +47,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..813adc699 100644 --- a/tests/SAML2/XML/alg/SigningMethodTest.php +++ b/tests/SAML2/XML/alg/SigningMethodTest.php @@ -4,17 +4,15 @@ namespace SimpleSAML\Test\SAML2\XML\alg; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\alg\AbstractAlgElement; -use SimpleSAML\SAML2\XML\alg\SigningMethod; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\alg\{AbstractAlgElement, SigningMethod}; use SimpleSAML\Test\SAML2\Constants as C; -use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; use SimpleSAML\XML\Exception\MissingAttributeException; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\PositiveIntegerValue; use function dirname; use function strval; @@ -50,9 +48,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..2fc870bcd 100644 --- a/tests/SAML2/XML/ecp/RelayStateTest.php +++ b/tests/SAML2/XML/ecp/RelayStateTest.php @@ -4,16 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\ecp; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\ecp\AbstractEcpElement; -use SimpleSAML\SAML2\XML\ecp\RelayState; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\SAML2\XML\ecp\{AbstractEcpElement, RelayState}; use SimpleSAML\SOAP\Constants as SOAP; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\Exception\MissingAttributeException; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -46,7 +44,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), diff --git a/tests/SAML2/XML/ecp/RequestAuthenticatedTest.php b/tests/SAML2/XML/ecp/RequestAuthenticatedTest.php index 31c8aa9b9..23718034c 100644 --- a/tests/SAML2/XML/ecp/RequestAuthenticatedTest.php +++ b/tests/SAML2/XML/ecp/RequestAuthenticatedTest.php @@ -4,16 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\ecp; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\ecp\AbstractEcpElement; -use SimpleSAML\SAML2\XML\ecp\RequestAuthenticated; +use SimpleSAML\SAML2\XML\ecp\{AbstractEcpElement, RequestAuthenticated}; use SimpleSAML\SOAP\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\Exception\MissingAttributeException; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\BooleanValue; use function dirname; use function strval; @@ -46,7 +44,9 @@ public static function setUpBeforeClass(): void */ public function testMarshalling(): void { - $ra = new RequestAuthenticated(false); + $ra = new RequestAuthenticated( + BooleanValue::fromBoolean(false), + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), diff --git a/tests/SAML2/XML/ecp/RequestTest.php b/tests/SAML2/XML/ecp/RequestTest.php index ebce837d0..a2e733d3d 100644 --- a/tests/SAML2/XML/ecp/RequestTest.php +++ b/tests/SAML2/XML/ecp/RequestTest.php @@ -4,20 +4,17 @@ namespace SimpleSAML\Test\SAML2\XML\ecp; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\ecp\AbstractEcpElement; -use SimpleSAML\SAML2\XML\ecp\Request; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, EntityIDValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\ecp\{AbstractEcpElement, 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\SAML2\XML\samlp\{GetComplete, IDPEntry, IDPList}; use SimpleSAML\SOAP\Constants as SOAP; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\Exception\MissingAttributeException; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\BooleanValue; use function dirname; use function strval; @@ -51,18 +48,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), diff --git a/tests/SAML2/XML/ecp/ResponseTest.php b/tests/SAML2/XML/ecp/ResponseTest.php index bfc0d43a4..46595bf9f 100644 --- a/tests/SAML2/XML/ecp/ResponseTest.php +++ b/tests/SAML2/XML/ecp/ResponseTest.php @@ -5,18 +5,15 @@ namespace SimpleSAML\Test\SAML2\XML\ecp; use DOMDocument; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\ecp\AbstractEcpElement; -use SimpleSAML\SAML2\XML\ecp\Response; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\ecp\{AbstractEcpElement, Response}; use SimpleSAML\SOAP\Constants as SOAP; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\Exception\MissingAttributeException; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -49,7 +46,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 +64,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,16 +76,6 @@ public function testToXMLResponseAppended(): void } - /** - */ - public function testInvalidACSThrowsException(): void - { - $this->expectException(ProtocolViolationException::class); - - new Response('some non-url'); - } - - /** */ public function testUnmarshallingWithMissingMustUnderstandThrowsException(): void diff --git a/tests/SAML2/XML/ecp/SubjectConfirmationTest.php b/tests/SAML2/XML/ecp/SubjectConfirmationTest.php index 2f49ff981..bea6e7f77 100644 --- a/tests/SAML2/XML/ecp/SubjectConfirmationTest.php +++ b/tests/SAML2/XML/ecp/SubjectConfirmationTest.php @@ -4,23 +4,19 @@ namespace SimpleSAML\Test\SAML2\XML\ecp; -use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\ecp\AbstractEcpElement; -use SimpleSAML\SAML2\XML\ecp\SubjectConfirmation; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, EntityIDValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\ecp\{AbstractEcpElement, SubjectConfirmation}; use SimpleSAML\SAML2\XML\saml\SubjectConfirmationData; use SimpleSAML\SOAP\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\{Chunk, DOMDocumentFactory}; use SimpleSAML\XML\Exception\MissingAttributeException; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; -use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; -use SimpleSAML\XMLSecurity\XML\ds\KeyName; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{IDValue, NCNameValue, StringValue}; +use SimpleSAML\XMLSecurity\XML\ds\{KeyInfo, KeyName}; use function dirname; use function strval; @@ -55,23 +51,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), diff --git a/tests/SAML2/XML/emd/RepublishRequestTest.php b/tests/SAML2/XML/emd/RepublishRequestTest.php index 279f8f7a8..ce01db64b 100644 --- a/tests/SAML2/XML/emd/RepublishRequestTest.php +++ b/tests/SAML2/XML/emd/RepublishRequestTest.php @@ -4,16 +4,12 @@ namespace SimpleSAML\Test\SAML2\XML\emd; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\emd\AbstractEmdElement; -use SimpleSAML\SAML2\XML\emd\RepublishRequest; -use SimpleSAML\SAML2\XML\emd\RepublishTarget; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\emd\{AbstractEmdElement, RepublishRequest, RepublishTarget}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -55,7 +51,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..71e3893da 100644 --- a/tests/SAML2/XML/emd/RepublishTargetTest.php +++ b/tests/SAML2/XML/emd/RepublishTargetTest.php @@ -4,12 +4,11 @@ namespace SimpleSAML\Test\SAML2\XML\emd; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; -use SimpleSAML\SAML2\XML\emd\AbstractEmdElement; -use SimpleSAML\SAML2\XML\emd\RepublishTarget; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\emd\{AbstractEmdElement, RepublishTarget}; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; @@ -46,7 +45,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 +65,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 3d94d9fd9..cf8b3b735 100644 --- a/tests/SAML2/XML/idpdisc/DiscoveryResponseTest.php +++ b/tests/SAML2/XML/idpdisc/DiscoveryResponseTest.php @@ -4,20 +4,17 @@ namespace SimpleSAML\Test\SAML2\XML\idpdisc; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLStringValue}; use SimpleSAML\SAML2\XML\idpdisc\DiscoveryResponse; -use SimpleSAML\SAML2\XML\md\AbstractIndexedEndpointType; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; +use SimpleSAML\SAML2\XML\md\{AbstractIndexedEndpointType, AbstractMdElement}; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\Attribute as XMLAttribute; -use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{BooleanValue, UnsignedShortValue}; use function dirname; use function strval; @@ -50,7 +47,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', @@ -81,10 +83,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], @@ -107,11 +109,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 8ad7d37eb..5159eec50 100644 --- a/tests/SAML2/XML/init/RequestInitiatorTest.php +++ b/tests/SAML2/XML/init/RequestInitiatorTest.php @@ -4,18 +4,16 @@ namespace SimpleSAML\Test\SAML2\XML\init; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLStringValue}; use SimpleSAML\SAML2\XML\init\RequestInitiator; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\Attribute as XMLAttribute; -use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -61,8 +59,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..97ca835d9 100644 --- a/tests/SAML2/XML/md/AbstractLocalizedNameTest.php +++ b/tests/SAML2/XML/md/AbstractLocalizedNameTest.php @@ -5,16 +5,13 @@ namespace SimpleSAML\Test\SAML2\XML\md; use DOMDocument; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\ServiceDescription; +use SimpleSAML\SAML2\XML\md\{AbstractLocalizedName, AbstractMdElement, ServiceDescription}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\MissingAttributeException; +use SimpleSAML\XML\Exception\{MissingAttributeException, SchemaViolationException}; use function dirname; @@ -43,33 +40,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 +66,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 +82,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..b0eff1b69 100644 --- a/tests/SAML2/XML/md/AdditionalMetadataLocationTest.php +++ b/tests/SAML2/XML/md/AdditionalMetadataLocationTest.php @@ -4,17 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\AdditionalMetadataLocation; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\md\{AbstractMdElement, 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\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -53,7 +50,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 +62,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..24f45b4ab 100644 --- a/tests/SAML2/XML/md/AffiliateMemberTest.php +++ b/tests/SAML2/XML/md/AffiliateMemberTest.php @@ -4,20 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\AffiliateMember; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\XML\md\{AbstractMdElement, AffiliateMember}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; -use function sprintf; -use function str_pad; use function strval; /** @@ -54,34 +48,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..62810bb0e 100644 --- a/tests/SAML2/XML/md/AffiliationDescriptorTest.php +++ b/tests/SAML2/XML/md/AffiliationDescriptorTest.php @@ -4,27 +4,27 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use DateTimeImmutable; use Exception; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; -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\Type\{SAMLDateTimeValue, EntityIDValue, KeyTypesValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\md\{ + AbstractMdElement, + AbstractMetadataDocument, + AbstractSignedMdElement, + AffiliateMember, + AffiliationDescriptor, + KeyDescriptor, + 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\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{DurationValue, IDValue}; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; -use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; -use SimpleSAML\XMLSecurity\XML\ds\KeyName; +use SimpleSAML\XMLSecurity\XML\ds\{KeyInfo, KeyName}; use function dirname; use function strval; @@ -67,22 +67,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 +103,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 +111,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 9dc045be2..9c11be1a9 100644 --- a/tests/SAML2/XML/md/ArtifactResolutionServiceTest.php +++ b/tests/SAML2/XML/md/ArtifactResolutionServiceTest.php @@ -4,20 +4,16 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; -use SimpleSAML\SAML2\XML\md\AbstractIndexedEndpointType; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\ArtifactResolutionService; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\md\{AbstractIndexedEndpointType, AbstractMdElement, ArtifactResolutionService}; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\Attribute as XMLAttribute; -use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{BooleanValue, StringValue, UnsignedShortValue}; use function array_merge; use function dirname; @@ -53,7 +49,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; @@ -81,10 +82,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], @@ -106,7 +107,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 aa92c175f..81095d136 100644 --- a/tests/SAML2/XML/md/AssertionConsumerServiceTest.php +++ b/tests/SAML2/XML/md/AssertionConsumerServiceTest.php @@ -4,19 +4,15 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\md\AbstractIndexedEndpointType; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\AssertionConsumerService; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\md\{AbstractIndexedEndpointType, AbstractMdElement, AssertionConsumerService}; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\Attribute as XMLAttribute; -use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{BooleanValue, StringValue, UnsignedShortValue}; use function dirname; use function strval; @@ -51,7 +47,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; @@ -80,11 +81,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..9e54cc824 100644 --- a/tests/SAML2/XML/md/AttributeAuthorityDescriptorTest.php +++ b/tests/SAML2/XML/md/AttributeAuthorityDescriptorTest.php @@ -5,27 +5,29 @@ namespace SimpleSAML\Test\SAML2\XML\md; use Exception; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\AbstractMetadataDocument; -use SimpleSAML\SAML2\XML\md\AbstractRoleDescriptor; -use SimpleSAML\SAML2\XML\md\AbstractRoleDescriptorType; -use SimpleSAML\SAML2\XML\md\AbstractSignedMdElement; -use SimpleSAML\SAML2\XML\md\AssertionIDRequestService; -use SimpleSAML\SAML2\XML\md\AttributeAuthorityDescriptor; -use SimpleSAML\SAML2\XML\md\AttributeProfile; -use SimpleSAML\SAML2\XML\md\AttributeService; -use SimpleSAML\SAML2\XML\md\NameIDFormat; -use SimpleSAML\SAML2\XML\saml\Attribute; -use SimpleSAML\SAML2\XML\saml\AttributeValue; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\md\{ + AbstractMdElement, + AbstractMetadataDocument, + AbstractRoleDescriptor, + AbstractRoleDescriptorType, + AbstractSignedMdElement, + AssertionIDRequestService, + AttributeAuthorityDescriptor, + AttributeProfile, + AttributeService, + NameIDFormat, +}; +use SimpleSAML\SAML2\XML\saml\{Attribute, AttributeValue}; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\Exception\MissingElementException; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -68,13 +70,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 +90,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'), @@ -110,16 +112,26 @@ public function testMarshalling(): void [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( @@ -157,7 +169,7 @@ 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]); } @@ -201,32 +213,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 4c9329386..36fe8d61e 100644 --- a/tests/SAML2/XML/md/AttributeConsumingServiceTest.php +++ b/tests/SAML2/XML/md/AttributeConsumingServiceTest.php @@ -4,22 +4,22 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\AttributeConsumingService; -use SimpleSAML\SAML2\XML\md\RequestedAttribute; -use SimpleSAML\SAML2\XML\md\ServiceDescription; -use SimpleSAML\SAML2\XML\md\ServiceName; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\md\{ + AbstractMdElement, + AttributeConsumingService, + RequestedAttribute, + ServiceDescription, + 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\XML\Exception\{MissingAttributeException, MissingElementException}; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{BooleanValue, LanguageValue, UnsignedShortValue}; use function dirname; use function strval; @@ -52,9 +52,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')], ); } @@ -69,11 +69,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( @@ -89,10 +99,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; @@ -124,10 +139,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'); @@ -146,7 +171,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], ); @@ -161,8 +186,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'), + ), + ], [], ); } @@ -184,44 +214,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..173158407 100644 --- a/tests/SAML2/XML/md/AttributeProfileTest.php +++ b/tests/SAML2/XML/md/AttributeProfileTest.php @@ -4,15 +4,13 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\AttributeProfile; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\md\{AbstractMdElement, AttributeProfile}; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -50,7 +48,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 e968f855d..3f3c150a1 100644 --- a/tests/SAML2/XML/md/AuthnAuthorityDescriptorTest.php +++ b/tests/SAML2/XML/md/AuthnAuthorityDescriptorTest.php @@ -4,24 +4,26 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\AbstractMetadataDocument; -use SimpleSAML\SAML2\XML\md\AbstractRoleDescriptor; -use SimpleSAML\SAML2\XML\md\AbstractRoleDescriptorType; -use SimpleSAML\SAML2\XML\md\AbstractSignedMdElement; -use SimpleSAML\SAML2\XML\md\AssertionIDRequestService; -use SimpleSAML\SAML2\XML\md\AuthnAuthorityDescriptor; -use SimpleSAML\SAML2\XML\md\AuthnQueryService; -use SimpleSAML\SAML2\XML\md\NameIDFormat; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\md\{ + AbstractMdElement, + AbstractMetadataDocument, + AbstractRoleDescriptor, + AbstractRoleDescriptorType, + AbstractSignedMdElement, + AssertionIDRequestService, + AuthnAuthorityDescriptor, + AuthnQueryService, + NameIDFormat, +}; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -61,8 +63,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'), + ); } @@ -78,8 +87,15 @@ public function testMarshalling(): void [self::$aqs], [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( @@ -100,7 +116,14 @@ public function testMarshallingWithoutAuthnQueryServices(): void [], [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), + ), + ], ); } @@ -119,21 +142,6 @@ public function testMarshallingWithoutOptionalElements(): void } - /** - * 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)], - ); - } - - /** * Test that creating an AuthnAuthorityDescriptor with a wrong AuthnQueryService fails. */ @@ -145,7 +153,14 @@ public function testMarshallingWithWrongAuthnQueryService(): void [self::$aqs, ''], [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), + ), + ], ); } @@ -161,7 +176,14 @@ public function testMarshallingWithWrongAssertionIDRequestService(): void [self::$aqs], [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..a33e88937 100644 --- a/tests/SAML2/XML/md/CompanyTest.php +++ b/tests/SAML2/XML/md/CompanyTest.php @@ -4,14 +4,12 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\Company; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\SAML2\XML\md\{AbstractMdElement, Company}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -50,7 +48,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 ab8db0849..d9ab945cc 100644 --- a/tests/SAML2/XML/md/ContactPersonTest.php +++ b/tests/SAML2/XML/md/ContactPersonTest.php @@ -5,11 +5,11 @@ namespace SimpleSAML\Test\SAML2\XML\md; use DOMDocument; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\{EmailAddressValue, SAMLStringValue}; use SimpleSAML\SAML2\XML\md\AbstractMdElement; use SimpleSAML\SAML2\XML\md\Company; use SimpleSAML\SAML2\XML\md\ContactPerson; @@ -19,12 +19,10 @@ use SimpleSAML\SAML2\XML\md\SurName; use SimpleSAML\SAML2\XML\md\TelephoneNumber; use SimpleSAML\XML\Attribute as XMLAttribute; -use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; use SimpleSAML\XML\Exception\MissingAttributeException; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\StringValue; use function dirname; use function strval; @@ -89,21 +87,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], ); @@ -123,7 +138,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..2ada3c903 100644 --- a/tests/SAML2/XML/md/EmailAddressTest.php +++ b/tests/SAML2/XML/md/EmailAddressTest.php @@ -4,16 +4,13 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\EmailAddress; +use SimpleSAML\SAML2\XML\md\{AbstractMdElement, EmailAddress}; +use SimpleSAML\SAML2\Type\EmailAddressValue; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; /** * Tests for EmailAddress. @@ -52,7 +49,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 +66,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..99a5e9e7a 100644 --- a/tests/SAML2/XML/md/EncryptionMethodTest.php +++ b/tests/SAML2/XML/md/EncryptionMethodTest.php @@ -4,20 +4,18 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, 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\SAML2\XML\md\{AbstractMdElement, EncryptionMethod}; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; use SimpleSAML\XML\Exception\MissingAttributeException; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; -use SimpleSAML\XMLSecurity\XML\xenc\KeySize; -use SimpleSAML\XMLSecurity\XML\xenc\OAEPparams; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\Base64BinaryValue; +use SimpleSAML\XMLSecurity\Type\KeySizeValue; +use SimpleSAML\XMLSecurity\XML\xenc\{KeySize, OAEPparams}; use function dirname; use function strval; @@ -58,13 +56,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 +84,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 +107,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 a8b3ab4b8..106eea78b 100644 --- a/tests/SAML2/XML/md/EndpointTypeTest.php +++ b/tests/SAML2/XML/md/EndpointTypeTest.php @@ -5,23 +5,22 @@ namespace SimpleSAML\Test\SAML2\XML\md; use DOMDocument; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\md\AbstractEndpointType; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\AssertionIDRequestService; -use SimpleSAML\SAML2\XML\md\AttributeService; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\md\{ + AbstractEndpointType, + AbstractMdElement, + AssertionIDRequestService, + AttributeService, +}; 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\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingAttributeException; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; +use SimpleSAML\XML\Exception\{InvalidDOMElementException, MissingAttributeException}; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\StringValue; use function dirname; use function strval; @@ -59,7 +58,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( @@ -76,12 +82,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], ); @@ -93,32 +99,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..630aa542c 100644 --- a/tests/SAML2/XML/md/EntitiesDescriptorTest.php +++ b/tests/SAML2/XML/md/EntitiesDescriptorTest.php @@ -4,23 +4,23 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\AbstractMetadataDocument; -use SimpleSAML\SAML2\XML\md\AbstractSignedMdElement; -use SimpleSAML\SAML2\XML\md\EntitiesDescriptor; -use SimpleSAML\SAML2\XML\md\EntityDescriptor; -use SimpleSAML\SAML2\XML\md\Extensions; -use SimpleSAML\SAML2\XML\mdrpi\PublicationInfo; -use SimpleSAML\SAML2\XML\mdrpi\UsagePolicy; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\md\{ + AbstractMdElement, + AbstractMetadataDocument, + AbstractSignedMdElement, + EntitiesDescriptor, + EntityDescriptor, + Extensions, +}; +use SimpleSAML\SAML2\XML\mdrpi\{PublicationInfo, UsagePolicy}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{IDValue, LanguageValue}; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -65,9 +65,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 +93,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 +169,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 c292fe1b0..c6301ac34 100644 --- a/tests/SAML2/XML/md/EntityDescriptorTest.php +++ b/tests/SAML2/XML/md/EntityDescriptorTest.php @@ -4,49 +4,52 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use DateTimeImmutable; use DOMText; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\AbstractMetadataDocument; -use SimpleSAML\SAML2\XML\md\AbstractSignedMdElement; -use SimpleSAML\SAML2\XML\md\AdditionalMetadataLocation; -use SimpleSAML\SAML2\XML\md\AffiliateMember; -use SimpleSAML\SAML2\XML\md\AffiliationDescriptor; -use SimpleSAML\SAML2\XML\md\AttributeAuthorityDescriptor; -use SimpleSAML\SAML2\XML\md\AttributeService; -use SimpleSAML\SAML2\XML\md\AuthnAuthorityDescriptor; -use SimpleSAML\SAML2\XML\md\AuthnQueryService; -use SimpleSAML\SAML2\XML\md\AuthzService; -use SimpleSAML\SAML2\XML\md\ContactPerson; -use SimpleSAML\SAML2\XML\md\EmailAddress; -use SimpleSAML\SAML2\XML\md\EntityDescriptor; -use SimpleSAML\SAML2\XML\md\Extensions; -use SimpleSAML\SAML2\XML\md\IDPSSODescriptor; -use SimpleSAML\SAML2\XML\md\Organization; -use SimpleSAML\SAML2\XML\md\OrganizationDisplayName; -use SimpleSAML\SAML2\XML\md\OrganizationName; -use SimpleSAML\SAML2\XML\md\OrganizationURL; -use SimpleSAML\SAML2\XML\md\PDPDescriptor; -use SimpleSAML\SAML2\XML\md\SingleSignOnService; -use SimpleSAML\SAML2\XML\md\UnknownRoleDescriptor; -use SimpleSAML\SAML2\XML\mdrpi\PublicationInfo; -use SimpleSAML\SAML2\XML\mdrpi\UsagePolicy; +use SimpleSAML\SAML2\Type\{ + SAMLAnyURIValue, + SAMLDateTimeValue, + EmailAddressValue, + EntityIDValue, + SAMLStringValue, +}; +use SimpleSAML\SAML2\XML\md\{ + AbstractMdElement, + AbstractMetadataDocument, + AbstractSignedMdElement, + AdditionalMetadataLocation, + AffiliateMember, + AffiliationDescriptor, + AttributeAuthorityDescriptor, + AttributeService, + AuthnAuthorityDescriptor, + AuthnQueryService, + AuthzService, + ContactPerson, + EmailAddress, + EntityDescriptor, + Extensions, + IDPSSODescriptor, + Organization, + OrganizationDisplayName, + OrganizationName, + OrganizationURL, + PDPDescriptor, + SingleSignOnService, + UnknownRoleDescriptor, +}; +use SimpleSAML\SAML2\XML\mdrpi\{PublicationInfo, UsagePolicy}; 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\XML\Exception\{MissingAttributeException, TooManyElementsException}; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{DurationValue, IDValue, LanguageValue, StringValue}; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; -use function str_pad; use function strval; /** @@ -86,17 +89,16 @@ 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], @@ -104,8 +106,8 @@ public function testMarshalling(): void $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], @@ -113,8 +115,8 @@ public function testMarshalling(): void $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], @@ -122,47 +124,85 @@ public function testMarshalling(): void $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], ); $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: [ @@ -229,45 +269,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 +360,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 +382,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 +394,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 +413,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 +431,7 @@ public function testUnmarshalling(): void 'urn:x-simplesamlphp:namespace', ); - $type = new XMLAttribute(C::NS_XSI, 'xsi', 'type', 'ssp:UnknownRoleDescriptor'); + $type = new XMLAttribute(C::NS_XSI, 'xsi', 'type', StringValue::fromString('ssp:UnknownRoleDescriptor')); $type->toXML($customd); $newline = new DOMText("\n "); @@ -394,7 +458,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(); @@ -477,30 +541,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..205d0cfcf 100644 --- a/tests/SAML2/XML/md/ExtensionsTest.php +++ b/tests/SAML2/XML/md/ExtensionsTest.php @@ -4,33 +4,23 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\alg\DigestMethod; -use SimpleSAML\SAML2\XML\alg\SigningMethod; -use SimpleSAML\SAML2\XML\emd\RepublishRequest; -use SimpleSAML\SAML2\XML\emd\RepublishTarget; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, CIDRValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\alg\{DigestMethod, SigningMethod}; +use SimpleSAML\SAML2\XML\emd\{RepublishRequest, RepublishTarget}; use SimpleSAML\SAML2\XML\idpdisc\DiscoveryResponse; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\Extensions; +use SimpleSAML\SAML2\XML\md\{AbstractMdElement, Extensions}; use SimpleSAML\SAML2\XML\mdattr\EntityAttributes; -use SimpleSAML\SAML2\XML\mdrpi\Publication; -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\DisplayName; -use SimpleSAML\SAML2\XML\mdui\IPHint; -use SimpleSAML\SAML2\XML\mdui\UIInfo; +use SimpleSAML\SAML2\XML\mdrpi\{Publication, PublicationInfo, PublicationPath, RegistrationInfo}; +use SimpleSAML\SAML2\XML\mdui\{DiscoHints, DisplayName, IPHint, UIInfo}; use SimpleSAML\SAML2\XML\saml\AttributeValue; use SimpleSAML\SAML2\XML\shibmd\Scope; -use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{LanguageValue, PositiveIntegerValue, UnsignedShortValue}; use function dirname; use function strval; @@ -71,20 +61,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 +195,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..e5d7a6ee0 100644 --- a/tests/SAML2/XML/md/IDPSSODescriptorTest.php +++ b/tests/SAML2/XML/md/IDPSSODescriptorTest.php @@ -4,35 +4,36 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\AbstractMetadataDocument; -use SimpleSAML\SAML2\XML\md\AbstractRoleDescriptor; -use SimpleSAML\SAML2\XML\md\AbstractRoleDescriptorType; -use SimpleSAML\SAML2\XML\md\AbstractSignedMdElement; -use SimpleSAML\SAML2\XML\md\ArtifactResolutionService; -use SimpleSAML\SAML2\XML\md\AssertionIDRequestService; -use SimpleSAML\SAML2\XML\md\AttributeProfile; -use SimpleSAML\SAML2\XML\md\IDPSSODescriptor; -use SimpleSAML\SAML2\XML\md\KeyDescriptor; -use SimpleSAML\SAML2\XML\md\ManageNameIDService; -use SimpleSAML\SAML2\XML\md\NameIDFormat; -use SimpleSAML\SAML2\XML\md\NameIDMappingService; -use SimpleSAML\SAML2\XML\md\SingleLogoutService; -use SimpleSAML\SAML2\XML\md\SingleSignOnService; -use SimpleSAML\SAML2\XML\saml\Attribute; -use SimpleSAML\SAML2\XML\saml\AttributeValue; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, KeyTypesValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\md\{ + AbstractMdElement, + AbstractMetadataDocument, + AbstractRoleDescriptor, + AbstractRoleDescriptorType, + AbstractSignedMdElement, + ArtifactResolutionService, + AssertionIDRequestService, + AttributeProfile, + IDPSSODescriptor, + KeyDescriptor, + KeyTypesEnum, + ManageNameIDService, + NameIDFormat, + NameIDMappingService, + SingleLogoutService, + SingleSignOnService, +}; +use SimpleSAML\SAML2\XML\saml\{Attribute, AttributeValue}; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{BooleanValue, IDValue, UnsignedShortValue}; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; -use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; -use SimpleSAML\XMLSecurity\XML\ds\KeyName; +use SimpleSAML\XMLSecurity\XML\ds\{KeyInfo, KeyName}; use function dirname; use function strval; @@ -77,53 +78,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, + 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 +140,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), + ), ], ); @@ -200,26 +213,17 @@ public function testMarshallingWithoutProtocolSupportThrowsException(): void $this->expectExceptionMessage('At least one protocol must be supported by this md:IDPSSODescriptor.'); new IDPSSODescriptor( - [new SingleSignOnService(C::BINDING_HTTP_POST, C::LOCATION_A)], + [ + new SingleSignOnService( + SAMLAnyURIValue::fromString(C::BINDING_HTTP_POST), + SAMLAnyURIValue::fromString(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('')], - ); - } - - /** * Test that creating an IDPSSODescriptor from scratch works if no optional arguments are provided. */ @@ -227,8 +231,14 @@ 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], ); @@ -259,23 +269,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 9007a7ab4..3715ef793 100644 --- a/tests/SAML2/XML/md/IndexedEndpointTypeTest.php +++ b/tests/SAML2/XML/md/IndexedEndpointTypeTest.php @@ -4,20 +4,20 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, DataProvider, 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; -use SimpleSAML\SAML2\XML\md\ArtifactResolutionService; -use SimpleSAML\SAML2\XML\md\AssertionConsumerService; +use SimpleSAML\SAML2\XML\md\{ + AbstractIndexedEndpointType, + AbstractMdElement, + ArtifactResolutionService, + AssertionConsumerService, +}; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\MissingAttributeException; +use SimpleSAML\XML\Exception\{InvalidDOMElementException, MissingAttributeException}; +use SimpleSAML\XML\Type\UnsignedShortValue; use function dirname; use function sprintf; @@ -55,7 +55,11 @@ public static function setUpBeforeClass(): void public function testMarshallingWithoutIsDefault(string $class): 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()); } @@ -78,7 +82,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()); } @@ -125,31 +129,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. * @@ -169,31 +148,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..7e10f9edb 100644 --- a/tests/SAML2/XML/md/KeyDescriptorTest.php +++ b/tests/SAML2/XML/md/KeyDescriptorTest.php @@ -4,18 +4,15 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\Assert\AssertionFailedException; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\EncryptionMethod; -use SimpleSAML\SAML2\XML\md\KeyDescriptor; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, KeyTypesValue}; +use SimpleSAML\SAML2\XML\md\{AbstractMdElement, EncryptionMethod, KeyDescriptor, KeyTypesEnum}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; -use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; -use SimpleSAML\XMLSecurity\XML\ds\KeyName; +use SimpleSAML\XML\Exception\SchemaViolationException; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\StringValue; +use SimpleSAML\XMLSecurity\XML\ds\{KeyInfo, KeyName}; use function dirname; use function strval; @@ -55,9 +52,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,27 +72,18 @@ 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()); @@ -117,8 +113,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); } diff --git a/tests/SAML2/XML/md/NameIDFormatTest.php b/tests/SAML2/XML/md/NameIDFormatTest.php index 9df3b5b21..58b60a5b8 100644 --- a/tests/SAML2/XML/md/NameIDFormatTest.php +++ b/tests/SAML2/XML/md/NameIDFormatTest.php @@ -4,15 +4,13 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\NameIDFormat; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\md\{AbstractMdElement, NameIDFormat}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -50,7 +48,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..eed5b984e 100644 --- a/tests/SAML2/XML/md/NameIDMappingServiceTest.php +++ b/tests/SAML2/XML/md/NameIDMappingServiceTest.php @@ -4,16 +4,15 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, 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; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -52,7 +51,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 +72,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..3a389dd8e 100644 --- a/tests/SAML2/XML/md/OrganizationDisplayNameTest.php +++ b/tests/SAML2/XML/md/OrganizationDisplayNameTest.php @@ -4,16 +4,13 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\OrganizationDisplayName; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\SAML2\XML\md\{AbstractLocalizedName, AbstractMdElement, OrganizationDisplayName}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\LanguageValue; use function dirname; use function strval; @@ -56,7 +53,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..e45e54f7b 100644 --- a/tests/SAML2/XML/md/OrganizationNameTest.php +++ b/tests/SAML2/XML/md/OrganizationNameTest.php @@ -4,16 +4,13 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\OrganizationName; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\SAML2\XML\md\{AbstractLocalizedName, AbstractMdElement, OrganizationName}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\LanguageValue; use function dirname; use function strval; @@ -56,7 +53,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 3635dd7d3..00da8be66 100644 --- a/tests/SAML2/XML/md/OrganizationTest.php +++ b/tests/SAML2/XML/md/OrganizationTest.php @@ -5,22 +5,22 @@ namespace SimpleSAML\Test\SAML2\XML\md; use DOMDocument; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\Extensions; -use SimpleSAML\SAML2\XML\md\Organization; -use SimpleSAML\SAML2\XML\md\OrganizationDisplayName; -use SimpleSAML\SAML2\XML\md\OrganizationName; -use SimpleSAML\SAML2\XML\md\OrganizationURL; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\md\{ + AbstractMdElement, + Extensions, + Organization, + OrganizationDisplayName, + OrganizationName, + OrganizationURL, +}; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\Attribute as XMLAttribute; -use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{LanguageValue, StringValue}; use function dirname; use function strval; @@ -83,15 +83,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..c2ad5ad02 100644 --- a/tests/SAML2/XML/md/OrganizationURLTest.php +++ b/tests/SAML2/XML/md/OrganizationURLTest.php @@ -4,17 +4,13 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; -use SimpleSAML\SAML2\XML\md\AbstractLocalizedURI; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\OrganizationURL; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\md\{AbstractLocalizedName, AbstractLocalizedURI, AbstractMdElement, OrganizationURL}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\LanguageValue; use function dirname; use function strval; @@ -58,7 +54,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 e6a8ce8d2..463b4883f 100644 --- a/tests/SAML2/XML/md/PDPDescriptorTest.php +++ b/tests/SAML2/XML/md/PDPDescriptorTest.php @@ -4,23 +4,25 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\AbstractMetadataDocument; -use SimpleSAML\SAML2\XML\md\AbstractRoleDescriptor; -use SimpleSAML\SAML2\XML\md\AbstractRoleDescriptorType; -use SimpleSAML\SAML2\XML\md\AbstractSignedMdElement; -use SimpleSAML\SAML2\XML\md\AssertionIDRequestService; -use SimpleSAML\SAML2\XML\md\AuthzService; -use SimpleSAML\SAML2\XML\md\NameIDFormat; -use SimpleSAML\SAML2\XML\md\PDPDescriptor; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\md\{ + AbstractMdElement, + AbstractMetadataDocument, + AbstractRoleDescriptor, + AbstractRoleDescriptorType, + AbstractSignedMdElement, + AssertionIDRequestService, + AuthzService, + NameIDFormat, + PDPDescriptor, +}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -63,13 +65,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'), ); } @@ -87,11 +89,17 @@ public function testMarshalling(): void ["urn:oasis:names:tc:SAML:2.0:protocol"], [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( diff --git a/tests/SAML2/XML/md/RequestedAttributeTest.php b/tests/SAML2/XML/md/RequestedAttributeTest.php index ab1bde7a0..60e4ab2fc 100644 --- a/tests/SAML2/XML/md/RequestedAttributeTest.php +++ b/tests/SAML2/XML/md/RequestedAttributeTest.php @@ -4,17 +4,15 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\RequestedAttribute; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\md\{AbstractMdElement, RequestedAttribute}; use SimpleSAML\SAML2\XML\saml\AttributeValue; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\BooleanValue; use function dirname; use function strval; @@ -54,11 +52,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,8 +73,10 @@ 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()); @@ -95,19 +97,4 @@ public function testUnmarshallingWithoutIsRequired(): void $ra = RequestedAttribute::fromXML($xmlRepresentation->documentElement); $this->assertNull($ra->getIsRequired()); } - - - /** - * 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 dcee1f5cb..fede4323a 100644 --- a/tests/SAML2/XML/md/RoleDescriptorTest.php +++ b/tests/SAML2/XML/md/RoleDescriptorTest.php @@ -4,42 +4,47 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\Compat\AbstractContainer; -use SimpleSAML\SAML2\Compat\ContainerSingleton; +use SimpleSAML\SAML2\Compat\{AbstractContainer, ContainerSingleton}; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\AbstractMetadataDocument; -use SimpleSAML\SAML2\XML\md\AbstractRoleDescriptor; -use SimpleSAML\SAML2\XML\md\AbstractRoleDescriptorType; -use SimpleSAML\SAML2\XML\md\AbstractSignedMdElement; -use SimpleSAML\SAML2\XML\md\Company; -use SimpleSAML\SAML2\XML\md\ContactPerson; -use SimpleSAML\SAML2\XML\md\EmailAddress; -use SimpleSAML\SAML2\XML\md\EncryptionMethod; -use SimpleSAML\SAML2\XML\md\Extensions; -use SimpleSAML\SAML2\XML\md\GivenName; -use SimpleSAML\SAML2\XML\md\KeyDescriptor; -use SimpleSAML\SAML2\XML\md\Organization; -use SimpleSAML\SAML2\XML\md\OrganizationDisplayName; -use SimpleSAML\SAML2\XML\md\OrganizationName; -use SimpleSAML\SAML2\XML\md\OrganizationURL; -use SimpleSAML\SAML2\XML\md\SurName; -use SimpleSAML\SAML2\XML\md\TelephoneNumber; -use SimpleSAML\SAML2\XML\md\UnknownRoleDescriptor; +use SimpleSAML\SAML2\Type\{ + SAMLAnyURIValue, + SAMLDateTimeValue, + EmailAddressValue, + KeyTypesValue, + SAMLStringValue, +}; +use SimpleSAML\SAML2\XML\md\{ + AbstractMdElement, + AbstractMetadataDocument, + AbstractRoleDescriptor, + AbstractRoleDescriptorType, + AbstractSignedMdElement, + Company, + ContactPerson, + EmailAddress, + EncryptionMethod, + Extensions, + GivenName, + KeyDescriptor, + KeyTypesEnum, + Organization, + OrganizationDisplayName, + OrganizationName, + OrganizationURL, + SurName, + TelephoneNumber, + UnknownRoleDescriptor, +}; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\Test\SAML2\CustomRoleDescriptor; use SimpleSAML\XML\Attribute as XMLAttribute; -use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; use SimpleSAML\XML\Exception\MissingAttributeException; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; -use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; -use SimpleSAML\XMLSecurity\XML\ds\KeyName; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{AnyURIValue, DurationValue, IDValue, LanguageValue, StringValue}; +use SimpleSAML\XMLSecurity\XML\ds\{KeyInfo, KeyName}; use function dirname; use function strval; @@ -86,13 +91,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 @@ -108,9 +106,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,47 +117,94 @@ public function testMarshalling(): void )->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/', + 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], @@ -182,7 +227,7 @@ 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]); @@ -195,9 +240,9 @@ public function testUnmarshalling(): void $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); @@ -219,14 +264,10 @@ 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::NS_XSI, 'xsi:type', 'ssp:UnknownRoleDescriptorType'); - $type = new XMLAttribute(C::NS_XSI, 'xsi', 'type', 'ssp:UnknownRoleDescriptorType'); + $type = new XMLAttribute(C::NS_XSI, 'xsi', 'type', StringValue::fromString('ssp:UnknownRoleDescriptorType')); $type->toXML($element); $descriptor = AbstractRoleDescriptor::fromXML($element); @@ -243,10 +284,10 @@ public function testUnmarshallingUnregistered(): void $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()); @@ -262,7 +303,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)); } @@ -271,14 +312,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); } @@ -287,23 +329,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 02ff6eaca..b6f4b96c6 100644 --- a/tests/SAML2/XML/md/SPSSODescriptorTest.php +++ b/tests/SAML2/XML/md/SPSSODescriptorTest.php @@ -4,43 +4,44 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\AbstractMetadataDocument; -use SimpleSAML\SAML2\XML\md\AbstractRoleDescriptor; -use SimpleSAML\SAML2\XML\md\AbstractRoleDescriptorType; -use SimpleSAML\SAML2\XML\md\AbstractSignedMdElement; -use SimpleSAML\SAML2\XML\md\ArtifactResolutionService; -use SimpleSAML\SAML2\XML\md\AssertionConsumerService; -use SimpleSAML\SAML2\XML\md\AttributeConsumingService; -use SimpleSAML\SAML2\XML\md\ContactPerson; -use SimpleSAML\SAML2\XML\md\EmailAddress; -use SimpleSAML\SAML2\XML\md\Extensions; -use SimpleSAML\SAML2\XML\md\KeyDescriptor; -use SimpleSAML\SAML2\XML\md\ManageNameIDService; -use SimpleSAML\SAML2\XML\md\NameIDFormat; -use SimpleSAML\SAML2\XML\md\Organization; -use SimpleSAML\SAML2\XML\md\OrganizationDisplayName; -use SimpleSAML\SAML2\XML\md\OrganizationName; -use SimpleSAML\SAML2\XML\md\OrganizationURL; -use SimpleSAML\SAML2\XML\md\RequestedAttribute; -use SimpleSAML\SAML2\XML\md\ServiceName; -use SimpleSAML\SAML2\XML\md\SingleLogoutService; -use SimpleSAML\SAML2\XML\md\SPSSODescriptor; -use SimpleSAML\SAML2\XML\mdrpi\PublicationInfo; -use SimpleSAML\SAML2\XML\mdrpi\UsagePolicy; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, EmailAddressValue, KeyTypesValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\md\{ + AbstractMdElement, + AbstractMetadataDocument, + AbstractRoleDescriptor, + AbstractRoleDescriptorType, + AbstractSignedMdElement, + ArtifactResolutionService, + AssertionConsumerService, + AttributeConsumingService, + ContactPerson, + EmailAddress, + Extensions, + KeyDescriptor, + KeyTypesEnum, + ManageNameIDService, + NameIDFormat, + Organization, + OrganizationDisplayName, + OrganizationName, + OrganizationURL, + RequestedAttribute, + ServiceName, + SingleLogoutService, + SPSSODescriptor, +}; +use SimpleSAML\SAML2\XML\mdrpi\{PublicationInfo, UsagePolicy}; use SimpleSAML\SAML2\XML\saml\AttributeValue; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\Exception\SchemaViolationException; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{BooleanValue, DurationValue, IDValue, LanguageValue, StringValue, UnsignedShortValue}; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; -use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; -use SimpleSAML\XMLSecurity\XML\ds\KeyName; +use SimpleSAML\XMLSecurity\XML\ds\{KeyInfo, KeyName}; use function dirname; use function strval; @@ -85,80 +86,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, + 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( @@ -189,7 +246,13 @@ public function testMarshallingWithoutAssertionConsumerService(): void public function testMarshallingWithoutOptionalArguments(): void { $spssod = new SPSSODescriptor( - [new AssertionConsumerService(0, C::BINDING_HTTP_POST, C::LOCATION_A)], + [ + new AssertionConsumerService( + UnsignedShortValue::fromInteger(0), + SAMLAnyURIValue::fromString(C::BINDING_HTTP_POST), + SAMLAnyURIValue::fromString(C::LOCATION_A), + ), + ], [C::NS_SAMLP], ); @@ -228,9 +291,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 +304,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..84b660f23 100644 --- a/tests/SAML2/XML/md/ServiceDescriptionTest.php +++ b/tests/SAML2/XML/md/ServiceDescriptionTest.php @@ -4,16 +4,13 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\ServiceDescription; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\SAML2\XML\md\{AbstractLocalizedName, AbstractMdElement, ServiceDescription}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\LanguageValue; use function dirname; use function strval; @@ -56,7 +53,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..f3172edca 100644 --- a/tests/SAML2/XML/md/ServiceNameTest.php +++ b/tests/SAML2/XML/md/ServiceNameTest.php @@ -4,19 +4,15 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\ServiceName; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\SAML2\XML\md\{AbstractLocalizedName, AbstractMdElement, ServiceName}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\Exception\MissingAttributeException; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\LanguageValue; use function dirname; use function strval; @@ -59,7 +55,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 +67,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 +78,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..3d80a8808 100644 --- a/tests/SAML2/XML/md/SingleSignOnServiceTest.php +++ b/tests/SAML2/XML/md/SingleSignOnServiceTest.php @@ -4,16 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\Assert\AssertionFailedException; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\SingleSignOnService; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\XML\md\{AbstractMdElement, SingleSignOnService}; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -52,7 +50,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 +67,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 +91,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..3d190349a 100644 --- a/tests/SAML2/XML/md/SurNameTest.php +++ b/tests/SAML2/XML/md/SurNameTest.php @@ -4,14 +4,12 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\SurName; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\SAML2\XML\md\{AbstractMdElement, SurName}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -50,7 +48,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..d805ff8b9 100644 --- a/tests/SAML2/XML/md/TelephoneNumberTest.php +++ b/tests/SAML2/XML/md/TelephoneNumberTest.php @@ -4,18 +4,15 @@ namespace SimpleSAML\Test\SAML2\XML\md; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; -use SimpleSAML\SAML2\XML\md\TelephoneNumber; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\SAML2\XML\md\{AbstractMdElement, TelephoneNumber}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; /** - * Tests for SurName. + * Tests for TelephoneNumber. * * @package simplesamlphp/saml2 */ @@ -47,11 +44,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..523d07623 100644 --- a/tests/SAML2/XML/mdattr/EntityAttributesTest.php +++ b/tests/SAML2/XML/mdattr/EntityAttributesTest.php @@ -4,26 +4,26 @@ namespace SimpleSAML\Test\SAML2\XML\mdattr; -use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\mdattr\AbstractMdattrElement; -use SimpleSAML\SAML2\XML\mdattr\EntityAttributes; -use SimpleSAML\SAML2\XML\saml\Assertion; -use SimpleSAML\SAML2\XML\saml\Attribute; -use SimpleSAML\SAML2\XML\saml\AttributeStatement; -use SimpleSAML\SAML2\XML\saml\AttributeValue; -use SimpleSAML\SAML2\XML\saml\Audience; -use SimpleSAML\SAML2\XML\saml\AudienceRestriction; -use SimpleSAML\SAML2\XML\saml\Conditions; -use SimpleSAML\SAML2\XML\saml\Issuer; -use SimpleSAML\SAML2\XML\saml\NameID; -use SimpleSAML\SAML2\XML\saml\Subject; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\mdattr\{AbstractMdattrElement, EntityAttributes}; +use SimpleSAML\SAML2\XML\saml\{ + Assertion, + Attribute, + AttributeStatement, + AttributeValue, + Audience, + AudienceRestriction, + Conditions, + Issuer, + NameID, + Subject, +}; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\Alg\Signature\SignatureAlgorithmFactory; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; @@ -61,8 +61,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 +71,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 +93,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 +125,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 +151,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..6daf0a624 100644 --- a/tests/SAML2/XML/mdrpi/PublicationInfoTest.php +++ b/tests/SAML2/XML/mdrpi/PublicationInfoTest.php @@ -4,19 +4,17 @@ namespace SimpleSAML\Test\SAML2\XML\mdrpi; -use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use DOMDocument; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\mdrpi\AbstractMdrpiElement; -use SimpleSAML\SAML2\XML\mdrpi\PublicationInfo; -use SimpleSAML\SAML2\XML\mdrpi\UsagePolicy; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, EntityIDValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\md\{AffiliationDescriptor, EntitiesDescriptor, EntityDescriptor, Extensions}; +use SimpleSAML\SAML2\XML\mdrpi\{AbstractMdrpiElement, PublicationInfo, 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\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\LanguageValue; use function dirname; use function strval; @@ -35,6 +33,9 @@ final class PublicationInfoTest extends TestCase use SchemaValidationTestTrait; use SerializableElementTestTrait; + /** @var \DOMDocument */ + private static DOMDocument $affiliationDescriptor; + /** */ @@ -46,6 +47,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 +65,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 +95,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 +126,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 +139,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..c4e297e57 100644 --- a/tests/SAML2/XML/mdrpi/PublicationPathTest.php +++ b/tests/SAML2/XML/mdrpi/PublicationPathTest.php @@ -4,17 +4,12 @@ namespace SimpleSAML\Test\SAML2\XML\mdrpi; -use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\mdrpi\AbstractMdrpiElement; -use SimpleSAML\SAML2\XML\mdrpi\Publication; -use SimpleSAML\SAML2\XML\mdrpi\PublicationPath; +use SimpleSAML\SAML2\XML\mdrpi\{AbstractMdrpiElement, Publication, PublicationPath}; +use SimpleSAML\SAML2\Type\{SAMLDateTimeValue, SAMLStringValue}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -64,11 +59,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..821219f42 100644 --- a/tests/SAML2/XML/mdrpi/PublicationTest.php +++ b/tests/SAML2/XML/mdrpi/PublicationTest.php @@ -4,18 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\mdrpi; -use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\mdrpi\AbstractMdrpiElement; -use SimpleSAML\SAML2\XML\mdrpi\Publication; +use SimpleSAML\SAML2\Type\{SAMLDateTimeValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\mdrpi\{AbstractMdrpiElement, 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\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -58,9 +54,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 +74,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..d428770a4 100644 --- a/tests/SAML2/XML/mdrpi/RegistrationInfoTest.php +++ b/tests/SAML2/XML/mdrpi/RegistrationInfoTest.php @@ -4,19 +4,17 @@ namespace SimpleSAML\Test\SAML2\XML\mdrpi; -use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use DOMDocument; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Exception\ProtocolViolationException; -use SimpleSAML\SAML2\XML\mdrpi\AbstractMdrpiElement; -use SimpleSAML\SAML2\XML\mdrpi\RegistrationInfo; -use SimpleSAML\SAML2\XML\mdrpi\RegistrationPolicy; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, EntityIDValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\md\{AffiliationDescriptor, EntitiesDescriptor, EntityDescriptor, Extensions}; +use SimpleSAML\SAML2\XML\mdrpi\{AbstractMdrpiElement, RegistrationInfo, 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\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\LanguageValue; use function dirname; use function strval; @@ -35,6 +33,9 @@ final class RegistrationInfoTest extends TestCase use SchemaValidationTestTrait; use SerializableElementTestTrait; + /** @var \DOMDocument */ + private static DOMDocument $affiliationDescriptor; + /** */ @@ -46,6 +47,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 +67,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 +109,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 +131,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..b6d5c8b54 100644 --- a/tests/SAML2/XML/mdrpi/RegistrationPolicyTest.php +++ b/tests/SAML2/XML/mdrpi/RegistrationPolicyTest.php @@ -4,16 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\mdrpi; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; -use SimpleSAML\SAML2\XML\md\AbstractLocalizedURI; -use SimpleSAML\SAML2\XML\mdrpi\AbstractMdrpiElement; -use SimpleSAML\SAML2\XML\mdrpi\RegistrationPolicy; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\md\{AbstractLocalizedName, AbstractLocalizedURI}; +use SimpleSAML\SAML2\XML\mdrpi\{AbstractMdrpiElement, RegistrationPolicy}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\LanguageValue; use function dirname; use function strval; @@ -56,7 +54,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..25167177e 100644 --- a/tests/SAML2/XML/mdrpi/UsagePolicyTest.php +++ b/tests/SAML2/XML/mdrpi/UsagePolicyTest.php @@ -4,16 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\mdrpi; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; -use SimpleSAML\SAML2\XML\md\AbstractLocalizedURI; -use SimpleSAML\SAML2\XML\mdrpi\AbstractMdrpiElement; -use SimpleSAML\SAML2\XML\mdrpi\UsagePolicy; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\md\{AbstractLocalizedName, AbstractLocalizedURI}; +use SimpleSAML\SAML2\XML\mdrpi\{AbstractMdrpiElement, UsagePolicy}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\LanguageValue; use function dirname; use function strval; @@ -56,7 +54,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..7ff564793 100644 --- a/tests/SAML2/XML/mdui/DescriptionTest.php +++ b/tests/SAML2/XML/mdui/DescriptionTest.php @@ -4,15 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\mdui; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\SAML2\XML\md\{AbstractLocalizedName, AbstractMdElement}; use SimpleSAML\SAML2\XML\mdui\Description; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\LanguageValue; use function dirname; use function strval; @@ -54,7 +53,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..6c5e54629 100644 --- a/tests/SAML2/XML/mdui/DiscoHintsTest.php +++ b/tests/SAML2/XML/mdui/DiscoHintsTest.php @@ -4,21 +4,21 @@ namespace SimpleSAML\Test\SAML2\XML\mdui; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\{CIDRValue, DomainValue, GeolocationValue, ListOfStringsValue}; use SimpleSAML\SAML2\Utils\XPath; -use SimpleSAML\SAML2\XML\mdui\AbstractMduiElement; -use SimpleSAML\SAML2\XML\mdui\DiscoHints; -use SimpleSAML\SAML2\XML\mdui\DomainHint; -use SimpleSAML\SAML2\XML\mdui\GeolocationHint; -use SimpleSAML\SAML2\XML\mdui\IPHint; -use SimpleSAML\SAML2\XML\mdui\Keywords; -use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\SAML2\XML\mdui\{ + AbstractMduiElement, + DiscoHints, + DomainHint, + GeolocationHint, + IPHint, + Keywords, +}; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\LanguageValue; use function dirname; use function strval; @@ -62,11 +62,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 +115,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 +159,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..2ea06974a 100644 --- a/tests/SAML2/XML/mdui/DisplayNameTest.php +++ b/tests/SAML2/XML/mdui/DisplayNameTest.php @@ -4,15 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\mdui; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\SAML2\XML\md\{AbstractLocalizedName, AbstractMdElement}; use SimpleSAML\SAML2\XML\mdui\DisplayName; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\LanguageValue; use function dirname; use function strval; @@ -54,7 +53,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..48a775399 100644 --- a/tests/SAML2/XML/mdui/DomainHintTest.php +++ b/tests/SAML2/XML/mdui/DomainHintTest.php @@ -4,15 +4,13 @@ namespace SimpleSAML\Test\SAML2\XML\mdui; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, 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; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -51,27 +49,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..e4c8dd098 100644 --- a/tests/SAML2/XML/mdui/GeolocationHintTest.php +++ b/tests/SAML2/XML/mdui/GeolocationHintTest.php @@ -4,14 +4,12 @@ namespace SimpleSAML\Test\SAML2\XML\mdui; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\mdui\AbstractMduiElement; -use SimpleSAML\SAML2\XML\mdui\GeolocationHint; +use SimpleSAML\SAML2\Type\GeolocationValue; +use SimpleSAML\SAML2\XML\mdui\{AbstractMduiElement, GeolocationHint}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -50,7 +48,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..0dafa8be2 100644 --- a/tests/SAML2/XML/mdui/IPHintTest.php +++ b/tests/SAML2/XML/mdui/IPHintTest.php @@ -4,14 +4,12 @@ namespace SimpleSAML\Test\SAML2\XML\mdui; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\mdui\AbstractMduiElement; -use SimpleSAML\SAML2\XML\mdui\IPHint; +use SimpleSAML\SAML2\Type\CIDRValue; +use SimpleSAML\SAML2\XML\mdui\{AbstractMduiElement, IPHint}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -50,7 +48,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..163d075d0 100644 --- a/tests/SAML2/XML/mdui/InformationURLTest.php +++ b/tests/SAML2/XML/mdui/InformationURLTest.php @@ -4,16 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\mdui; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; -use SimpleSAML\SAML2\XML\md\AbstractLocalizedURI; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\md\{AbstractLocalizedName, AbstractLocalizedURI, AbstractMdElement}; use SimpleSAML\SAML2\XML\mdui\InformationURL; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\LanguageValue; use function dirname; use function strval; @@ -56,7 +54,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..ed40309bc 100644 --- a/tests/SAML2/XML/mdui/KeywordsTest.php +++ b/tests/SAML2/XML/mdui/KeywordsTest.php @@ -4,16 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\mdui; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\Assert\AssertionFailedException; -use SimpleSAML\SAML2\XML\mdui\AbstractMduiElement; -use SimpleSAML\SAML2\XML\mdui\Keywords; +use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\ListOfStringsValue; +use SimpleSAML\SAML2\XML\mdui\{AbstractMduiElement, Keywords}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\LanguageValue; use function dirname; use function strval; @@ -54,8 +52,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 +69,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..ae95273cf 100644 --- a/tests/SAML2/XML/mdui/LogoTest.php +++ b/tests/SAML2/XML/mdui/LogoTest.php @@ -4,18 +4,16 @@ namespace SimpleSAML\Test\SAML2\XML\mdui; -use InvalidArgumentException; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; -use SimpleSAML\SAML2\XML\mdui\AbstractMduiElement; -use SimpleSAML\SAML2\XML\mdui\Logo; +use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\mdui\{AbstractMduiElement, 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\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{LanguageValue, PositiveIntegerValue}; use function dirname; use function strval; @@ -68,7 +66,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 +90,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 +115,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 +143,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..9df2802ce 100644 --- a/tests/SAML2/XML/mdui/PrivacyStatementURLTest.php +++ b/tests/SAML2/XML/mdui/PrivacyStatementURLTest.php @@ -4,16 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\mdui; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\md\AbstractLocalizedName; -use SimpleSAML\SAML2\XML\md\AbstractLocalizedURI; -use SimpleSAML\SAML2\XML\md\AbstractMdElement; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\md\{AbstractLocalizedName, AbstractLocalizedURI, AbstractMdElement}; use SimpleSAML\SAML2\XML\mdui\PrivacyStatementURL; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\LanguageValue; use function dirname; use function strval; @@ -56,7 +54,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..ba0fa8689 100644 --- a/tests/SAML2/XML/mdui/UIInfoTest.php +++ b/tests/SAML2/XML/mdui/UIInfoTest.php @@ -4,26 +4,26 @@ namespace SimpleSAML\Test\SAML2\XML\mdui; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, CIDRValue, ListOfStringsValue, SAMLStringValue}; use SimpleSAML\SAML2\Utils\XPath; -use SimpleSAML\SAML2\XML\mdui\AbstractMduiElement; -use SimpleSAML\SAML2\XML\mdui\Description; -use SimpleSAML\SAML2\XML\mdui\DiscoHints; -use SimpleSAML\SAML2\XML\mdui\DisplayName; -use SimpleSAML\SAML2\XML\mdui\InformationURL; -use SimpleSAML\SAML2\XML\mdui\IPHint; -use SimpleSAML\SAML2\XML\mdui\Keywords; -use SimpleSAML\SAML2\XML\mdui\Logo; -use SimpleSAML\SAML2\XML\mdui\PrivacyStatementURL; -use SimpleSAML\SAML2\XML\mdui\UIInfo; -use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\SAML2\XML\mdui\{ + AbstractMduiElement, + Description, + DiscoHints, + DisplayName, + InformationURL, + IPHint, + Keywords, + Logo, + PrivacyStatementURL, + UIInfo, +}; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{LanguageValue, PositiveIntegerValue}; use function dirname; use function strval; @@ -70,22 +70,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 +120,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 +146,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 +246,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 +268,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 +290,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 +312,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 +334,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..993ccd462 100644 --- a/tests/SAML2/XML/saml/ActionTest.php +++ b/tests/SAML2/XML/saml/ActionTest.php @@ -4,11 +4,10 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\Action; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\saml\{AbstractSamlElement, Action}; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; @@ -49,8 +48,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 d1421c4ff..43a527079 100644 --- a/tests/SAML2/XML/saml/AdviceTest.php +++ b/tests/SAML2/XML/saml/AdviceTest.php @@ -5,19 +5,18 @@ namespace SimpleSAML\SAML2\Test\SAML2\XML\saml; use DOMDocument; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\Advice; -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; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\SAML2\XML\saml\{ + AbstractSamlElement, + Advice, + Assertion, + AssertionIDRef, + AssertionURIRef, + EncryptedAssertion, +}; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; diff --git a/tests/SAML2/XML/saml/AssertionIDRefTest.php b/tests/SAML2/XML/saml/AssertionIDRefTest.php index 916a6c4b7..6034dec73 100644 --- a/tests/SAML2/XML/saml/AssertionIDRefTest.php +++ b/tests/SAML2/XML/saml/AssertionIDRefTest.php @@ -4,14 +4,12 @@ namespace SimpleSAML\SAML2\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\AssertionIDRef; +use SimpleSAML\SAML2\XML\saml\{AbstractSamlElement, AssertionIDRef}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\NCNameValue; use function dirname; use function strval; @@ -45,7 +43,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 0f4224194..15abe18d4 100644 --- a/tests/SAML2/XML/saml/AssertionTest.php +++ b/tests/SAML2/XML/saml/AssertionTest.php @@ -4,49 +4,48 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use DateTimeImmutable; use Exception; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; -use SimpleSAML\SAML2\Compat\AbstractContainer; -use SimpleSAML\SAML2\Compat\ContainerSingleton; +use SimpleSAML\SAML2\Compat\{AbstractContainer, ContainerSingleton}; +use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, DomainValue, EntityIDValue, SAMLStringValue}; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\Utils\XPath; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\Assertion; -use SimpleSAML\SAML2\XML\saml\Attribute; -use SimpleSAML\SAML2\XML\saml\AttributeStatement; -use SimpleSAML\SAML2\XML\saml\AttributeValue; -use SimpleSAML\SAML2\XML\saml\Audience; -use SimpleSAML\SAML2\XML\saml\AudienceRestriction; -use SimpleSAML\SAML2\XML\saml\AuthenticatingAuthority; -use SimpleSAML\SAML2\XML\saml\AuthnContext; -use SimpleSAML\SAML2\XML\saml\AuthnContextClassRef; -use SimpleSAML\SAML2\XML\saml\AuthnContextDeclRef; -use SimpleSAML\SAML2\XML\saml\AuthnStatement; -use SimpleSAML\SAML2\XML\saml\Conditions; -use SimpleSAML\SAML2\XML\saml\EncryptedAssertion; -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\saml\SubjectConfirmation; -use SimpleSAML\SAML2\XML\saml\SubjectConfirmationData; -use SimpleSAML\SAML2\XML\saml\SubjectLocality; +use SimpleSAML\SAML2\XML\saml\{ + AbstractSamlElement, + Assertion, + Attribute, + AttributeStatement, + AttributeValue, + Audience, + AudienceRestriction, + AuthenticatingAuthority, + AuthnContext, + AuthnContextClassRef, + AuthnContextDeclRef, + AuthnStatement, + Conditions, + EncryptedAssertion, + EncryptedID, + Issuer, + NameID, + Subject, + SubjectConfirmation, + SubjectConfirmationData, + 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\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{Base64BinaryValue, IDValue, NCNameValue}; use SimpleSAML\XMLSecurity\Alg\KeyTransport\KeyTransportAlgorithmFactory; use SimpleSAML\XMLSecurity\Alg\Signature\SignatureAlgorithmFactory; use SimpleSAML\XMLSecurity\Exception\SignatureVerificationFailedException; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; -use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; -use SimpleSAML\XMLSecurity\XML\ds\X509Certificate; -use SimpleSAML\XMLSecurity\XML\ds\X509Data; +use SimpleSAML\XMLSecurity\XML\ds\{KeyInfo, X509Certificate, X509Data}; use function dirname; use function strval; @@ -105,63 +104,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'), ), ), ], @@ -170,8 +187,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], @@ -252,15 +269,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)), + ], ), ], ); @@ -268,18 +290,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 @@ -287,18 +320,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), + ], ), ], ); @@ -307,8 +347,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, ); @@ -325,22 +365,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); @@ -512,7 +552,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)), + ), ]), ]); @@ -686,7 +728,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), ); @@ -699,7 +741,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()); } @@ -713,7 +755,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), ); @@ -739,7 +781,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), ); @@ -781,7 +823,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), ); @@ -842,8 +884,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); } @@ -1071,21 +1112,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); @@ -1100,17 +1146,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], @@ -1125,25 +1174,32 @@ public function testNameIdEncryption(): void $this->assertInstanceOf(EncryptedID::class, $identifier); $decryptor = (new KeyTransportAlgorithmFactory())->getAlgorithm( - $identifier->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm(), + $identifier->getEncryptedKey()->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 @@ -1151,14 +1207,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'), + ], ), ], ); @@ -1166,16 +1227,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]; @@ -1183,7 +1249,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, @@ -1263,7 +1330,7 @@ public function testEncryption(): void $doc = DOMDocumentFactory::fromString(strval($encass)); $decryptor = (new KeyTransportAlgorithmFactory())->getAlgorithm( - $encass->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm(), + $encass->getEncryptedKey()->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 3cde1d499..9146ccf12 100644 --- a/tests/SAML2/XML/saml/AssertionURIRefTest.php +++ b/tests/SAML2/XML/saml/AssertionURIRefTest.php @@ -4,14 +4,12 @@ namespace SimpleSAML\SAML2\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\AssertionURIRef; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\saml\{AbstractSamlElement, AssertionURIRef}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -45,7 +43,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 000b506fd..72f4b79c0 100644 --- a/tests/SAML2/XML/saml/AttributeStatementTest.php +++ b/tests/SAML2/XML/saml/AttributeStatementTest.php @@ -4,17 +4,16 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, 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; use SimpleSAML\SAML2\XML\saml\AttributeValue; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -54,16 +53,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 2b316ff06..71e8ab621 100644 --- a/tests/SAML2/XML/saml/AttributeTest.php +++ b/tests/SAML2/XML/saml/AttributeTest.php @@ -5,21 +5,17 @@ namespace SimpleSAML\Test\SAML2\XML\saml; use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\Compat\AbstractContainer; -use SimpleSAML\SAML2\Compat\ContainerSingleton; +use SimpleSAML\SAML2\Compat\{AbstractContainer, ContainerSingleton}; use SimpleSAML\SAML2\Constants as C; -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\SAML2\Type\{SAMLAnyURIValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\saml\{AbstractSamlElement, Attribute, AttributeValue, 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\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\StringValue; use SimpleSAML\XMLSecurity\Alg\KeyTransport\KeyTransportAlgorithmFactory; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; @@ -78,13 +74,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'), @@ -137,7 +133,7 @@ public function testEncryption(): void $encattr = EncryptedAttribute::fromXML($doc->documentElement); $decryptor = (new KeyTransportAlgorithmFactory())->getAlgorithm( - $encattr->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm(), + $encattr->getEncryptedKey()->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 41ba123ff..ed9272d41 100644 --- a/tests/SAML2/XML/saml/AttributeValueTest.php +++ b/tests/SAML2/XML/saml/AttributeValueTest.php @@ -5,16 +5,12 @@ namespace SimpleSAML\Test\SAML2\XML\saml; use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\AttributeValue; -use SimpleSAML\SAML2\XML\saml\NameID; +use SimpleSAML\SAML2\XML\saml\{AbstractSamlElement, AttributeValue, NameID}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; diff --git a/tests/SAML2/XML/saml/AudienceRestrictionTest.php b/tests/SAML2/XML/saml/AudienceRestrictionTest.php index 44e8c7799..76c6115e3 100644 --- a/tests/SAML2/XML/saml/AudienceRestrictionTest.php +++ b/tests/SAML2/XML/saml/AudienceRestrictionTest.php @@ -4,15 +4,12 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\Audience; -use SimpleSAML\SAML2\XML\saml\AudienceRestriction; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\saml\{AbstractSamlElement, Audience, AudienceRestriction}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -51,8 +48,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 f1813f0bb..6a67bc999 100644 --- a/tests/SAML2/XML/saml/AudienceTest.php +++ b/tests/SAML2/XML/saml/AudienceTest.php @@ -4,15 +4,12 @@ namespace SimpleSAML\SAML2\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\saml\AbstractConditionType; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\Audience; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\saml\{AbstractConditionType, AbstractSamlElement, Audience}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -47,7 +44,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 7cd4ce242..b13279fde 100644 --- a/tests/SAML2/XML/saml/AuthenticatingAuthorityTest.php +++ b/tests/SAML2/XML/saml/AuthenticatingAuthorityTest.php @@ -4,14 +4,12 @@ namespace SimpleSAML\SAML2\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\AuthenticatingAuthority; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\XML\saml\{AbstractSamlElement, AuthenticatingAuthority}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -45,7 +43,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 0a538179f..7da910bd8 100644 --- a/tests/SAML2/XML/saml/AuthnContextClassRefTest.php +++ b/tests/SAML2/XML/saml/AuthnContextClassRefTest.php @@ -4,15 +4,13 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\AuthnContextClassRef; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\saml\{AbstractSamlElement, AuthnContextClassRef}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -47,7 +45,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 961bd27b0..ad9827dfe 100644 --- a/tests/SAML2/XML/saml/AuthnContextDeclRefTest.php +++ b/tests/SAML2/XML/saml/AuthnContextDeclRefTest.php @@ -4,14 +4,12 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\AuthnContextDeclRef; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\saml\{AbstractSamlElement, AuthnContextDeclRef}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -48,7 +46,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 9cba1a942..cb645bca3 100644 --- a/tests/SAML2/XML/saml/AuthnContextDeclTest.php +++ b/tests/SAML2/XML/saml/AuthnContextDeclTest.php @@ -4,16 +4,13 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\AuthnContextDecl; +use SimpleSAML\SAML2\XML\saml\{AbstractSamlElement, AuthnContextDecl}; use SimpleSAML\XML\Attribute as XMLAttribute; -use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\StringValue; use function dirname; use function strval; @@ -65,7 +62,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..9ae8afb7f 100644 --- a/tests/SAML2/XML/saml/AuthnContextTest.php +++ b/tests/SAML2/XML/saml/AuthnContextTest.php @@ -5,17 +5,19 @@ namespace SimpleSAML\Test\SAML2\XML\saml; use DOMDocument; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\AuthenticatingAuthority; -use SimpleSAML\SAML2\XML\saml\AuthnContext; -use SimpleSAML\SAML2\XML\saml\AuthnContextClassRef; -use SimpleSAML\SAML2\XML\saml\AuthnContextDecl; -use SimpleSAML\SAML2\XML\saml\AuthnContextDeclRef; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, EntityIDValue}; +use SimpleSAML\SAML2\XML\saml\{ + AbstractSamlElement, + AuthenticatingAuthority, + AuthnContext, + AuthnContextClassRef, + AuthnContextDecl, + AuthnContextDeclRef, +}; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\Exception\TooManyElementsException; @@ -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 089871e2e..fa57873a3 100644 --- a/tests/SAML2/XML/saml/AuthnContextWithClassRefAndDeclRefTest.php +++ b/tests/SAML2/XML/saml/AuthnContextWithClassRefAndDeclRefTest.php @@ -4,18 +4,19 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\AuthenticatingAuthority; -use SimpleSAML\SAML2\XML\saml\AuthnContext; -use SimpleSAML\SAML2\XML\saml\AuthnContextClassRef; -use SimpleSAML\SAML2\XML\saml\AuthnContextDeclRef; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, EntityIDValue}; +use SimpleSAML\SAML2\XML\saml\{ + AbstractSamlElement, + AuthenticatingAuthority, + AuthnContext, + AuthnContextClassRef, + AuthnContextDeclRef, +}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -51,10 +52,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 56130f4b6..a11751755 100644 --- a/tests/SAML2/XML/saml/AuthnContextWithClassRefAndDeclTest.php +++ b/tests/SAML2/XML/saml/AuthnContextWithClassRefAndDeclTest.php @@ -4,20 +4,21 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\AuthenticatingAuthority; -use SimpleSAML\SAML2\XML\saml\AuthnContext; -use SimpleSAML\SAML2\XML\saml\AuthnContextClassRef; -use SimpleSAML\SAML2\XML\saml\AuthnContextDecl; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, EntityIDValue}; +use SimpleSAML\SAML2\XML\saml\{ + AbstractSamlElement, + AuthenticatingAuthority, + AuthnContext, + AuthnContextClassRef, + AuthnContextDecl, +}; use SimpleSAML\XML\Attribute as XMLAttribute; -use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\StringValue; use function dirname; use function strval; @@ -67,14 +68,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 bd37ae7c5..019ba4142 100644 --- a/tests/SAML2/XML/saml/AuthnContextWithClassRefTest.php +++ b/tests/SAML2/XML/saml/AuthnContextWithClassRefTest.php @@ -4,17 +4,13 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\AuthenticatingAuthority; -use SimpleSAML\SAML2\XML\saml\AuthnContext; -use SimpleSAML\SAML2\XML\saml\AuthnContextClassRef; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, EntityIDValue}; +use SimpleSAML\SAML2\XML\saml\{AbstractSamlElement, AuthenticatingAuthority, AuthnContext, AuthnContextClassRef}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -50,10 +46,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 1239cfa52..a884fef7e 100644 --- a/tests/SAML2/XML/saml/AuthnContextWithDeclRefTest.php +++ b/tests/SAML2/XML/saml/AuthnContextWithDeclRefTest.php @@ -4,13 +4,10 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\AuthenticatingAuthority; -use SimpleSAML\SAML2\XML\saml\AuthnContext; -use SimpleSAML\SAML2\XML\saml\AuthnContextDeclRef; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, EntityIDValue}; +use SimpleSAML\SAML2\XML\saml\{AbstractSamlElement, AuthenticatingAuthority, AuthnContext, AuthnContextDeclRef}; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; @@ -50,9 +47,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 ada51076e..84b8a5cd6 100644 --- a/tests/SAML2/XML/saml/AuthnContextWithDeclTest.php +++ b/tests/SAML2/XML/saml/AuthnContextWithDeclTest.php @@ -4,18 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\AuthenticatingAuthority; -use SimpleSAML\SAML2\XML\saml\AuthnContext; -use SimpleSAML\SAML2\XML\saml\AuthnContextDecl; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\XML\saml\{AbstractSamlElement, AuthenticatingAuthority, AuthnContext, AuthnContextDecl}; use SimpleSAML\XML\Attribute as XMLAttribute; -use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\StringValue; use function dirname; use function strval; @@ -65,14 +61,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 c769b6c70..b95f73ab3 100644 --- a/tests/SAML2/XML/saml/AuthnStatementTest.php +++ b/tests/SAML2/XML/saml/AuthnStatementTest.php @@ -4,24 +4,22 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, DomainValue, EntityIDValue, SAMLStringValue}; use SimpleSAML\SAML2\Utils\XPath; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\AuthenticatingAuthority; -use SimpleSAML\SAML2\XML\saml\AuthnContext; -use SimpleSAML\SAML2\XML\saml\AuthnContextClassRef; -use SimpleSAML\SAML2\XML\saml\AuthnStatement; -use SimpleSAML\SAML2\XML\saml\SubjectLocality; +use SimpleSAML\SAML2\XML\saml\{ + AbstractSamlElement, + AuthenticatingAuthority, + AuthnContext, + AuthnContextClassRef, + AuthnStatement, + 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\XML\Exception\{MissingAttributeException, MissingElementException, TooManyElementsException}; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -60,15 +58,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( @@ -84,15 +91,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 56b34df87..26e4f83f4 100644 --- a/tests/SAML2/XML/saml/AuthzDecisionStatementTest.php +++ b/tests/SAML2/XML/saml/AuthzDecisionStatementTest.php @@ -5,18 +5,19 @@ namespace SimpleSAML\SAML2\Test\SAML2\XML\saml; use DOMDocument; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLStringValue}; use SimpleSAML\SAML2\XML\Decision; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\AbstractStatement; -use SimpleSAML\SAML2\XML\saml\Action; -use SimpleSAML\SAML2\XML\saml\AuthzDecisionStatement; -use SimpleSAML\SAML2\XML\saml\Evidence; +use SimpleSAML\SAML2\XML\saml\{ + AbstractSamlElement, + AbstractStatement, + Action, + AuthzDecisionStatement, + Evidence, +}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -60,11 +61,17 @@ public static function setUpBeforeClass(): void public function testMarshalling(): void { $authzDecisionStatement = new AuthzDecisionStatement( - 'urn:x-simplesamlphp:resource', + SAMLAnyURIValue::fromString('urn:x-simplesamlphp:resource'), Decision::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), ); diff --git a/tests/SAML2/XML/saml/BaseIDTest.php b/tests/SAML2/XML/saml/BaseIDTest.php index 67ed575e6..bf0b2c7df 100644 --- a/tests/SAML2/XML/saml/BaseIDTest.php +++ b/tests/SAML2/XML/saml/BaseIDTest.php @@ -4,21 +4,20 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\Compat\AbstractContainer; -use SimpleSAML\SAML2\Compat\ContainerSingleton; -use SimpleSAML\SAML2\XML\saml\AbstractBaseID; -use SimpleSAML\SAML2\XML\saml\AbstractBaseIDType; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\Audience; -use SimpleSAML\SAML2\XML\saml\UnknownID; -use SimpleSAML\Test\SAML2\Constants as C; -use SimpleSAML\Test\SAML2\CustomBaseID; +use SimpleSAML\SAML2\Compat\{AbstractContainer, ContainerSingleton}; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\saml\{ + AbstractBaseID, + AbstractBaseIDType, + AbstractSamlElement, + Audience, + UnknownID, +}; +use SimpleSAML\Test\SAML2\{Constants as C, CustomBaseID}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -79,9 +78,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( @@ -129,7 +132,10 @@ public function testUnmarshallingUnregistered(): void $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..db0b156ad 100644 --- a/tests/SAML2/XML/saml/ConditionTest.php +++ b/tests/SAML2/XML/saml/ConditionTest.php @@ -4,21 +4,20 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\Compat\AbstractContainer; -use SimpleSAML\SAML2\Compat\ContainerSingleton; -use SimpleSAML\SAML2\XML\saml\AbstractCondition; -use SimpleSAML\SAML2\XML\saml\AbstractConditionType; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\Audience; -use SimpleSAML\SAML2\XML\saml\UnknownCondition; -use SimpleSAML\Test\SAML2\Constants as C; -use SimpleSAML\Test\SAML2\CustomCondition; +use SimpleSAML\SAML2\Compat\{AbstractContainer, ContainerSingleton}; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\saml\{ + AbstractCondition, + AbstractConditionType, + AbstractSamlElement, + Audience, + UnknownCondition, +}; +use SimpleSAML\Test\SAML2\{Constants as C, CustomCondition}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -78,9 +77,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), @@ -102,7 +103,10 @@ public function testUnmarshallingUnregistered(): void $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 191b04319..b52282fd1 100644 --- a/tests/SAML2/XML/saml/ConditionsTest.php +++ b/tests/SAML2/XML/saml/ConditionsTest.php @@ -4,20 +4,21 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\Audience; -use SimpleSAML\SAML2\XML\saml\AudienceRestriction; -use SimpleSAML\SAML2\XML\saml\Conditions; -use SimpleSAML\SAML2\XML\saml\OneTimeUse; -use SimpleSAML\SAML2\XML\saml\ProxyRestriction; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue}; +use SimpleSAML\SAML2\XML\saml\{ + AbstractSamlElement, + Audience, + AudienceRestriction, + Conditions, + OneTimeUse, + ProxyRestriction, +}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\NonNegativeIntegerValue; use function dirname; use function strval; @@ -55,22 +56,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 abd32ce1f..057aee253 100644 --- a/tests/SAML2/XML/saml/EncryptedAssertionTest.php +++ b/tests/SAML2/XML/saml/EncryptedAssertionTest.php @@ -4,34 +4,39 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; -use SimpleSAML\SAML2\Compat\AbstractContainer; -use SimpleSAML\SAML2\Compat\ContainerSingleton; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\Assertion; -use SimpleSAML\SAML2\XML\saml\EncryptedAssertion; -use SimpleSAML\SAML2\XML\saml\Issuer; -use SimpleSAML\SAML2\XML\saml\NameID; -use SimpleSAML\SAML2\XML\saml\Subject; +use SimpleSAML\SAML2\Compat\{AbstractContainer, ContainerSingleton}; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\saml\{ + AbstractSamlElement, + Assertion, + EncryptedAssertion, + Issuer, + NameID, + Subject, +}; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{AnyURIValue, Base64BinaryValue, IDValue, StringValue}; use SimpleSAML\XMLSecurity\Alg\KeyTransport\KeyTransportAlgorithmFactory; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; -use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; -use SimpleSAML\XMLSecurity\XML\ds\RetrievalMethod; -use SimpleSAML\XMLSecurity\XML\ds\Transform; -use SimpleSAML\XMLSecurity\XML\ds\Transforms; -use SimpleSAML\XMLSecurity\XML\ds\XPath; -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 SimpleSAML\XMLSecurity\XML\ds\{ + KeyInfo, + RetrievalMethod, + Transform, + Transforms, + XPath, +}; +use SimpleSAML\XMLSecurity\XML\xenc\{ + CipherData, + CipherValue, + EncryptedData, + EncryptedKey, + EncryptionMethod, +}; use function dirname; use function strval; @@ -91,24 +96,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::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, @@ -129,10 +152,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( @@ -147,7 +176,7 @@ public function testEncryption(): void $encAssertion = EncryptedAssertion::fromXML($doc->documentElement); /** @psalm-suppress PossiblyNullArgument */ $decryptor = (new KeyTransportAlgorithmFactory())->getAlgorithm( - $encAssertion->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm(), + $encAssertion->getEncryptedKey()->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 5e3aacc26..d42bc9547 100644 --- a/tests/SAML2/XML/saml/EncryptedAttributeTest.php +++ b/tests/SAML2/XML/saml/EncryptedAttributeTest.php @@ -4,18 +4,13 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\Compat\AbstractContainer; -use SimpleSAML\SAML2\Compat\ContainerSingleton; -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\SAML2\Compat\{AbstractContainer, ContainerSingleton}; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\SAML2\XML\saml\{AbstractSamlElement, Attribute, AttributeValue, EncryptedAttribute}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use SimpleSAML\XMLSecurity\Alg\KeyTransport\KeyTransportAlgorithmFactory; use SimpleSAML\XMLSecurity\Constants as C; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; @@ -73,8 +68,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( @@ -100,7 +97,7 @@ public function testDecryptAttribute(): void /** @psalm-suppress PossiblyNullArgument */ $decryptor = (new KeyTransportAlgorithmFactory())->getAlgorithm( - $encryptedAttribute->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm(), + $encryptedAttribute->getEncryptedKey()->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 599e6b170..c9e4ff8fa 100644 --- a/tests/SAML2/XML/saml/EncryptedIDTest.php +++ b/tests/SAML2/XML/saml/EncryptedIDTest.php @@ -5,34 +5,37 @@ namespace SimpleSAML\Test\SAML2\XML\saml; use InvalidArgumentException; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\Compat\AbstractContainer; -use SimpleSAML\SAML2\Compat\ContainerSingleton; +use SimpleSAML\SAML2\Compat\{AbstractContainer, ContainerSingleton}; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLStringValue}; use SimpleSAML\SAML2\Utils\XPath; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\Attribute; -use SimpleSAML\SAML2\XML\saml\Audience; -use SimpleSAML\SAML2\XML\saml\EncryptedID; -use SimpleSAML\SAML2\XML\saml\NameID; -use SimpleSAML\SAML2\XML\saml\UnknownID; +use SimpleSAML\SAML2\XML\saml\{ + AbstractSamlElement, + Attribute, + Audience, + EncryptedID, + NameID, + UnknownID, +}; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\Test\SAML2\CustomBaseID; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{AnyURIValue, Base64BinaryValue, IDValue, StringValue}; use SimpleSAML\XMLSecurity\Alg\KeyTransport\KeyTransportAlgorithmFactory; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; -use SimpleSAML\XMLSecurity\XML\xenc\CarriedKeyName; -use SimpleSAML\XMLSecurity\XML\xenc\CipherData; -use SimpleSAML\XMLSecurity\XML\xenc\CipherValue; -use SimpleSAML\XMLSecurity\XML\xenc\DataReference; -use SimpleSAML\XMLSecurity\XML\xenc\EncryptedData; -use SimpleSAML\XMLSecurity\XML\xenc\EncryptedKey; -use SimpleSAML\XMLSecurity\XML\xenc\EncryptionMethod; -use SimpleSAML\XMLSecurity\XML\xenc\ReferenceList; +use SimpleSAML\XMLSecurity\XML\xenc\{ + CarriedKeyName, + CipherData, + CipherValue, + DataReference, + EncryptedData, + EncryptedKey, + EncryptionMethod, + ReferenceList, +}; use function dirname; use function strval; @@ -90,30 +93,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]); @@ -130,29 +149,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(); @@ -186,7 +222,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)); @@ -194,7 +234,7 @@ public function testEncryption(): void $encid = EncryptedID::fromXML($doc->documentElement); /** @psalm-suppress PossiblyNullArgument */ $decryptor = (new KeyTransportAlgorithmFactory())->getAlgorithm( - $encid->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm(), + $encid->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm()->getValue(), $privKey, ); $id = $encid->decrypt($decryptor); @@ -203,9 +243,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)); @@ -215,7 +259,7 @@ public function testEncryption(): void $encid = EncryptedID::fromXML($doc->documentElement); /** @psalm-suppress PossiblyNullArgument */ $decryptor = (new KeyTransportAlgorithmFactory())->getAlgorithm( - $encid->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm(), + $encid->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm()->getValue(), $privKey, ); $id = $encid->decrypt($decryptor); @@ -238,7 +282,7 @@ public function testEncryption(): void $encid = EncryptedID::fromXML($doc->documentElement); /** @psalm-suppress PossiblyNullArgument */ $decryptor = (new KeyTransportAlgorithmFactory())->getAlgorithm( - $encid->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm(), + $encid->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm()->getValue(), $privKey, ); $id = $encid->decrypt($decryptor); @@ -247,7 +291,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 5047d33c5..a84f319df 100644 --- a/tests/SAML2/XML/saml/EvidenceTest.php +++ b/tests/SAML2/XML/saml/EvidenceTest.php @@ -5,18 +5,18 @@ namespace SimpleSAML\SAML2\Test\SAML2\XML\saml; use DOMDocument; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -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\SAML2\XML\saml\Evidence; +use SimpleSAML\SAML2\XML\saml\{ + AbstractSamlElement, + Assertion, + AssertionIDRef, + AssertionURIRef, + EncryptedAssertion, + Evidence, +}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; diff --git a/tests/SAML2/XML/saml/IssuerTest.php b/tests/SAML2/XML/saml/IssuerTest.php index c68a7b0e9..2ebb7861d 100644 --- a/tests/SAML2/XML/saml/IssuerTest.php +++ b/tests/SAML2/XML/saml/IssuerTest.php @@ -4,17 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\Issuer; -use SimpleSAML\SAML2\XML\saml\NameIDType; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\saml\{AbstractSamlElement, Issuer, NameIDType}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -53,11 +50,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( @@ -76,11 +73,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'), ); } @@ -95,10 +92,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..239fa2bd4 100644 --- a/tests/SAML2/XML/saml/NameIDTest.php +++ b/tests/SAML2/XML/saml/NameIDTest.php @@ -4,16 +4,12 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\NameID; -use SimpleSAML\SAML2\XML\saml\NameIDType; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\saml\{AbstractSamlElement, NameID, NameIDType}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -62,11 +58,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/OneTimeUseTest.php b/tests/SAML2/XML/saml/OneTimeUseTest.php index 0da52352c..038b4c974 100644 --- a/tests/SAML2/XML/saml/OneTimeUseTest.php +++ b/tests/SAML2/XML/saml/OneTimeUseTest.php @@ -4,15 +4,11 @@ namespace SimpleSAML\SAML2\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\saml\AbstractConditionType; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\OneTimeUse; +use SimpleSAML\SAML2\XML\saml\{AbstractConditionType, AbstractSamlElement, OneTimeUse}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; diff --git a/tests/SAML2/XML/saml/ProxyRestrictionTest.php b/tests/SAML2/XML/saml/ProxyRestrictionTest.php index c9579120b..737da03db 100644 --- a/tests/SAML2/XML/saml/ProxyRestrictionTest.php +++ b/tests/SAML2/XML/saml/ProxyRestrictionTest.php @@ -4,15 +4,13 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\Audience; -use SimpleSAML\SAML2\XML\saml\ProxyRestriction; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\saml\{AbstractSamlElement, Audience, ProxyRestriction}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\NonNegativeIntegerValue; use function dirname; use function strval; @@ -51,10 +49,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..e863f2399 100644 --- a/tests/SAML2/XML/saml/StatementTest.php +++ b/tests/SAML2/XML/saml/StatementTest.php @@ -4,21 +4,20 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\Compat\AbstractContainer; -use SimpleSAML\SAML2\Compat\ContainerSingleton; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\AbstractStatement; -use SimpleSAML\SAML2\XML\saml\AbstractStatementType; -use SimpleSAML\SAML2\XML\saml\Audience; -use SimpleSAML\SAML2\XML\saml\UnknownStatement; -use SimpleSAML\Test\SAML2\Constants as C; -use SimpleSAML\Test\SAML2\CustomStatement; +use SimpleSAML\SAML2\Compat\{AbstractContainer, ContainerSingleton}; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\saml\{ + AbstractSamlElement, + AbstractStatement, + AbstractStatementType, + Audience, + UnknownStatement, +}; +use SimpleSAML\Test\SAML2\{Constants as C, CustomStatement}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -78,9 +77,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), @@ -122,7 +123,10 @@ public function testUnmarshallingUnregistered(): void $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 0873df296..fc05a93b2 100644 --- a/tests/SAML2/XML/saml/SubjectConfirmationDataTest.php +++ b/tests/SAML2/XML/saml/SubjectConfirmationDataTest.php @@ -4,20 +4,15 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\SubjectConfirmationData; +use SimpleSAML\SAML2\Type\{SAMLDateTimeValue, EntityIDValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\saml\{AbstractSamlElement, SubjectConfirmationData}; use SimpleSAML\Test\SAML2\Constants as C; -use SimpleSAML\XML\Attribute as XMLAttribute; -use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; -use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; -use SimpleSAML\XMLSecurity\XML\ds\KeyName; +use SimpleSAML\XML\{Attribute as XMLAttribute, Chunk, DOMDocumentFactory}; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{NCNameValue, StringValue}; +use SimpleSAML\XMLSecurity\XML\ds\{KeyInfo, KeyName}; use function dirname; use function strval; @@ -56,17 +51,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], @@ -85,17 +84,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], @@ -103,15 +106,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 755d7c199..48334c344 100644 --- a/tests/SAML2/XML/saml/SubjectConfirmationTest.php +++ b/tests/SAML2/XML/saml/SubjectConfirmationTest.php @@ -4,27 +4,20 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, EntityIDValue, SAMLStringValue}; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\Utils\XPath; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\NameID; -use SimpleSAML\SAML2\XML\saml\SubjectConfirmation; -use SimpleSAML\SAML2\XML\saml\SubjectConfirmationData; +use SimpleSAML\SAML2\XML\saml\{AbstractSamlElement, NameID, SubjectConfirmation, SubjectConfirmationData}; 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\Exception\TooManyElementsException; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; -use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; -use SimpleSAML\XMLSecurity\XML\ds\KeyName; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; +use SimpleSAML\XML\Exception\{MissingAttributeException, TooManyElementsException}; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{NCNameValue, StringValue}; +use SimpleSAML\XMLSecurity\XML\ds\{KeyInfo, KeyName}; use function dirname; use function strval; @@ -65,25 +58,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], @@ -102,8 +99,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; @@ -129,9 +128,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 @@ -202,7 +205,7 @@ public function testMultipleIdentifiers(): void $document = DOMDocumentFactory::fromString( << - SomeNameIDValue + SomeNameIDValue AnotherNameIDValue @@ -228,8 +231,8 @@ public function testManySubjectConfirmationDataThrowsException(): void << SomeNameIDValue - - + + XML , diff --git a/tests/SAML2/XML/saml/SubjectLocalityTest.php b/tests/SAML2/XML/saml/SubjectLocalityTest.php index bd6cb4d1b..13f8a7868 100644 --- a/tests/SAML2/XML/saml/SubjectLocalityTest.php +++ b/tests/SAML2/XML/saml/SubjectLocalityTest.php @@ -4,15 +4,13 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\SubjectLocality; +use SimpleSAML\SAML2\Type\{DomainValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\saml\{AbstractSamlElement, SubjectLocality}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -50,8 +48,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 8e85bee8c..b30c938ac 100644 --- a/tests/SAML2/XML/saml/SubjectTest.php +++ b/tests/SAML2/XML/saml/SubjectTest.php @@ -4,29 +4,26 @@ namespace SimpleSAML\Test\SAML2\XML\saml; -use DateTimeImmutable; use DOMDocument; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, EntityIDValue, SAMLStringValue}; use SimpleSAML\SAML2\Utils\XPath; -use SimpleSAML\SAML2\XML\saml\AbstractBaseID; -use SimpleSAML\SAML2\XML\saml\AbstractSamlElement; -use SimpleSAML\SAML2\XML\saml\Audience; -use SimpleSAML\SAML2\XML\saml\NameID; -use SimpleSAML\SAML2\XML\saml\Subject; -use SimpleSAML\SAML2\XML\saml\SubjectConfirmation; -use SimpleSAML\SAML2\XML\saml\SubjectConfirmationData; -use SimpleSAML\Test\SAML2\Constants as C; -use SimpleSAML\Test\SAML2\CustomBaseID; -use SimpleSAML\XML\Attribute as XMLAttribute; -use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; +use SimpleSAML\SAML2\XML\saml\{ + AbstractBaseID, + AbstractSamlElement, + Audience, + NameID, + Subject, + SubjectConfirmation, + SubjectConfirmationData, +}; +use SimpleSAML\Test\SAML2\{Constants as C, CustomBaseID}; +use SimpleSAML\XML\{Attribute as XMLAttribute, Chunk, DOMDocumentFactory}; use SimpleSAML\XML\Exception\TooManyElementsException; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; -use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; -use SimpleSAML\XMLSecurity\XML\ds\KeyName; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{NCNameValue, StringValue}; +use SimpleSAML\XMLSecurity\XML\ds\{KeyInfo, KeyName}; use function dirname; use function strval; @@ -95,17 +92,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], @@ -113,17 +112,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, ), @@ -143,17 +144,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], @@ -161,17 +164,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, ), @@ -200,17 +205,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], @@ -218,17 +225,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, ), @@ -315,7 +326,7 @@ public function testMultipleIdentifiers(): void $document = DOMDocumentFactory::fromString( << - + urn:some:audience documentElement); - $this->assertEquals('2.0', $unsignedMessage->getVersion()); - $unsignedMessage->sign($signer); $signedMessage = MessageFactory::fromXML($unsignedMessage->toXML()); @@ -140,12 +140,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 +169,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 +194,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..77e968a48 100644 --- a/tests/SAML2/XML/samlp/AbstractStatusResponseTest.php +++ b/tests/SAML2/XML/samlp/AbstractStatusResponseTest.php @@ -4,26 +4,28 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, DomainValue, SAMLStringValue}; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\Utils\XPath; use SimpleSAML\SAML2\XML\saml\Issuer; -use SimpleSAML\SAML2\XML\samlp\AbstractMessage; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\AbstractStatusResponse; -use SimpleSAML\SAML2\XML\samlp\Extensions; -use SimpleSAML\SAML2\XML\samlp\Response; -use SimpleSAML\SAML2\XML\samlp\Status; -use SimpleSAML\SAML2\XML\samlp\StatusCode; -use SimpleSAML\SAML2\XML\samlp\StatusMessage; +use SimpleSAML\SAML2\XML\samlp\{ + AbstractMessage, + AbstractSamlpElement, + AbstractStatusResponse, + Extensions, + Response, + Status, + StatusCode, + StatusMessage, +}; use SimpleSAML\SAML2\XML\shibmd\Scope; -use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; use SimpleSAML\XML\Exception\MissingElementException; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\Alg\Signature\SignatureAlgorithmFactory; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; @@ -56,17 +58,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 +104,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 +132,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..f6e662102 100644 --- a/tests/SAML2/XML/samlp/ArtifactResolveTest.php +++ b/tests/SAML2/XML/samlp/ArtifactResolveTest.php @@ -4,19 +4,20 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\{SAMLDateTimeValue, SAMLStringValue}; use SimpleSAML\SAML2\XML\saml\Issuer; -use SimpleSAML\SAML2\XML\samlp\AbstractMessage; -use SimpleSAML\SAML2\XML\samlp\AbstractRequest; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\Artifact; -use SimpleSAML\SAML2\XML\samlp\ArtifactResolve; +use SimpleSAML\SAML2\XML\samlp\{ + AbstractMessage, + AbstractRequest, + AbstractSamlpElement, + Artifact, + ArtifactResolve, +}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{Base64BinaryValue, IDValue}; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -53,15 +54,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..388d8004b 100644 --- a/tests/SAML2/XML/samlp/ArtifactResponseTest.php +++ b/tests/SAML2/XML/samlp/ArtifactResponseTest.php @@ -4,23 +4,24 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; use SimpleSAML\SAML2\XML\saml\Issuer; -use SimpleSAML\SAML2\XML\samlp\AbstractMessage; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\AbstractStatusResponse; -use SimpleSAML\SAML2\XML\samlp\ArtifactResponse; -use SimpleSAML\SAML2\XML\samlp\AuthnRequest; -use SimpleSAML\SAML2\XML\samlp\NameIDPolicy; -use SimpleSAML\SAML2\XML\samlp\Status; -use SimpleSAML\SAML2\XML\samlp\StatusCode; +use SimpleSAML\SAML2\XML\samlp\{ + AbstractMessage, + AbstractSamlpElement, + AbstractStatusResponse, + ArtifactResponse, + AuthnRequest, + NameIDPolicy, + Status, + StatusCode, +}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{BooleanValue, IDValue, NCNameValue}; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -57,20 +58,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 +81,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 9a5a1b436..fb258e735 100644 --- a/tests/SAML2/XML/samlp/ArtifactTest.php +++ b/tests/SAML2/XML/samlp/ArtifactTest.php @@ -4,14 +4,12 @@ namespace SimpleSAML\SAML2\Test\SAML2\XML\samlp; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\Artifact; +use SimpleSAML\SAML2\XML\samlp\{AbstractSamlpElement, Artifact}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\Base64BinaryValue; use function dirname; use function strval; @@ -45,7 +43,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..5ec530035 100644 --- a/tests/SAML2/XML/samlp/AssertionIDRequestTest.php +++ b/tests/SAML2/XML/samlp/AssertionIDRequestTest.php @@ -4,19 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\saml\AssertionIDRef; -use SimpleSAML\SAML2\XML\saml\Issuer; -use SimpleSAML\SAML2\XML\samlp\AbstractMessage; -use SimpleSAML\SAML2\XML\samlp\AbstractRequest; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\AssertionIDRequest; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\saml\{AssertionIDRef, Issuer}; +use SimpleSAML\SAML2\XML\samlp\{AbstractMessage, AbstractRequest, AbstractSamlpElement, AssertionIDRequest}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{IDValue, NCNameValue}; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -59,11 +54,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..a7279f976 100644 --- a/tests/SAML2/XML/samlp/AttributeQueryTest.php +++ b/tests/SAML2/XML/samlp/AttributeQueryTest.php @@ -4,30 +4,25 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\Utils\XPath; -use SimpleSAML\SAML2\XML\saml\Attribute; -use SimpleSAML\SAML2\XML\saml\AttributeValue; -use SimpleSAML\SAML2\XML\saml\Issuer; -use SimpleSAML\SAML2\XML\saml\NameID; -use SimpleSAML\SAML2\XML\saml\Subject; -use SimpleSAML\SAML2\XML\samlp\AbstractMessage; -use SimpleSAML\SAML2\XML\samlp\AbstractRequest; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\AbstractSubjectQuery; -use SimpleSAML\SAML2\XML\samlp\AttributeQuery; +use SimpleSAML\SAML2\XML\saml\{Attribute, AttributeValue, Issuer, NameID, Subject}; +use SimpleSAML\SAML2\XML\samlp\{ + AbstractMessage, + AbstractRequest, + AbstractSamlpElement, + AbstractSubjectQuery, + 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\XML\Exception\{MissingAttributeException, MissingElementException, TooManyElementsException}; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -73,20 +68,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 +92,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 +103,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 +119,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 +145,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..9ec7e10f4 100644 --- a/tests/SAML2/XML/samlp/AuthnQueryTest.php +++ b/tests/SAML2/XML/samlp/AuthnQueryTest.php @@ -4,25 +4,23 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; use SimpleSAML\SAML2\XML\Comparison; -use SimpleSAML\SAML2\XML\saml\AuthnContextDeclRef; -use SimpleSAML\SAML2\XML\saml\Issuer; -use SimpleSAML\SAML2\XML\saml\NameID; -use SimpleSAML\SAML2\XML\saml\Subject; -use SimpleSAML\SAML2\XML\samlp\AbstractMessage; -use SimpleSAML\SAML2\XML\samlp\AbstractRequest; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\AbstractSubjectQuery; -use SimpleSAML\SAML2\XML\samlp\AuthnQuery; -use SimpleSAML\SAML2\XML\samlp\RequestedAuthnContext; +use SimpleSAML\SAML2\XML\saml\{AuthnContextDeclRef, Issuer, NameID, Subject}; +use SimpleSAML\SAML2\XML\samlp\{ + AbstractMessage, + AbstractRequest, + AbstractSamlpElement, + AbstractSubjectQuery, + AuthnQuery, + RequestedAuthnContext, +}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -62,20 +60,25 @@ 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'); + $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], Comparison::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 43e7a39aa..5145b89d8 100644 --- a/tests/SAML2/XML/samlp/AuthnRequestTest.php +++ b/tests/SAML2/XML/samlp/AuthnRequestTest.php @@ -4,45 +4,46 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Compat\ContainerSingleton; use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, EntityIDValue, 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; -use SimpleSAML\SAML2\XML\saml\Conditions; -use SimpleSAML\SAML2\XML\saml\EncryptedID; -use SimpleSAML\SAML2\XML\saml\Issuer; -use SimpleSAML\SAML2\XML\saml\NameID; -use SimpleSAML\SAML2\XML\saml\OneTimeUse; -use SimpleSAML\SAML2\XML\saml\ProxyRestriction; -use SimpleSAML\SAML2\XML\saml\Subject; -use SimpleSAML\SAML2\XML\samlp\AbstractMessage; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\AuthnRequest; -use SimpleSAML\SAML2\XML\samlp\GetComplete; -use SimpleSAML\SAML2\XML\samlp\IDPEntry; -use SimpleSAML\SAML2\XML\samlp\IDPList; -use SimpleSAML\SAML2\XML\samlp\NameIDPolicy; -use SimpleSAML\SAML2\XML\samlp\RequestedAuthnContext; -use SimpleSAML\SAML2\XML\samlp\RequesterID; -use SimpleSAML\SAML2\XML\samlp\Scoping; +use SimpleSAML\SAML2\XML\saml\{ + Audience, + AudienceRestriction, + AuthnContextClassRef, + Conditions, + EncryptedID, + Issuer, + NameID, + OneTimeUse, + ProxyRestriction, + Subject, +}; +use SimpleSAML\SAML2\XML\samlp\{ + AbstractMessage, + AbstractSamlpElement, + AuthnRequest, + GetComplete, + IDPEntry, + IDPList, + NameIDPolicy, + RequestedAuthnContext, + RequesterID, + 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\XML\Exception\{MissingAttributeException, TooManyElementsException}; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{BooleanValue, IDValue, NonNegativeIntegerValue, UnsignedShortValue}; use SimpleSAML\XMLSecurity\Alg\KeyTransport\KeyTransportAlgorithmFactory; -use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; -use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; +use SimpleSAML\XMLSecurity\TestUtils\{PEMCertificatesMock, SignedElementTestTrait}; use function dirname; use function strval; @@ -87,17 +88,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( @@ -112,59 +115,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, ); // 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, ); @@ -198,28 +226,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()); } @@ -231,20 +258,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->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm()->getValue(), PEMCertificatesMock::getPrivateKey(PEMCertificatesMock::SELFSIGNED_PRIVATE_KEY), ); @@ -299,14 +325,13 @@ public function testScopeWithoutProviderIDThrowsException(): void $xmlRequest = << - https://sp.example.com/SAML2 + https://sp.example.com/SAML2 @@ -326,14 +351,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 +378,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 +408,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 +437,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 +464,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 8c7877bf1..073cd0d1e 100644 --- a/tests/SAML2/XML/samlp/AuthzDecisionQueryTest.php +++ b/tests/SAML2/XML/samlp/AuthzDecisionQueryTest.php @@ -4,26 +4,22 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use DateTimeImmutable; use DOMDocument; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\saml\Action; -use SimpleSAML\SAML2\XML\saml\Assertion; -use SimpleSAML\SAML2\XML\saml\Evidence; -use SimpleSAML\SAML2\XML\saml\Issuer; -use SimpleSAML\SAML2\XML\saml\NameID; -use SimpleSAML\SAML2\XML\saml\Subject; -use SimpleSAML\SAML2\XML\samlp\AbstractMessage; -use SimpleSAML\SAML2\XML\samlp\AbstractRequest; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\AbstractSubjectQuery; -use SimpleSAML\SAML2\XML\samlp\AuthzDecisionQuery; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\saml\{Action, Assertion, Evidence, Issuer, NameID, Subject}; +use SimpleSAML\SAML2\XML\samlp\{ + AbstractMessage, + AbstractRequest, + AbstractSamlpElement, + AbstractSubjectQuery, + AuthzDecisionQuery, +}; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -70,25 +66,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/ExtensionsTest.php b/tests/SAML2/XML/samlp/ExtensionsTest.php index 0cf475d6b..e4080cc76 100644 --- a/tests/SAML2/XML/samlp/ExtensionsTest.php +++ b/tests/SAML2/XML/samlp/ExtensionsTest.php @@ -4,17 +4,13 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Exception\ProtocolViolationException; use SimpleSAML\SAML2\XML\saml\AttributeValue; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\Extensions; -use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\SAML2\XML\samlp\{AbstractSamlpElement, Extensions}; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; diff --git a/tests/SAML2/XML/samlp/GetCompleteTest.php b/tests/SAML2/XML/samlp/GetCompleteTest.php index 5ec4332fc..3cc524ccb 100644 --- a/tests/SAML2/XML/samlp/GetCompleteTest.php +++ b/tests/SAML2/XML/samlp/GetCompleteTest.php @@ -4,15 +4,12 @@ namespace SimpleSAML\SAML2\Test\SAML2\XML\samlp; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\GetComplete; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\samlp\{AbstractSamlpElement, GetComplete}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -49,10 +46,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..577850c1e 100644 --- a/tests/SAML2/XML/samlp/IDPEntryTest.php +++ b/tests/SAML2/XML/samlp/IDPEntryTest.php @@ -4,15 +4,12 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\IDPEntry; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, EntityIDValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\samlp\{AbstractSamlpElement, IDPEntry}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -54,7 +51,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 +72,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..f391d27eb 100644 --- a/tests/SAML2/XML/samlp/IDPListTest.php +++ b/tests/SAML2/XML/samlp/IDPListTest.php @@ -4,19 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, EntityIDValue, 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\SAML2\XML\samlp\{AbstractSamlpElement, GetComplete, IDPEntry, 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\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -60,9 +55,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 +81,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 +124,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 f02ecb681..1da930f1e 100644 --- a/tests/SAML2/XML/samlp/LogoutRequestTest.php +++ b/tests/SAML2/XML/samlp/LogoutRequestTest.php @@ -4,30 +4,28 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use Psr\Clock\ClockInterface; use SimpleSAML\SAML2\Compat\ContainerSingleton; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; use SimpleSAML\SAML2\Utils; use SimpleSAML\SAML2\Utils\XPath; -use SimpleSAML\SAML2\XML\saml\EncryptedID; -use SimpleSAML\SAML2\XML\saml\Issuer; -use SimpleSAML\SAML2\XML\saml\NameID; -use SimpleSAML\SAML2\XML\samlp\AbstractMessage; -use SimpleSAML\SAML2\XML\samlp\AbstractRequest; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\LogoutRequest; -use SimpleSAML\SAML2\XML\samlp\SessionIndex; +use SimpleSAML\SAML2\XML\saml\{EncryptedID, Issuer, NameID}; +use SimpleSAML\SAML2\XML\samlp\{ + AbstractMessage, + AbstractRequest, + AbstractSamlpElement, + LogoutRequest, + 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\XML\Exception\{MissingElementException, TooManyElementsException}; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\IDValue; use SimpleSAML\XMLSecurity\Alg\KeyTransport\KeyTransportAlgorithmFactory; -use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; -use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; +use SimpleSAML\XMLSecurity\TestUtils\{PEMCertificatesMock, SignedElementTestTrait}; use function dirname; @@ -70,12 +68,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(); @@ -92,11 +95,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(); @@ -112,12 +121,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(); @@ -158,12 +172,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->getEncryptedKey()->getEncryptionMethod()?->getAlgorithm()->getValue(), PEMCertificatesMock::getPrivateKey(PEMCertificatesMock::SELFSIGNED_PRIVATE_KEY), ); $identifier = $encid->decrypt($decryptor); @@ -180,7 +194,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, @@ -290,7 +308,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()); } @@ -298,15 +316,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(), ); } @@ -340,10 +365,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); @@ -379,21 +412,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..6274e7ae5 100644 --- a/tests/SAML2/XML/samlp/LogoutResponseTest.php +++ b/tests/SAML2/XML/samlp/LogoutResponseTest.php @@ -4,21 +4,22 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; use SimpleSAML\SAML2\XML\saml\Issuer; -use SimpleSAML\SAML2\XML\samlp\AbstractMessage; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\AbstractStatusResponse; -use SimpleSAML\SAML2\XML\samlp\LogoutResponse; -use SimpleSAML\SAML2\XML\samlp\Status; -use SimpleSAML\SAML2\XML\samlp\StatusCode; +use SimpleSAML\SAML2\XML\samlp\{ + AbstractMessage, + AbstractSamlpElement, + AbstractStatusResponse, + LogoutResponse, + Status, + StatusCode, +}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{IDValue, NCNameValue}; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -57,14 +58,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..ad3180a78 100644 --- a/tests/SAML2/XML/samlp/MessageFactoryTest.php +++ b/tests/SAML2/XML/samlp/MessageFactoryTest.php @@ -4,19 +4,19 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, DataProvider, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\XML\saml\Attribute; -use SimpleSAML\SAML2\XML\samlp\ArtifactResolve; -use SimpleSAML\SAML2\XML\samlp\ArtifactResponse; -use SimpleSAML\SAML2\XML\samlp\AttributeQuery; -use SimpleSAML\SAML2\XML\samlp\AuthnRequest; -use SimpleSAML\SAML2\XML\samlp\LogoutRequest; -use SimpleSAML\SAML2\XML\samlp\LogoutResponse; -use SimpleSAML\SAML2\XML\samlp\MessageFactory; -use SimpleSAML\SAML2\XML\samlp\Response; +use SimpleSAML\SAML2\XML\samlp\{ + ArtifactResolve, + ArtifactResponse, + AttributeQuery, + AuthnRequest, + LogoutRequest, + LogoutResponse, + MessageFactory, + Response, +}; use SimpleSAML\XML\DOMDocumentFactory; use SimpleSAML\XML\Exception\InvalidDOMElementException; diff --git a/tests/SAML2/XML/samlp/NameIDPolicyTest.php b/tests/SAML2/XML/samlp/NameIDPolicyTest.php index 398762249..d24f54fc3 100644 --- a/tests/SAML2/XML/samlp/NameIDPolicyTest.php +++ b/tests/SAML2/XML/samlp/NameIDPolicyTest.php @@ -4,16 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\NameIDPolicy; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\samlp\{AbstractSamlpElement, NameIDPolicy}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\BooleanValue; use function dirname; use function strval; @@ -56,9 +54,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 +75,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 758482616..3cf2c0b6c 100644 --- a/tests/SAML2/XML/samlp/RequestedAuthnContextTest.php +++ b/tests/SAML2/XML/samlp/RequestedAuthnContextTest.php @@ -4,19 +4,17 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\Assert\AssertionFailedException; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Exception\ProtocolViolationException; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; use SimpleSAML\SAML2\XML\Comparison; -use SimpleSAML\SAML2\XML\saml\AuthnContextClassRef; -use SimpleSAML\SAML2\XML\saml\AuthnContextDeclRef; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\RequestedAuthnContext; +use SimpleSAML\SAML2\XML\saml\{AuthnContextClassRef, AuthnContextDeclRef}; +use SimpleSAML\SAML2\XML\samlp\{AbstractSamlpElement, RequestedAuthnContext}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\Exception\SchemaViolationException; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -51,9 +49,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], + Comparison::EXACT, + ); $this->assertEquals( self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), @@ -66,13 +69,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], + Comparison::EXACT, + ); } @@ -80,9 +90,11 @@ 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', @@ -116,7 +128,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 931fac76f..fb71348f7 100644 --- a/tests/SAML2/XML/samlp/RequesterIDTest.php +++ b/tests/SAML2/XML/samlp/RequesterIDTest.php @@ -4,15 +4,12 @@ namespace SimpleSAML\SAML2\Test\SAML2\XML\samlp; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\RequesterID; +use SimpleSAML\SAML2\Type\EntityIDValue; +use SimpleSAML\SAML2\XML\samlp\{AbstractSamlpElement, RequesterID}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\ArrayizableElementTestTrait; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{ArrayizableElementTestTrait, SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -49,7 +46,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..8a3c8815b 100644 --- a/tests/SAML2/XML/samlp/ResponseTest.php +++ b/tests/SAML2/XML/samlp/ResponseTest.php @@ -4,22 +4,22 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use DateTimeImmutable; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\XML\saml\Assertion; -use SimpleSAML\SAML2\XML\saml\Issuer; -use SimpleSAML\SAML2\XML\samlp\AbstractMessage; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\AbstractStatusResponse; -use SimpleSAML\SAML2\XML\samlp\Response; -use SimpleSAML\SAML2\XML\samlp\Status; -use SimpleSAML\SAML2\XML\samlp\StatusCode; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; +use SimpleSAML\SAML2\XML\saml\{Assertion, Issuer}; +use SimpleSAML\SAML2\XML\samlp\{ + AbstractMessage, + AbstractSamlpElement, + AbstractStatusResponse, + Response, + Status, + StatusCode, +}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{IDValue, NCNameValue}; use SimpleSAML\XMLSecurity\TestUtils\SignedElementTestTrait; use function dirname; @@ -58,21 +58,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..634279271 100644 --- a/tests/SAML2/XML/samlp/ScopingTest.php +++ b/tests/SAML2/XML/samlp/ScopingTest.php @@ -4,20 +4,22 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, EntityIDValue, 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\SAML2\XML\samlp\RequesterID; -use SimpleSAML\SAML2\XML\samlp\Scoping; +use SimpleSAML\SAML2\XML\samlp\{ + AbstractSamlpElement, + GetComplete, + IDPEntry, + IDPList, + RequesterID, + Scoping, +}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\NonNegativeIntegerValue; use function dirname; use function strval; @@ -52,12 +54,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 +84,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 019fc2c0c..1b3f31bdb 100644 --- a/tests/SAML2/XML/samlp/SessionIndexTest.php +++ b/tests/SAML2/XML/samlp/SessionIndexTest.php @@ -4,14 +4,12 @@ namespace SimpleSAML\SAML2\Test\SAML2\XML\samlp; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\SessionIndex; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\SAML2\XML\samlp\{AbstractSamlpElement, SessionIndex}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -45,7 +43,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..b869fb727 100644 --- a/tests/SAML2/XML/samlp/StatusCodeTest.php +++ b/tests/SAML2/XML/samlp/StatusCodeTest.php @@ -4,15 +4,13 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\StatusCode; +use SimpleSAML\SAML2\Type\SAMLAnyURIValue; +use SimpleSAML\SAML2\XML\samlp\{AbstractSamlpElement, StatusCode}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -49,9 +47,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/StatusDetailTest.php b/tests/SAML2/XML/samlp/StatusDetailTest.php index db0aa8614..bf711661a 100644 --- a/tests/SAML2/XML/samlp/StatusDetailTest.php +++ b/tests/SAML2/XML/samlp/StatusDetailTest.php @@ -4,16 +4,12 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\StatusDetail; -use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\SAML2\XML\samlp\{AbstractSamlpElement, StatusDetail}; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; diff --git a/tests/SAML2/XML/samlp/StatusMessageTest.php b/tests/SAML2/XML/samlp/StatusMessageTest.php index 42fe691e7..3e6c22bf4 100644 --- a/tests/SAML2/XML/samlp/StatusMessageTest.php +++ b/tests/SAML2/XML/samlp/StatusMessageTest.php @@ -4,14 +4,12 @@ namespace SimpleSAML\SAML2\Test\SAML2\XML\samlp; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\StatusMessage; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\SAML2\XML\samlp\{AbstractSamlpElement, StatusMessage}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -45,7 +43,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 87dd0333f..d8c233449 100644 --- a/tests/SAML2/XML/samlp/StatusTest.php +++ b/tests/SAML2/XML/samlp/StatusTest.php @@ -5,20 +5,14 @@ namespace SimpleSAML\Test\SAML2\XML\samlp; use DOMDocument; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLStringValue}; use SimpleSAML\SAML2\Utils\XPath; -use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement; -use SimpleSAML\SAML2\XML\samlp\Status; -use SimpleSAML\SAML2\XML\samlp\StatusCode; -use SimpleSAML\SAML2\XML\samlp\StatusDetail; -use SimpleSAML\SAML2\XML\samlp\StatusMessage; -use SimpleSAML\XML\Chunk; -use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\SAML2\XML\samlp\{AbstractSamlpElement, Status, StatusCode, StatusDetail, StatusMessage}; +use SimpleSAML\XML\{Chunk, DOMDocumentFactory}; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; use function dirname; use function strval; @@ -62,14 +56,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( @@ -92,14 +88,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..95cc7ca12 100644 --- a/tests/SAML2/XML/shibmd/KeyAuthorityTest.php +++ b/tests/SAML2/XML/shibmd/KeyAuthorityTest.php @@ -4,18 +4,15 @@ namespace SimpleSAML\Test\SAML2\XML\shibmd; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; -use SimpleSAML\SAML2\XML\shibmd\AbstractShibmdElement; -use SimpleSAML\SAML2\XML\shibmd\KeyAuthority; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\SAML2\XML\shibmd\{AbstractShibmdElement, KeyAuthority}; use SimpleSAML\XML\Attribute as XMLAttribute; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; -use SimpleSAML\XMLSecurity\XML\ds\KeyInfo; -use SimpleSAML\XMLSecurity\XML\ds\X509Certificate; -use SimpleSAML\XMLSecurity\XML\ds\X509Data; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\{Base64BinaryValue, IDValue, UnsignedByteValue}; +use SimpleSAML\XMLSecurity\XML\ds\{KeyInfo, X509Certificate, X509Data}; use function dirname; use function strval; @@ -56,25 +53,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..03e7340c0 100644 --- a/tests/SAML2/XML/shibmd/ScopeTest.php +++ b/tests/SAML2/XML/shibmd/ScopeTest.php @@ -4,15 +4,14 @@ namespace SimpleSAML\Test\SAML2\XML\shibmd; -use PHPUnit\Framework\Attributes\CoversClass; -use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\{CoversClass, Group}; use PHPUnit\Framework\TestCase; use SimpleSAML\SAML2\Utils\XPath; -use SimpleSAML\SAML2\XML\shibmd\AbstractShibmdElement; -use SimpleSAML\SAML2\XML\shibmd\Scope; +use SimpleSAML\SAML2\Type\SAMLStringValue; +use SimpleSAML\SAML2\XML\shibmd\{AbstractShibmdElement, Scope}; use SimpleSAML\XML\DOMDocumentFactory; -use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait; -use SimpleSAML\XML\TestUtils\SerializableElementTestTrait; +use SimpleSAML\XML\TestUtils\{SchemaValidationTestTrait, SerializableElementTestTrait}; +use SimpleSAML\XML\Type\BooleanValue; use function dirname; use function strval; @@ -48,7 +47,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 +59,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 +93,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 +108,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..a22a07fdd 100644 --- a/tests/bin/authnrequest.php +++ b/tests/bin/authnrequest.php @@ -7,11 +7,13 @@ use DateTimeZone; use SimpleSAML\SAML2\Compat\ContainerSingleton; use SimpleSAML\SAML2\Compat\MockContainer; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, 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 +27,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..6f098897f 100644 --- a/tests/bin/entityattributes.php +++ b/tests/bin/entityattributes.php @@ -6,6 +6,7 @@ use DateTimeImmutable; use DateTimeZone; use SimpleSAML\SAML2\Constants as C; +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; use SimpleSAML\SAML2\XML\mdattr\EntityAttributes; use SimpleSAML\SAML2\XML\saml\Assertion; use SimpleSAML\SAML2\XML\saml\Attribute; @@ -17,6 +18,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 +30,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 +88,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..303ea833a 100644 --- a/tests/bin/logoutrequest.php +++ b/tests/bin/logoutrequest.php @@ -7,11 +7,13 @@ use DateTimeZone; use SimpleSAML\SAML2\Compat\ContainerSingleton; use SimpleSAML\SAML2\Compat\MockContainer; +use SimpleSAML\SAML2\Type\{SAMLDateTimeValue, 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 +26,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..8213fce17 100644 --- a/tests/bin/signedresponse_with_signedassertion.php +++ b/tests/bin/signedresponse_with_signedassertion.php @@ -3,6 +3,7 @@ require_once(dirname(__FILE__, 3) . '/vendor/autoload.php'); +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; use SimpleSAML\SAML2\XML\saml\Assertion; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\samlp\Response; @@ -10,6 +11,7 @@ use SimpleSAML\SAML2\XML\samlp\StatusCode; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; +use SimpleSAML\XML\Type\{IDValue, NCNameValue}; use SimpleSAML\XMLSecurity\Alg\Signature\SignatureAlgorithmFactory; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; @@ -24,13 +26,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..1ad35bc45 100644 --- a/tests/bin/signedresponse_with_unsignedassertion.php +++ b/tests/bin/signedresponse_with_unsignedassertion.php @@ -3,6 +3,7 @@ require_once(dirname(__FILE__, 3) . '/vendor/autoload.php'); +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; use SimpleSAML\SAML2\XML\saml\Assertion; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\samlp\Response; @@ -10,6 +11,7 @@ use SimpleSAML\SAML2\XML\samlp\StatusCode; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; +use SimpleSAML\XML\Type\{IDValue, NCNameValue}; use SimpleSAML\XMLSecurity\Alg\Signature\SignatureAlgorithmFactory; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; @@ -17,13 +19,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..bff82610b 100644 --- a/tests/bin/unsignedresponse_with_signedassertion.php +++ b/tests/bin/unsignedresponse_with_signedassertion.php @@ -3,6 +3,7 @@ require_once(dirname(__FILE__, 3) . '/vendor/autoload.php'); +use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue}; use SimpleSAML\SAML2\XML\saml\Assertion; use SimpleSAML\SAML2\XML\saml\Issuer; use SimpleSAML\SAML2\XML\samlp\Response; @@ -10,6 +11,7 @@ use SimpleSAML\SAML2\XML\samlp\StatusCode; use SimpleSAML\Test\SAML2\Constants as C; use SimpleSAML\XML\DOMDocumentFactory; +use SimpleSAML\XML\Type\{IDValue, NCNameValue}; use SimpleSAML\XMLSecurity\Alg\Signature\SignatureAlgorithmFactory; use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; @@ -26,13 +28,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/md_Extensions.xml b/tests/resources/xml/md_Extensions.xml index 9052cccbd..881a2ce3e 100644 --- a/tests/resources/xml/md_Extensions.xml +++ b/tests/resources/xml/md_Extensions.xml @@ -1,5 +1,5 @@ - SomeScope + SomeScope @@ -9,7 +9,7 @@ Example - 127.0.0.1 + 127.0.0.0/8 diff --git a/tests/resources/xml/md_RoleDescriptor.xml b/tests/resources/xml/md_RoleDescriptor.xml index 946c7f5a2..fe6048a5b 100644 --- a/tests/resources/xml/md_RoleDescriptor.xml +++ b/tests/resources/xml/md_RoleDescriptor.xml @@ -1,5 +1,5 @@ - - + + Some @@ -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/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/samlp_ArtifactResolve.xml b/tests/resources/xml/samlp_ArtifactResolve.xml index 0356c2952..cab08e88c 100644 --- a/tests/resources/xml/samlp_ArtifactResolve.xml +++ b/tests/resources/xml/samlp_ArtifactResolve.xml @@ -1,4 +1,4 @@ - - https://ServiceProvider.com/SAML + + https://ServiceProvider.com/SAML AAQAADWNEw5VT47wcO4zX/iEzMmFQvGknDfws2ZtqSGdkNSbsW1cmVR0bzU= diff --git a/tests/resources/xml/samlp_ArtifactResponse.xml b/tests/resources/xml/samlp_ArtifactResponse.xml index b99806614..4fd5c3baa 100644 --- a/tests/resources/xml/samlp_ArtifactResponse.xml +++ b/tests/resources/xml/samlp_ArtifactResponse.xml @@ -1,10 +1,10 @@ - - https://sp.example.com/SAML2 + + https://sp.example.com/SAML2 - urn:example:other + urn:example:other diff --git a/tests/resources/xml/samlp_AssertionIDRequest.xml b/tests/resources/xml/samlp_AssertionIDRequest.xml index 36c7f85f3..f1b7f0556 100644 --- a/tests/resources/xml/samlp_AssertionIDRequest.xml +++ b/tests/resources/xml/samlp_AssertionIDRequest.xml @@ -1,5 +1,5 @@ - - https://gateway.stepup.org/saml20/sp/metadata - _abc123 - _def456 + + https://gateway.stepup.org/saml20/sp/metadata + _abc123 + _def456 diff --git a/tests/resources/xml/samlp_AttributeQuery.xml b/tests/resources/xml/samlp_AttributeQuery.xml index af91a1b96..c3f97ecec 100644 --- a/tests/resources/xml/samlp_AttributeQuery.xml +++ b/tests/resources/xml/samlp_AttributeQuery.xml @@ -1,19 +1,19 @@ - - https://example.org/ - + + https://example.org/ + urn:example:subject - + test1_attrv1 test1_attrv2 - + test2_attrv1 test2_attrv2 test2_attrv3 - - + + 4 23 diff --git a/tests/resources/xml/samlp_AuthnQuery.xml b/tests/resources/xml/samlp_AuthnQuery.xml index c4f985018..7db034df1 100644 --- a/tests/resources/xml/samlp_AuthnQuery.xml +++ b/tests/resources/xml/samlp_AuthnQuery.xml @@ -1,9 +1,9 @@ - - https://example.org/ - + + https://example.org/ + urn:example:subject - https://example.org/relative/path/to/document.xml + https://example.org/relative/path/to/document.xml diff --git a/tests/resources/xml/samlp_AuthnRequest.xml b/tests/resources/xml/samlp_AuthnRequest.xml index ece73dcc1..147ace7c5 100644 --- a/tests/resources/xml/samlp_AuthnRequest.xml +++ b/tests/resources/xml/samlp_AuthnRequest.xml @@ -1,6 +1,6 @@ - - https://gateway.stepup.org/saml20/sp/metadata - + + https://gateway.stepup.org/saml20/sp/metadata + user@example.org diff --git a/tests/resources/xml/samlp_AuthzDecisionQuery.xml b/tests/resources/xml/samlp_AuthzDecisionQuery.xml index 54bdd11e4..ded7f4c06 100644 --- a/tests/resources/xml/samlp_AuthzDecisionQuery.xml +++ b/tests/resources/xml/samlp_AuthzDecisionQuery.xml @@ -1,11 +1,11 @@ - - https://example.org/ - + + https://example.org/ + urn:example:subject - SomeAction - SomeOtherAction - + SomeAction + SomeOtherAction + urn:x-simplesamlphp:issuer diff --git a/tests/resources/xml/samlp_LogoutRequest.xml b/tests/resources/xml/samlp_LogoutRequest.xml index 2b4345bed..5e00e9116 100644 --- a/tests/resources/xml/samlp_LogoutRequest.xml +++ b/tests/resources/xml/samlp_LogoutRequest.xml @@ -1,6 +1,6 @@ - - urn:x-simplesamlphp:issuer - + + urn:x-simplesamlphp:issuer + diff --git a/tests/resources/xml/samlp_LogoutResponse.xml b/tests/resources/xml/samlp_LogoutResponse.xml index 20b24d5dd..252fe39aa 100644 --- a/tests/resources/xml/samlp_LogoutResponse.xml +++ b/tests/resources/xml/samlp_LogoutResponse.xml @@ -1,5 +1,5 @@ - - urn:x-simplesamlphp:issuer + + urn:x-simplesamlphp:issuer diff --git a/tests/resources/xml/samlp_Response.xml b/tests/resources/xml/samlp_Response.xml index 6bbfab336..dbf0d4394 100644 --- a/tests/resources/xml/samlp_Response.xml +++ b/tests/resources/xml/samlp_Response.xml @@ -1,5 +1,5 @@ - - https://IdentityProvider.com + + https://IdentityProvider.com