Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

MDL-18597 Various code improvements, new logout return url config opt…

…ion and better instructions regarding Shibboleth logout
  • Loading branch information...
commit f21a6c674c9c62169c27761ccd6db7948cb742f7 1 parent c7904ac
exe-cutor authored
View
28 auth/shibboleth/README.txt
@@ -2,8 +2,8 @@ Shibboleth Authentication for Moodle
-------------------------------------------------------------------------------
Requirements:
-- Shibboleth target 1.1 or later. See documentation for your Shibboleth
- federation on how to set up Shibboleth.
+- Shibboleth Service Provider 1.3 or newer. Recommended is 2.1 or newer.
+ See documentation for your Shibboleth federation on how to set up Shibboleth.
Changes:
- 11. 2004: Created by Markus Hagman
@@ -23,6 +23,8 @@ Changes:
- 12. 2008: Shibboleth 2.x and Single Logout support added
- 1. 2008: Added logout hook and moved Shibboleth config strings to utf8 auth
language files.
+- 3. 2009: Added various improvements and bug fixes reported by Ina M�ller from
+ university Tuebingen and Peter Ellis of University of Washington
Moodle Configuration with Dual login
-------------------------------------------------------------------------------
@@ -42,7 +44,20 @@ Moodle Configuration with Dual login
with something that fits your needs, e.g. 'require affiliation student'.
For IIS you have protect the auth/shibboleth directory directly in the
- RequestMap of the Shibboleth configuration file (shibboleth.xml). See
+ RequestMap of the Shibboleth configuration file (shibboleth.xml or
+ shibboleth2.xml).
+
+--
+<Path name="moodle" requireSession="false" >
+ <Path name="auth/shibboleth/index.php" requireSession="true" >
+ <AccessControl>
+ ...
+ </AccessControl>
+ </Path>
+</Path>
+--
+
+ Also see:
https://spaces.internet2.edu/display/SHIB2/NativeSPRequestMapper and
https://spaces.internet2.edu/display/SHIB2/NativeSPAccessControl
@@ -274,10 +289,13 @@ Shibboleth installation). If everything worked well, you should see a Shibboleth
page saying that you were successfully logged out and if you go back to Moodle
you also should be logged out from Moodle.
+Requirements:
+- PHP needs the Soap Extension, which maybe must installed manually:
+ More information is available here http://ch.php.net/soap
+- Logout only works with Shibboleth Service Provider 2.1 or higher
Limitations:
-Single Logout is only supported with SAML2 and so far only with the Shibboleth
-Service Provider 2.x.
+Single Logout is only supported when SAML2 is used at the SP and the IdP.
As of December 2008, the Shibboleth Identity Provider 2.1.1 does not yet support
Single Logout (SLO). Therefore, the single logout feature cannot be used yet.
One of the reasons why SLO isn't supported yet is because there aren't many
View
14 auth/shibboleth/auth.php
@@ -196,8 +196,17 @@ function logoutpage_hook() {
isset($this->config->logout_handler)
&& !empty($this->config->logout_handler)
){
- // Backup old redirect url
- $temp_redirect = $redirect;
+ // Check if there is an alternative logout return url defined
+ if (
+ isset($this->config->logout_return_url)
+ && !empty($this->config->logout_return_url)
+ ){
+ // Set temp_redirect to alternative return url
+ $temp_redirect = $this->config->logout_return_url;
+ } else {
+ // Backup old redirect url
+ $temp_redirect = $redirect;
+ }
// Overwrite redirect in order to send user to Shibboleth logout page and let him return back
$redirect = $this->config->logout_handler.'?return='.urlencode($temp_redirect);
@@ -266,6 +275,7 @@ function process_config($config) {
set_config('organization_selection', $config->organization_selection, 'auth/shibboleth');
}
set_config('logout_handler', $config->logout_handler, 'auth/shibboleth');
+ set_config('logout_return_url', $config->logout_return_url, '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');
View
12 auth/shibboleth/config.html
@@ -94,6 +94,18 @@
</tr>
<tr valign="top">
+ <td align="right"><?php print_string("auth_shib_logout_return_url", "auth") ?>:</td>
+ <td>
+ <input name="logout_return_url" type="text" size="30" value="<?php
+ if ( isset($config->logout_return_url) and !empty($config->logout_return_url)){
+ echo $config->logout_return_url;
+ }
+ ?>" />
+ </td>
+ <td><?php print_string("auth_shib_logout_return_url_description", "auth") ?></td>
+</tr>
+
+<tr valign="top">
<td align="right"><?php print_string("auth_shib_auth_method", "auth") ?>:</td>
<td>
<input name="login_name" type="text" size="30" value="<?php
View
294 auth/shibboleth/logout.php
@@ -9,38 +9,47 @@
require_once($CFG->dirroot."/auth/shibboleth/auth.php");
+// Find out whether host supports https
+$protocol = 'http://';
+if ( isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on'){
+ $protocol = 'https://';
+}
+
// Front channel logout
if (
- isset($_GET['return'])
- && isset($_GET['action'])
- && $_GET['action'] == 'logout'
+ isset($_GET['return'])
+ && isset($_GET['action'])
+ && $_GET['action'] == 'logout'
){
-
- // Logout out user from application
- // E.g. destroy application session/cookie etc
- require_logout();
-
- // Finally, send user to the return URL
- redirect($_GET['return']);
+
+ // Logout out user from application
+ // E.g. destroy application session/cookie etc
+ require_logout();
+
+ // Finally, send user to the return URL
+ redirect($_GET['return']);
}
// Back channel logout
elseif (!empty($HTTP_RAW_POST_DATA)) {
-
- // Requires PHP 5
-
- // Set SOAP header
- $server = new SoapServer('https://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'/LogoutNotification.wsdl');
- $server->addFunction("LogoutNotification");
- $server->handle();
+
+ // Requires PHP 5
+
+
+ // Set SOAP header
+ $server = new SoapServer($protocol.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'/LogoutNotification.wsdl');
+
+
+ $server->addFunction("LogoutNotification");
+ $server->handle();
}
// Return WSDL
else {
-
- header('Content-Type: text/xml');
-
- echo <<<WSDL
+
+ header('Content-Type: text/xml');
+
+ echo <<<WSDL
<?xml version ="1.0" encoding ="UTF-8" ?>
<definitions name="LogoutNotification"
targetNamespace="urn:mace:shibboleth:2.0:sp:notify"
@@ -61,144 +70,139 @@
- https://spaces.internet2.edu/display/SHIB2/NativeSPNotify
-->
- <types>
- <schema targetNamespace="urn:mace:shibboleth:2.0:sp:notify"
- xmlns="http://www.w3.org/2000/10/XMLSchema"
- xmlns:notify="urn:mace:shibboleth:2.0:sp:notify">
-
- <simpleType name="string">
- <restriction base="string">
- <minLength value="1"/>
- </restriction>
- </simpleType>
-
- <element name="OK" type="notify:OKType"/>
- <complexType name="OKType">
- <sequence/>
- </complexType>
-
- </schema>
- </types>
-
- <message name="getLogoutNotificationRequest">
- <part name="SessionID" type="notify:string" />
- </message>
-
- <message name="getLogoutNotificationResponse" >
- <part name="OK"/>
- </message>
-
- <portType name="LogoutNotificationPortType">
- <operation name="LogoutNotification">
- <input message="getLogoutNotificationRequest"/>
- <output message="getLogoutNotificationResponse"/>
- </operation>
- </portType>
-
- <binding name="LogoutNotificationBinding" type="notify:LogoutNotificationPortType">
- <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
- <operation name="LogoutNotification">
- <soap:operation soapAction="urn:xmethods-logout-notification#LogoutNotification"/>
- </operation>
- </binding>
-
- <service name="LogoutNotificationService">
- <port name="LogoutNotificationPort" binding="notify:LogoutNotificationBinding">
- <soap:address location="https://{$_SERVER['HTTP_HOST']}{$_SERVER['PHP_SELF']}"/>
- </port>
- </service>
+ <types>
+ <schema targetNamespace="urn:mace:shibboleth:2.0:sp:notify"
+ xmlns="http://www.w3.org/2000/10/XMLSchema"
+ xmlns:notify="urn:mace:shibboleth:2.0:sp:notify">
+
+ <simpleType name="string">
+ <restriction base="string">
+ <minLength value="1"/>
+ </restriction>
+ </simpleType>
+
+ <element name="OK" type="notify:OKType"/>
+ <complexType name="OKType">
+ <sequence/>
+ </complexType>
+
+ </schema>
+ </types>
+
+ <message name="getLogoutNotificationRequest">
+ <part name="SessionID" type="notify:string" />
+ </message>
+
+ <message name="getLogoutNotificationResponse" >
+ <part name="OK"/>
+ </message>
+
+ <portType name="LogoutNotificationPortType">
+ <operation name="LogoutNotification">
+ <input message="getLogoutNotificationRequest"/>
+ <output message="getLogoutNotificationResponse"/>
+ </operation>
+ </portType>
+
+ <binding name="LogoutNotificationBinding" type="notify:LogoutNotificationPortType">
+ <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
+ <operation name="LogoutNotification">
+ <soap:operation soapAction="urn:xmethods-logout-notification#LogoutNotification"/>
+ </operation>
+ </binding>
+
+ <service name="LogoutNotificationService">
+ <port name="LogoutNotificationPort" binding="notify:LogoutNotificationBinding">
+ <soap:address location="{$protocol}{$_SERVER['HTTP_HOST']}{$_SERVER['PHP_SELF']}"/>
+ </port>
+ </service>
</definitions>
WSDL;
- exit;
+ exit;
}
/******************************************************************************/
function LogoutNotification($SessionID){
-
- global $CFG, $SESSION;
-
- // Delete session of user using $SessionID
- if(empty($CFG->dbsessions)) {
-
- // File session
- $dir = $CFG->dataroot .'/sessions';
- if (is_dir($dir)) {
- if ($dh = opendir($dir)) {
- while (($file = readdir($dh)) !== false) {
- //echo $dir.'/'.$file."\n";exit;
- if (is_file($dir.'/'.$file)){
- $session_key = ereg_replace('sess_', '', $file);
-
- $data = file($dir.'/'.$file);
- if (isset($data[0])){
- $user_session = unserializesession($data[0]);
-
- if (isset($user_session['SESSION']) && isset($user_session['SESSION']->shibboleth_session_id)){
- //echo '2. Shibboleth Session (from filesystem session) of '.$user_session['USER']->username.':' .$user_session['SESSION']->shibboleth_session_id."\n";
- // If there is a match, delete file
- if ($user_session['SESSION']->shibboleth_session_id == $SessionID){
- // Delete this file
- if (!unlink($dir.'/'.$file)){
- return new SoapFault('LogoutError', 'Could not delete Moodle session file.');
- }
- }
- }
- //print_r($user_session);
- }
-
- //echo "Moodle session: $session_key \n";
- //echo "filename: $file \n";
- }
- }
- closedir($dh);
- }
- }
- } else {
- // DB Session
- if (!empty($CFG->sessiontimeout)) {
- $ADODB_SESS_LIFE = $CFG->sessiontimeout;
- }
-
- if ($user_session_data = get_records_sql('SELECT sesskey, sessdata FROM '. $CFG->prefix .'sessions2 WHERE expiry > NOW()')) {
- foreach ($user_session_data as $session_data) {
-
- //print_r($session_data);
- $user_session = adodb_unserialize( urldecode($session_data->sessdata) );
-
- if (isset($user_session['SESSION']) && isset($user_session['SESSION']->shibboleth_session_id)){
- //echo '3. Shibboleth Session (from ADODB session) of '.$user_session['USER']->username.':' .$user_session['SESSION']->shibboleth_session_id."\n";
-
- // If there is a match, delete file
- if ($user_session['SESSION']->shibboleth_session_id == $SessionID){
- // Delete this session entry
- if (ADODB_Session::destroy($session_data->sesskey) !== true){
- return new SoapFault('LogoutError', 'Could not delete Moodle session entry in database.');
- }
- }
- }
-
- //print_r($user_session);
- }
- }
- }
-
- // If now SoapFault was thrown the function will return OK as the SP assumes
-
+
+ global $CFG, $SESSION;
+
+ // Delete session of user using $SessionID
+ if(empty($CFG->dbsessions)) {
+
+ // File session
+ $dir = $CFG->dataroot .'/sessions';
+ if (is_dir($dir)) {
+ if ($dh = opendir($dir)) {
+ // Read all session files
+ while (($file = readdir($dh)) !== false) {
+ // Check if it is a file
+ if (is_file($dir.'/'.$file)){
+ $session_key = ereg_replace('sess_', '', $file);
+
+ // Read session file data
+ $data = file($dir.'/'.$file);
+ if (isset($data[0])){
+ $user_session = unserializesession($data[0]);
+
+ // Check if we have found session that shall be deleted
+ if (isset($user_session['SESSION']) && isset($user_session['SESSION']->shibboleth_session_id)){
+
+ // If there is a match, delete file
+ if ($user_session['SESSION']->shibboleth_session_id == $SessionID){
+ // Delete session file
+ if (!unlink($dir.'/'.$file)){
+ return new SoapFault('LogoutError', 'Could not delete Moodle session file.');
+ }
+ }
+ }
+ }
+ }
+ }
+ closedir($dh);
+ }
+ }
+ } else {
+ // DB Session
+ if (!empty($CFG->sessiontimeout)) {
+ $ADODB_SESS_LIFE = $CFG->sessiontimeout;
+ }
+
+ if ($user_session_data = get_records_sql('SELECT sesskey, sessdata FROM '. $CFG->prefix .'sessions2 WHERE expiry > NOW()')) {
+ foreach ($user_session_data as $session_data) {
+
+ // Get user session
+ $user_session = adodb_unserialize( urldecode($session_data->sessdata) );
+
+ if (isset($user_session['SESSION']) && isset($user_session['SESSION']->shibboleth_session_id)){
+
+ // If there is a match, delete file
+ if ($user_session['SESSION']->shibboleth_session_id == $SessionID){
+ // Delete this session entry
+ if (ADODB_Session::destroy($session_data->sesskey) !== true){
+ return new SoapFault('LogoutError', 'Could not delete Moodle session entry in database.');
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // If now SoapFault was thrown the function will return OK as the SP assumes
+
}
/*****************************************************************************/
// Same function as in adodb, but cannot be used for file session for some reason...
function unserializesession( $serialized_string ){
- $variables = array( );
- $a = preg_split( "/(\w+)\|/", $serialized_string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE );
- for( $i = 0; $i < count( $a ); $i = $i+2 ) {
- $variables[$a[$i]] = unserialize( $a[$i+1] );
- }
- return( $variables );
+ $variables = array( );
+ $a = preg_split( "/(\w+)\|/", $serialized_string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE );
+ for( $i = 0; $i < count( $a ); $i = $i+2 ) {
+ $variables[$a[$i]] = unserialize( $a[$i+1] );
+ }
+ return( $variables );
}
-
?>
Please sign in to comment.
Something went wrong with that request. Please try again.