Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 46
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
ExternalAuthController
0.00% covered (danger)
0.00%
0 / 46
0.00% covered (danger)
0.00%
0 / 2
132
0.00% covered (danger)
0.00%
0 / 1
 ezproxyLoginAction
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 1
72
 createEzproxyTicketUrl
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3/**
4 * External Authentication/Authorization 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/wiki/development:plugins:controllers Wiki
28 */
29
30namespace VuFind\Controller;
31
32use Laminas\Log\LoggerAwareInterface;
33
34/**
35 * External Authentication/Authorization Controller
36 *
37 * Provides authorization support for external systems, e.g. EZproxy
38 *
39 * @category VuFind
40 * @package  Controller
41 * @author   Ere Maijala <ere.maijala@helsinki.fi>
42 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
43 * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
44 */
45class ExternalAuthController extends AbstractBase implements LoggerAwareInterface
46{
47    use \VuFind\Log\LoggerAwareTrait;
48
49    /**
50     * Permission from permissions.ini required for EZProxy authorization.
51     *
52     * @var string
53     */
54    protected $ezproxyRequiredPermission = 'ezproxy.authorized';
55
56    /**
57     * Provides an EZproxy session to an authorized user
58     *
59     * @return mixed
60     *
61     * @throws \Exception
62     */
63    public function ezproxyLoginAction()
64    {
65        $config = $this->getConfig();
66        if (empty($config->EZproxy->host)) {
67            throw new \Exception('EZproxy host not defined in configuration');
68        }
69
70        $user = $this->getUser();
71
72        $authService = $this->serviceLocator
73            ->get(\LmcRbacMvc\Service\AuthorizationService::class);
74        if ($authService->isGranted($this->ezproxyRequiredPermission)) {
75            // Access granted, redirect to EZproxy
76            if (empty($config->EZproxy->disable_ticket_auth_logging)) {
77                $logger = $this->serviceLocator->get(\VuFind\Log\Logger::class);
78                $logger->info(
79                    "EZproxy login to '" . $config->EZproxy->host
80                    . "' for '" . ($user ? $user->getUsername() : 'anonymous')
81                    . "' from IP address "
82                    . $this->request->getServer()->get('REMOTE_ADDR')
83                );
84            }
85            $url = $this->params()->fromPost(
86                'url',
87                $this->params()->fromQuery('url')
88            );
89            $username = (!empty($config->EZproxy->anonymous_ticket) || !$user)
90                ? 'anonymous' : $user->getUsername();
91            return $this->redirect()->toUrl(
92                $this->createEzproxyTicketUrl($username, $url)
93            );
94        }
95
96        if ($user) {
97            // User already logged in, inform that the current login does not
98            // allow access.
99            $view = $this->createViewModel();
100            $view->unauthorized = true;
101            $this->flashMessenger()->addErrorMessage(
102                'external_auth_unauthorized'
103            );
104            return $view;
105        }
106        return $this->forceLogin('external_auth_login_message');
107    }
108
109    /**
110     * Create a ticket login URL for EZproxy
111     *
112     * @param string $user User name to pass on to EZproxy
113     * @param string $url  The original URL
114     *
115     * @return string EZproxy URL
116     *
117     * @throws \Exception
118     * @see    https://www.oclc.org/support/services/ezproxy/documentation/usr
119     * /ticket/php.en.html
120     */
121    protected function createEzproxyTicketUrl($user, $url)
122    {
123        $config = $this->getConfig();
124        if (empty($config->EZproxy->secret)) {
125            throw new \Exception('EZproxy secret not defined in configuration');
126        }
127
128        $packet = '$u' . time() . '$e';
129        $hash = new \Laminas\Crypt\Hash();
130        $algorithm = !empty($config->EZproxy->secret_hash_method)
131            ? $config->EZproxy->secret_hash_method : 'SHA512';
132        $ticket = $config->EZproxy->secret . $user . $packet;
133        $ticket = $hash->compute($algorithm, $ticket);
134        $ticket .= $packet;
135        $params = http_build_query(
136            ['user' => $user, 'ticket' => $ticket, 'url' => $url]
137        );
138        return $config->EZproxy->host . "/login?$params";
139    }
140}