HTTP Basic Auth

Store username/password list in an edge dictionary, authorize user at the edge, reject requests that don't have correct credentials.

VCL

Use this solution in your VCL service (click RUN below to test this solution or clone it to make changes):

Compute@Edge

Use this solution in your Compute@Edge service:

  1. Rust
// To generate username/password pairs, on a bash shell you should be able to do:
// echo -n "alice:secretpassword" | base64
let mut username_password = HashSet::new();
username_password.insert("YWxpY2U6c2VjcmV0cGFzc3dvcmQ=".to_string());
if let Some(credential) = req
.get_header(AUTHORIZATION)
.and_then(|header| header.to_str().ok())
.and_then(get_credential)
.filter(|credential| username_password.contains(credential))
{
// Decode the credential so we can pull the user name out.
let bytes = base64::decode(credential)?;
let no_secret = str::from_utf8(&bytes)?;
let username = get_username(no_secret).unwrap();
req.set_url(HTML_URL);
req.remove_header(AUTHORIZATION);
req.set_header("authorized-user", &username);
log::debug!("Access granted for user {}", username);
return Ok(req.send(BACKEND_NAME)?);
};
log::debug!("Access denied");
// Catch all other requests and return a 401.
let the_body = "\
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">
<html>
<head>
<title>Error</title>
<meta HTTP-EQUIV='Content-Type' CONTENT='text/html;'>
</head>
<body><h1>401 Unauthorized (Fastly)</h1></body>
</html>";
Ok(Response::from_body(the_body)
.with_status(StatusCode::UNAUTHORIZED)
.with_content_type(mime::TEXT_HTML_UTF_8)
.with_header(WWW_AUTHENTICATE, "Basic realm=MYREALM"))
fn get_credential(input: &str) -> Option<String> {
lazy_static! {
static ref RE: Regex = Regex::new(r"Basic (?P<credential>.*)$").unwrap();
}
RE.captures(input).and_then(|cap| {
cap.name("credential")
.map(|credential| credential.as_str().to_owned())
})
}