97 lines
2.5 KiB
PHP
97 lines
2.5 KiB
PHP
<?php
|
|
|
|
/**
|
|
* @file classes/security/authorization/internal/ApiCsrfMiddleware.php
|
|
*
|
|
* Copyright (c) 2014-2021 Simon Fraser University
|
|
* Copyright (c) 2000-2021 John Willinsky
|
|
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
|
*
|
|
* @class ApiCsrfMiddleware
|
|
*
|
|
* @ingroup security_authorization
|
|
*
|
|
* @brief Slim middleware which requires a CSRF token for POST, PUT and DELETE
|
|
* operations whenever an API Token is not in use.
|
|
*/
|
|
|
|
namespace PKP\security\authorization\internal;
|
|
|
|
use APP\core\Application;
|
|
use PKP\core\APIResponse;
|
|
use PKP\handler\APIHandler;
|
|
use Slim\Http\Request as SlimRequest;
|
|
|
|
class ApiCsrfMiddleware
|
|
{
|
|
/** @var APIHandler $handler Reference to api handler */
|
|
protected $_handler = null;
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
*/
|
|
public function __construct(APIHandler $handler)
|
|
{
|
|
$this->_handler = $handler;
|
|
}
|
|
|
|
/**
|
|
* Middleware invokable function
|
|
*
|
|
* @param SlimRequest $slimRequest request
|
|
* @param APIResponse $response response
|
|
* @param callable $next Next middleware
|
|
*
|
|
* @return APIResponse
|
|
*/
|
|
public function __invoke($slimRequest, $response, $next)
|
|
{
|
|
if ($this->_isCSRFRequired($slimRequest) && !$this->_isCSRFValid($slimRequest)) {
|
|
return $response->withJson([
|
|
'error' => 'form.csrfInvalid',
|
|
'errorMessage' => __('form.csrfInvalid'),
|
|
], 403);
|
|
}
|
|
$response = $next($slimRequest, $response);
|
|
return $response;
|
|
}
|
|
|
|
/**
|
|
* Check if a CSRF token is required
|
|
*
|
|
* @param SlimRequest $slimRequest
|
|
*
|
|
* @return bool
|
|
*/
|
|
protected function _isCSRFRequired($slimRequest)
|
|
{
|
|
if ($this->_handler->getApiToken()) {
|
|
return false;
|
|
}
|
|
$server = $slimRequest->getServerParams();
|
|
return !empty($server['REQUEST_METHOD']) && in_array($server['REQUEST_METHOD'], ['POST', 'PUT', 'DELETE']);
|
|
}
|
|
|
|
/**
|
|
* Check if the CSRF token is present and valid
|
|
*
|
|
* @param SlimRequest $slimRequest
|
|
*
|
|
* @return bool
|
|
*/
|
|
protected function _isCSRFValid($slimRequest)
|
|
{
|
|
$server = $slimRequest->getServerParams();
|
|
if (empty($server['HTTP_X_CSRF_TOKEN'])) {
|
|
return false;
|
|
}
|
|
$session = Application::get()->getRequest()->getSession();
|
|
return $session && $session->getCSRFToken() === $server['HTTP_X_CSRF_TOKEN'];
|
|
}
|
|
}
|
|
|
|
if (!PKP_STRICT_MODE) {
|
|
class_alias('\PKP\security\authorization\internal\ApiCsrfMiddleware', '\ApiCsrfMiddleware');
|
|
}
|