Completed
Push — master ( e0a4c6...1ad79e )
by Morris
27:44
created

SameSiteCookieMiddleware::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 5
rs 9.4285
1
<?php
2
/**
3
 * @copyright 2017, Roeland Jago Douma <[email protected]>
4
 *
5
 * @author Roeland Jago Douma <[email protected]>
6
 *
7
 * @license GNU AGPL version 3 or any later version
8
 *
9
 * This program is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Affero General Public License as
11
 * published by the Free Software Foundation, either version 3 of the
12
 * License, or (at your option) any later version.
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 Affero General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Affero General Public License
20
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 *
22
 */
23
namespace OC\AppFramework\Middleware\Security;
24
25
use OC\AppFramework\Http\Request;
26
use OC\AppFramework\Middleware\Security\Exceptions\LaxSameSiteCookieFailedException;
27
use OC\AppFramework\Utility\ControllerMethodReflector;
28
use OCP\AppFramework\Http;
29
use OCP\AppFramework\Http\Response;
30
use OCP\AppFramework\Middleware;
31
32
class SameSiteCookieMiddleware extends Middleware {
33
34
	/** @var Request */
35
	private $request;
36
37
	/** @var ControllerMethodReflector */
38
	private $reflector;
39
40
	public function __construct(Request $request,
41
								ControllerMethodReflector $reflector) {
42
		$this->request = $request;
43
		$this->reflector = $reflector;
44
	}
45
46
	public function beforeController($controller, $methodName) {
47
		$requestUri = $this->request->getScriptName();
48
		$processingScript = explode('/', $requestUri);
49
		$processingScript = $processingScript[count($processingScript)-1];
50
51
		if ($processingScript !== 'index.php') {
52
			return;
53
		}
54
55
		$noSSC = $this->reflector->hasAnnotation('NoSameSiteCookieRequired');
56
		if ($noSSC) {
57
			return;
58
		}
59
60
		if (!$this->request->passesLaxCookieCheck()) {
61
			throw new LaxSameSiteCookieFailedException();
62
		}
63
	}
64
65
	public function afterException($controller, $methodName, \Exception $exception) {
66
		if ($exception instanceof LaxSameSiteCookieFailedException) {
67
			$respone = new Response();
68
			$respone->setStatus(Http::STATUS_FOUND);
69
			$respone->addHeader('Location', $this->request->getRequestUri());
70
71
			$this->setSameSiteCookie();
72
73
			return $respone;
74
		}
75
76
		throw $exception;
77
	}
78
79 View Code Duplication
	protected function setSameSiteCookie() {
80
		$cookieParams = $this->request->getCookieParams();
81
		$secureCookie = ($cookieParams['secure'] === true) ? 'secure; ' : '';
82
		$policies = [
83
			'lax',
84
			'strict',
85
		];
86
87
		// Append __Host to the cookie if it meets the requirements
88
		$cookiePrefix = '';
89
		if($cookieParams['secure'] === true && $cookieParams['path'] === '/') {
90
			$cookiePrefix = '__Host-';
91
		}
92
93
		foreach($policies as $policy) {
94
			header(
95
				sprintf(
96
					'Set-Cookie: %snc_sameSiteCookie%s=true; path=%s; httponly;' . $secureCookie . 'expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=%s',
97
					$cookiePrefix,
98
					$policy,
99
					$cookieParams['path'],
100
					$policy
101
				),
102
				false
103
			);
104
		}
105
	}
106
}
107