annotate mod_auth_http_async/mod_auth_http_async.lua @ 5472:b80b6947b079

mod_http_oauth2: Always show early errors to user Before having validated the client_id, communicating an error back to the client via redirect would make this an open redirect, so we may just as well skip past that logic, and especially the warning log message.
author Kim Alvefur <zash@zash.se>
date Thu, 18 May 2023 13:43:17 +0200
parents 39156d6f7268
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1421
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
1 -- Prosody IM
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
2 -- Copyright (C) 2008-2013 Matthew Wild
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
3 -- Copyright (C) 2008-2013 Waqas Hussain
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
4 -- Copyright (C) 2014 Kim Alvefur
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
5 --
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
6 -- This project is MIT/X11 licensed. Please see the
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
7 -- COPYING file in the source package for more information.
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
8 --
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
9
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
10 local new_sasl = require "util.sasl".new;
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
11 local base64 = require "util.encodings".base64.encode;
2159
5e8dec076afc mod_auth_http_async: Fall back to non-async calling of http_auth_url
JC Brand <jcbrand@minddistrict.com>
parents: 1939
diff changeset
12 local have_async, async = pcall(require, "util.async");
1421
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
13
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
14 local log = module._log;
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
15 local host = module.host;
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
16
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
17 local api_base = module:get_option_string("http_auth_url", ""):gsub("$host", host);
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
18 if api_base == "" then error("http_auth_url required") end
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
19
2629
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
20 local provider = {};
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
21
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
22 -- globals required by socket.http
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
23 if rawget(_G, "PROXY") == nil then
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
24 rawset(_G, "PROXY", false)
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
25 end
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
26 if rawget(_G, "base_parsed") == nil then
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
27 rawset(_G, "base_parsed", false)
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
28 end
2811
39156d6f7268 mod_auth_http_async: Allow LuaSocket to pollute the global scope (fixes #1033)
Kim Alvefur <zash@zash.se>
parents: 2750
diff changeset
29 if not have_async then -- FINE! Set your globals then
39156d6f7268 mod_auth_http_async: Allow LuaSocket to pollute the global scope (fixes #1033)
Kim Alvefur <zash@zash.se>
parents: 2750
diff changeset
30 prosody.unlock_globals()
39156d6f7268 mod_auth_http_async: Allow LuaSocket to pollute the global scope (fixes #1033)
Kim Alvefur <zash@zash.se>
parents: 2750
diff changeset
31 require "ltn12"
39156d6f7268 mod_auth_http_async: Allow LuaSocket to pollute the global scope (fixes #1033)
Kim Alvefur <zash@zash.se>
parents: 2750
diff changeset
32 require "socket"
39156d6f7268 mod_auth_http_async: Allow LuaSocket to pollute the global scope (fixes #1033)
Kim Alvefur <zash@zash.se>
parents: 2750
diff changeset
33 require "socket.http"
39156d6f7268 mod_auth_http_async: Allow LuaSocket to pollute the global scope (fixes #1033)
Kim Alvefur <zash@zash.se>
parents: 2750
diff changeset
34 require "ssl.https"
39156d6f7268 mod_auth_http_async: Allow LuaSocket to pollute the global scope (fixes #1033)
Kim Alvefur <zash@zash.se>
parents: 2750
diff changeset
35 prosody.lock_globals()
39156d6f7268 mod_auth_http_async: Allow LuaSocket to pollute the global scope (fixes #1033)
Kim Alvefur <zash@zash.se>
parents: 2750
diff changeset
36 end
2629
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
37
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
38 local function async_http_auth(url, username, password)
2811
39156d6f7268 mod_auth_http_async: Allow LuaSocket to pollute the global scope (fixes #1033)
Kim Alvefur <zash@zash.se>
parents: 2750
diff changeset
39 module:log("debug", "async_http_auth()");
2630
96eb1c4f9ff7 mod_auth_http_async: Use "net.http" for async case.
JC Brand <jc@opkode.com>
parents: 2629
diff changeset
40 local http = require "net.http";
2159
5e8dec076afc mod_auth_http_async: Fall back to non-async calling of http_auth_url
JC Brand <jcbrand@minddistrict.com>
parents: 1939
diff changeset
41 local wait, done = async.waiter();
1927
439711709d29 mod_auth_http_async: Wrap up async http request in a function
Kim Alvefur <zash@zash.se>
parents: 1749
diff changeset
42 local content, code, request, response;
2629
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
43 local ex = {
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
44 headers = { Authorization = "Basic "..base64(username..":"..password); };
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
45 }
1930
95bbf3c4aa27 mod_auth_http_async: Don't set global
Kim Alvefur <zash@zash.se>
parents: 1927
diff changeset
46 local function cb(content_, code_, request_, response_)
1927
439711709d29 mod_auth_http_async: Wrap up async http request in a function
Kim Alvefur <zash@zash.se>
parents: 1749
diff changeset
47 content, code, request, response = content_, code_, request_, response_;
439711709d29 mod_auth_http_async: Wrap up async http request in a function
Kim Alvefur <zash@zash.se>
parents: 1749
diff changeset
48 done();
439711709d29 mod_auth_http_async: Wrap up async http request in a function
Kim Alvefur <zash@zash.se>
parents: 1749
diff changeset
49 end
1931
bd5412eb0a6d mod_auth_http_async: Actually do the HTTP request
Kim Alvefur <zash@zash.se>
parents: 1930
diff changeset
50 http.request(url, ex, cb);
1927
439711709d29 mod_auth_http_async: Wrap up async http request in a function
Kim Alvefur <zash@zash.se>
parents: 1749
diff changeset
51 wait();
2629
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
52 if code >= 200 and code <= 299 then
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
53 module:log("debug", "HTTP auth provider confirmed valid password");
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
54 return true;
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
55 else
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
56 module:log("debug", "HTTP auth provider returned status code %d", code);
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
57 end
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
58 return nil, "Auth failed. Invalid username or password.";
1927
439711709d29 mod_auth_http_async: Wrap up async http request in a function
Kim Alvefur <zash@zash.se>
parents: 1749
diff changeset
59 end
439711709d29 mod_auth_http_async: Wrap up async http request in a function
Kim Alvefur <zash@zash.se>
parents: 1749
diff changeset
60
2750
1d139e33c502 mod_auth_http_async: Updated sync_http_auth function to accept username and password and send those as a basic authentication header
Matt Loupe <mloupe2@gmail.com>
parents: 2630
diff changeset
61 local function sync_http_auth(url,username, password)
2811
39156d6f7268 mod_auth_http_async: Allow LuaSocket to pollute the global scope (fixes #1033)
Kim Alvefur <zash@zash.se>
parents: 2750
diff changeset
62 module:log("debug", "sync_http_auth()");
39156d6f7268 mod_auth_http_async: Allow LuaSocket to pollute the global scope (fixes #1033)
Kim Alvefur <zash@zash.se>
parents: 2750
diff changeset
63 require "ltn12";
2630
96eb1c4f9ff7 mod_auth_http_async: Use "net.http" for async case.
JC Brand <jc@opkode.com>
parents: 2629
diff changeset
64 local http = require "socket.http";
96eb1c4f9ff7 mod_auth_http_async: Use "net.http" for async case.
JC Brand <jc@opkode.com>
parents: 2629
diff changeset
65 local https = require "ssl.https";
2629
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
66 local request;
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
67 if string.sub(url, 1, string.len('https')) == 'https' then
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
68 request = https.request;
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
69 else
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
70 request = http.request;
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
71 end
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
72 local _, code, headers, status = request{
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
73 url = url,
2750
1d139e33c502 mod_auth_http_async: Updated sync_http_auth function to accept username and password and send those as a basic authentication header
Matt Loupe <mloupe2@gmail.com>
parents: 2630
diff changeset
74 headers = { Authorization = "Basic "..base64(username..":"..password); }
2629
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
75 };
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
76 if type(code) == "number" and code >= 200 and code <= 299 then
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
77 module:log("debug", "HTTP auth provider confirmed valid password");
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
78 return true;
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
79 else
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
80 module:log("debug", "HTTP auth provider returned status code: "..code);
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
81 end
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
82 return nil, "Auth failed. Invalid username or password.";
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
83 end
1421
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
84
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
85 function provider.test_password(username, password)
2629
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
86 local url = api_base:gsub("$user", username):gsub("$password", password);
2442
b2a198665946 mod_auth_http_async: Log URL when testing password
JC Brand <jc@opkode.com>
parents: 2159
diff changeset
87 log("debug", "Testing password for user %s at host %s with URL %s", username, host, url);
2159
5e8dec076afc mod_auth_http_async: Fall back to non-async calling of http_auth_url
JC Brand <jcbrand@minddistrict.com>
parents: 1939
diff changeset
88 if (have_async) then
2629
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
89 return async_http_auth(url, username, password);
1421
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
90 else
2750
1d139e33c502 mod_auth_http_async: Updated sync_http_auth function to accept username and password and send those as a basic authentication header
Matt Loupe <mloupe2@gmail.com>
parents: 2630
diff changeset
91 return sync_http_auth(url, username, password);
1421
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
92 end
2629
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
93 end
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
94
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
95 function provider.users()
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
96 return function()
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
97 return nil;
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
98 end
1421
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
99 end
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
100
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
101 function provider.set_password(username, password)
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
102 return nil, "Changing passwords not supported";
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
103 end
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
104
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
105 function provider.user_exists(username)
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
106 return true;
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
107 end
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
108
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
109 function provider.create_user(username, password)
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
110 return nil, "User creation not supported";
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
111 end
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
112
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
113 function provider.delete_user(username)
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
114 return nil , "User deletion not supported";
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
115 end
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
116
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
117 function provider.get_sasl_handler()
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
118 return new_sasl(host, {
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
119 plain_test = function(sasl, username, password, realm)
1939
54f9e8663139 mod_auth_http_async: Correctly pass password to provider.test_password (thanks mother)
Kim Alvefur <zash@zash.se>
parents: 1938
diff changeset
120 return provider.test_password(username, password), true;
1421
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
121 end
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
122 });
295c30e44ba8 mod_auth_http_async: Async HTTP auth module
Kim Alvefur <zash@zash.se>
parents:
diff changeset
123 end
2629
a11568bfaf4c mod_auth_http_async: For sync calls, use LuaSockets' HTTP lib
JC Brand <jc@opkode.com>
parents: 2442
diff changeset
124
2811
39156d6f7268 mod_auth_http_async: Allow LuaSocket to pollute the global scope (fixes #1033)
Kim Alvefur <zash@zash.se>
parents: 2750
diff changeset
125 module:provides("auth", provider);