Skip to content

Commit

Permalink
Feature/standalone metadata (#21)
Browse files Browse the repository at this point in the history
* Do not rely on SimpleSAMLphp for metadata-building

* Fix

* Introduce a clokc

* Generate ID

* Cleanup
  • Loading branch information
tvdijen committed Sep 1, 2024
1 parent 162d155 commit c7e80ba
Show file tree
Hide file tree
Showing 4 changed files with 358 additions and 127 deletions.
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
"php": "^8.1",
"ext-dom": "*",

"beste/clock": "^3.0",
"psr/clock": "^1.0",
"simplesamlphp/assert": "^1.1",
"simplesamlphp/saml11": "^1.0",
"simplesamlphp/saml2": "^5@dev",
Expand Down
135 changes: 9 additions & 126 deletions src/Controller/Adfs.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,11 @@
namespace SimpleSAML\Module\adfs\Controller;

use Exception;
use SimpleSAML\Configuration;
use SimpleSAML\{Configuration, IdP, Logger, Metadata, Module, Session, Utils};
use SimpleSAML\Error as SspError;
use SimpleSAML\IdP;
use SimpleSAML\Logger;
use SimpleSAML\Metadata;
use SimpleSAML\Module;
use SimpleSAML\Module\adfs\IdP\ADFS as ADFS_IDP;
use SimpleSAML\SAML2\Constants as C;
use SimpleSAML\Session;
use SimpleSAML\Utils;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use SimpleSAML\Module\adfs\IdP\MetadataBuilder;
use Symfony\Component\HttpFoundation\{Request, Response, StreamedResponse};

/**
* Controller class for the adfs module.
Expand Down Expand Up @@ -79,123 +71,14 @@ public function metadata(Request $request): Response
}
$idpmeta = $this->metadata->getMetaDataConfig($idpentityid, 'adfs-idp-hosted');

$availableCerts = [];
$keys = [];
$certInfo = $this->cryptoUtils->loadPublicKey($idpmeta, false, 'new_');
$builder = new MetadataBuilder($this->config, $idpmeta);

if ($certInfo !== null) {
$availableCerts['new_idp.crt'] = $certInfo;
$keys[] = [
'type' => 'X509Certificate',
'signing' => true,
'encryption' => true,
'X509Certificate' => $certInfo['certData'],
];
$hasNewCert = true;
} else {
$hasNewCert = false;
}

/** @var array $certInfo */
$certInfo = $this->cryptoUtils->loadPublicKey($idpmeta, true);
$availableCerts['idp.crt'] = $certInfo;
$keys[] = [
'type' => 'X509Certificate',
'signing' => true,
'encryption' => ($hasNewCert ? false : true),
'X509Certificate' => $certInfo['certData'],
];

if ($idpmeta->hasValue('https.certificate')) {
/** @var array $httpsCert */
$httpsCert = $this->cryptoUtils->loadPublicKey($idpmeta, true, 'https.');
Assert::keyExists($httpsCert, 'certData');
$availableCerts['https.crt'] = $httpsCert;
$keys[] = [
'type' => 'X509Certificate',
'signing' => true,
'encryption' => false,
'X509Certificate' => $httpsCert['certData'],
];
}

$adfs_service_location = Module::getModuleURL('adfs') . '/idp/prp.php';
$metaArray = [
'metadata-set' => 'adfs-idp-remote',
'entityid' => $idpentityid,
'SingleSignOnService' => [
0 => [
'Binding' => C::BINDING_HTTP_REDIRECT,
'Location' => $adfs_service_location,
],
],
'SingleLogoutService' => [
0 => [
'Binding' => C::BINDING_HTTP_REDIRECT,
'Location' => $adfs_service_location,
],
],
];

if (count($keys) === 1) {
$metaArray['certData'] = $keys[0]['X509Certificate'];
} else {
$metaArray['keys'] = $keys;
}

$metaArray['NameIDFormat'] = $idpmeta->getOptionalString(
'NameIDFormat',
C::NAMEID_TRANSIENT,
);

if ($idpmeta->hasValue('OrganizationName')) {
$metaArray['OrganizationName'] = $idpmeta->getLocalizedString('OrganizationName');
$metaArray['OrganizationDisplayName'] = $idpmeta->getOptionalLocalizedString(
'OrganizationDisplayName',
$metaArray['OrganizationName'],
);

if (!$idpmeta->hasValue('OrganizationURL')) {
throw new SspError\Exception('If OrganizationName is set, OrganizationURL must also be set.');
}
$metaArray['OrganizationURL'] = $idpmeta->getLocalizedString('OrganizationURL');
}

if ($idpmeta->hasValue('scope')) {
$metaArray['scope'] = $idpmeta->getArray('scope');
}

if ($idpmeta->hasValue('EntityAttributes')) {
$metaArray['EntityAttributes'] = $idpmeta->getArray('EntityAttributes');
}

if ($idpmeta->hasValue('UIInfo')) {
$metaArray['UIInfo'] = $idpmeta->getArray('UIInfo');
}

if ($idpmeta->hasValue('DiscoHints')) {
$metaArray['DiscoHints'] = $idpmeta->getArray('DiscoHints');
}

if ($idpmeta->hasValue('RegistrationInfo')) {
$metaArray['RegistrationInfo'] = $idpmeta->getArray('RegistrationInfo');
}

$metaBuilder = new Metadata\SAMLBuilder($idpentityid);
$metaBuilder->addSecurityTokenServiceType($metaArray);
$metaBuilder->addOrganizationInfo($metaArray);
$technicalContactEmail = $this->config->getOptionalString('technicalcontact_email', null);
if ($technicalContactEmail !== null && $technicalContactEmail !== '[email protected]') {
$metaBuilder->addContact(Utils\Config\Metadata::getContact([
'emailAddress' => $technicalContactEmail,
'givenName' => $this->config->getOptionalString('technicalcontact_name', null),
'contactType' => 'technical',
]));
}
$metaxml = $metaBuilder->getEntityDescriptorText();
$document = $builder->buildDocument()->toXML();
// Some products like DirX are known to break on pretty-printed XML
$document->ownerDocument->formatOutput = false;
$document->ownerDocument->encoding = 'UTF-8';

// sign the metadata if enabled
$metaxml = Metadata\Signer::sign($metaxml, $idpmeta->toArray(), 'ADFS IdP');
$metaxml = $document->ownerDocument->saveXML();

$response = new Response();
$response->setEtag(hash('sha256', $metaxml));
Expand Down
1 change: 0 additions & 1 deletion src/IdP/ADFS.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use DateTimeImmutable;
use DateTimeZone;
use Exception;
use SimpleSAML\Assert\Assert;
use SimpleSAML\Configuration;
use SimpleSAML\Error;
use SimpleSAML\IdP;
Expand Down
Loading

0 comments on commit c7e80ba

Please sign in to comment.