Skip to content

Commit

Permalink
Add samlp:StatusCode
Browse files Browse the repository at this point in the history
  • Loading branch information
tvdijen committed Nov 19, 2024
1 parent 953f1f6 commit a046c96
Show file tree
Hide file tree
Showing 5 changed files with 258 additions and 1 deletion.
77 changes: 76 additions & 1 deletion src/SAML11/Constants.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ class Constants extends \SimpleSAML\XMLSecurity\Constants
*/
public const NAMEID_UNSPECIFIED = 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified';


/**
* Windows Domain Qualifier Name NameID format.
*/
Expand All @@ -102,4 +101,80 @@ class Constants extends \SimpleSAML\XMLSecurity\Constants
* The namespace for the SAML 1.1 protocol.
*/
public const NS_SAMLP = 'urn:oasis:names:tc:SAML:1.0:protocol';

/**
* The SAML responder or SAML authority is able to process the request but has chosen not to respond.
* This status code MAY be used when there is concern about the security context of the request message or
* the sequence of request messages received from a particular requester.
*
* Second-level status code.
*/
public const STATUS_REQUEST_DENIED = 'samlp:RequestDenied';

/**
* The SAML responder cannot process any requests with the protocol version specified in the request.
*
* Second-level status code.
*/
public const STATUS_REQUEST_VERSION_DEPRECATED = 'samlp:RequestVersionDeprecated';

/**
* The SAML responder cannot process the request because the protocol version specified in the request message
* is a major upgrade from the highest protocol version supported by the responder.
*
* Second-level status code.
*/
public const STATUS_REQUEST_VERSION_TOO_HIGH = 'samlp:RequestVersionTooHigh';

/**
* The SAML responder cannot process the request because the protocol version specified in the request message
* is too low.
*
* Second-level status code.
*/
public const STATUS_REQUEST_VERSION_TOO_LOW = 'samlp:RequestVersionTooLow';

/**
* The request could not be performed due to an error on the part of the requester.
*
* Top-level status code.
*/
public const STATUS_REQUESTER = 'samlp:Requester';

/**
* The resource value provided in the request message is invalid or unrecognized.
*
* Second-level status code.
*/
public const STATUS_RESOURCE_NOT_RECOGNIZED = 'samlp:ResourceNotRecognized';

/**
* The request could not be performed due to an error on the part of the SAML responder or SAML authority.
*
* Top-level status code.
*/
public const STATUS_RESPONDER = 'samlp:Responder';

/**
* Top-level status code indicating successful processing of the request.
* The request succeeded. Additional information MAY be returned in the <StatusMessage>
* and/or <StatusDetail> elements.
*
* Top-level status code.
*/
public const STATUS_SUCCESS = 'samlp:Success';

/**
* The response message would contain more elements than the SAML responder is able to return.
*
* Second-level status code.
*/
public const STATUS_TOO_MANY_RESPONSES = 'samlp:TooManyResponses';

/**
* The SAML responder could not process the request because the version of the request message was incorrect.
*
* Top-level status code.
*/
public const STATUS_VERSION_MISMATCH = 'samlp:VersionMismatch';
}
100 changes: 100 additions & 0 deletions src/SAML11/XML/samlp/AbstractStatusCodeType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\SAML11\XML\samlp;

use DOMElement;
use SimpleSAML\Assert\Assert;
use SimpleSAML\SAML11\Constants as C;
use SimpleSAML\XML\Exception\InvalidDOMElementException;

/**
* SAML StatusCode data type.
*
* @package simplesamlphp/saml11
*/
abstract class AbstractStatusCodeType extends AbstractSamlpElement
{
/**
* Initialize a samlp:StatusCode
*
* @param string $Value
* @param \SimpleSAML\SAML11\XML\samlp\StatusCode[] $subCodes
*/
final public function __construct(
protected string $Value = C::STATUS_SUCCESS,
protected array $subCodes = [],
) {
Assert::validQName($Value);
Assert::maxCount($subCodes, C::UNBOUNDED_LIMIT);
Assert::allIsInstanceOf($subCodes, StatusCode::class);
}


/**
* Collect the Value
*
* @return string
*/
public function getValue(): string
{
return $this->Value;
}


/**
* Collect the subcodes
*
* @return \SimpleSAML\SAML11\XML\samlp\StatusCode[]
*/
public function getSubCodes(): array
{
return $this->subCodes;
}


/**
* Convert XML into a StatusCode
*
* @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
* @throws \SimpleSAML\XML\Exception\MissingAttributeException
* if the supplied element is missing one of the mandatory attributes
*/
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,
);
}


/**
* Convert this StatusCode to XML.
*
* @param \DOMElement|null $parent The element we should append this StatusCode to.
* @return \DOMElement
*/
public function toXML(DOMElement $parent = null): DOMElement
{
$e = $this->instantiateParentElement($parent);
$e->setAttribute('Value', $this->getValue());

foreach ($this->getSubCodes() as $subCode) {
$subCode->toXML($e);
}

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

declare(strict_types=1);

namespace SimpleSAML\SAML11\XML\samlp;

/**
* Class representing a saml:StatusCode element.
*
* @package simplesamlphp/saml11
*/
final class StatusCode extends AbstractStatusCodeType
{
}
3 changes: 3 additions & 0 deletions tests/resources/xml/samlp_StatusCode.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<samlp:StatusCode xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" Value="samlp:Responder">
<samlp:StatusCode Value="samlp:RequestDenied"/>
</samlp:StatusCode>
65 changes: 65 additions & 0 deletions tests/src/SAML11/XML/samlp/StatusCodeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\Test\SAML11\XML\samlp;

use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\TestCase;
use SimpleSAML\SAML11\Constants as C;
use SimpleSAML\SAML11\XML\samlp\AbstractSamlpElement;
use SimpleSAML\SAML11\XML\samlp\StatusCode;
use SimpleSAML\XML\DOMDocumentFactory;
use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait;
use SimpleSAML\XML\TestUtils\SerializableElementTestTrait;

use function dirname;
use function strval;

/**
* Class \SimpleSAML\SAML11\XML\samlp\StatusCodeTest
*
* @package simplesamlphp/saml11
*/
#[Group('samlp')]
#[CoversClass(StatusCode::class)]
#[CoversClass(AbstractSamlpElement::class)]
final class StatusCodeTest extends TestCase
{
use SchemaValidationTestTrait;
use SerializableElementTestTrait;


/**
*/
public static function setUpBeforeClass(): void
{
self::$schemaFile = dirname(__FILE__, 6) . '/resources/schemas/oasis-sstc-saml-schema-protocol-1.1.xsd';

self::$testedClass = StatusCode::class;

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


/**
*/
public function testMarshalling(): void
{

$statusCode = new StatusCode(
C::STATUS_RESPONDER,
[
new StatusCode(C::STATUS_REQUEST_DENIED),
],
);

$this->assertEquals(
self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement),
strval($statusCode),
);
}
}

0 comments on commit a046c96

Please sign in to comment.