Varnish/Drupal caching for logged in users Problem

Varnish is caching pages when I go onto my website anonymously.

I have "Cache Pages for anonymous users" turned on so this is expected.

But when I login it continues to load the cached page for the pages I visited when I was logged out, so the user specific menu never shows and the login button continues to show even though I'm logged in. 

I though Varnish didn't work for logged in users and I'm using the default drupal caching system which I thought didn't work for logged in users? How can I prevent this?

Server Set-Up

LEMP Stack - Ubuntu Server 12.04

APC + Memcached

Varnish

Drupal Caching Settings:

Cache pages for anonymous users -> enabled

Minimum cache lifetime -> 0

Expiration of cached pages -> 6 hours

Varnish Module Settings:

Varnish cache clearing: Drupal default

I installed Varnish using this guide and this Varnish config file: http://andrewdunkle.com/how-install-varnish-drupal-7

Browser Caching

I disabled browser caching in Firefox and I still get Varnish cache hits on my homepage however now the menu loads correctly. What does this imply?
You have two options:

Solution 1: Disallow caching in the browser

In order to prevent a browser from storing and reusing a page, you have to make sure that Cache-Control:no-cache, must-revalidate, post-check=0, pre-check=0 is on the respective (HTML) pages.

You can force this header in sub vcl_deliver. Just make sure that you do not put that header on static assets (like images, CSS and JavaScript files):

sub vcl_deliver {
  set req.http.Cache-Control = "no-cache, must-revalidate, post-check=0, pre-check=0";
}


Solution 2: Ensure that Vary: Cookie is on the response

If you want to force the browser to invalidate its cache whenever the cookies change (i.e. a session is opened), you have to ensure that the Vary: Cookie header is on the response.

sub vcl_deliver {
  if (resp.http.Vary !~ "Cookie") {
    set resp.http.Vary = resp.http.Vary + ", Cookie";
    set resp.http.Vary = regsub(resp.http.Vary, "^,\s*", "");
  }
}


Again, the cache is more effective if you restrict this fragment the page / filetypes which have different contents depending on whether a user is logged in or not.

Safari (at least v5 which is the last one for Windows and the one on iPad 1 and some older iPhones) has a nasty bug. I recommend to add the following snipped in order to deactivate the Safari browser cache:

sub vcl_deliver {
  if (resp.http.X-Generator ~ "Drupal" &amp;&amp; req.http.user-agent ~ "Safari" &amp;&amp; req.http.user-agent !~ "Chrome") {
    set resp.http.Cache-Control = "no-cache, must-revalidate, post-check=0, pre-check=0";
  }
}


Note: This is a little bit different from the solutions proposed in the comments of the bug report. By placing the snipped into vcl_deliver instead of vcl_fetch we avoid having to separate the bins. Also note that by matching on X-Generator ~ "Drupal" we avoid disabling the browser cache for static assets.

Today (November 2013) I reproduced this misbehavior on Safari 5.1.1 (Windows), 6.1 (Mac OS X 10.8 / Mountain Lion) and 7.0 (iOS 7).