]> git.mjollnir.org Git - moodle.git/commitdiff
Merged Shibboleth integrated WAYF service from 18_STABLE
authorexe-cutor <exe-cutor>
Fri, 1 Feb 2008 12:45:24 +0000 (12:45 +0000)
committerexe-cutor <exe-cutor>
Fri, 1 Feb 2008 12:45:24 +0000 (12:45 +0000)
auth/shibboleth/README.txt
auth/shibboleth/auth.php
auth/shibboleth/config.html

index 815bc6919a9b7d8af7d6d929dd4a427874b0d68b..2c88215367a4ce3b00973b6cfd8c05645df09ad3 100644 (file)
@@ -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.
 
index fab06b7d99c7e2a264f846f9baeaf03b7b0dbac5..05c69a2b312b8650ffc545b46bc38fe9f3d17c36 100644 (file)
@@ -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;
+    }
+
+
 ?>
index 073666b757ea8d93c3e8c5435f29205224dcfdca..115327599fd9a4351a2e0515b00a39ae20007246 100755 (executable)
     <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);