c9fa33d72ec42732280d5d0bf011a0083e5a06ea
[moodle.git] / auth / shibboleth / logout.php
1 <?php
3 // Implements logout for Shibboleth authenticated users according to:
4 // - https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPLogoutInitiator
5 // - https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPNotify
7 require_once("../../config.php");
9 require_once($CFG->dirroot."/auth/shibboleth/auth.php");
11 $action = optional_param('action', '', PARAM_ALPHA);
12 $redirect = optional_param('return', '', PARAM_URL);
14 // Find out whether host supports https
15 $protocol = 'http://';
16 if (is_https()) {
17     $protocol = 'https://';
18 }
20 // If the shibboleth plugin is not enable, throw an exception.
21 if (!is_enabled_auth('shibboleth')) {
22     throw new moodle_exception(get_string('pluginnotenabled', 'auth', 'shibboleth'));
23 }
25 // Front channel logout.
26 $inputstream = file_get_contents("php://input");
27 if ($action == 'logout' && !empty($redirect)) {
29     if (isloggedin($USER) && $USER->auth == 'shibboleth') {
30         // Logout user from application.
31         require_logout();
32     }
34     // Finally, send user to the return URL.
35     redirect($redirect);
37 } else if (!empty($inputstream)) {
39     // Back channel logout.
40     // Set SOAP header.
41     $server = new SoapServer($protocol.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'/LogoutNotification.wsdl');
42     $server->addFunction("LogoutNotification");
43     $server->handle();
45 } else {
47     // Return WSDL.
48     header('Content-Type: text/xml');
50     echo <<<WSDL
51 <?xml version ="1.0" encoding ="UTF-8" ?>
52 <definitions name="LogoutNotification"
53   targetNamespace="urn:mace:shibboleth:2.0:sp:notify"
54   xmlns:notify="urn:mace:shibboleth:2.0:sp:notify"
55   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
56   xmlns="http://schemas.xmlsoap.org/wsdl/">
58 <!--
59 This page either has to be called with the GET arguments 'action' and 'return' via
60 a redirect from the Shibboleth Service Provider logout handler (front-channel
61 logout) or via a SOAP request by a Shibboleth Service Provider (back-channel
62 logout).
63 Because neither of these two variants seems to be the case, the WSDL file for
64 the web service is returned.
66 For more information see:
67 - https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPLogoutInitiator
68 - https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPNotify
69 -->
71     <types>
72        <schema targetNamespace="urn:mace:shibboleth:2.0:sp:notify"
73            xmlns="http://www.w3.org/2000/10/XMLSchema"
74            xmlns:notify="urn:mace:shibboleth:2.0:sp:notify">
76             <simpleType name="string">
77                 <restriction base="string">
78                     <minLength value="1"/>
79                 </restriction>
80             </simpleType>
82             <element name="OK" type="notify:OKType"/>
83             <complexType name="OKType">
84                 <sequence/>
85             </complexType>
87         </schema>
88     </types>
90     <message name="getLogoutNotificationRequest">
91         <part name="SessionID" type="notify:string" />
92     </message>
94     <message name="getLogoutNotificationResponse" >
95         <part name="OK"/>
96     </message>
98     <portType name="LogoutNotificationPortType">
99         <operation name="LogoutNotification">
100             <input message="getLogoutNotificationRequest"/>
101             <output message="getLogoutNotificationResponse"/>
102         </operation>
103     </portType>
105     <binding name="LogoutNotificationBinding" type="notify:LogoutNotificationPortType">
106         <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
107         <operation name="LogoutNotification">
108             <soap:operation soapAction="urn:xmethods-logout-notification#LogoutNotification"/>
109         </operation>
110     </binding>
112     <service name="LogoutNotificationService">
113           <port name="LogoutNotificationPort" binding="notify:LogoutNotificationBinding">
114             <soap:address location="{$protocol}{$_SERVER['HTTP_HOST']}{$_SERVER['PHP_SELF']}"/>
115           </port>
116     </service>
117 </definitions>
118 WSDL;
119     exit;
121 /******************************************************************************/
123 /**
124  * Handles SOAP Back-channel logout notification
125  *
126  * @param string $spsessionid SP-provided Shibboleth Session ID
127  * @return SoapFault or void if everything was fine
128  */
129 function LogoutNotification($spsessionid) {
130     global $CFG;
132     // Delete session of user using $spsessionid.
133     // The setting $CFG->session_handler_class may not be set. But if it is,
134     // it should override $CFG->dbsessions.
135     if (!empty($CFG->session_handler_class)) {
136         $sessionclass = $CFG->session_handler_class;
137         if (preg_match('/database/i', $sessionclass) === 1) {
138             return \auth_shibboleth\helper::logout_db_session($spsessionid);
139         } else if (preg_match('/file/i', $sessionclass) === 1) {
140             return \auth_shibboleth\helper::logout_file_session($spsessionid);
141         } else {
142             throw new moodle_exception("Shibboleth logout not implemented for '$sessionclass'");
143         }
144     } else {
145         // Session handler class is not specified, check dbsessions instead.
146         if (!empty($CFG->dbsessions)) {
147             return \auth_shibboleth\helper::logout_db_session($spsessionid);
148         }
149         // Assume file sessions if dbsessions isn't used.
150         return \auth_shibboleth\helper::logout_file_session($spsessionid);
151     }
152     // If no SoapFault was thrown, the function will return OK as the SP assumes.