processone / ejabberd-contrib

Growing and curated ejabberd contributions repository - PR or ask to join !
http://ejabberd.im
248 stars 137 forks source link

ejabberd_auth_http: How to get registered users or search for users? #272

Closed vkelman closed 5 years ago

vkelman commented 5 years ago

It's probably not an issue but my lack of understanding.

I used the default ejabberd 19.02 installation on Windows with its default Mnesia storage. I registered one additional user in command window by running ejabberdctl register vkelman planetrisk.com vkelman I can see two registered users (an admin I created during installation and vkelman I registered above) either by issuing ejabberdctl registered_users planetrisk.com or by using Web admin interface.

Now, I installed ejabberd_auth_http, and set

auth_method: http
auth_opts:
  host: "http://localhost"
  connection_pool_size: 10
  connection_opts: []
  basic_auth: ""
  path_prefix: "/services/imd35000/api/v1/ejabberd/"

auth_use_cache: false

I created a simple Web Api app with a controller which two GET methods listening on http://localhost/services/imd35000/api/v1/ejabberd/check_password and http://localhost/services/imd35000/api/v1/ejabberd/user_exists

When I open ejabberd web admin console I see that a break point inside check_password is hit.

Now, neither web admin console nor ejabberdctl registered_users planetrisk.com shows registered users anymore. Apparently they cannot access the list of registered users if auth_method: http.

Sometimes (but not always, I couldn't get any pattern) ejabberd logs show error / crash related to ejabberd_auth_http:

2019-04-25 17:19:10.017 [error] <0.522.0>@ejabberd_auth_http:make_req:225 Supervisor ejabberd_http_sup had child undefined started with {ejabberd_http,start_link,undefined} at <0.560.0> exit with reason no match of right hand value {error,timeout} in ejabberd_auth_http:make_req/5 line 225 in context child_terminated 2019-04-25 17:19:15.231 [error] <0.561.0>@ejabberd_auth_http:make_req:225 CRASH REPORT Process <0.561.0> with 0 neighbours crashed with reason: no match of right hand value {error,timeout} in ejabberd_auth_http:make_req/5 line 225

What I don't understand: after we switch from default authentication to ejabberd_auth_http, does ejabberd still use and maintain its internal Mnesia database with users?

@badlop , in https://github.com/processone/ejabberd-contrib/issues/266 you said, "you can use an authentication method (mnesia, sql, external script, whatever), and configure the modules to use whatever storage method you want." So, persistence mechanism like Mnesia or SQL should work regardless of using ejabberd_auth_http, that's what you're saying? What if I implement necessary REST points like register, remove_user for ejabberd_auth_http to use? Would Mnesia user storage still be maintained by ejabberd? If not, then how could the list of registered users be obtained? I don't see that ejabberd_auth_http provides an API for getting user list or XEP-0055: Jabber Search.

I tried to use an external script written in C# as ejabberd authentication method instead. I see the same results as with using ejabberd_auth_http: I can log in, but cannot get the list of users.

badlop commented 5 years ago

Now, neither web admin console nor ejabberdctl registered_users planetrisk.com shows registered users anymore. Apparently they cannot access the list of registered users if auth_method: http.

Right. If you look at ejabberd_auth_http.erl exported functions, none of them provides the list of accounts.

What I don't understand: after we switch from default authentication to ejabberd_auth_http, does ejabberd still use and maintain its internal Mnesia database with users?

No, it uses whtaever auth method is configured, both for registering, authenticating...

@badlop , in #266 you said, "you can use an authentication method (mnesia, sql, external script, whatever), and configure the modules to use whatever storage method you want." So, persistence mechanism like Mnesia or SQL should work regardless of using ejabberd_auth_http, that's what you're saying?

It means that authenticating accounts can be done using ejabberd_auth_mnesia, or ejabberd_auth_http, or ldap..., or any other of the available. And later, mod_roster can be configured to store the roster items in any other method supported by mod_roster, like mnesia, ODBC, or whatever. Same for mod_private, and any other modules.

What if I implement necessary REST points like register, remove_user for ejabberd_auth_http to use? Would Mnesia user storage still be maintained by ejabberd?

No, it doesn't.

If not, then how could the list of registered users be obtained? I don't see that ejabberd_auth_http provides an API for getting user list or XEP-0055: Jabber Search.

Exactly, that's what you found: ejabberd_auth_http does not provide a get_users function, so the feature of seeing the list of users in ejabberd admin tools does not work.

I tried to use an external script written in C# as ejabberd authentication method instead. I see the same results as with using ejabberd_auth_http: I can log in, but cannot get the list of users.

Right. And in that case, you will see that ejabberd_auth_external.erl doesn't provide a get_users function either.

Solution: to implement such a function. For testing purposes, I apply this simple change:

diff --git a/src/ejabberd_auth_external.erl b/src/ejabberd_auth_external.erl
index 6b2e2852e..7cc49eae4 100644
--- a/src/ejabberd_auth_external.erl
+++ b/src/ejabberd_auth_external.erl
@@ -33,10 +33,14 @@

 -export([start/1, stop/1, reload/1, set_password/3, check_password/4,
     try_register/3, user_exists/2, remove_user/2,
+    get_users/2,
     store_type/1, plain_password_required/1, opt_type/1]).

 -include("logger.hrl").

+get_users(Server, _Options) ->
+    [{<<"user111">>, Server}, {<<"user222">>, Server}].
+
 %%%----------------------------------------------------------------------
 %%% API
 %%%----------------------------------------------------------------------

Then configure like this:

auth_method: external

And this finally works:

$ ejabberdctl registered_users localhost
user111
user222
vkelman commented 5 years ago

Thank you. You answered my questions. Unfortunately, I'm not Erlang developer (yet). And my knowledge of XMPP protocols is not sufficient. For now I switched to default ejabberd authentication mechanism and am using ejabberd ReST API to sync user base of our system with user base of ejabberd. ReST API is quite good and comprehensive.

P.S. I know that ejabberd implements XEP-0055: Jabber Search protocol https://xmpp.org/extensions/xep-0055.html. I assume it's related to the registered_users functionality. So, when somebody is using external script or ejabberd_auth_http, search functionality needs to be re-implemented as well.