Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions classes/element.registry.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
declare(strict_types=1);

return [
'urn:oasis:names:tc:SAML:2.0:protocol:ext:async-slo' => [
'Asynchronous' => '\SimpleSAML\SAML2\XML\aslo\Asynchronous',
],
'urn:oasis:names:tc:SAML:metadata:algsupport' => [
'DigestMethod' => '\SimpleSAML\SAML2\XML\alg\DigestMethod',
'SigningMethod' => '\SimpleSAML\SAML2\XML\alg\SigningMethod',
Expand Down
13 changes: 13 additions & 0 deletions resources/schemas/saml-async-slo-v1.0.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>

<schema xmlns:aslo="urn:oasis:names:tc:SAML:2.0:protocol:ext:async-slo"
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:oasis:names:tc:SAML:2.0:protocol:ext:async-slo"
elementFormDefault="qualified">

<element name="Asynchronous" type="aslo:AsynchronousType" />
<complexType name="AsynchronousType" />

<attribute name="supportsAsynchronous" type="boolean"/>

</schema>
5 changes: 5 additions & 0 deletions src/Constants.php
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,11 @@ class Constants extends \SimpleSAML\XMLSecurity\Constants
*/
public const string NS_ALG = 'urn:oasis:names:tc:SAML:metadata:algsupport';

/**
* The namespace for the SAML 2 Asynchronous Single Logout Profile Extension
*/
public const string NS_ASLO = 'urn:oasis:names:tc:SAML:2.0:protocol:ext:async-slo';

/**
* The namespace for the ECP protocol.
*/
Expand Down
23 changes: 23 additions & 0 deletions src/XML/aslo/AbstractAsloElement.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\SAML2\XML\aslo;

use SimpleSAML\SAML2\Constants as C;
use SimpleSAML\XML\AbstractElement;

/**
* Abstract class to be implemented by all the classes in this namespace
*
* @see https://docs.oasis-open.org/security/saml/Post2.0/saml-async-slo/v1.0/saml-async-slo-v1.0.pdf
* @package simplesamlphp/saml2
*/
abstract class AbstractAsloElement extends AbstractElement
{
public const string NS = C::NS_ASLO;

public const string NS_PREFIX = 'aslo';

public const string SCHEMA = 'resources/schemas/saml-async-slo-v1.0.xsd';
}
45 changes: 45 additions & 0 deletions src/XML/aslo/Asynchronous.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\SAML2\XML\aslo;

use Dom;
use SimpleSAML\SAML2\Assert\Assert;
use SimpleSAML\XML\SchemaValidatableElementInterface;
use SimpleSAML\XML\SchemaValidatableElementTrait;
use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException;

/**
* Class representing a aslo:Asynchronous element.
*
* @package simplesaml/saml2
*/
final class Asynchronous extends AbstractAsloElement implements SchemaValidatableElementInterface
{
use SchemaValidatableElementTrait;


/**
* Convert XML into a Asynchronous
*
* @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException
* if the qualified name of the supplied element is wrong
*/
public static function fromXML(Dom\Element $xml): static
{
Assert::same($xml->localName, 'Asynchronous', InvalidDOMElementException::class);
Assert::same($xml->namespaceURI, Asynchronous::NS, InvalidDOMElementException::class);

return new static();
}


/**
* Convert this Asynchronous to XML.
*/
public function toXML(?Dom\Element $parent = null): Dom\Element
{
return $this->instantiateParentElement($parent);
}
}
34 changes: 34 additions & 0 deletions src/XML/aslo/SupportsAsynchronousTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\SAML2\XML\aslo;

use SimpleSAML\XMLSchema\Type\BooleanValue;

/**
* @package simplesamlphp/saml2
*/
trait SupportsAsynchronousTrait
{
/** @var \SimpleSAML\XMLSchema\Type\BooleanValue|null */
protected ?BooleanValue $supportsAsynchronous;


/**
* @return \SimpleSAML\XMLSchema\Type\BooleanValue|null
*/
public function getSupportsAsynchronous(): ?BooleanValue
{
return $this->supportsAsynchronous;
}


/**
* @param \SimpleSAML\XMLSchema\Type\BooleanValue $supportsAsynchronous|null
*/
private function setSupportsAsynchronous(?BooleanValue $supportsAsynchronous): void
{
$this->supportsAsynchronous = $supportsAsynchronous;
}
}
82 changes: 82 additions & 0 deletions src/XML/md/SingleLogoutService.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,93 @@

namespace SimpleSAML\SAML2\XML\md;

use Dom;
use SimpleSAML\SAML2\Assert\Assert;
use SimpleSAML\SAML2\Type\SAMLAnyURIValue;
use SimpleSAML\SAML2\XML\aslo\SupportsAsynchronousTrait;
use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException;
use SimpleSAML\XMLSchema\Type\BooleanValue;

/**
* SingleLogoutService element of type EndpointType
*
* @package simplesamlphp/saml2
*/
final class SingleLogoutService extends AbstractEndpointType
{
use SupportsAsynchronousTrait;


/**
* SingleLogoutService constructor.
*
* @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $binding
* @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue $location
* @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $responseLocation
* @param \SimpleSAML\XMLSchema\Type\BooleanValue $supportsAsynchronous
* @param \SimpleSAML\XML\ElementInterface[] $children
* @param array<\SimpleSAML\XML\Attribute> $attributes
*
* @throws \SimpleSAML\Assert\AssertionFailedException
*/
public function __construct(
SAMLAnyURIValue $binding,
SAMLAnyURIValue $location,
?SAMLAnyURIValue $responseLocation = null,
protected ?BooleanValue $supportsAsynchronous = null,
array $children = [],
array $attributes = [],
) {
$this->setSupportsAsynchronous($supportsAsynchronous);

parent::__construct($binding, $location, $responseLocation, $children, $attributes);
}


/**
* Initialize a SingleLogoutService.
*
* @param \Dom\Element $xml The XML element we should load.
*
* @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException
* if the qualified name of the supplied element is wrong
* @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException
* if the supplied element is missing any of the mandatory attributes
*/
public static function fromXML(Dom\Element $xml): static
{
$qualifiedName = static::getClassName(static::class);
Assert::eq(
$xml->localName,
$qualifiedName,
'Unexpected name for endpoint: ' . $xml->localName . '. Expected: ' . $qualifiedName . '.',
InvalidDOMElementException::class,
);

return new static(
self::getAttribute($xml, 'Binding', SAMLAnyURIValue::class),
self::getAttribute($xml, 'Location', SAMLAnyURIValue::class),
self::getOptionalAttribute($xml, 'ResponseLocation', SAMLAnyURIValue::class, null),
self::getOptionalAttribute($xml, 'supportsAsynchronous', BooleanValue::class, null),
self::getChildElementsFromXML($xml),
self::getAttributesNSFromXML($xml),
);
}


/**
* Add this endpoint to an XML element.
*
* @param \Dom\Element $parent The element we should append this endpoint to.
*/
public function toXML(?Dom\Element $parent = null): Dom\Element
{
$e = parent::toXML($parent);

if ($this->getSupportsAsynchronous() !== null) {
$e->setAttribute('supportsAsynchronous', $this->getSupportsAsynchronous()->getValue());
}

return $e;
}
}
57 changes: 57 additions & 0 deletions tests/SAML2/XML/aslo/AsynchronousTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\SAML2\Test\SAML2\XML\aslo;

use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\TestCase;
use SimpleSAML\SAML2\XML\aslo\AbstractAsloElement;
use SimpleSAML\SAML2\XML\aslo\Asynchronous;
use SimpleSAML\XML\DOMDocumentFactory;
use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait;
use SimpleSAML\XML\TestUtils\SerializableElementTestTrait;

use function dirname;
use function strval;

/**
* Class \SimpleSAML\SAML2\XML\aslo\AsynchronousTest
*
* @package simplesamlphp/saml2
*/
#[Group('aslo')]
#[CoversClass(Asynchronous::class)]
#[CoversClass(AbstractAsloElement::class)]
final class AsynchronousTest extends TestCase
{
use SchemaValidationTestTrait;
use SerializableElementTestTrait;


/**
*/
public static function setUpBeforeClass(): void
{
self::$testedClass = Asynchronous::class;

self::$xmlRepresentation = DOMDocumentFactory::fromFile(
dirname(__FILE__, 4) . '/resources/xml/aslo_Asynchronous.xml',
);
}


/**
*/
public function testMarshalling(): void
{
$asynchronous = new Asynchronous();

$expectedXml = self::$xmlRepresentation->saveXml(self::$xmlRepresentation->documentElement);
$this->assertNotFalse($expectedXml);
$actualXml = strval($asynchronous);

$this->assertXmlStringEqualsXmlString($expectedXml, $actualXml);
}
}
1 change: 1 addition & 0 deletions tests/resources/xml/aslo_Asynchronous.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<aslo:Asynchronous xmlns:aslo="urn:oasis:names:tc:SAML:2.0:protocol:ext:async-slo" />
Loading