Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 41
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
ShibbolethLogoutNotificationController
0.00% covered (danger)
0.00%
0 / 41
0.00% covered (danger)
0.00%
0 / 5
90
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getAction
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 postAction
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
12
 logoutNotification
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
12
 getWsdl
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * Shibboleth Logout Notification API Controller
5 *
6 * PHP version 8
7 *
8 * Copyright (C) The National Library of Finland 2016.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2,
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 *
23 * @category VuFind
24 * @package  Controller
25 * @author   Ere Maijala <ere.maijala@helsinki.fi>
26 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
27 * @link     https://vufind.org Main Site
28 */
29
30namespace VuFind\Controller;
31
32use Laminas\ServiceManager\ServiceLocatorInterface;
33use Laminas\Stdlib\ResponseInterface as Response;
34use VuFind\Db\Service\ExternalSessionServiceInterface;
35
36use function extension_loaded;
37
38/**
39 * Handles Shibboleth back-channel logout notifications.
40 *
41 * @category VuFind
42 * @package  Controller
43 * @author   Ere Maijala <ere.maijala@helsinki.fi>
44 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
45 * @link     https://vufind.org Main Site
46 */
47class ShibbolethLogoutNotificationController extends AbstractBase
48{
49    /**
50     * Constructor
51     *
52     * @param ServiceLocatorInterface $sm Service locator
53     */
54    public function __construct(ServiceLocatorInterface $sm)
55    {
56        $this->accessPermission = 'access.api.ShibbolethLogoutNotification';
57        $this->accessDeniedBehavior = 'exception';
58        parent::__construct($sm);
59    }
60
61    /**
62     * GET method handler for the logout handler
63     *
64     * @return Response
65     */
66    public function getAction()
67    {
68        $this->disableSessionWrites();
69        $response = $this->getResponse();
70        $response->getHeaders()->addHeaderLine(
71            'Content-Type',
72            'application/wsdl+xml'
73        );
74        $response->setContent($this->getWsdl());
75        return $response;
76    }
77
78    /**
79     * POST method handler for the logout handler
80     *
81     * @return Response
82     */
83    public function postAction()
84    {
85        if (!extension_loaded('soap')) {
86            throw new \Exception('SOAP extension is not loaded.');
87        }
88        $this->disableSessionWrites();
89        $soapServer = new \SoapServer(
90            'data://text/plain;base64,' . base64_encode($this->getWsdl())
91        );
92        $soapServer->setObject($this);
93
94        ob_start();
95        try {
96            $request = file_get_contents('php://input');
97            $soapServer->handle($request);
98            $soapResponse = ob_get_clean();
99        } catch (\Exception $e) {
100            ob_end_clean();
101            $soapResponse = (string)$e;
102        }
103
104        $response = $this->getResponse();
105        $response->getHeaders()->addHeaderLine('Content-Type', 'text/xml');
106        $response->setContent($soapResponse);
107        return $response;
108    }
109
110    /**
111     * Logout notification handler
112     *
113     * @param string $sessionId External session id
114     *
115     * @return void
116     */
117    public function logoutNotification($sessionId)
118    {
119        $rows = $this->getDbService(ExternalSessionServiceInterface::class)
120            ->getAllByExternalSessionId(trim($sessionId));
121        if ($rows) {
122            $sessionManager = $this->serviceLocator->get(\Laminas\Session\SessionManager::class);
123            $handler = $sessionManager->getSaveHandler();
124            foreach ($rows as $row) {
125                $handler->destroy($row->getSessionId());
126            }
127        }
128    }
129
130    /**
131     * Get WSDL for the service
132     *
133     * @return string
134     */
135    protected function getWsdl()
136    {
137        [$uri] = explode('?', $this->getRequest()->getUriString());
138        return <<<EOT
139            <?xml version="1.0" encoding="UTF-8" ?>
140            <definitions name="LogoutNotification"
141              targetNamespace="urn:mace:shibboleth:2.0:sp:notify"
142              xmlns:notify="urn:mace:shibboleth:2.0:sp:notify"
143              xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
144              xmlns="http://schemas.xmlsoap.org/wsdl/">
145
146                <types>
147                   <schema targetNamespace="urn:mace:shibboleth:2.0:sp:notify"
148                       xmlns="http://www.w3.org/2000/10/XMLSchema"
149                       xmlns:notify="urn:mace:shibboleth:2.0:sp:notify">
150
151                        <simpleType name="string">
152                            <restriction base="string">
153                                <minLength value="1"/>
154                            </restriction>
155                        </simpleType>
156
157                        <element name="OK" type="notify:OKType"/>
158                        <complexType name="OKType">
159                            <sequence/>
160                        </complexType>
161
162                    </schema>
163                </types>
164
165                <message name="getLogoutNotificationRequest">
166                    <part name="SessionID" type="notify:string"/>
167                </message>
168
169                <message name="getLogoutNotificationResponse" >
170                    <part name="OK"/>
171                </message>
172
173                <portType name="LogoutNotificationPortType">
174                    <operation name="LogoutNotification">
175                        <input message="getLogoutNotificationRequest"/>
176                        <output message="getLogoutNotificationResponse"/>
177                    </operation>
178                </portType>
179
180                <binding name="LogoutNotificationBinding"
181                    type="notify:LogoutNotificationPortType">
182                    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
183                    <operation name="LogoutNotification">
184                        <soap:operation
185                            soapAction="urn:xmethods-logout-notification#LogoutNotification"/>
186                    </operation>
187                </binding>
188
189                <service name="LogoutNotificationService">
190                      <port name="LogoutNotificationPort"
191                        binding="notify:LogoutNotificationBinding">
192                        <soap:address location="$uri"/>
193                      </port>
194                </service>
195            </definitions>
196            EOT;
197    }
198}