--- 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 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
-local function get_group_query()
- -- if there's no groups, just return an empty string
- if #hub_groups == 0 then
+local group_query = collect(hub_groups):map( + return string.format("in:%q", item)
- -- 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 ") .. "\")"
-local group_query = get_group_query()
@@ -68,10 +62,13 @@
- body = http.formencode(body);
- local function cb(content_, code_, request_, response_)
+ if body and #body > 0 then + ex["body"] = formencode(body); + local function cb(content_, code_, response_, request_) code, response = code_, response_.body;
@@ -105,10 +102,13 @@
local _, code, _ = request{
- body = http.formencode(body),
sink = ltn12.sink.table(t),
+ if body and #body > 0 then + request['body'] = formencode(body) content = table.concat(t),
@@ -117,20 +117,29 @@
local function check_group(username, token)
- local headers = { Authorization = "Bearer "..token; };
+ Authorization = "Bearer "..token; { 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) - 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" + 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" @@ -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); };
+ Authorization = "Basic "..base64(hub_client_id..":"..hub_client_secret); { 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)
+ return check_group(username, json_payload.access_token) module:log("debug", "HTTP auth provider returned status code %d", resp.code);