Skip to content

Commit 2962312

Browse files
committed
WIP: Create ResponseValidator + necessary helper-classes
1 parent 1ce34ef commit 2962312

10 files changed

+261
-0
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\SAML2\Exception;
6+
7+
/**
8+
* Exception to be raised when validation of a constraint fails.
9+
*/
10+
class ConstraintViolationFailedException extends RuntimeException
11+
{
12+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\SAML2\Process\ConstraintValidation;
6+
7+
use SimpleSAML\XML\SerializableElementInterface;
8+
9+
interface ConstraintValidatorInterface
10+
{
11+
/**
12+
* Runs the validation.
13+
*
14+
* If this function returns, the validation has been succesful.
15+
*
16+
* @throws \SimpleSAML\SAML2\Exception\ConstraintViolationFailedException when the condition fails.
17+
*/
18+
public function validate(SerializableElementInterface $element): void;
19+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\SAML2\Process\ConstraintValidation\Response;
6+
7+
use SimpleSAML\SAML2\{Binding, Metadata};
8+
use SimpleSAML\SAML2\Exception\Protocol\ResourceNotRecognizedException;
9+
use SimpleSAML\SAML2\Process\{ServiceProviderAwareInterface, ServiceProviderAwareTrait};
10+
use SimpleSAML\SAML2\Process\ConstraintValidation\ConstraintValidatorInterface;
11+
use SimpleSAML\XML\SerializableElementInterface;
12+
13+
final class DestinationMatches implements ConstraintValidatorInterface
14+
{
15+
/**
16+
* DestinationMatches constructor.
17+
*
18+
* @param \SimpleSAML\SAML2\Metadata\ServiceProvider $spMetadata
19+
* @param \SimpleSAML\SAML2\Binding $binding
20+
*/
21+
public function __construct(
22+
private Metadata\ServiceProvider $spMetadata,
23+
private Binding $binding,
24+
) {
25+
}
26+
27+
28+
/**
29+
* @param \SimpleSAML\XML\SerializableElementInterface $response
30+
*/
31+
public function validate(SerializableElementInterface $response): void
32+
{
33+
// Validate that the destination matches the appropriate endpoint from the SP-metadata
34+
foreach ($this->spMetadata->getAssertionConsumerService() as $assertionConsumerService) {
35+
if ($assertionConsumerService->getLocation() === $response->getDestination()) {
36+
if (Binding::getBinding($assertionConsumerService->getBinding()) instanceof $this->binding) {
37+
return;
38+
}
39+
}
40+
}
41+
throw new ResourceNotRecognizedException();
42+
}
43+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\SAML2\Process;
6+
7+
use SimpleSAML\SAML2\Metadata;
8+
9+
interface IdentityProviderAwareInterface
10+
{
11+
/**
12+
* Set the IdP metadata.
13+
*/
14+
public function setIdPMetadata(Metadata\IdentityProvider $idpMetadata): void;
15+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\SAML2\Process;
6+
7+
use SimpleSAML\SAML2\Metadata;
8+
9+
trait IdentityProviderAwareTrait
10+
{
11+
protected Metadata\IdentityProvider $idpMetadata;
12+
13+
/**
14+
* Set the IdP metadata.
15+
*/
16+
public function setIdPMetadata(Metadata\IdentityProvider $idpMetadata): void
17+
{
18+
$this->idpMetadata = $idpMetadata;
19+
}
20+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\SAML2\Process;
6+
7+
use SimpleSAML\SAML2\Metadata;
8+
9+
interface ServiceProviderAwareInterface
10+
{
11+
/**
12+
* Set the SP metadata.
13+
*/
14+
public function setSPMetadata(Metadata\ServiceProvider $spMetadata): void;
15+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\SAML2\Process;
6+
7+
use SimpleSAML\SAML2\Metadata;
8+
9+
trait ServiceProviderAwareTrait
10+
{
11+
protected Metadata\ServiceProvider $spMetadata;
12+
13+
/**
14+
* Set the SP metadata.
15+
*/
16+
public function setSPMetadata(Metadata\ServiceProvider $spMetadata): void
17+
{
18+
$this->spMetadata = $spMetadata;
19+
}
20+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\SAML2\Process\Validator;
6+
7+
use SimpleSAML\SAML2\{Binding, Metadata};
8+
use SimpleSAML\SAML2\Process\ConstraintValidation\Response\{DestinationMatches, IsSuccessful};
9+
10+
class ResponseValidator implements ValidatorInterface
11+
{
12+
use ValidatorTrait;
13+
14+
/**
15+
* @param \SimpleSAML\SAML2\Metadata\IdentityProvider The IdP-metadata
16+
* @param \SimpleSAML\SAML2\Metadata\ServiceProvider The SP-metadata
17+
*/
18+
private function __construct(
19+
protected ?Metadata\IdentityProvider $idpMetadata,
20+
protected Metadata\ServiceProvider $spMetadata,
21+
) {
22+
}
23+
24+
25+
/**
26+
* @param \SimpleSAML\SAML2\Metadata\IdentityProvider|null $idpMetadata
27+
* @param \SimpleSAML\SAML2\Metadata\ServiceProvider $spMetadata
28+
* @param string $binding
29+
* @return \SimpleSAML\SAML2\Validator\ResponseValidator
30+
*/
31+
public static function createResponseValidator(
32+
?Metadata\IdentityProvider $idpMetadata,
33+
Metadata\ServiceProvider $spMetadata,
34+
Binding $binding,
35+
): ResponseValidator {
36+
$validator = new self($idpMetadata, $spMetadata);
37+
$validator->addConstraintValidator(new DestinationMatches($spMetadata, $binding));
38+
// $validator->addConstraintValidator(new IsSuccesful());
39+
40+
return $validator;
41+
}
42+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\SAML2\Process\Validator;
6+
7+
use SimpleSAML\SAML2\Process\ConstraintValidation\ConstraintValidatorInterface;
8+
use SimpleSAML\XML\SerializableElementInterface;
9+
10+
interface ValidatorInterface
11+
{
12+
/**
13+
* Runs all the validations in the validation chain.
14+
*
15+
* If this function returns, all validations have been succesful.
16+
*
17+
* @throws \SimpleSAML\SAML2\Exception\ConstraintValidationFailedException when one of the conditions fail.
18+
*/
19+
public function validate(SerializableElementInterface $element): void;
20+
21+
22+
/**
23+
* Add a validation to the chain.
24+
*/
25+
public function addConstraintValidator(ConstraintValidatorInterface $validation);
26+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\SAML2\Process\Validator;
6+
7+
use SimpleSAML\SAML2\Process\{IdentityProviderAwareInterface, ServiceProviderAwareInterface};
8+
use SimpleSAML\SAML2\Process\ConstraintValidation\ConstraintValidatorInterface;
9+
use SimpleSAML\XML\SerializableElementInterface;
10+
11+
trait ValidatorTrait
12+
{
13+
/** @var array<\SimpleSAML\SAML2\Process\ConstraintValidation\ConstraintValidatorInterface> */
14+
protected array $validators;
15+
16+
17+
/**
18+
* Add a validation to the chain.
19+
*
20+
* @param \SimpleSAML\SAML2\Process\ConstraintValidation\ConstraintValidatorInterface $validation
21+
*/
22+
public function addConstraintValidator(ConstraintValidatorInterface $validator)
23+
{
24+
if ($validator instanceof IdentityProviderAwareInterface) {
25+
$validator->setIdentityProvider($this->idpMetadata);
26+
}
27+
28+
if ($validator instanceof ServiceProviderAwareInterface) {
29+
$validator->setServiceProvider($this->spMetadata);
30+
}
31+
32+
$this->validators[] = $validator;
33+
}
34+
35+
36+
/**
37+
* Runs all the validations in the validation chain.
38+
*
39+
* If this function returns, all validations have been succesful.
40+
*
41+
* @throws \SimpleSAML\SAML2\Exception\ConstraintViolationFailedException when one of the conditions fail.
42+
*/
43+
public function validate(SerializableElementInterface $element): void
44+
{
45+
foreach ($this->validators as $validator) {
46+
$validator->validate($element);
47+
}
48+
}
49+
}

0 commit comments

Comments
 (0)