]> BookStack Code Mirror - bookstack/commitdiff
Forced response cache revalidation on logged-in responses
authorDan Brown <redacted>
Fri, 8 Oct 2021 14:22:09 +0000 (15:22 +0100)
committerDan Brown <redacted>
Fri, 8 Oct 2021 14:22:09 +0000 (15:22 +0100)
- Prevents authenticated responses being visible when back button
  pressed in browser.
- Previously, 'no-cache, private' was added by default by Symfony which
  would have prevents proxy cache issues but this adds no-store and a
  max-age option to also invalidate all caching.

Thanks to @haxatron via huntr.dev
Ref: https://huntr.dev/bounties/6cda9df9-4987-4e1c-b48f-855b6901ef53/

app/Http/Kernel.php
app/Http/Middleware/PreventAuthenticatedResponseCaching.php [new file with mode: 0644]
tests/SecurityHeaderTest.php

index a98528d0f9ebc747a4224974a3500c573e67f0ac..8c71e2194700d220d7e425f37bdf1aea2e2ae39a 100644 (file)
@@ -2,6 +2,7 @@
 
 namespace BookStack\Http;
 
+use BookStack\Http\Middleware\PreventAuthenticatedResponseCaching;
 use Illuminate\Foundation\Http\Kernel as HttpKernel;
 
 class Kernel extends HttpKernel
@@ -30,6 +31,7 @@ class Kernel extends HttpKernel
             \Illuminate\Session\Middleware\StartSession::class,
             \Illuminate\View\Middleware\ShareErrorsFromSession::class,
             \BookStack\Http\Middleware\VerifyCsrfToken::class,
+            \BookStack\Http\Middleware\PreventAuthenticatedResponseCaching::class,
             \BookStack\Http\Middleware\CheckEmailConfirmed::class,
             \BookStack\Http\Middleware\RunThemeActions::class,
             \BookStack\Http\Middleware\Localization::class,
@@ -39,6 +41,7 @@ class Kernel extends HttpKernel
             \BookStack\Http\Middleware\EncryptCookies::class,
             \BookStack\Http\Middleware\StartSessionIfCookieExists::class,
             \BookStack\Http\Middleware\ApiAuthenticate::class,
+            \BookStack\Http\Middleware\PreventAuthenticatedResponseCaching::class,
             \BookStack\Http\Middleware\CheckEmailConfirmed::class,
         ],
     ];
diff --git a/app/Http/Middleware/PreventAuthenticatedResponseCaching.php b/app/Http/Middleware/PreventAuthenticatedResponseCaching.php
new file mode 100644 (file)
index 0000000..3ad5b39
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+
+namespace BookStack\Http\Middleware;
+
+use Closure;
+use Symfony\Component\HttpFoundation\Response;
+
+class PreventAuthenticatedResponseCaching
+{
+    /**
+     * Handle an incoming request.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \Closure  $next
+     * @return mixed
+     */
+    public function handle($request, Closure $next)
+    {
+        /** @var Response $response */
+        $response = $next($request);
+
+        if (signedInUser()) {
+            $response->headers->set('Cache-Control', 'max-age=0, no-store, private');
+            $response->headers->set('Pragma', 'no-cache');
+            $response->headers->set('Expires', 'Sun, 12 Jul 2015 19:01:00 GMT');
+        }
+
+        return $response;
+    }
+}
index 2bde890ad58139ef0bc4d33416e3d4cfe68fa462..10551fc55a8d6dd90d7bf0f66ad430a8e9aee50c 100644 (file)
@@ -119,6 +119,15 @@ class SecurityHeaderTest extends TestCase
         $this->assertEquals('base-uri \'self\'', $scriptHeader);
     }
 
+    public function test_cache_control_headers_are_strict_on_responses_when_logged_in()
+    {
+        $this->asEditor();
+        $resp = $this->get('/');
+        $resp->assertHeader('Cache-Control', 'max-age=0, no-store, private');
+        $resp->assertHeader('Pragma', 'no-cache');
+        $resp->assertHeader('Expires', 'Sun, 12 Jul 2015 19:01:00 GMT');
+    }
+
     /**
      * Get the value of the first CSP header of the given type.
      */