Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion example/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
],
'sp_org_name' => 'test',
'sp_org_display_name' => 'Test',
//'sp_org_url' => 'https://www.aggregatorSite.com/', // Only for aggregator
'sp_key_cert_values' => [
'countryName' => 'IT',
'stateOrProvinceName' => 'Milan',
Expand All @@ -33,7 +34,31 @@
'sp_attributeconsumingservice' => [
["name", "familyName", "fiscalNumber", "email"],
["name", "familyName", "fiscalNumber", "email", "spidCode"]
]
],
/*'sp_contact_persons' => [ // Only for aggregator
[
'contactType' => 'other',
'entityType' => 'spid:aggregator',
'ipaCode' => '',
'vatNumber' => 'VATNumber',
'fiscalCode' => 'FiscalCode',
'emptyTag' => 'PublicServicesLightAggregator',
'company' => 'AggregatorCompany',
'emailAddress' => 'aggregator@mail.com',
'telephoneNumber' => 'TelephoneNumber'
],
[
'contactType' => 'other',
'entityType' => 'spid:aggregated',
'ipaCode' => 'IPAcode',
'vatNumber' => '',
'fiscalCode' => '',
'emptyTag' => 'Public',
'company' => 'Test',
'emailAddress' => '',
'telephoneNumber' => ''
]
]*/
];
$sp = new Italia\Spid\Sp($settings);

Expand Down
98 changes: 91 additions & 7 deletions src/Spid/Saml.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,16 @@ public function getSPMetadata(): string
$entityID = htmlspecialchars($this->settings['sp_entityid'], ENT_XML1);
$id = preg_replace('/[^a-z0-9_-]/', '_', $entityID);
$cert = Settings::cleanOpenSsl($this->settings['sp_cert_file']);
if (array_key_exists('sp_org_url', $this->settings)) {
$orgUrl = $this->settings['sp_org_url'];
}

$sloLocationArray = $this->settings['sp_singlelogoutservice'] ?? array();
$assertcsArray = $this->settings['sp_assertionconsumerservice'] ?? array();
$attrcsArray = $this->settings['sp_attributeconsumingservice'] ?? array();

$xml = <<<XML
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="$entityID" ID="$id">
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:spid="https://spid.gov.it/saml-extensions" entityID="$entityID" ID="$id">
<md:SPSSODescriptor
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"
AuthnRequestsSigned="true" WantAssertionsSigned="true">
Expand Down Expand Up @@ -136,14 +139,95 @@ public function getSPMetadata(): string
if (array_key_exists('sp_org_name', $this->settings)) {
$orgName = $this->settings['sp_org_name'];
$orgDisplayName = $this->settings['sp_org_display_name'];
$xml .= <<<XML
<md:Organization>
<md:OrganizationName xml:lang="it">$orgName</md:OrganizationName>
<md:OrganizationDisplayName xml:lang="it">$orgDisplayName</md:OrganizationDisplayName>
<md:OrganizationURL xml:lang="it">$entityID</md:OrganizationURL>
</md:Organization>
if(empty($orgUrl)) {
$xml .= <<<XML
<md:Organization>
<md:OrganizationName xml:lang="it">$orgName</md:OrganizationName>
<md:OrganizationDisplayName xml:lang="it">$orgDisplayName</md:OrganizationDisplayName>
<md:OrganizationURL xml:lang="it">$entityID</md:OrganizationURL>
</md:Organization>
XML;
} else {
$xml .= <<<XML
<md:Organization>
<md:OrganizationName xml:lang="it">$orgName</md:OrganizationName>
<md:OrganizationDisplayName xml:lang="it">$orgDisplayName</md:OrganizationDisplayName>
<md:OrganizationURL xml:lang="it">$orgUrl</md:OrganizationURL>
</md:Organization>
XML;
}
}

if (array_key_exists('sp_contact_persons', $this->settings)) {
$contactPersonsArray = $this->settings['sp_contact_persons'] ?? array();

foreach ($contactPersonsArray as $cp) {
$contactType = (isset($cp['contactType'])) ? $cp['contactType'] : '';
$entityType = (isset($cp['entityType'])) ? $cp['entityType'] : '';
$ipaCode = (isset($cp['ipaCode'])) ? $cp['ipaCode'] : '';
$vatNumber = (isset($cp['vatNumber'])) ? $cp['vatNumber'] : '';
$fiscalCode = (isset($cp['fiscalCode'])) ? $cp['fiscalCode'] : '';
$tagVuoto = (isset($cp['emptyTag'])) ? $cp['emptyTag'] : '';
$company = (isset($cp['company'])) ? $cp['company'] : '';
$emailAddress = (isset($cp['emailAddress'])) ? $cp['emailAddress'] : '';
$telephoneNumber = (isset($cp['telephoneNumber'])) ? $cp['telephoneNumber'] : '';

if (strcasecmp($entityType, "") !== 0) {
$xml .= <<<XML
<md:ContactPerson contactType="$contactType" spid:entityType="$entityType">
<md:Extensions>
XML;
} else {
$xml .= <<<XML
<md:ContactPerson contactType="$contactType">
<md:Extensions>
XML;
}

if (strcasecmp($ipaCode, "") !== 0) {
$xml .= <<<XML
<spid:IPACode>$ipaCode</spid:IPACode>
XML;
}
if (strcasecmp($vatNumber, "") !== 0) {
$xml .= <<<XML
<spid:VATNumber>$vatNumber</spid:VATNumber>
XML;
}
if (strcasecmp($fiscalCode, "") !== 0) {
$xml .= <<<XML
<spid:FiscalCode>$fiscalCode</spid:FiscalCode>
XML;
}
if (strcasecmp($tagVuoto, "") !== 0) {
$xml .= <<<XML
<spid:$tagVuoto/>
XML;
}
$xml .= <<<XML
</md:Extensions>
XML;
if (strcasecmp($company, "") !== 0) {
$xml .= <<<XML
<md:Company>$company</md:Company>
XML;
}
if (strcasecmp($emailAddress, "") !== 0) {
$xml .= <<<XML
<md:EmailAddress>$emailAddress</md:EmailAddress>
XML;
}
if (strcasecmp($telephoneNumber, "") !== 0) {
$xml .= <<<XML
<md:TelephoneNumber>$telephoneNumber</md:TelephoneNumber>
XML;
}
$xml .= <<<XML
</md:ContactPerson>
XML;
}
}

$xml .= '</md:EntityDescriptor>';

return SignatureUtils::signXml($xml, $this->settings);
Expand Down
75 changes: 74 additions & 1 deletion src/Spid/Saml/Settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class Settings
'sp_attributeconsumingservice' => self::NOT_REQUIRED,
'sp_org_name' => self::NOT_REQUIRED,
'sp_org_display_name' => self::NOT_REQUIRED,
'sp_org_url' => self::NOT_REQUIRED,
'sp_key_cert_values' => [
self::NOT_REQUIRED => [
'countryName' => self::REQUIRED,
Expand All @@ -30,7 +31,20 @@ class Settings
]
],
'idp_metadata_folder' => self::REQUIRED,
'accepted_clock_skew_seconds' => self::NOT_REQUIRED
'accepted_clock_skew_seconds' => self::NOT_REQUIRED,
'sp_contact_persons' => [
self::NOT_REQUIRED => [
'contactType' => self::REQUIRED,
'entityType' => self::NOT_REQUIRED,
'ipaCode' => self::NOT_REQUIRED,
'vatNumber' => self::NOT_REQUIRED,
'fiscalCode' => self::NOT_REQUIRED,
'emptyTag' => self::REQUIRED,
'company' => self::REQUIRED,
'emailAddress' => self::NOT_REQUIRED,
'telephoneNumber' => self::NOT_REQUIRED
]
]
];

private static $validAttributeFields = [
Expand Down Expand Up @@ -246,5 +260,64 @@ private static function checkSettingsValues($settings)
'"exact", "minimum", "better" or "maximum"');
}
}
if (isset($settings['sp_contact_persons'])) {
if (!is_array($settings['sp_contact_persons'])) {
throw new \InvalidArgumentException('sp_contact_persons should be an array');
}
array_walk($settings['sp_contact_persons'], function ($cp) {
if (!is_array($cp)) {
throw new \InvalidArgumentException('sp_contact_persons elements should be an array');
}
if (count($cp) == 0) {
throw new \InvalidArgumentException(
'sp_contact_persons elements should contain at least one element'
);
}
if (isset($cp['contactType'])) {
if (strcasecmp($cp['contactType'], "other") != 0 &&
strcasecmp($cp['contactType'], "billing") != 0) {
throw new \InvalidArgumentException('contactType value should be one of:' .
'"other", "billing"');
}

if(strcasecmp($cp['contactType'], "other") == 0) {
if (isset($cp['entityType']) && !empty($cp['entityType'])) {
if (strcasecmp($cp['entityType'], "spid:aggregator") != 0 &&
strcasecmp($cp['entityType'], "spid:aggregated") != 0) {
throw new \InvalidArgumentException('entityType value should be one of:' .
'"spid:aggregator", "spid:aggregated"');
}
}
} else {
if (isset($cp['entityType']) && !empty($cp['entityType'])) {
throw new \InvalidArgumentException('when contactType is equal to "billing", entityType value should be empty');
}
}
} else {
throw new \Exception('Missing settings field: contactType');
}

if (isset($cp['emptyTag']) && !empty($cp['emptyTag'])) {
if (strcasecmp($cp['emptyTag'], "Public") != 0 &&
strcasecmp($cp['emptyTag'], "Private") != 0 &&
strcasecmp($cp['emptyTag'], "PublicServicesFullAggregator") != 0 &&
strcasecmp($cp['emptyTag'], "PublicServicesLightAggregator") != 0 &&
strcasecmp($cp['emptyTag'], "PrivateServicesFullAggregator") != 0 &&
strcasecmp($cp['emptyTag'], "PrivateServicesLightAggregator") != 0 &&
strcasecmp($cp['emptyTag'], "PublicServicesFullOperator") != 0 &&
strcasecmp($cp['emptyTag'], "PublicServicesLightOperator") != 0) {
throw new \InvalidArgumentException('emptyTag value should be one of:' .
'"Public", "Private", "PublicServicesFullAggregator", "PublicServicesLightAggregator", ' .
'"PrivateServicesFullAggregator", "PrivateServicesLightAggregator", "PublicServicesFullOperator", "PublicServicesLightOperator"');
}
} else {
throw new \Exception('Missing settings field: emptyTag');
}

if (!isset($cp['company']) || empty($cp['company'])) {
throw new \Exception('Missing settings field: company');
}
});
}
}
}