Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
14.29% covered (danger)
14.29%
4 / 28
33.33% covered (danger)
33.33%
1 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
CsrfToken
14.29% covered (danger)
14.29%
4 / 28
33.33% covered (danger)
33.33%
1 / 3
37.86
0.00% covered (danger)
0.00%
0 / 1
 render
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 validate
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
20
 logCsrfFailure
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3/**
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; under version 2
7 * of the License (non-upgradable).
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 *
18 * Copyright (c) 2019 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT);
19 *
20 */
21
22namespace oat\tao\helpers\form\elements\xhtml;
23
24use common_session_SessionManager;
25use oat\oatbox\log\LoggerAwareTrait;
26use oat\oatbox\service\ServiceManager;
27use oat\oatbox\service\ServiceManagerAwareTrait;
28use oat\tao\model\security\xsrf\TokenService;
29use tao_helpers_form_elements_xhtml_Hidden;
30
31/**
32 * Class provides the CSRF token form element
33 *
34 * @author Martijn Swinkels <m.swinkels@taotesting.com>
35 */
36class CsrfToken extends tao_helpers_form_elements_xhtml_Hidden
37{
38    use LoggerAwareTrait;
39
40    /**
41     * @inheritdoc
42     */
43    public function render()
44    {
45        /** @var TokenService $tokenService */
46        $tokenService = ServiceManager::getServiceManager()->get(TokenService::SERVICE_ID);
47        $formToken = $tokenService->getFormToken();
48        $this->setValue($formToken->getValue());
49
50        return parent::render();
51    }
52
53    /**
54     * @inheritdoc
55     */
56    public function validate()
57    {
58        $csrfToken = $this->getEvaluatedValue();
59        if (!$csrfToken) {
60            $this->logCsrfFailure('No CSRF token provided in form');
61            return false;
62        }
63
64        /** @var TokenService $tokenService */
65        $tokenService = ServiceManager::getServiceManager()->get(TokenService::SERVICE_ID);
66
67        if (!$tokenService->checkFormToken($csrfToken)) {
68            $this->logCsrfFailure('Invalid token received', $csrfToken);
69            return false;
70        }
71
72        $tokenService->revokeToken($csrfToken);
73
74        try {
75            $tokenService->addFormToken();
76        } catch (\common_Exception $e) {
77            return false;
78        }
79
80        return parent::validate();
81    }
82
83    /**
84     * Log a failed CSRF validation attempt
85     *
86     * @param string $exceptionMessage
87     * @param string|null $csrfToken
88     * @throws \common_exception_Error
89     */
90    private function logCsrfFailure($exceptionMessage, $csrfToken = null)
91    {
92        $userIdentifier = common_session_SessionManager::getSession()->getUser()->getIdentifier();
93
94        $this->logWarning(
95            '[CSRF] - Failed to validate CSRF token. The following exception occurred: ' . $exceptionMessage
96        );
97        $this->logWarning(
98            "[CSRF] \n" .
99            "CSRF validation information: \n" .
100            'Provided token: ' . ($csrfToken ?: 'none') . " \n" .
101            'User identifier: ' . $userIdentifier . " \n" .
102            'Form: ' . $this->name
103        );
104    }
105}