Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
CRAP
0.00% covered (danger)
0.00%
0 / 1
CsrfMiddleware
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
20
0.00% covered (danger)
0.00%
0 / 1
 call
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2/**
3 * @section LICENSE
4 * This file is part of Wikimedia Slim application library
5 *
6 * Wikimedia Slim application library is free software: you can
7 * redistribute it and/or modify it under the terms of the GNU General Public
8 * License as published by the Free Software Foundation, either version 3 of
9 * the License, or (at your option) any later version.
10 *
11 * Wikimedia Slim application library is distributed in the hope that it
12 * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with Wikimedia Grants Review application.  If not, see
18 * <http://www.gnu.org/licenses/>.
19 *
20 * @file
21 * @copyright © 2015 Bryan Davis, Wikimedia Foundation and contributors.
22 */
23
24namespace Wikimedia\Slimapp;
25
26use Slim\Middleware;
27
28/**
29 * Middleware to manage Cross Site Request Forgery (CSRF) mitigation.
30 *
31 * Ensures that the user's session contains a random CSRF token. Verifies that
32 * HTTP requests using POST, PUT and DELETE verbs provide a parameter that
33 * matches the user's unique CSRF token. Exports 'csrf_param' and 'csrf_token'
34 * values to the view that can be used to generate appropriate form inputs.
35 *
36 * @author Bryan Davis <bd808@wikimedia.org>
37 * @copyright © 2015 Bryan Davis, Wikimedia Foundation and contributors.
38 */
39class CsrfMiddleware extends Middleware {
40
41    private const PARAM = 'csrf_token';
42
43    /**
44     * Handle CSRF validation and view injection.
45     */
46    public function call() {
47        if ( !isset( $_SESSION[self::PARAM] ) ) {
48            $_SESSION[self::PARAM] = sha1( session_id() . microtime() );
49        }
50
51        $token = $_SESSION[self::PARAM];
52        $method = $this->app->request()->getMethod();
53
54        if ( in_array( $method, [ 'POST', 'PUT', 'DELETE' ] ) ) {
55            $requestToken = $this->app->request()->post( self::PARAM );
56            if ( $token !== $requestToken ) {
57                $this->app->log->error( 'Missing or invalid CSRF token', [
58                    'got' => $requestToken,
59                    'expected' => $token,
60                ] );
61                $this->app->render( 'csrf.html', [], 400 );
62                return;
63            }
64        }
65
66        $this->app->view()->replace( [
67            'csrf_param' => self::PARAM,
68            'csrf_token' => $token,
69        ] );
70
71        $this->next->call();
72    }
73
74}