mirrored from git://git.moodle.org/moodle.git
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Merged Shibboleth logout support from 1.9 stable
- Loading branch information
exe-cutor
committed
Dec 4, 2008
1 parent
636bbc8
commit 2db6ec1
Showing
3 changed files
with
270 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
<?php // $Id$ | ||
|
||
// Implements logout for Shibboleth authenticated users according to: | ||
// - https://spaces.internet2.edu/display/SHIB2/NativeSPLogoutInitiator | ||
// - https://spaces.internet2.edu/display/SHIB2/NativeSPNotify | ||
|
||
require_once("../../config.php"); | ||
|
||
require_once($CFG->dirroot."/auth/shibboleth/auth.php"); | ||
|
||
|
||
// Front channel logout | ||
if ( | ||
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']); | ||
} | ||
|
||
// 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(); | ||
} | ||
|
||
// Return WSDL | ||
else { | ||
|
||
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" | ||
xmlns:notify="urn:mace:shibboleth:2.0:sp:notify" | ||
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" | ||
xmlns="http://schemas.xmlsoap.org/wsdl/"> | ||
<!-- | ||
This page either has to be called with the GET arguments 'action' and 'return' via | ||
a redirect from the Shibboleth Service Provider logout handler (front-channel | ||
logout) or via a SOAP request by a Shibboleth Service Provider (back-channel | ||
logout). | ||
Because neither of these two variants seems to be the case, the WSDL file for | ||
the web service is returned. | ||
For more information see: | ||
- https://spaces.internet2.edu/display/SHIB2/NativeSPLogoutInitiator | ||
- 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> | ||
</definitions> | ||
WSDL; | ||
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 | ||
|
||
} | ||
|
||
/*****************************************************************************/ | ||
|
||
// 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 ); | ||
} | ||
|
||
|
||
?> |