view mod_auth_http_async/mod_auth_http_async.lua @ 2159:5e8dec076afc

mod_auth_http_async: Fall back to non-async calling of http_auth_url if util.async is not available
author JC Brand <jcbrand@minddistrict.com>
date Fri, 15 Apr 2016 13:45:01 +0000
parents 54f9e8663139
children b2a198665946
line wrap: on
line source

-- Prosody IM
-- Copyright (C) 2008-2013 Matthew Wild
-- Copyright (C) 2008-2013 Waqas Hussain
-- Copyright (C) 2014 Kim Alvefur
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--

local new_sasl = require "util.sasl".new;
local base64 = require "util.encodings".base64.encode;
local have_async, async = pcall(require, "util.async");
local http = require "net.http";

local log = module._log;
local host = module.host;

local api_base = module:get_option_string("http_auth_url",  ""):gsub("$host", host);
if api_base == "" then error("http_auth_url required") end

local function async_http_request(url, ex)
	local wait, done = async.waiter();
	local content, code, request, response;
	local function cb(content_, code_, request_, response_)
		content, code, request, response = content_, code_, request_, response_;
		done();
	end
	http.request(url, ex, cb);
	wait();
	return content, code, request, response;
end

local provider = {};

function provider.test_password(username, password)
	log("debug", "test password for user %s at host %s", username, host);
	local url = api_base:gsub("$user", username);
	local ex = {
		headers = { Authorization = "Basic "..base64(username..":"..password); };
	}
	if (have_async) then
	    local _, code = async_http_request(url, ex);
	    if code >= 200 and code <= 299 then
			module:log("debug", "HTTP auth provider confirmed valid password");
	        return true;
	    else
	        module:log("debug", "HTTP auth provider returned status code %d", code);
	    end
	else
	    local ok, err = http.request(url, ex, function(body, code)
			if code >= 200 and code <= 299 then
				module:log("debug", "HTTP auth provider confirmed valid password");
			else
				module:log("debug", "HTTP auth provider returned status code %d", code);
			end
		end);
	    if ok then
	        return true;
	    end
	end
	return nil, "Auth failed. Invalid username or password.";
end

function provider.set_password(username, password)
	return nil, "Changing passwords not supported";
end

function provider.user_exists(username)
	return true;
end

function provider.create_user(username, password)
	return nil, "User creation not supported";
end

function provider.delete_user(username)
	return nil , "User deletion not supported";
end

function provider.get_sasl_handler()
	return new_sasl(host, {
		plain_test = function(sasl, username, password, realm)
			return provider.test_password(username, password), true;
		end
	});
end
	
module:provides("auth", provider);