[Varnish] HTTP Authentication

Put in place a basic HTTP authentication on a website with a Varnish can be a little tricky.

If you add the authentication on the backend without any changes into the varnish configuration, as soon as an authenticated client browse the website, filtered contents will be accessible to other users.

To avoid this behavior you can add the following block into your vcl_recv :

if (req.http.Authorization) {
   return (pass);
}

but that mean bypassing all cache for the filtered-content. If you want to protect the whole website this setting make Varnish completely useless. Fortunately, it is possible to implement the HTTP authentication on the Varnish side.

Encode user and password

As varnish is a reverse-proxy and not an HTTP server, there is nothing surprising in the fact that there is no support for password file. To bypass this limitation, we will add the login and password directly inside Varnish’s configuration, encoded into a base64 string, generated like this:

# echo -n "$LOGIN:$PW" | base64

VCL modifications

Into the vcl_recv add this block:

if (! req.http.Authorization ~ "Basic XXXXXXXXXXXX"){
   error 401 "Restricted" ;
}

where XXXXXXXXXXXX is your base64 encoded string.

Then add into the vcl_error :

if (obj.status == 401) {
   set obj.http.Content-Type = "text/html; charset=utf-8";
   set obj.http.WWW-Authenticate = "Basic realm=Secured";
   synthetic {"
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<HTML>
<HEAD>
<TITLE>Forbidden</TITLE>
<META HTTP-EQUIV='Content-Type' CONTENT='text/html;'>
</HEAD>
<BODY><H1>401 Forbidden</H1></BODY>
</HTML>
  "};
  return (deliver);
}