Skip to content

Commit

Permalink
Adds IDP settings
Browse files Browse the repository at this point in the history
* en/disable moodle as an IDP.
* Whitelist services by their <saml:Issuer>
  • Loading branch information
mark-webster-catalyst committed Nov 13, 2024
1 parent da2d734 commit b4cc8bc
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 23 deletions.
51 changes: 30 additions & 21 deletions idp/metadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,35 @@

$saml2auth = new \auth_saml2\auth();

$cert = file_get_contents($saml2auth->certcrt);
$cert = preg_replace('~(-----(BEGIN|END) CERTIFICATE-----)|\n~', '', $cert);
$baseurl = $CFG->wwwroot . '/auth/saml2/idp';
if ($saml2auth->config->moodleidpenabled) {
$download = optional_param('download', '', PARAM_RAW);
if ($download) {
header('Content-Disposition: attachment; filename=' . $saml2auth->spname . '.xml');
}

$xml = <<<EOF
<md:EntityDescriptor entityID="{$baseurl}/metadata.php" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata">
<md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol" WantAuthnRequestsSigned="false">
<md:KeyDescriptor>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<X509Data><X509Certificate>{$cert}</X509Certificate></X509Data>
</KeyInfo>
</md:KeyDescriptor>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="{$baseurl}/slo.php" />
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="{$baseurl}/sso.php" />
</md:IDPSSODescriptor>
</md:EntityDescriptor>
EOF;
$cert = file_get_contents($saml2auth->certcrt);
$cert = preg_replace('~(-----(BEGIN|END) CERTIFICATE-----)|\n~', '', $cert);
$baseurl = $CFG->wwwroot . '/auth/saml2/idp';

header('Content-Type: text/xml');
echo($xml);
$xml = <<<EOF
<md:EntityDescriptor entityID="{$baseurl}/metadata.php" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata">
<md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol" WantAuthnRequestsSigned="false">
<md:KeyDescriptor>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<X509Data><X509Certificate>{$cert}</X509Certificate></X509Data>
</KeyInfo>
</md:KeyDescriptor>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="{$baseurl}/slo.php" />
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="{$baseurl}/sso.php" />
</md:IDPSSODescriptor>
</md:EntityDescriptor>
EOF;

header('Content-Type: text/xml');
echo($xml);
} else {
throw new saml2_exception('idp_enabled_error', get_string('moodleidpenabled_error', 'auth_saml2'));
}
17 changes: 15 additions & 2 deletions idp/sso.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@

if (isguestuser()) {
// Guest user not allowed here.
// TODO: add exception.
die;
throw new saml2_exception('guest_error', get_string('moodleidpguest_error', 'auth_saml2'));
}

// Get the request data.
Expand All @@ -55,6 +54,20 @@
$destination = htmlspecialchars($xpath->evaluate('normalize-space(/*/@AssertionConsumerServiceURL)'));
$sp = $xpath->evaluate('normalize-space(/*/*[local-name() = "Issuer"])');

// Confirm we know about this SP.
$knownsps = [];
foreach (explode(PHP_EOL, $saml2auth->config->moodleidpsplist) as $ksp) {
$ksp = trim($ksp);
if (empty($ksp)) {
continue;
}
$knownsps[] = $ksp;
}

if (!in_array($sp, $knownsps)) {
throw new saml2_exception('unknown_sp_error', get_string('moodleidpsplist_error', 'auth_saml2', $sp));
}

// Get time in UTC.
$datetime = new DateTime();
$datetime->setTimezone(new DatetimeZone('UTC'));
Expand Down
11 changes: 11 additions & 0 deletions lang/en/auth_saml2.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,17 @@
$string['metadatafetchfailed'] = 'Metadata fetch failed: {$a}';
$string['metadatafetchfailedstatus'] = 'Metadata fetch failed: Status code {$a}';
$string['metadatafetchfailedunknown'] = 'Metadata fetch failed: Unknown cURL error';
$string['moodleidpdescription'] = 'Settings for Moodle as an Identity Provider for other services.';
$string['moodleidpenabled'] = 'Enable IDP';
$string['moodleidpenabled_error'] = 'Moodle IDP is not enabled. Check Settings.';
$string['moodleidpenabled_help'] = 'Allow Moodle to act as an IDP for external services.';
$string['moodleidpguest_error'] = 'Guest users cannot log in via SAML.';
$string['moodleidpheading'] = 'Moodle IDP Settings';
$string['moodleidpmetadata'] = 'IDP Metadata';
$string['moodleidpmetadata_help'] = '<a href=\'{$a}\'>View Identity Provider Metadata</a> | <a href=\'{$a}?download=1\'>Download IDP Metadata</a>';
$string['moodleidpsplist'] = 'Valid Issuers';
$string['moodleidpsplist_error'] = 'Unknown service attempting to authenticate: {$a}. Check config.';
$string['moodleidpsplist_help'] = 'List of services allowed to use this moodle as an IDP identified by the <code>saml:Issuer</code> tag in the SAML request. One per line. {$a->example}';
$string['multiidp:label:displayname'] = 'Display name';
$string['multiidp:label:alias'] = 'Alias';
$string['multiidp:label:active'] = 'Active';
Expand Down
28 changes: 28 additions & 0 deletions settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -427,4 +427,32 @@
',',
PARAM_TEXT,
5));

// Moodle as an IDP feature setting section.
$settings->add(new admin_setting_heading('auth_saml2/moodleidpheading', get_string('moodleidpheading', 'auth_saml2'),
new lang_string('moodleidpdescription', 'auth_saml2')));

// Enable Moodle IDP.
$settings->add(new admin_setting_configselect(
'auth_saml2/moodleidpenabled',
get_string('moodleidpenabled', 'auth_saml2'),
get_string('moodleidpenabled_help', 'auth_saml2'),
0, $yesno));

// IDP Metadata.
$settings->add(new setting_textonly(
'auth_saml2/moodleidpmetadata',
get_string('moodleidpmetadata', 'auth_saml2'),
get_string('moodleidpmetadata_help', 'auth_saml2', $CFG->wwwroot . '/auth/saml2/idp/metadata.php')
));

// List valid SPs.
$settings->add(new admin_setting_configtextarea(
'auth_saml2/moodleidpsplist',
get_string('moodleidpsplist', 'auth_saml2'),
get_string('moodleidpsplist_help', 'auth_saml2', ['example' => "<pre>
https://www.someothermoodle.com/auth/saml2/sp/metadata.php
</pre>"]),
'',
PARAM_TEXT));
}

0 comments on commit b4cc8bc

Please sign in to comment.