comparison mod_auth_oauth_external/mod_auth_oauth_external.lua @ 6364:9c110fbecd86

mod_auth_oauth_external: Record existence of users This allows iterating over users as well as existence checks.
author Kim Alvefur <zash@zash.se>
date Sat, 17 Jan 2026 05:14:25 +0100
parents 97a9f939d472
children 42866d42e267
comparison
equal deleted inserted replaced
6363:8f65b23a5fd2 6364:9c110fbecd86
25 registration -> { client_id client_secret } 25 registration -> { client_id client_secret }
26 { client_id client_secret validation } -> required 26 { client_id client_secret validation } -> required
27 } 27 }
28 --]] 28 --]]
29 29
30 local accounts = module:open_store("accounts");
31
30 local host = module.host; 32 local host = module.host;
31 local provider = {}; 33 local provider = {};
32 34
35 -- TODO remove, not needed after https://hg.prosody.im/trunk/rev/01f95f3de6fc
33 local function not_implemented() 36 local function not_implemented()
34 return nil, "method not implemented" 37 return nil, "method not implemented"
35 end 38 end
36 39
37 -- With proper OAuth 2, most of these should be handled at the authorization 40 -- With proper OAuth 2, most of these should be handled at the authorization
40 provider.get_password = not_implemented; 43 provider.get_password = not_implemented;
41 provider.set_password = not_implemented; 44 provider.set_password = not_implemented;
42 provider.create_user = not_implemented; 45 provider.create_user = not_implemented;
43 provider.delete_user = not_implemented; 46 provider.delete_user = not_implemented;
44 47
45 function provider.user_exists(_username) 48 function provider.get_account_info(username)
46 -- Can this even be done in a generic way in OAuth 2? 49 local account = accounts:get(username);
47 -- OIDC and WebFinger perhaps? 50 if not account then return nil, "Account not available"; end
48 return true; 51 return {
52 created = account.created;
53 password_updated = account.updated;
54 enabled = not account.disabled;
55 };
56 end
57
58 function provider.user_exists(username)
59 local account, err = accounts:get(username);
60 if err then
61 return nil, err;
62 elseif account then
63 return true;
64 else
65 return false
66 end
49 end 67 end
50 68
51 function provider.users() 69 function provider.users()
52 -- TODO this could be done by recording known users locally 70 return accounts:users();
53 return function ()
54 module:log("debug", "User iteration not supported");
55 return nil;
56 end
57 end 71 end
58 72
59 function provider.get_sasl_handler() 73 function provider.get_sasl_handler()
60 local profile = {}; 74 local profile = {};
61 profile.http_client = http.default:new({ connection_pooling = true }); -- TODO configurable 75 profile.http_client = http.default:new({ connection_pooling = true }); -- TODO configurable
84 end 98 end
85 if not validation_endpoint then 99 if not validation_endpoint then
86 -- We're not going to get more info, only the username 100 -- We're not going to get more info, only the username
87 self.username = jid.escape(username); 101 self.username = jid.escape(username);
88 self.token_info = token_resp; 102 self.token_info = token_resp;
103 accounts:set(self.username, { exists = true });
89 return true, true; 104 return true, true;
90 end 105 end
91 local ret, err = async.wait_for(self.profile.http_client:request(validation_endpoint, 106 local ret, err = async.wait_for(self.profile.http_client:request(validation_endpoint,
92 { headers = { ["Authorization"] = "Bearer " .. token_resp.access_token; ["Accept"] = "application/json" } })); 107 { headers = { ["Authorization"] = "Bearer " .. token_resp.access_token; ["Accept"] = "application/json" } }));
93 if err then 108 if err then
102 elseif type(response[username_field]) ~= "string" then 117 elseif type(response[username_field]) ~= "string" then
103 return false, nil, nil; 118 return false, nil, nil;
104 end 119 end
105 self.username = jid.escape(response[username_field]); 120 self.username = jid.escape(response[username_field]);
106 self.token_info = response; 121 self.token_info = response;
122 accounts:set(self.username, { exists = true });
107 return true, true; 123 return true, true;
108 end 124 end
109 end 125 end
110 if validation_endpoint then 126 if validation_endpoint then
111 function profile:oauthbearer(token) 127 function profile:oauthbearer(token)