diff --git a/idp/metadata.php b/idp/metadata.php index cf91b7644..d04662604 100644 --- a/idp/metadata.php +++ b/idp/metadata.php @@ -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 = << - - - - {$cert} - - - -urn:oasis:names:tc:SAML:2.0:nameid-format:persistent - - - -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); \ No newline at end of file + $xml = << + + + + {$cert} + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:persistent + + + + EOF; + + header('Content-Type: text/xml'); + echo($xml); +} else { + throw new saml2_exception('idp_enabled_error', get_string('moodleidpenabled_error', 'auth_saml2')); +} diff --git a/idp/sso.php b/idp/sso.php index 3fa221207..bdd0cb4c2 100644 --- a/idp/sso.php +++ b/idp/sso.php @@ -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. @@ -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')); diff --git a/lang/en/auth_saml2.php b/lang/en/auth_saml2.php index a345c27dd..c677a6d68 100644 --- a/lang/en/auth_saml2.php +++ b/lang/en/auth_saml2.php @@ -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'] = 'View Identity Provider Metadata | Download IDP Metadata'; +$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 saml:Issuer 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'; diff --git a/settings.php b/settings.php index f26039875..3d30952c2 100644 --- a/settings.php +++ b/settings.php @@ -444,4 +444,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' => "
+https://www.someothermoodle.com/auth/saml2/sp/metadata.php
+
"]), + '', + PARAM_TEXT)); }