Avoid showing user specific information by wrongful caching in Varnish Cache

Usually guests see some bits different then logged in users. A simple way to start with Varnish is to avoid all the caching logic for logged in users.

There are other ways to achieve high caching hit rate, also in combination with logged in users. But for starters it is sufficient to start with just skipping all the cache specific business logic in Varnish and pass logged in users right through to the application.

We need an indicator

Somehow we need to know how to differentiate between a logged in users and guests. And most of the time this is done using cookies.

If a user does not send a cookie like "loggedin" with each request, we can assume that this is a guest. Some CMS or applications do it out of the box. For example: TYPO3 sets a "be_user" for logged in backend users, or "fe_user" for logged in frontend users.

In Varnish you could handle that case like this:

1 sub vcl_recv {
2   if (req.http.Cookie ~ "(?i)(loggedin|be_user|fe_user)") {
3     return (pass);
4   }
5 }

But then there are application frameworks like Laravel which do nothing of the kind. Here we need to put in some little extra work. The way to go is: on login, or even better, as a middleware on each request: check if a user is logged in, and if he is, set a cookie indicating the he is logged in, with the exact duration of his session. Something like this:

 1 <?php
 2 
 3 namespace App\Http\Middleware;
 4 
 5 use Illuminate\Http\Request;
 6 
 7 class AddAuthStatus
 8 {
 9     public function handle(Request $request, \Closure $next)
10     {
11         /** @var \Illuminate\Http\Response $response */
12         $response = $next($request);
13 
14         if (\Auth::guard()->check() && method_exists($response, 'cookie')) {
15             $response->cookie('loggedin', 1, config('session.lifetime'));
16         }
17 
18         return $response;
19     }
20 }

And finally you add this middleware to your Kernel:

 1 <?php
 2 
 3 namespace App\Http;
 4 
 5 use Illuminate\Foundation\Http\Kernel as HttpKernel;
 6 
 7 class Kernel extends HttpKernel
 8 {
 9     protected $middlewareGroups = [
10         'web' => [
11             // ...

12             \App\Http\Middleware\AddAuthStatus::class,
13         ],
14     ];
15 }