Skip to content

Instantly share code, notes, and snippets.

@bangarangadang
Created December 5, 2016 00:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bangarangadang/4c4d50192ec2984cc6341664f5665f7b to your computer and use it in GitHub Desktop.
Save bangarangadang/4c4d50192ec2984cc6341664f5665f7b to your computer and use it in GitHub Desktop.
Discourse Authentication Module for Prosody
-- Discourse Authentication Module for Prosody
-- https://meta.discourse.org/t/use-discourse-for-sso-in-a-non-web-app/40584/9
--
local new_sasl = require "util.sasl".new;
local http = require "net.http";
local json = require "util.json";
local log = module._log;
local host = module.host;
local discourse_url = module:get_option_string("discourse_url", ""):gsub("$host", host);
if discourse_url == "" then error("discourse_url required") end
local function discourse(username, password)
module:log("debug", "fetching token for user %s", username);
local url = discourse_url:gsub("$user", username);
local credentials = {
{ name = "login", value = username };
{ name = "password", value = password };
}
local function discourse_verify(response, code)
module:log("debug", "response: %s", response);
if string.match(response, '"username":"(.-)"') == username:gsub("^%l", string.upper) then
module:log("debug", "login successful for user: %s", username)
else
module:log("debug", "login failed for user: %s", username)
end
end
local function discourse_login(response, code, request)
csrf = string.match(response, '"csrf":"(.-)"');
cookie = string.match(request.responseheaders["set-cookie"], '(.-);');
module:log("debug", "csrf: %s", csrf);
module:log("debug", "cookie: %s", cookie);
if csrf == nil or cookie == nil then
module:log("debug", "no csrf or cookie fetched for user %s. abort login", username);
else
module:log("debug", "trying to login with fetched csrf and cookie for user %s", username);
local ex = {
headers = {
["Origin"] = url,
["X-CSRF-Token"] = csrf,
["Cookie"] = cookie,
["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8",
["Referer"] = url,
["X-Requested-With"] = "XMLHttpRequest"
};
body = http.formencode(credentials);
}
http.request (url .. "session", ex, discourse_verify)
end
end
local ex = {
headers = {
["X-CSRF-Token"] = "undefined",
["Referer"] = url,
["X-Requested-With"] = "XMLHttpRequest"
};
}
http.request(url .. "session/csrf", ex, discourse_login);
end
local provider = {};
function provider.test_password(username, password)
return nil, "Not supported"
end
function provider.get_password(username)
return nil, "Not supported"
end
function provider.set_password(username, password)
return nil, "Not supported"
end
function provider.user_exists(username)
return true;
end
function provider.create_user(username, password)
return nil, "Not supported"
end
function provider.delete_user(username)
return nil, "Not supported"
end
function provider.get_sasl_handler()
return new_sasl(host, {
plain_test = function(sasl, username, password, realm)
return discourse(username, password), true;
end
});
end
module:provides("auth", provider);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment