Created
August 1, 2018 22:22
-
-
Save swichers/a850557aca488970d6fc3efe47e581ed to your computer and use it in GitHub Desktop.
Varnish VCL for checking authorization against a different page and then forcing a cached response.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
vcl 4.0; | |
# !!Important!! Do not use this if your authenticated response can vary | |
# between users or roles. | |
# Note: This is only useful if the following things are true: | |
# * Access to the jsonapi endpoints is restricted to authorized users only. | |
# * jsonapi request results will be the same for all authorized users. No | |
# customized or filtered results based on role or other access checks. | |
# Note: Was implemented and tested as an include file. Priority of includes | |
# does matter. Example: | |
# | |
# vcl 4.0; | |
# include "jsonapi.vcl" | |
# include "base.vcl" | |
# include "debug.vcl" | |
sub vcl_recv { | |
if (req.restarts == 0) { | |
# Remove our auth header if Varnish wasn't responsible for adding it. | |
unset req.http.X-JSON-Authed; | |
} | |
# Special handling to ping the lightweight JSONAPI auth check endpoint | |
# instead of potentially hitting heavy endpoints on each check. This does | |
# not cut the number of web requests but can potentially save substantial | |
# time in the response. | |
# | |
# We only want our extra handling to process URLs below the /jsonapi/ path. | |
if (req.url ~ "^/jsonapi/.+$") { | |
# If our API auth header is missing then we need to ping the auth check | |
# endpoint to verify this user can actually access JSONAPI resources. | |
if (!req.http.X-JSON-Authed) { | |
set req.http.X-Original-URL = req.url; | |
set req.url = "/jsonapi"; | |
return (pass); | |
} | |
elseif (req.http.X-JSON-Authed == "true") { | |
return (hash); | |
} | |
# Authed was FALSE or some other issue. | |
return (synth(403, "Access denied")); | |
} | |
} | |
sub vcl_deliver { | |
# We need the additional check for X-Original-URL to make sure direct access | |
# to /jsonapi still works without causing a redirect loop. | |
if (req.url == "/jsonapi" && req.http.X-Original-URL) { | |
# Fail open if there was a server error. | |
if (resp.status >= 500 && resp.status < 600) { | |
set req.http.X-JSON-Authed = "true"; | |
} | |
else if (resp.status == 200) { | |
set req.http.X-JSON-Authed = "true"; | |
} | |
else if (resp.status == 401) { | |
return (deliver); | |
} | |
else { | |
set req.http.X-JSON-Authed = "false"; | |
} | |
# Continue the original request with our new header. | |
set req.url = req.http.X-Original-URL; | |
unset req.http.X-Original-URL; | |
return (restart); | |
} | |
} | |
sub vcl_backend_response { | |
if (bereq.url ~ "^/jsonapi/.+") { | |
if (beresp.status == 200 || beresp.status == 302) { | |
# Strip out parts of the response that will always block caching. | |
unset beresp.http.Set-Cookie; | |
unset beresp.http.Authorization; | |
unset beresp.http.Cookie; | |
# TODO: Custom handler on Drupal side that will set this information. | |
set beresp.http.Cache-Control = "max-age=900, public"; | |
set beresp.ttl = 15m; | |
return (deliver); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment