Skip to content

Commit

Permalink
Implement saml:Statement
Browse files Browse the repository at this point in the history
  • Loading branch information
tvdijen committed Feb 27, 2024
1 parent 954a927 commit 98df222
Show file tree
Hide file tree
Showing 7 changed files with 440 additions and 125 deletions.
123 changes: 0 additions & 123 deletions src/SAML11/XML/saml/AbstractStatement.php

This file was deleted.

113 changes: 111 additions & 2 deletions src/SAML11/XML/saml/AbstractStatementType.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,120 @@

namespace SimpleSAML\SAML11\XML\saml;

use DOMElement;
use SimpleSAML\Assert\Assert;
use SimpleSAML\SAML11\Constants as C;
use SimpleSAML\SAML11\Utils;
use SimpleSAML\SAML11\XML\ExtensionPointInterface;
use SimpleSAML\SAML11\XML\ExtensionPointTrait;
use SimpleSAML\XML\Attribute as XMLAttribute;
use SimpleSAML\XML\Chunk;
use SimpleSAML\XML\Exception\InvalidDOMElementException;
use SimpleSAML\XML\Exception\SchemaViolationException;

use function count;
use function explode;

/**
* Base abstract class for all Statement types.
* Class implementing the <saml:Statement> extension point.
*
* @package simplesamlphp/saml11
*/
abstract class AbstractStatementType extends AbstractSamlElement
abstract class AbstractStatementType extends AbstractSamlElement implements ExtensionPointInterface
{
use ExtensionPointTrait;

/** @var string */
public const LOCALNAME = 'Statement';


/**
* Initialize a custom saml:Statement element.
*
* @param string $type
*/
protected function __construct(
protected string $type,
) {
}


/**
* @inheritDoc
*/
public function getXsiType(): string
{
return $this->type;
}


/**
* Convert an XML element into a Statement.
*
* @param \DOMElement $xml The root XML element
* @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, 'Statement', InvalidDOMElementException::class);
Assert::same($xml->namespaceURI, C::NS_SAML, InvalidDOMElementException::class);
Assert::true(
$xml->hasAttributeNS(C::NS_XSI, 'type'),
'Missing required xsi:type in <saml:Statement> 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]);

// 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 statement
return new UnknownStatement(new Chunk($xml), $type);
}

Assert::subclassOf(
$handler,
AbstractStatement::class,
'Elements implementing Statement must extend \SimpleSAML\SAML11\XML\saml\AbstractStatement.',
);
return $handler::fromXML($xml);
}


/**
* Convert this Statement to XML.
*
* @param \DOMElement $parent The element we are converting to XML.
* @return \DOMElement The XML element after adding the data corresponding to this Statement.
*/
public function toXML(DOMElement $parent = null): DOMElement
{
$e = $this->instantiateParentElement($parent);
$e->setAttributeNS(
'http://www.w3.org/2000/xmlns/',
'xmlns:' . static::getXsiTypePrefix(),
static::getXsiTypeNamespaceURI(),
);

$type = new XMLAttribute(C::NS_XSI, 'xsi', 'type', $this->getXsiType());
$type->toXML($e);

return $e;
}
}
50 changes: 50 additions & 0 deletions src/SAML11/XML/saml/UnknownStatement.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\SAML11\XML\saml;

use DOMElement;
use SimpleSAML\XML\Chunk;

/**
* Class for unknown statements.
*
* @package simplesamlphp/saml11
*/
final class UnknownStatement extends AbstractStatementType
{
/**
* @param \SimpleSAML\XML\Chunk $chunk The whole Statement element as a chunk object.
* @param string $type The xsi:type of this statement
*/
public function __construct(
protected Chunk $chunk,
string $type,
) {
parent::__construct($type);
}


/**
* Get the raw version of this statement as a Chunk.
*
* @return \SimpleSAML\XML\Chunk
*/
public function getRawStatement(): Chunk
{
return $this->chunk;
}


/**
* Convert this unknown statement 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 unknown statement.
*/
public function toXML(DOMElement $parent = null): DOMElement
{
return $this->getRawStatement()->toXML($parent);
}
}
46 changes: 46 additions & 0 deletions tests/resources/schemas/simplesamlphp.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE schema
PUBLIC "-//W3C//DTD XMLSchema 200102//EN" "http://www.w3.org/2001/XMLSchema.dtd"
[
<!ATTLIST schema
xmlns:ds CDATA #FIXED "urn:x-simplesamlphp:namespace">
<!ENTITY ssp 'urn:x-simplesamlphp:namespace'>
<!ENTITY % p ''>
<!ENTITY % s ''>
]>

<!-- Schema for SimpleSAMLphp dummy classes -->


<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:ssp="urn:x-simplesamlphp:namespace"
xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion"
targetNamespace="urn:x-simplesamlphp:namespace"
version="0.1" elementFormDefault="qualified">

<import namespace='urn:oasis:names:tc:SAML:1.0:assertion'
schemaLocation='../../../resources/schemas/oasis-sstc-saml-schema-assertion-1.1.xsd'/>

<!-- Start Chunk -->

<element name="Chunk" type="string"/>

<!-- End Chunk -->

<!-- Start CustomStatement -->

<element name="CustomStatement" type="ssp:CustomStatementType"/>
<complexType name="CustomStatementType">
<complexContent>
<extension base="saml:StatementAbstractType">
<sequence>
<element ref="saml:Audience" maxOccurs="unbounded"/>
</sequence>
</extension>
</complexContent>
</complexType>

<!-- End CustomStatement -->

</schema>

3 changes: 3 additions & 0 deletions tests/resources/xml/saml_Statement.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<saml:Statement xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:ssp="urn:x-simplesamlphp:namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ssp:CustomStatementType">
<saml:Audience>urn:some:audience</saml:Audience>
</saml:Statement>
Loading

0 comments on commit 98df222

Please sign in to comment.