Skip to content
Snippets Groups Projects
Commit 7bea57bb authored by Olav Morken's avatar Olav Morken
Browse files

saml:SP: Add support for specifying bindings and required attributes in metadata.

This patch adds two enhancements to metadata generation:
 * Support for specifying attributes that are required.
 * Support for removing some of the AssertionConsumerService bindings.

Thanks to Benjamin Andresen for implementing this!

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3092 44740490-163a-0410-bde0-09ae8108e29a
parent d74b7715
Branches
Tags
No related merge requests found
......@@ -105,6 +105,38 @@ Here we will list some examples for this authentication source.
),
### Specifying attributes and required attributes
An SP that wants eduPersonPrincipalName and mail, where eduPersonPrincipalName should be listed as required:
'example-attributes => array(
'saml:SP',
'name' => array( //Name required for AttributeConsumingService-element.
'en' => 'Example service',
'no' => 'Eksempeltjeneste',
),
'attributes' => array(
'eduPersonPrincipalName',
'mail',
)
'attributes.required' => array (
'eduPersonPrincipalName',
),
'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic',
),
### Limiting supported AssertionConsumerService endpoint bindings
'example-acs-limit' => array(
'saml:SP',
'acs.Bindings' => array(
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
'urn:oasis:names:tc:SAML:1.0:profiles:browser-post',
),
),
### Requesting a specific authentication method.
$auth = new SimpleSAML_Auth_Simple('default-sp');
......@@ -127,6 +159,16 @@ Here we will list some examples for this authentication source.
Options
-------
`acs.Bindings`
: List of bindings the SP should support. If it is unset, all will be added.
: Possible values:
* `urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST`
* `urn:oasis:names:tc:SAML:1.0:profiles:browser-post`
* `urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact`
* `urn:oasis:names:tc:SAML:1.0:profiles:artifact-01`
* `urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser`
`assertion.encryption`
: Whether assertions received by this SP must be encrypted. The default value is `FALSE`.
If this option is set to `TRUE`, unencrypted assertions will be rejected.
......@@ -147,6 +189,10 @@ Options
`attributes.NameFormat`
: The `NameFormat` for the requested attributes.
`attributes.required`
: If you have attributes added you can here specify which should be marked as required.
: The attributes should still be present in `attributes`.
`AuthnContextClassRef`
: The SP can request authentication with a specific authentication context class.
One example of usage could be if the IdP supports both username/password authentication as well as software-PKI.
......
<?php
if (!array_key_exists('PATH_INFO', $_SERVER)) {
throw new SimpleSAML_Error_BadRequest('Missing authentication source id in metadata URL');
}
......@@ -48,36 +47,48 @@ if ($store instanceof SimpleSAML_Store_SQL) {
$sp->SingleLogoutService[] = $slo;
}
$acs = new SAML2_XML_md_IndexedEndpointType();
$acs->index = 0;
$acs->Binding = SAML2_Const::BINDING_HTTP_POST;
$acs->Location = SimpleSAML_Module::getModuleURL('saml/sp/saml2-acs.php/' . $sourceId);
$sp->AssertionConsumerService[] = $acs;
$acs = new SAML2_XML_md_IndexedEndpointType();
$acs->index = 1;
$acs->Binding = 'urn:oasis:names:tc:SAML:1.0:profiles:browser-post';
$acs->Location = SimpleSAML_Module::getModuleURL('saml/sp/saml1-acs.php/' . $sourceId);
$sp->AssertionConsumerService[] = $acs;
$acs = new SAML2_XML_md_IndexedEndpointType();
$acs->index = 2;
$acs->Binding = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact';
$acs->Location = SimpleSAML_Module::getModuleURL('saml/sp/saml2-acs.php/' . $sourceId);
$sp->AssertionConsumerService[] = $acs;
$acs = new SAML2_XML_md_IndexedEndpointType();
$acs->index = 3;
$acs->Binding = 'urn:oasis:names:tc:SAML:1.0:profiles:artifact-01';
$acs->Location = SimpleSAML_Module::getModuleURL('saml/sp/saml1-acs.php/' . $sourceId . '/artifact');
$sp->AssertionConsumerService[] = $acs;
$acs = new SAML2_XML_md_IndexedEndpointType();
$acs->index = 4;
$acs->Binding = 'urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser';
$acs->ProtocolBinding = SAML2_Const::BINDING_HTTP_POST;
$acs->Location = SimpleSAML_Module::getModuleURL('saml/sp/saml2-acs.php/' . $sourceId);
$sp->AssertionConsumerService[] = $acs;
$assertionsconsumerservicesdefault = array(
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
'urn:oasis:names:tc:SAML:1.0:profiles:browser-post',
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact',
'urn:oasis:names:tc:SAML:1.0:profiles:artifact-01',
'urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser',
);
$assertionsconsumerservices = $spconfig->getArray('acs.Bindings', $assertionsconsumerservicesdefault);
$index = 0;
foreach ($assertionsconsumerservices as $services) {
$acs = new SAML2_XML_md_IndexedEndpointType();
$acs->index = $index;
switch ($services) {
case 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST':
$acs->Binding = SAML2_Const::BINDING_HTTP_POST;
$acs->Location = SimpleSAML_Module::getModuleURL('saml/sp/saml2-acs.php/' . $sourceId);
break;
case 'urn:oasis:names:tc:SAML:1.0:profiles:browser-post':
$acs->Binding = 'urn:oasis:names:tc:SAML:1.0:profiles:browser-post';
$acs->Location = SimpleSAML_Module::getModuleURL('saml/sp/saml1-acs.php/' . $sourceId);
break;
case 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact':
$acs->Binding = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact';
$acs->Location = SimpleSAML_Module::getModuleURL('saml/sp/saml2-acs.php/' . $sourceId);
break;
case 'urn:oasis:names:tc:SAML:1.0:profiles:artifact-01':
$acs->Binding = 'urn:oasis:names:tc:SAML:1.0:profiles:artifact-01';
$acs->Location = SimpleSAML_Module::getModuleURL('saml/sp/saml1-acs.php/' . $sourceId . '/artifact');
break;
case 'urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser':
$acs->Binding = 'urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser';
$acs->ProtocolBinding = SAML2_Const::BINDING_HTTP_POST;
$acs->Location = SimpleSAML_Module::getModuleURL('saml/sp/saml2-acs.php/' . $sourceId);
break;
}
$sp->AssertionConsumerService[] = $acs;
$index++;
}
$keys = array();
$certInfo = SimpleSAML_Utilities::loadPublicKey($spconfig, FALSE, 'new_');
......@@ -99,7 +110,6 @@ if ($certInfo !== NULL && array_key_exists('certData', $certInfo)) {
'encryption' => TRUE,
'X509Certificate' => $certInfo['certData'],
);
} else {
$hasNewCert = FALSE;
}
......@@ -124,14 +134,17 @@ if ($certInfo !== NULL && array_key_exists('certData', $certInfo)) {
'encryption' => ($hasNewCert ? FALSE : TRUE),
'X509Certificate' => $certInfo['certData'],
);
} else {
$certData = NULL;
}
$name = $spconfig->getLocalizedString('name', NULL);
$attributes = $spconfig->getArray('attributes', array());
if ($name !== NULL && !empty($attributes)) {
$attributesrequired = $spconfig->getArray('attributes.required', array());
/* We have everything necessary to add an AttributeConsumingService. */
$acs = new SAML2_XML_md_AttributeConsumingService();
$sp->AttributeConsumingService[] = $acs;
......@@ -149,6 +162,10 @@ if ($name !== NULL && !empty($attributes)) {
$a = new SAML2_XML_md_RequestedAttribute();
$a->Name = $attribute;
$a->NameFormat = $nameFormat;
// Is the attribute required
if (in_array($attribute, $attributesrequired))
$a->isRequired = true;
$acs->RequestedAttribute[] = $a;
}
......@@ -163,6 +180,7 @@ if ($name !== NULL && !empty($attributes)) {
}
}
$orgName = $spconfig->getLocalizedString('OrganizationName', NULL);
if ($orgName !== NULL) {
$o = new SAML2_XML_md_Organization();
......@@ -233,5 +251,4 @@ if (array_key_exists('output', $_REQUEST) && $_REQUEST['output'] == 'xhtml') {
header('Content-Type: application/samlmetadata+xml');
echo($xml);
}
?>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment