aboutsummaryrefslogtreecommitdiffstats
path: root/lib/private/AppFramework/Middleware/Security/SameSiteCookieMiddleware.php
diff options
context:
space:
mode:
Diffstat (limited to 'lib/private/AppFramework/Middleware/Security/SameSiteCookieMiddleware.php')
-rw-r--r--lib/private/AppFramework/Middleware/Security/SameSiteCookieMiddleware.php83
1 files changed, 83 insertions, 0 deletions
diff --git a/lib/private/AppFramework/Middleware/Security/SameSiteCookieMiddleware.php b/lib/private/AppFramework/Middleware/Security/SameSiteCookieMiddleware.php
new file mode 100644
index 00000000000..097ed1b2b8f
--- /dev/null
+++ b/lib/private/AppFramework/Middleware/Security/SameSiteCookieMiddleware.php
@@ -0,0 +1,83 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\AppFramework\Middleware\Security;
+
+use OC\AppFramework\Http\Request;
+use OC\AppFramework\Middleware\Security\Exceptions\LaxSameSiteCookieFailedException;
+use OC\AppFramework\Utility\ControllerMethodReflector;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\Response;
+use OCP\AppFramework\Middleware;
+
+class SameSiteCookieMiddleware extends Middleware {
+ public function __construct(
+ private Request $request,
+ private ControllerMethodReflector $reflector,
+ ) {
+ }
+
+ public function beforeController($controller, $methodName) {
+ $requestUri = $this->request->getScriptName();
+ $processingScript = explode('/', $requestUri);
+ $processingScript = $processingScript[count($processingScript) - 1];
+
+ if ($processingScript !== 'index.php') {
+ return;
+ }
+
+ $noSSC = $this->reflector->hasAnnotation('NoSameSiteCookieRequired');
+ if ($noSSC) {
+ return;
+ }
+
+ if (!$this->request->passesLaxCookieCheck()) {
+ throw new LaxSameSiteCookieFailedException();
+ }
+ }
+
+ public function afterException($controller, $methodName, \Exception $exception) {
+ if ($exception instanceof LaxSameSiteCookieFailedException) {
+ $response = new Response();
+ $response->setStatus(Http::STATUS_FOUND);
+ $response->addHeader('Location', $this->request->getRequestUri());
+
+ $this->setSameSiteCookie();
+
+ return $response;
+ }
+
+ throw $exception;
+ }
+
+ protected function setSameSiteCookie(): void {
+ $cookieParams = $this->request->getCookieParams();
+ $secureCookie = ($cookieParams['secure'] === true) ? 'secure; ' : '';
+ $policies = [
+ 'lax',
+ 'strict',
+ ];
+
+ // Append __Host to the cookie if it meets the requirements
+ $cookiePrefix = '';
+ if ($cookieParams['secure'] === true && $cookieParams['path'] === '/') {
+ $cookiePrefix = '__Host-';
+ }
+
+ foreach ($policies as $policy) {
+ header(
+ sprintf(
+ 'Set-Cookie: %snc_sameSiteCookie%s=true; path=%s; httponly;' . $secureCookie . 'expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=%s',
+ $cookiePrefix,
+ $policy,
+ $cookieParams['path'],
+ $policy
+ ),
+ false
+ );
+ }
+ }
+}