Skip to content

Commit

Permalink
Some more work
Browse files Browse the repository at this point in the history
  • Loading branch information
tvdijen committed Jul 26, 2024
1 parent 76a509b commit 7a4b1ee
Show file tree
Hide file tree
Showing 12 changed files with 201 additions and 50 deletions.
64 changes: 41 additions & 23 deletions src/SAML2/Entity/ServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@
use Exception;
use Psr\Http\Message\ServerRequestInterface;
use SimpleSAML\Assert\Assert;
use SimpleSAML\SAML2\{Binding, HTTPArtifact, Metadata, StateProviderInterface, Utils};
use SimpleSAML\SAML2\{
Binding,
HTTPArtifact,
Metadata,
MetadataProviderInterface,
StateProviderInterface,
StorageProviderInterface,
Utils,
};
use SimpleSAML\SAML2\Exception\{MetadataNotFoundException, RemoteException, RuntimeException};
use SimpleSAML\SAML2\Exception\Protocol\{RequestDeniedException, ResourceNotRecognizedException};
use SimpleSAML\SAML2\Process\Validator\ResponseValidator;
Expand Down Expand Up @@ -38,7 +46,6 @@
*/
final class ServiceProvider
{
protected ?Metadata\MetadataProviderInterface $metadataProvider = null;
protected ?StateProviderInterface $stateProvider = null;
protected ?StorageProviderInterface $storageProvider = null;

Check failure on line 50 in src/SAML2/Entity/ServiceProvider.php

View workflow job for this annotation

GitHub Actions / Quality control

Property SimpleSAML\SAML2\Entity\ServiceProvider::$storageProvider has unknown class SimpleSAML\SAML2\StorageProviderInterface as its type.
protected ?Metadata\IdentityProvider $idpMetadata = null;
Expand All @@ -54,6 +61,7 @@ final class ServiceProvider
* @param bool $validateLogout Whether to validate the signature of LogoutRequest/LogoutResponse received
*/
public function __construct(
protected MetadataProviderInterface $metadataProvider,
protected Metadata\ServiceProvider $spMetadata,
protected readonly bool $encryptedAssertions = false,
protected readonly bool $disableScoping = false,
Expand All @@ -78,6 +86,14 @@ public function setStateProvider(StateProviderInterface $stateProvider): void
}


/**
*/
public function setStorageProvider(StorageProviderInterface $storageProvider): void

Check failure on line 91 in src/SAML2/Entity/ServiceProvider.php

View workflow job for this annotation

GitHub Actions / Quality control

Parameter $storageProvider of method SimpleSAML\SAML2\Entity\ServiceProvider::setStorageProvider() has invalid type SimpleSAML\SAML2\StorageProviderInterface.
{
$this->storageProvider = $storageProvider;
}


/**
* Receive a verified, and optionally validated Response.
*
Expand All @@ -95,11 +111,7 @@ public function receiveResponse(ServerRequestInterface $request): Response
$binding = Binding::getCurrentBinding($request);

if ($binding instanceof HTTPArtifact) {
if ($this->metadataProvider === null) {
throw new RuntimeException(
"A MetadataProvider is required to use the HTTP-Artifact binding.",
);
} elseif ($this->storageProvider === null) {
if ($this->storageProvider === null) {
throw new RuntimeException(
"A StorageProvider is required to use the HTTP-Artifact binding.",
);
Expand All @@ -110,7 +122,7 @@ public function receiveResponse(ServerRequestInterface $request): Response

if ($this->idpMetadata === null) {
throw new MetadataNotFoundException(sprintf(
'No metadata found for remote provider with SHA1 ID: %s',
'No metadata found for remote entity with SHA1 ID: %s',
$artifact->getSourceId(),
));
}
Expand All @@ -127,6 +139,18 @@ public function receiveResponse(ServerRequestInterface $request): Response
return $rawResponse;
}

// Fetch the metadata for the remote entity
if (!($binding instanceof HTTPArtifact)) {
$this->idpMetadata = $this->metadataProvider->getIdPMetadata($rawResponse->getIssuer()->getContent());

if ($this->idpMetadata === null) {
throw new MetadataNotFoundException(sprintf(
'No metadata found for remote entity with entityID: %s',
$rawResponse->getIssuer()->getContent(),
));
}
}

// Verify the signature (if any)
$verifiedResponse = $rawResponse->isSigned() ? $this->verifyElementSignature($rawResponse) : $rawResponse;

Expand All @@ -152,32 +176,26 @@ public function receiveResponse(ServerRequestInterface $request): Response
}
}

$issuer = $verifiedResponse->getIssuer()->getContent();
if ($state === null) {
if ($this->enableUnsolicited === false) {
throw new RequestDeniedException('Unsolicited responses are denied by configuration.');
}
} else {
// check that the issuer is the one we are expecting
Assert::keyExists($state, 'ExpectedIssuer');
$issuer = $verifiedResponse->getIssuer()->getContent();

if ($state['ExpectedIssuer'] !== $issuer) {
throw new ResourceNotRecognizedException("Issuer doesn't match the one the AuthnRequest was sent to.");
}
}

if ($this->metadataProvider === null) {
throw new RuntimeException(
"A MetadataProvider is required to be able to perform token decryption.",
);
}

$this->idpMetadata = $this->metadataProvider->getIdPMetadata($issuer);
if ($this->idpMetadata === null) {
throw new MetadataNotFoundException(sprintf(
'No metadata found for remote identity provider with entityID: %s',
$issuer,
));
}
$this->idpMetadata = $this->metadataProvider->getIdPMetadata($issuer);
if ($this->idpMetadata === null) {
throw new MetadataNotFoundException(sprintf(
'No metadata found for remote identity provider with entityID: %s',
$issuer,
));
}

$responseValidator = ResponseValidator::createResponseValidator(
Expand Down Expand Up @@ -308,7 +326,7 @@ protected function verifyElementSignature(SignedElementInterface $element): Sign
$factory = $this->spMetadata->getSignatureAlgorithmFactory();
$signatureAlgorithm = $element->getSignature()->getSignedInfo()->getSignatureMethod()->getAlgorithm();

foreach ($this->spMetadata->getValidatingKeys() as $validatingKey) {
foreach ($this->idpMetadata->getValidatingKeys() as $validatingKey) {
$verifier = $factory->getAlgorithm($signatureAlgorithm, $validatingKey);

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,33 @@

declare(strict_types=1);

namespace SimpleSAML\SAML2\Metadata;
namespace SimpleSAML\SAML2;

use SimpleSAML\SAML2\Metadata\IdentityProvider;
use SimpleSAML\SAML2\Metadata\ServiceProvider;

interface MetadataProviderInterface
{
/**
* Find IdP-metadata based on a SHA-1 hash of the entityID. Return `null` if not found.
*/
public function getIdPMetadataForSha1(string $hash): IdentityProvider;
public function getIdPMetadataForSha1(string $hash): ?IdentityProvider;


/**
* Find SP-metadata based on a SHA-1 hash of the entityID. Return `null` if not found.
*/
public function getSPMetadataForSha1(string $hash): ServiceProvider;
public function getSPMetadataForSha1(string $hash): ?ServiceProvider;


/**
* Find IdP-metadata based on an entityID. Return `null` if not found.
*/
public function getIdPMetadata(string $entityId): IdentityProvider;
public function getIdPMetadata(string $entityId): ?IdentityProvider;


/**
* Find SP-metadata based on an entityID. Return `null` if not found.
*/
public function getSPMetadata(string $entityId): ServiceProvider;
public function getSPMetadata(string $entityId): ?ServiceProvider;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use SimpleSAML\SAML2\Exception\Protocol\ResourceNotRecognizedException;
use SimpleSAML\SAML2\Process\{ServiceProviderAwareInterface, ServiceProviderAwareTrait};
use SimpleSAML\SAML2\Process\Validation\ConstraintValidatorInterface;
use SimpleSAML\SAML2\XML\samlp\Response;
use SimpleSAML\XML\SerializableElementInterface;

final class DestinationMatches implements ConstraintValidatorInterface
Expand Down
2 changes: 1 addition & 1 deletion src/SAML2/Process/Validator/ValidatorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

namespace SimpleSAML\SAML2\Process\Validator;

use SimpleSAML\XML\SerializableElementInterface;
use SimpleSAML\SAML2\Process\Validation\ConstraintValidatorInterface;
use SimpleSAML\XML\SerializableElementInterface;

interface ValidatorInterface
{
Expand Down
Loading

0 comments on commit 7a4b1ee

Please sign in to comment.