I have an application that is fronted by a Varnish server. Parts of the page is rendered using ESI includes.
My problem is that the upstream response includes an encrypted session cookie, which among other things contains a CSRF token (no server-side session storage at all).
For an initial request (no cookie in the request), the ESI requests will not include a cookie set by the first response from the upstream server.
I've tried setting req.http.Cookie
in the vcl_deliver
hook, as it's the only place in the request flow I've found where both req
and res
are R/W accessible. However, looking at the requests with varnishlog reveals the ESI requests are unaffected and don't include the cookie.
I've done my best to trawl through the documentation, but can't find anything remotely useful.
Is it possible to achieve what I want, i.e. update req
so that the ESI requests include the cookie returned by the initial upstream response?
Best Answer
We need to make a clear distinction between a request containing a
Cookie
header and a response containing aSet-Cookie
header.Assuming a CSRF token was set through a
Set-Cookie
header of the parent response, you probably want to access that value through aCookie
request header in your ESI subrequest.Assuming the Cookie header already contains the CSRF token
The
req_top.http.Cookie
variable has access to the cookies of the parent request, howeverreq_top
not accessible invcl_backend_response
where the ESI placeholders are parsed.You can bypass this limitation with the following VCL snippet:
This will enable the
X-Parent-Cookie
header which is available invcl_backend_response
throughbereq.http.X-Parent-Cookie
.Assuming the Cookie header does not yet contain the CSRF token
It is realistic to assume that
req_top.http.Cookie
doesn't yet contain the value of the CSRF token because when ESI subrequests are processed, theCookie
header is not yet set by the client.The only solution I can think off is storing the parent
Set-Cookie
value in a variable. Variables aren't supported natively in Varnish and require the official https://github.com/varnish/varnish-modules to be installed.You'll have to compile this from source.
See https://github.com/varnish/varnish-modules/blob/master/src/vmod_var.vcc for the
vmod_var
API and code examples.