changeset 2884:16e9f37b3f82

mod_http_auth_check: New HTTP module to test user credentials
author Nicolas Cedilnik <nicoco@nicoco.fr>
date Tue, 20 Feb 2018 12:57:44 +0000 (2018-02-20)
parents 7c16afc70d11
children 88b16084eda7
files mod_http_auth_check/README.markdown mod_http_auth_check/mod_http_auth_check.lua
diffstat 2 files changed, 68 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_http_auth_check/README.markdown	Tue Feb 20 12:57:44 2018 +0000
@@ -0,0 +1,31 @@
+---
+labels:
+summary: 'Test account credentials using HTTP'
+...
+
+Introduction
+------------
+
+This module lets you test whether a set of credentials are valid,
+using Prosody's configured authentication mechanism.
+
+This is useful as an easy way to allow other (e.g. non-XMPP) applications
+to authenticate users using their XMPP credentials.
+
+Syntax
+------
+
+To test credentials, issue a simple GET request with HTTP basic auth:
+
+    GET /auth_check HTTP/1.1
+    Authorization: Basic <base64(jid:password)>
+
+Prosody will return a 2xx code on success (user exists and credentials are
+correct), or 401 if the credentials are invalid. Any other code may be returned
+if there is a problem handling the request.
+
+### Example usage
+
+Here follows some example usage using `curl`.
+
+    curl http://prosody.local:5280/data/accounts -u user@example.com:secr1t
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_http_auth_check/mod_http_auth_check.lua	Tue Feb 20 12:57:44 2018 +0000
@@ -0,0 +1,37 @@
+-- HTTP Is User Valid
+-- By Nicolas Cedilnik <nicoco@nicoco.fr>
+
+local jid_prep = require "util.jid".prep;
+local jid_split = require "util.jid".split;
+local test_password = require "core.usermanager".test_password;
+local b64_decode = require "util.encodings".base64.decode;
+local saslprep = require "util.encodings".stringprep.saslprep;
+local realm = module:get_host() .. "/" .. module:get_name();
+module:depends"http";
+
+local function authenticate (event, path)
+	local request = event.request;
+	local response = event.response;
+	local headers = request.headers;
+	if not headers.authorization then
+		return 400
+	end
+	local from_jid, password = b64_decode(headers.authorization:match"[^ ]*$"):match"([^:]*):(.*)";
+	from_jid = jid_prep(from_jid);
+	password = saslprep(password);
+	if from_jid and password then
+		local user, host = jid_split(from_jid);
+		local ok, err = test_password(user, host, password);
+		if ok and user and host then
+			return 200
+		elseif err then
+			return 401
+		end
+	end
+end
+
+module:provides("http", {
+	route = {
+		GET = authenticate
+	};
+});