9
9
require_once($CFG->dirroot."/auth/shibboleth/auth.php");
12
// Find out whether host supports https
13
$protocol = 'http://';
14
if ( isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on'){
15
$protocol = 'https://';
12
18
// Front channel logout
14
isset($_GET['return'])
15
&& isset($_GET['action'])
16
&& $_GET['action'] == 'logout'
20
isset($_GET['return'])
21
&& isset($_GET['action'])
22
&& $_GET['action'] == 'logout'
19
// Logout out user from application
20
// E.g. destroy application session/cookie etc
23
// Finally, send user to the return URL
24
redirect($_GET['return']);
25
// Logout out user from application
26
// E.g. destroy application session/cookie etc
29
// Finally, send user to the return URL
30
redirect($_GET['return']);
27
33
// Back channel logout
28
34
elseif (!empty($HTTP_RAW_POST_DATA)) {
33
$server = new SoapServer('https://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'/LogoutNotification.wsdl');
34
$server->addFunction("LogoutNotification");
40
$server = new SoapServer($protocol.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'/LogoutNotification.wsdl');
43
$server->addFunction("LogoutNotification");
41
header('Content-Type: text/xml');
50
header('Content-Type: text/xml');
44
53
<?xml version ="1.0" encoding ="UTF-8" ?>
45
54
<definitions name="LogoutNotification"
46
55
targetNamespace="urn:mace:shibboleth:2.0:sp:notify"
61
70
- https://spaces.internet2.edu/display/SHIB2/NativeSPNotify
65
<schema targetNamespace="urn:mace:shibboleth:2.0:sp:notify"
66
xmlns="http://www.w3.org/2000/10/XMLSchema"
67
xmlns:notify="urn:mace:shibboleth:2.0:sp:notify">
69
<simpleType name="string">
70
<restriction base="string">
71
<minLength value="1"/>
75
<element name="OK" type="notify:OKType"/>
76
<complexType name="OKType">
83
<message name="getLogoutNotificationRequest">
84
<part name="SessionID" type="notify:string" />
87
<message name="getLogoutNotificationResponse" >
91
<portType name="LogoutNotificationPortType">
92
<operation name="LogoutNotification">
93
<input message="getLogoutNotificationRequest"/>
94
<output message="getLogoutNotificationResponse"/>
98
<binding name="LogoutNotificationBinding" type="notify:LogoutNotificationPortType">
99
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
100
<operation name="LogoutNotification">
101
<soap:operation soapAction="urn:xmethods-logout-notification#LogoutNotification"/>
105
<service name="LogoutNotificationService">
106
<port name="LogoutNotificationPort" binding="notify:LogoutNotificationBinding">
107
<soap:address location="https://{$_SERVER['HTTP_HOST']}{$_SERVER['PHP_SELF']}"/>
74
<schema targetNamespace="urn:mace:shibboleth:2.0:sp:notify"
75
xmlns="http://www.w3.org/2000/10/XMLSchema"
76
xmlns:notify="urn:mace:shibboleth:2.0:sp:notify">
78
<simpleType name="string">
79
<restriction base="string">
80
<minLength value="1"/>
84
<element name="OK" type="notify:OKType"/>
85
<complexType name="OKType">
92
<message name="getLogoutNotificationRequest">
93
<part name="SessionID" type="notify:string" />
96
<message name="getLogoutNotificationResponse" >
100
<portType name="LogoutNotificationPortType">
101
<operation name="LogoutNotification">
102
<input message="getLogoutNotificationRequest"/>
103
<output message="getLogoutNotificationResponse"/>
107
<binding name="LogoutNotificationBinding" type="notify:LogoutNotificationPortType">
108
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
109
<operation name="LogoutNotification">
110
<soap:operation soapAction="urn:xmethods-logout-notification#LogoutNotification"/>
114
<service name="LogoutNotificationService">
115
<port name="LogoutNotificationPort" binding="notify:LogoutNotificationBinding">
116
<soap:address location="{$protocol}{$_SERVER['HTTP_HOST']}{$_SERVER['PHP_SELF']}"/>
116
125
/******************************************************************************/
118
127
function LogoutNotification($SessionID){
120
global $CFG, $SESSION;
122
// Delete session of user using $SessionID
123
if(empty($CFG->dbsessions)) {
126
$dir = $CFG->dataroot .'/sessions';
128
if ($dh = opendir($dir)) {
129
while (($file = readdir($dh)) !== false) {
130
//echo $dir.'/'.$file."\n";exit;
131
if (is_file($dir.'/'.$file)){
132
$session_key = ereg_replace('sess_', '', $file);
134
$data = file($dir.'/'.$file);
135
if (isset($data[0])){
136
$user_session = unserializesession($data[0]);
138
if (isset($user_session['SESSION']) && isset($user_session['SESSION']->shibboleth_session_id)){
139
//echo '2. Shibboleth Session (from filesystem session) of '.$user_session['USER']->username.':' .$user_session['SESSION']->shibboleth_session_id."\n";
140
// If there is a match, delete file
141
if ($user_session['SESSION']->shibboleth_session_id == $SessionID){
143
if (!unlink($dir.'/'.$file)){
144
return new SoapFault('LogoutError', 'Could not delete Moodle session file.');
148
//print_r($user_session);
151
//echo "Moodle session: $session_key \n";
152
//echo "filename: $file \n";
160
if (!empty($CFG->sessiontimeout)) {
161
$ADODB_SESS_LIFE = $CFG->sessiontimeout;
164
if ($user_session_data = get_records_sql('SELECT sesskey, sessdata FROM '. $CFG->prefix .'sessions2 WHERE expiry > NOW()')) {
165
foreach ($user_session_data as $session_data) {
167
//print_r($session_data);
168
$user_session = adodb_unserialize( urldecode($session_data->sessdata) );
170
if (isset($user_session['SESSION']) && isset($user_session['SESSION']->shibboleth_session_id)){
171
//echo '3. Shibboleth Session (from ADODB session) of '.$user_session['USER']->username.':' .$user_session['SESSION']->shibboleth_session_id."\n";
173
// If there is a match, delete file
174
if ($user_session['SESSION']->shibboleth_session_id == $SessionID){
175
// Delete this session entry
176
if (ADODB_Session::destroy($session_data->sesskey) !== true){
177
return new SoapFault('LogoutError', 'Could not delete Moodle session entry in database.');
182
//print_r($user_session);
187
// If now SoapFault was thrown the function will return OK as the SP assumes
129
global $CFG, $SESSION;
131
// Delete session of user using $SessionID
132
if(empty($CFG->dbsessions)) {
135
$dir = $CFG->dataroot .'/sessions';
137
if ($dh = opendir($dir)) {
138
// Read all session files
139
while (($file = readdir($dh)) !== false) {
140
// Check if it is a file
141
if (is_file($dir.'/'.$file)){
142
$session_key = ereg_replace('sess_', '', $file);
144
// Read session file data
145
$data = file($dir.'/'.$file);
146
if (isset($data[0])){
147
$user_session = unserializesession($data[0]);
149
// Check if we have found session that shall be deleted
150
if (isset($user_session['SESSION']) && isset($user_session['SESSION']->shibboleth_session_id)){
152
// If there is a match, delete file
153
if ($user_session['SESSION']->shibboleth_session_id == $SessionID){
154
// Delete session file
155
if (!unlink($dir.'/'.$file)){
156
return new SoapFault('LogoutError', 'Could not delete Moodle session file.');
168
if (!empty($CFG->sessiontimeout)) {
169
$ADODB_SESS_LIFE = $CFG->sessiontimeout;
172
if ($user_session_data = get_records_sql('SELECT sesskey, sessdata FROM '. $CFG->prefix .'sessions2 WHERE expiry > NOW()')) {
173
foreach ($user_session_data as $session_data) {
176
$user_session = adodb_unserialize( urldecode($session_data->sessdata) );
178
if (isset($user_session['SESSION']) && isset($user_session['SESSION']->shibboleth_session_id)){
180
// If there is a match, delete file
181
if ($user_session['SESSION']->shibboleth_session_id == $SessionID){
182
// Delete this session entry
183
if (ADODB_Session::destroy($session_data->sesskey) !== true){
184
return new SoapFault('LogoutError', 'Could not delete Moodle session entry in database.');
192
// If now SoapFault was thrown the function will return OK as the SP assumes
191
196
/*****************************************************************************/
193
198
// Same function as in adodb, but cannot be used for file session for some reason...
194
199
function unserializesession( $serialized_string ){
195
$variables = array( );
196
$a = preg_split( "/(\w+)\|/", $serialized_string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE );
197
for( $i = 0; $i < count( $a ); $i = $i+2 ) {
198
$variables[$a[$i]] = unserialize( $a[$i+1] );
200
return( $variables );
200
$variables = array( );
201
$a = preg_split( "/(\w+)\|/", $serialized_string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE );
202
for( $i = 0; $i < count( $a ); $i = $i+2 ) {
203
$variables[$a[$i]] = unserialize( $a[$i+1] );
205
return( $variables );