grim/prosody_mod_auth_jetbrains_hub

d3192c27e286
Parents acb40e1d5fac
Children 58723e5d2735
Lots of cleanups including group checking that actually works
--- a/mod_auth_jetbrains_hub.lua Sun Nov 03 04:05:36 2019 -0600
+++ b/mod_auth_jetbrains_hub.lua Thu Feb 11 06:00:22 2021 -0600
@@ -11,7 +11,9 @@
local new_sasl = require "util.sasl".new;
local base64 = require "util.encodings".base64.encode;
local json_decode = require "util.json".decode
+local formencode = require "util.http".formencode
local have_async, async = pcall(require, "util.async");
+local collect = require "util.array".collect
local log = module._log;
local host = module.host;
@@ -30,23 +32,15 @@
if not hub_client_secret then error("jetbrains_hub_client_secret required") end
local hub_groups = module:get_option_set("jetbrains_hub_groups", {});
+if hub_groups:empty() then error("jetbrains_hub_groups must specify at least one group") end
-- we only need to update the group part of the query once on load so do it
-- right away
-local function get_group_query()
- -- if there's no groups, just return an empty string
- if #hub_groups == 0 then
- return ""
+local group_query = collect(hub_groups):map(
+ function(item)
+ return string.format("in:%q", item)
end
-
- -- we have at least one group, so build the query that checks that the user
- -- is in at least one of the groups. For example, if we groups was set to
- -- {"admins", "users"} the results of this would be:
- -- ' and (in:"admins" or in:"users")'
- return " and (in:\"" .. table.concat(hub_groups, " or ") .. "\")"
-end
-
-local group_query = get_group_query()
+):concat(" or ")
local provider = {};
@@ -68,10 +62,13 @@
local ex = {
headers = headers;
- body = http.formencode(body);
}
- local function cb(content_, code_, request_, response_)
+ if body and #body > 0 then
+ ex["body"] = formencode(body);
+ end
+
+ local function cb(content_, code_, response_, request_)
code, response = code_, response_.body;
done();
end
@@ -105,10 +102,13 @@
local _, code, _ = request{
url = url,
headers = headers,
- body = http.formencode(body),
sink = ltn12.sink.table(t),
};
+ if body and #body > 0 then
+ request['body'] = formencode(body)
+ end
+
return {
code = code,
content = table.concat(t),
@@ -117,20 +117,29 @@
end
local function check_group(username, token)
- local headers = { Authorization = "Bearer "..token; };
- local body = {
+ local headers = {
+ Authorization = "Bearer "..token;
+ };
+ local params = {
{ name = "$top", value = "1" };
- { name = "query", value = "login:"..username..group_query };
- { name = "fields", value = "type" };
+ { name = "query", value = string.format("login:%s and (%s)", username, group_query )};
+ { name = "fields", value = "login" };
}
- local resp = http_request(hub_url .. "/api/rest/users", headers, body)
+ local url = string.format('%s/api/rest/users?%s', hub_url, formencode(params))
+ local resp = http_request(url, headers, nil)
if resp.code == 200 then
- local json_payload = json_decode(response.body);
+ local json_payload = json_decode(resp.content);
if json_payload.total ~= 1 then
- return nil, "Permission denied";
+ module:log("warn", "user %q authenticated but is not in any approved groups", username)
+ return nil, "Permission denied"
+ end
+
+ if json_payload.users[1]['login'] ~= username then
+ module:log("warn", "user %q authenticated is in an approved group but the returned username was different", username)
+ return nil, "Permission denied"
end
return true;
@@ -141,7 +150,9 @@
function provider.test_password(username, password)
module:log("debug", "testing password for jbhub auth")
- local headers = { Authorization = "Basic "..base64(hub_client_id..":"..hub_client_secret); };
+ local headers = {
+ Authorization = "Basic "..base64(hub_client_id..":"..hub_client_secret);
+ };
local body = {
{ name = "grant_type", value = "password" };
{ name = "username", value = username };
@@ -153,13 +164,10 @@
if resp.code >= 200 and resp.code <= 299 then
module:log("debug", "HTTP auth provider confirmed valid password");
- if #hub_groups > 0 then
- local json_payload = json_decode(resp.content);
+ -- a group is required to we need to do that check now.
+ local json_payload = json_decode(resp.content);
- return async_group_check(username, json_payload.access_token)
- end
-
- return true;
+ return check_group(username, json_payload.access_token)
else
module:log("debug", "HTTP auth provider returned status code %d", resp.code);
end