From: exe-cutor <exe-cutor> Date: Fri, 1 Feb 2008 12:45:24 +0000 (+0000) Subject: Merged Shibboleth integrated WAYF service from 18_STABLE X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=eefd788bdc6e1d95855c9c1eff9bfcf20505d301;p=moodle.git Merged Shibboleth integrated WAYF service from 18_STABLE --- diff --git a/auth/shibboleth/README.txt b/auth/shibboleth/README.txt index 815bc6919a..2c88215367 100644 --- a/auth/shibboleth/README.txt +++ b/auth/shibboleth/README.txt @@ -19,15 +19,16 @@ Changes: - 07. 2007: Fixed a but that caused problems with uppercase usernames - 10. 2007: Removed the requirement for email address, surname and given name attributes on request of Markus Hagman +- 11. 2007: Integrated WAYF Service in Moodle Moodle Configuration with Dual login ------------------------------------------------------------------------------- -1. Protect the directory moodle/auth/shibboleth/ with Shibboleth. +1. Protect the directory moodle/auth/shibboleth/index.php with Shibboleth. The page index.php in that directory actually logs in a Shibboleth user. For Apache you have to define a rule like the following in the Apache config: -- -<Location ~ "/auth/shibboleth"> +<Location ~ "/auth/shibboleth/index.php"> AuthType shibboleth ShibRequireSession On require valid-user @@ -46,7 +47,7 @@ Moodle Configuration with Dual login Options' and click on the the 'Shibboleth' settings. 3. Fill in the fields of the form. The fields 'Username', 'First name', - 'Surname', etc should contain the name of the environment variables of the + 'Surname', etc. should contain the name of the environment variables of the Shibboleth attributes that you want to map onto the corresponding Moodle variable (e.g. 'HTTP_SHIB_PERSON_SURNAME' for the person's last name, refer the Shibboleth documentation or the documentation of your Shibboleth @@ -56,20 +57,36 @@ Moodle Configuration with Dual login ############################################################################# Shibboleth Attributes needed by Moodle: - For Moodle to work properly Shibboleth should at least provide the attributes - that are used as username, firstname, lastname and email in Moodle. - The attribute used for the username has to be unique for all Shibboleth user. - All attributes must obey a certain length, otherwise Moodle cuts off the - ends. Consult the Moodle documentation for further information on the maximum - lengths for each field in the user profile. + For Moodle to work properly Shibboleth should at least provide the attribute + that is used as usernam in Moodle. It has to be unique for all Shibboleth + users. + All attributes used for moodle must obey a certain length, otherwise Moodle + cuts off the ends. Consult the Moodle documentation for further information + on the maximum lengths for each field in the user profile. ############################################################################# 4. Save the changes for the 'Shibboleth settings'. -5.a If you want Shibboleth as your only authentication method, set the - 'Alternate Login URL' in the 'Common settings' in - 'Administrations >> Users >> Authentication Options' to the the URL of the - file 'moodle/auth/shibboleth/index.php'. This will enforce Shibboleth login. +5.a If you want Shibboleth as your only authentication method with an external + Where Are You From (WAYF) Service , set the 'Alternate Login URL' in the + 'Common settings' in 'Administrations >> Users >> Authentication Options' + to the the URL of the file 'moodle/auth/shibboleth/index.php'. + This will enforce Shibboleth login. + +5.b If you want to use the Moodle internal WAYF service, you have to activate it + in the Moodle Shibboleth authentication settings by checking the + 'Moodle WAYF Service' checkbox and providing a list of entity IDs in the + 'Identity Providers' textarea together with a name and an optional + SessionInitiator URL, which usually is an absolute or relative URL pointing + to the same host. If no SessionInitiator URL is given, the default one + '/Shibboleth.sso' will be used. + Also see https://spaces.internet2.edu/display/SHIB/SessionInitiator + + Important Note: If you upgraded from a previous version of Moodle and now + want to use the integrated WAYF, you have to make sure that + in step 1 only the index.php script in + moodle/auth/shibboleth/ is protected but *not* the other + scripts and especially not the login.php script. 6.b If you want to use another authentication method together with Shibboleth, in parallel, change the 'Instructions' in the 'Common settings' of the @@ -110,11 +127,11 @@ authentication method unless they have two accounts in Moodle. Shibboleth dual login with custom login page -------------------------------------------------------------------------------- -Of course you can create a dual login page that better fits your needs. For this -to work, you have to set up the two authentication methods (e.g. 'Manual' and -'Shibboleth') and specify an alternate login link to your own dual login page. -On that page you basically need a link to the Shibboleth-protected page -('/auth/shibboleth/index.php') for the Shibboleth login and a +You can create a dual login page that better fits your needs. For this +to work, you have to set up the two authentication methods (e.g. 'Manual +Accounts' and 'Shibboleth') and specify an alternate login link to your own dual +login page. On that page you basically need a link to the Shibboleth-protected +page ('/auth/shibboleth/index.php') for the Shibboleth login and a form that sends 'username' and 'password' to moodle/login/index.php. Consult the Moodle documentation for further instructions and requirements. diff --git a/auth/shibboleth/auth.php b/auth/shibboleth/auth.php index fab06b7d99..05c69a2b31 100644 --- a/auth/shibboleth/auth.php +++ b/auth/shibboleth/auth.php @@ -19,6 +19,8 @@ * 2006-10-27 Upstream 1.7 changes merged in, added above credits from lib.php :-) * 2007-03-09 Fixed authentication but may need some other changes * 2007-10-03 Removed requirement for email address, surname and given name on request of Markus Hagman + * 2008-01-21 Added WAYF functionality + */ if (!defined('MOODLE_INTERNAL')) { @@ -113,8 +115,10 @@ class auth_plugin_shibboleth extends auth_plugin_base { return $result; } - /* + /** * Returns array containg attribute mappings between Moodle and Shibboleth. + * + * @return array */ function get_attributes() { $configarray = (array) $this->config; @@ -153,6 +157,10 @@ class auth_plugin_shibboleth extends auth_plugin_base { return false; } + /** + * Hook for login page + * + */ function loginpage_hook() { global $SESSION, $CFG; @@ -193,21 +201,58 @@ class auth_plugin_shibboleth extends auth_plugin_base { if (!isset ($config->convert_data)) { $config->convert_data = ''; } + if (!isset($config->changepasswordurl)) { $config->changepasswordurl = ''; } + + if (!isset($config->login_name)) { + $config->login_name = 'Shibboleth Login'; + } + + // Clean idp list + if (isset($config->organization_selection) && !empty($config->organization_selection) && isset($config->alt_login) && $config->alt_login == 'on') { + $idp_list = get_idp_list($config->organization_selection); + if (count($idp_list) < 1){ + return false; + } + $config->organization_selection = ''; + foreach ($idp_list as $idp => $value){ + $config->organization_selection .= $idp.', '.$value[0].', '.$value[1]."\n"; + } + } + // save settings set_config('user_attribute', $config->user_attribute, 'auth/shibboleth'); + + if (isset($config->organization_selection) && !empty($config->organization_selection)) { + set_config('organization_selection', $config->organization_selection, 'auth/shibboleth'); + } + set_config('login_name', $config->login_name, 'auth/shibboleth'); set_config('convert_data', $config->convert_data, 'auth/shibboleth'); set_config('auth_instructions', $config->auth_instructions, 'auth/shibboleth'); set_config('changepasswordurl', $config->changepasswordurl, 'auth/shibboleth'); - + + if (isset($config->alt_login) && $config->alt_login == 'on'){ + set_config('alt_login', $config->alt_login, 'auth/shibboleth'); + set_config('alternateloginurl', $CFG->wwwroot.'/auth/shibboleth/login.php'); + } else { + set_config('alt_login', 'off', 'auth/shibboleth'); + set_config('alternateloginurl', ''); + $config->alt_login = 'off'; + } + // Check values and return false if something is wrong // Patch Anyware Technologies (14/05/07) if (($config->convert_data != '')&&(!file_exists($config->convert_data) || !is_readable($config->convert_data))){ return false; } + + // Check if there is at least one entry in the IdP list + if (isset($config->organization_selection) && empty($config->organization_selection) && isset($config->alt_login) && $config->alt_login == 'on'){ + return false; + } return true; } @@ -225,4 +270,126 @@ class auth_plugin_shibboleth extends auth_plugin_base { } } + + /** + * Sets the standard SAML domain cookie that is also used to preselect + * the right entry on the local wayf + * + * @param IdP identifiere + */ + function set_saml_cookie($selectedIDP) { + if (isset($_COOKIE['_saml_idp'])) + { + $IDPArray = generate_cookie_array($_COOKIE['_saml_idp']); + } + else + { + $IDPArray = array(); + } + $IDPArray = appendCookieValue($selectedIDP, $IDPArray); + setcookie ('_saml_idp', generate_cookie_value($IDPArray), time() + (100*24*3600)); + } + + /** + * Prints the option elements for the select element of the drop down list + * + */ + function print_idp_list(){ + $config = get_config('auth/shibboleth'); + + $IdPs = get_idp_list($config->organization_selection); + if (isset($_COOKIE['_saml_idp'])){ + $idp_cookie = generate_cookie_array($_COOKIE['_saml_idp']); + do { + $selectedIdP = array_pop($idp_cookie); + } while (!isset($IdPs[$selectedIdP]) && count($idp_cookie) > 0); + + } else { + $selectedIdP = '-'; + } + + foreach($IdPs as $IdP => $data){ + if ($IdP == $selectedIdP){ + echo '<option value="'.$IdP.'" selected="selected">'.$data[0].'</option>'; + } else { + echo '<option value="'.$IdP.'">'.$data[0].'</option>'; + } + } + } + + + /** + * Generate array of IdPs from Moodle Shibboleth settings + * + * @param string Text containing tuble/triple of IdP entityId, name and (optionally) session initiator + * @return array Identifier of IdPs and their name/session initiator + */ + + function get_idp_list($organization_selection) { + $idp_list = array(); + + $idp_raw_list = split("\n", $organization_selection); + + foreach ($idp_raw_list as $idp_line){ + $idp_data = split(',', $idp_line); + if (isset($idp_data[2])) + { + $idp_list[trim($idp_data[0])] = array(trim($idp_data[1]),trim($idp_data[2])); + } + elseif(isset($idp_data[1])) + { + $idp_list[trim($idp_data[0])] = array(trim($idp_data[1])); + } + } + + return $idp_list; + } + + /** + * Generates an array of IDPs using the cookie value + * + * @param string Value of SAML domain cookie + * @return array Identifiers of IdPs + */ + function generate_cookie_array($value) { + + // Decodes and splits cookie value + $CookieArray = split(' ', $value); + $CookieArray = array_map('base64_decode', $CookieArray); + + return $CookieArray; + } + + /** + * Generate the value that is stored in the cookie using the list of IDPs + * + * @param array IdP identifiers + * @return string SAML domain cookie value + */ + function generate_cookie_value($CookieArray) { + + // Merges cookie content and encodes it + $CookieArray = array_map('base64_encode', $CookieArray); + $value = implode(' ', $CookieArray); + return $value; + } + + /** + * Append a value to the array of IDPs + * + * @param string IdP identifier + * @param array IdP identifiers + * @return array IdP identifiers with appended IdP + */ + function appendCookieValue($value, $CookieArray) { + + array_push($CookieArray, $value); + $CookieArray = array_reverse($CookieArray); + $CookieArray = array_unique($CookieArray); + $CookieArray = array_reverse($CookieArray); + + return $CookieArray; + } + + ?> diff --git a/auth/shibboleth/config.html b/auth/shibboleth/config.html index 073666b757..115327599f 100755 --- a/auth/shibboleth/config.html +++ b/auth/shibboleth/config.html @@ -27,45 +27,75 @@ <td><?php print_string("auth_shib_username_description", "auth") ?></td> </tr> -<!-- -This is kind of obsolete because the login instructions are now centralized -On the other hand it would be great for Shibboleth to have seperate login -instructions ---> -<!-- <tr valign="top"> - <td align="right"><?php print_string("instructions", "auth") ?>:</td> - <td> - <textarea name="auth_instructions" cols="30" rows="10" wrap="virtual"><?php p($config->auth_instructions) ?></textarea> - </td> + <td align="right"><?php print_string("auth_shib_convert_data", "auth") ?>:</td> <td> + <input name="convert_data" type="text" size="30" value="<?php echo $config->convert_data?>" /> <?php - - print_string("auth_shib_instructions_help", "auth", htmlspecialchars($CFG->wwwroot.'/auth/shibboleth/index.php')); - helpbutton("text", get_string("helptext")); + + if ($config->convert_data and $config->convert_data != '' and !is_readable($config->convert_data)) { + echo '<br/><font color="red">'; + print_string("auth_shib_convert_data_warning", "auth"); + echo '</font>'; + } ?> </td> + <td><?php print_string("auth_shib_convert_data_description", "auth"); echo $config->alt_login ?></td> </tr> ---> <tr valign="top"> - <td align="right"><?php print_string("auth_shib_convert_data", "auth") ?>:</td> + <td align="right">Moodle WAYF Service:</td> <td> - <input name="convert_data" type="text" size="30" value="<?php echo $config->convert_data?>" /> - <?php + <input name="alt_login" type="checkbox" <?php + if ( isset($config->alt_login) and $config->alt_login == 'on' ){ + echo 'checked="checked"'; + } + ?> /> + </td> + <td>If you check this, Moodle will use its own WAYF service instead of the one configured for Shibboleth. Moodle will display a drop-down list on this alternative login page where the user has to select his Identity Provider.</td> +</tr> - if ($config->convert_data and $config->convert_data != '' and !is_readable($config->convert_data)) { +<tr valign="top"> + <td align="right">Identity Providers:</td> + <td> + <textarea name="organization_selection" rows="10" cols="30" style="overflow: auto;" wrap="off" +><?php + if (!isset($config->organization_selection)){ + echo 'urn:mace:organization1:providerID, Example Organization 1 +https://another.idp-id.com/shibboleth, Other Example Organization +urn:mace:organization2:providerID, Example Organization 2, /Shibboleth.sso/WAYF/SWITCHaai'; + } else { + echo $config->organization_selection; + } + ?> +</textarea> + <? + if (isset($config->organization_selection) && empty($config->organization_selection) && isset($config->alt_login) && $config->alt_login == 'on') { echo '<br/><font color="red">'; - print_string("auth_shib_convert_data_warning", "auth"); + print_string("auth_shib_no_organizations_warning", "auth"); echo '</font>'; } - - ?> + ?> </td> - <td><?php print_string("auth_shib_convert_data_description", "auth") ?></td> + <td>Provide a list of Identity Provider entityIDs to let the user choose from on the login page. +On each line there must be a comma-separated tuple for entityID of the IdP (see the Shibboleth metadata file) and Name of IdP as it shall be displayed in the drow-down list. +As an optional third parameter you can add the location of a Shibboleth session initiator that shall be used in case your Moodle installation is part of a multi federation setup.</td> </tr> +<tr valign="top"> + <td align="right">Authentication Method Name:</td> + <td> + <input name="login_name" type="text" size="30" value="<?php + if ( isset($config->login_name) and !empty($config->login_name)){ + echo $config->login_name; + } else { + echo 'Shibboleth Login'; + } + ?>" /> + </td> + <td>Provide a name for the Shibboleth authentication method that is familiar to your users. This could be the name of your Shibboleth federation, e.g. "SWITCHaai Login" or "InCommon Login" and so on.</td> +</tr> <tr valign="top"> <td align="right"><?php print_string('auth_shib_changepasswordurl', 'auth') ?>: </td> @@ -82,6 +112,8 @@ instructions <td><?php print_string('changepasswordhelp', 'auth') ?></td> </tr> + + <?php print_auth_lock_options('shibboleth', $user_fields, '<!-- empty help -->', true, false);