Mercurial > prosody-modules
comparison mod_auth_http_async/mod_auth_http_async.lua @ 2629:a11568bfaf4c
mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
| author | JC Brand <jc@opkode.com> |
|---|---|
| date | Tue, 21 Mar 2017 09:14:03 +0000 |
| parents | b2a198665946 |
| children | 96eb1c4f9ff7 |
comparison
equal
deleted
inserted
replaced
| 2628:fbb26a56a667 | 2629:a11568bfaf4c |
|---|---|
| 6 -- This project is MIT/X11 licensed. Please see the | 6 -- This project is MIT/X11 licensed. Please see the |
| 7 -- COPYING file in the source package for more information. | 7 -- COPYING file in the source package for more information. |
| 8 -- | 8 -- |
| 9 | 9 |
| 10 local new_sasl = require "util.sasl".new; | 10 local new_sasl = require "util.sasl".new; |
| 11 local http = require "socket.http"; | |
| 12 local https = require "ssl.https"; | |
| 11 local base64 = require "util.encodings".base64.encode; | 13 local base64 = require "util.encodings".base64.encode; |
| 12 local have_async, async = pcall(require, "util.async"); | 14 local have_async, async = pcall(require, "util.async"); |
| 13 local http = require "net.http"; | |
| 14 | 15 |
| 15 local log = module._log; | 16 local log = module._log; |
| 16 local host = module.host; | 17 local host = module.host; |
| 17 | 18 |
| 18 local api_base = module:get_option_string("http_auth_url", ""):gsub("$host", host); | 19 local api_base = module:get_option_string("http_auth_url", ""):gsub("$host", host); |
| 19 if api_base == "" then error("http_auth_url required") end | 20 if api_base == "" then error("http_auth_url required") end |
| 20 | 21 |
| 21 local function async_http_request(url, ex) | 22 local provider = {}; |
| 23 | |
| 24 -- globals required by socket.http | |
| 25 if rawget(_G, "PROXY") == nil then | |
| 26 rawset(_G, "PROXY", false) | |
| 27 end | |
| 28 if rawget(_G, "base_parsed") == nil then | |
| 29 rawset(_G, "base_parsed", false) | |
| 30 end | |
| 31 | |
| 32 local function async_http_auth(url, username, password) | |
| 22 local wait, done = async.waiter(); | 33 local wait, done = async.waiter(); |
| 23 local content, code, request, response; | 34 local content, code, request, response; |
| 35 local ex = { | |
| 36 headers = { Authorization = "Basic "..base64(username..":"..password); }; | |
| 37 } | |
| 24 local function cb(content_, code_, request_, response_) | 38 local function cb(content_, code_, request_, response_) |
| 25 content, code, request, response = content_, code_, request_, response_; | 39 content, code, request, response = content_, code_, request_, response_; |
| 26 done(); | 40 done(); |
| 27 end | 41 end |
| 28 http.request(url, ex, cb); | 42 http.request(url, ex, cb); |
| 29 wait(); | 43 wait(); |
| 30 return content, code, request, response; | 44 if code >= 200 and code <= 299 then |
| 45 module:log("debug", "HTTP auth provider confirmed valid password"); | |
| 46 return true; | |
| 47 else | |
| 48 module:log("debug", "HTTP auth provider returned status code %d", code); | |
| 49 end | |
| 50 return nil, "Auth failed. Invalid username or password."; | |
| 31 end | 51 end |
| 32 | 52 |
| 33 local provider = {}; | 53 local function sync_http_auth(url) |
| 54 local request; | |
| 55 if string.sub(url, 1, string.len('https')) == 'https' then | |
| 56 request = https.request; | |
| 57 else | |
| 58 request = http.request; | |
| 59 end | |
| 60 local _, code, headers, status = request{ | |
| 61 url = url, | |
| 62 headers = { ACCEPT = "application/json, text/plain, */*"; } | |
| 63 }; | |
| 64 if type(code) == "number" and code >= 200 and code <= 299 then | |
| 65 module:log("debug", "HTTP auth provider confirmed valid password"); | |
| 66 return true; | |
| 67 else | |
| 68 module:log("debug", "HTTP auth provider returned status code: "..code); | |
| 69 end | |
| 70 return nil, "Auth failed. Invalid username or password."; | |
| 71 end | |
| 34 | 72 |
| 35 function provider.test_password(username, password) | 73 function provider.test_password(username, password) |
| 36 local url = api_base:gsub("$user", username); | 74 local url = api_base:gsub("$user", username):gsub("$password", password); |
| 37 log("debug", "Testing password for user %s at host %s with URL %s", username, host, url); | 75 log("debug", "Testing password for user %s at host %s with URL %s", username, host, url); |
| 38 local ex = { | |
| 39 headers = { Authorization = "Basic "..base64(username..":"..password); }; | |
| 40 } | |
| 41 if (have_async) then | 76 if (have_async) then |
| 42 local _, code = async_http_request(url, ex); | 77 return async_http_auth(url, username, password); |
| 43 if code >= 200 and code <= 299 then | |
| 44 module:log("debug", "HTTP auth provider confirmed valid password"); | |
| 45 return true; | |
| 46 else | |
| 47 module:log("debug", "HTTP auth provider returned status code %d", code); | |
| 48 end | |
| 49 else | 78 else |
| 50 local ok, err = http.request(url, ex, function(body, code) | 79 return sync_http_auth(url); |
| 51 if code >= 200 and code <= 299 then | |
| 52 module:log("debug", "HTTP auth provider confirmed valid password"); | |
| 53 else | |
| 54 module:log("debug", "HTTP auth provider returned status code %d", code); | |
| 55 end | |
| 56 end); | |
| 57 if ok then | |
| 58 return true; | |
| 59 end | |
| 60 end | 80 end |
| 61 return nil, "Auth failed. Invalid username or password."; | 81 end |
| 82 | |
| 83 function provider.users() | |
| 84 return function() | |
| 85 return nil; | |
| 86 end | |
| 62 end | 87 end |
| 63 | 88 |
| 64 function provider.set_password(username, password) | 89 function provider.set_password(username, password) |
| 65 return nil, "Changing passwords not supported"; | 90 return nil, "Changing passwords not supported"; |
| 66 end | 91 end |
| 82 plain_test = function(sasl, username, password, realm) | 107 plain_test = function(sasl, username, password, realm) |
| 83 return provider.test_password(username, password), true; | 108 return provider.test_password(username, password), true; |
| 84 end | 109 end |
| 85 }); | 110 }); |
| 86 end | 111 end |
| 87 | 112 |
| 88 module:provides("auth", provider); | 113 module:provides("auth", provider); |
