--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_http_authentication/README.markdown Mon Oct 17 13:03:38 2016 +0000
@@ -0,0 +1,29 @@
+---
+labels:
+- 'Stage-Beta'
+summary: Enforces HTTP Basic authentication across all HTTP endpoints served by Prosody
+...
+
+# mod_http_authentication
+
+This module enforces HTTP Basic authentication across all HTTP endpoints served by Prosody.
+
+## Configuration
+
+Name Default Description
+------------------------------- ------------------------------- -----------------------------
+minddistrict_http_credentials "minddistrict:secretpassword" The credentials that HTTP clients must provide to access the HTTP interface. Should be a string with the syntax "username:password".
+unauthenticated_http_endpoints { "/http-bind", "/http-bind/" } A list of paths that should be excluded from authentication.
+
+## Usage
+
+This is a global module, so should be added to the global `modules_enabled` option in your config file. It applies to all HTTP virtual hosts.
+
+## Known issues
+
+The module use a new API in Prosody 0.10. This API currently has an open issue ([issue #554](https://prosody.im/issues/issue/554))
+that means this module cannot be unloaded dynamically at runtime. In practice this shouldn't be an issue, and we will resolve the problem inside Prosody in due course.
+
+## Details
+
+By Kim Alvefur \<zash@zash.se\>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_http_authentication/mod_http_authentication.lua Mon Oct 17 13:03:38 2016 +0000
@@ -0,0 +1,25 @@
+
+module:set_global();
+
+local b64_decode = require "util.encodings".base64.decode;
+local server = require "net.http.server";
+
+local credentials = module:get_option_string("http_credentials", "username:secretpassword");
+local unauthed_endpoints = module:get_option_set("unauthenticated_http_endpoints", { "/http-bind", "/http-bind/" })._items;
+
+module:wrap_object_event(server._events, false, function (handlers, event_name, event_data)
+ local request = event_data.request;
+ if request and not unauthed_endpoints[request.path] then
+ local response = event_data.response;
+ local headers = request.headers;
+ if not headers.authorization then
+ response.headers.www_authenticate = ("Basic realm=%q"):format(module.host.."/"..module.name);
+ return 401;
+ end
+ local user_password = b64_decode(headers.authorization:match("%s(%S*)$"));
+ if user_password ~= credentials then
+ return 401;
+ end
+ end
+ return handlers(event_name, event_data);
+end);