Automatically registering new users by admin

975 views
Skip to first unread message

Szymon Nowak

unread,
Jun 8, 2011, 4:13:06 PM6/8/11
to str...@googlegroups.com
Hey,

I've got a web site with XMPP based chat (how original :)) and I'd like to automatically create XMPP account for every user who registers on my site. I'm using ejabberd server and I know that I can create new users with ejabberdctl command, but I don't really want to do it by executing a system command. I read a bit about in-band registration, but it looks like it allows anybody to register - I'd like only authorized user(s) to be able to register new users. Ejabberd provides admin web interface where it's possible to register new users, so I guess it is somehow possible to do what I want, but I have no idea how.

Cheers,
Szymon

Dingding Ye

unread,
Jun 8, 2011, 4:18:11 PM6/8/11
to str...@googlegroups.com
Hey, Szymon.

I think you can use any xmpp client to communicate with the server directly. So just follow the protocol and do the auto registration once a user signup in your site.

Best regards.

Dingding Ye

-- 
Dingding Ye

--
You received this message because you are subscribed to the Google Groups "Strophe" group.
To view this discussion on the web visit https://groups.google.com/d/msg/strophe/-/S3pBOXk3dmI2MHdK.
To post to this group, send email to str...@googlegroups.com.
To unsubscribe from this group, send email to strophe+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/strophe?hl=en.

Jack Moffitt

unread,
Jun 8, 2011, 4:22:40 PM6/8/11
to str...@googlegroups.com

You can always look at the ejabberd code for how its done :)

The way I've usually done this is to use one of the SQL backends and
just have my web app create the user's account directly in the
database, and skip the XMPP part. If your web app already has a user
table, you can even get ejabberd to use it by writing an auth plugin
or modifying the existing one, or perhaps in your database by mapping
the view ejabberd expects to your particular table.

jack.

Douglas Ehlenberger

unread,
Jun 8, 2011, 4:33:31 PM6/8/11
to str...@googlegroups.com
I ran into the same problem. I couldnt find any programmatic way to do it so I gave up and did what you were trying to avoid, i.e. make a system call. Ran into further complications in that the web server user had to setuid to root and that got real ugly. Its definitely not the way to do it. Note that I am using Prosody as my XMPP server and it has an option to store the user's info as files or in a database. I think the best solution if it works is to just create the information yourself, that is if you can make the XMPP server aware of the new info.

--

Douglas Ehlenberger

unread,
Jun 8, 2011, 4:36:53 PM6/8/11
to str...@googlegroups.com
Jack, this seems like a common problem. Is there some way to provide this functionality in the strophe.js library (or libstrophe) itself? Or is this strictly an XMPP server issue and cannot be controlled by the client?

--
You received this message because you are subscribed to the Google Groups "Strophe" group.

Jack Moffitt

unread,
Jun 8, 2011, 4:41:57 PM6/8/11
to str...@googlegroups.com
> Jack, this seems like a common problem. Is there some way to provide this
> functionality in the strophe.js library (or libstrophe) itself? Or is this
> strictly an XMPP server issue and cannot be controlled by the client?

In band registration is highly discouraged because it allow anyone to
create an account on your server, not just Strophe. Most servers now
come with it turned off, although it used to be commonly enabled and
had fairly wide client support. I think it's useful only in a minimum
of cases, most of which you can solve by doing it at the web service
level.

Any server admin on ejabberd can use the web UI to manipulate accounts
or use Ad-Hoc Commands to so do over XMPP (or you can use the command
line tool, ejabberdctl).

Unfortunately, the command is likely to be ejabberd specific, so even
if I added direct support for it in strophe, it would only work for
some people.

I'm open to suggestions for making this better, but most people I've
talked to seem to use SQL databases and direct user creation.

jack.

yiğit boyar

unread,
Jun 8, 2011, 4:43:14 PM6/8/11
to str...@googlegroups.com
I would not suggest using system calls because any call may fail causing inconsistency in your data. (e.g. what if your ejabberd server goes down? will you stop signups?)

We had the same issue and solved it using external auth method in ejabberd.
You need to set the following lines in your ejabberd config file:
{auth_method, external}.
{extauth_program, "/opt/ejabberd.cluster/sdbin/sd-auth"}.

each time a user wants to log in, ejabberd will wake up the sd-auth script w/ command line arguments. 
To not to tightly couple backend and this sd-auth script (because ejabberd is in a seperate server), we went even further and gave users dynamic passwords that are generated using a secret key and date. Each time user loads the site, we push the xmpp password which is an md5 hash of (date()-secret-username) and sd-auth script knows how to verify it.

Let me know if you need further details but this is the most elegant loosely coupled solution we could find.

yigit
> --
> You received this message because you are subscribed to the Google Groups
> "Strophe" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/strophe/-/S3pBOXk3dmI2MHdK.

Szymon Nowak

unread,
Jun 8, 2011, 5:00:15 PM6/8/11
to str...@googlegroups.com
It looks like a great solution! Do you have any links where it is explained in detail? While I'd really like to learn Erlang (and hopefully I will finally start learning it soon :)), I'm not sure I have enough time right now, so any kind of tutorial would be really helpful :) I'd probably have to automatically generate another password just for XMPP account, because it's going to be displayed in plain text in javascript on the client side...

Anyway, would it be possible to make ejabberd read subscription info from SQL database as well? One of the other XMPP related features of the site is that one can send an invitation to other users that can be accepted or rejected and it should automatically create proper XMPP subscription info based on these invitations. If I could just insert a record into the database without messing with sending messages and handling XMPP server responses on the server side it would be really awesome :)

yiğit boyar

unread,
Jun 8, 2011, 5:17:35 PM6/8/11
to str...@googlegroups.com
Actually, the good part of my solution is that you dont need to learn erlang :).
The sd-auth script is just a regular script, in our case, it is ruby script. Here is the stripped version of the script. I think you can fill in the blanks if not, you can send a direct email to ybo...@gmail.com not to spam the group. 

buffer = String.new
while STDIN.sysread(2, buffer) && buffer.length == 2

  length = buffer.unpack('n')[0]
  operation, username, domain, password = 
      STDIN.sysread(length).split(':')      

  member_id = username
      
  response = case operation 
      when 'auth'
          auth ( member_id ? member_id : "" ), ( password ? password.chomp : "" )
      when 'isuser'              
          isuser ( member_id ? member_id : "" )
      else
          0
      end
   
  STDOUT.syswrite([2, response].pack('nn'))
end
yigit


On Wed, Jun 8, 2011 at 2:00 PM, Szymon Nowak <szi...@gmail.com> wrote:
It looks like a great solution! Do you have any links where it is explained in detail? While I'd really like to learn Erlang (and hopefully I will finally start learning it soon :)), I'm not sure I have enough time right now, so any kind of tutorial would be really helpful :) I'd probably have to automatically generate another password just for XMPP account, because it's going to be displayed in plain text in javascript on the client side...

Anyway, would it be possible to make ejabberd read subscription info from SQL database as well? One of the other XMPP related features of the site is that one can send an invitation to other users that can be accepted or rejected and it should automatically create proper XMPP subscription info based on these invitations. If I could just insert a record into the database without messing with sending messages and handling XMPP server responses on the server side it would be really awesome :)

--
You received this message because you are subscribed to the Google Groups "Strophe" group.
To view this discussion on the web visit https://groups.google.com/d/msg/strophe/-/cGJlbHVrMGpoYUVK.

Jack Moffitt

unread,
Jun 8, 2011, 5:46:24 PM6/8/11
to str...@googlegroups.com
> now, so any kind of tutorial would be really helpful :) I'd probably have to
> automatically generate another password just for XMPP account, because it's
> going to be displayed in plain text in javascript on the client side...

Ack! Just do the auth on the server side and then pass authenticated
tokens in the JavaScript. That's what connection.attach() is for.
There's no need to leak passwords.

Another alternative would be to create a new auth method that used
tokens; this is what Google does.

> Anyway, would it be possible to make ejabberd read subscription info from
> SQL database as well? One of the other XMPP related features of the site is
> that one can send an invitation to other users that can be accepted or
> rejected and it should automatically create proper XMPP subscription info
> based on these invitations. If I could just insert a record into the
> database without messing with sending messages and handling XMPP server
> responses on the server side it would be really awesome :)

You can do this, but ejabberd has no way to no you've done it to
notify the various parties. That means it is unreliable at best. I do
not know a good way to do this at the moment. One solution might be
to store the invites themselves so that the next time the user logs in
they send them.

jack.

yiğit boyar

unread,
Jun 8, 2011, 5:56:33 PM6/8/11
to str...@googlegroups.com
I don't know if there is a good way to authenticate in backend but as much as i know, it would require connecting your backend w/ ejabberd, which is unwanted in our case. Instead, backend and ejabberd only shares a secret key and an algorithm to create password. As long as the password is dynamic and temporary, i dont see any problem in this approach. 

yigit


--
You received this message because you are subscribed to the Google Groups "Strophe" group.

Jack Moffitt

unread,
Jun 8, 2011, 6:11:56 PM6/8/11
to str...@googlegroups.com
> I don't know if there is a good way to authenticate in backend but as much
> as i know, it would require connecting your backend w/ ejabberd, which is
> unwanted in our case. Instead, backend and ejabberd only shares a secret key
> and an algorithm to create password. As long as the password is dynamic and
> temporary, i dont see any problem in this approach.

By "connecting your backend w/ ejabberd" I am talking about making
normal HTTP requests via BOSH but from your backend instead of the
frontend. Not only does it not require any password juggling, but it
dramatically reduces startup latency.

jack.

yiğit boyar

unread,
Jun 8, 2011, 6:29:44 PM6/8/11
to str...@googlegroups.com
I think in this case, decision depends how important chat system compared to your overall product (can it work w/o xmpp connection?). 

If you send an HTTP request to ejabberd on each page load, if ejabberd is slow, overloaded or down; it is going to slow down your website. In my case, since the password is a simple hash function, if ejabberd slows down, site will keep functioning and there will be no performance hit on the rest of the site.
 
yigit



jack.

Jack Moffitt

unread,
Jun 8, 2011, 6:35:53 PM6/8/11
to str...@googlegroups.com
> If you send an HTTP request to ejabberd on each page load, if ejabberd is
> slow, overloaded or down; it is going to slow down your website. In my case,
> since the password is a simple hash function, if ejabberd slows down, site
> will keep functioning and there will be no performance hit on the rest of
> the site.

You can easily fix this by making the request at the end of <body> for
a <script> that includes the credentials. If that script is slow, it's
not a big deal, doesn't block any rendering and the user just sees the
chat connection start slower if ejabberd is acting up, the same as if
you did it all client side. You can hide it further by loading a small
script which does dynamic <script> tag injection that gets the
credentials. Then it's no different than any other ajax request. You
can also use AJAX directly to a server side API that provides the
SID/RID.

(I'm not trying to convince you to change, just using you as a foil so
that others can see two alternatives in detail.)

jack.

yiğit boyar

unread,
Jun 8, 2011, 6:56:31 PM6/8/11
to str...@googlegroups.com
No no, I'm totally ok with alternatives and actually like the conversation.

I was also thinking about your Ajax request solution. For someone who does not want to write the auth script or want to stay standard compliant; it looks like the best solution. (auth script also binds you w/ ejabberd since it is server specific feature). 

Btw, in our  environment, we use flash sockets to connect to XMPP server (but strophe handles iq creation etc) so exported dynamic password still works faster than doing an additional ajax request.
Thanks for suggestions, I think Szymon got what he needs and i got some good feedback.

Btw, outside the topic but assuming that many people come to this case (sync between xmpp server and application); another common problem is roster. We also dont use XMPP Roster because our rosters are very dynamic and synchronization on the backend is painful. Instead, we use directed presence msgs which are more expensive in terms of network but works great and there is no sync issue (client fetches buddy list from backend on load).
 
yigit



jack.

Szymon Nowak

unread,
Jun 9, 2011, 4:03:10 AM6/9/11
to str...@googlegroups.com
Thanks a lot guys. I'm new to all this stuff, so please bear with me a little bit longer :)

1. Registration/authentication
@jack and @yigit - you guys are not talking about the same thing, right? You're both talking about authenticating ejabberd users directly from my own database, but yigit's solution requires an external script, while jack's solution doesn't, right?

@ygit - in case of an external script, how does ejabberd know who's registered when I call "ejabberdctl registered_users localhost"?
@jack - do you have a link to a page describing how to hook up my own database to ejabberd (what's the db schema and so on)? Would it be possible to tell it to fetch just username and password from my db (e.g. from a view based on my current "users" table) and the rest from wherever ejabberd stores it by default? 

2. Attaching to existing BOSH session
@jack - thanks a lot for this tip! The only problem is that I'd need something on the server side that talks BOSH, so I'd probably have to use strophe-ruby that looks a bit outdated... Do you know if it can work synchronously, so that I don't have to handle asynch callbacks on the server side?

Szymon Nowak

unread,
Jun 9, 2011, 9:48:42 AM6/9/11
to str...@googlegroups.com
I think I got the registration/authentication working using my own database without any external script.

I had some problems with enabling ODBC support in erlang and ejabberd, but finally worked it out - just for the record the configuration switch is called "--enable-odbc", not "--with-odbc" :) I used db schema from https://github.com/processone/ejabberd/tree/2.1.x/src/odbc to create a separate database, but instead of creating "users" table, I created a view that maps "users" table from my app's database to "users" view with columns expected by ejabberd.

Cheers,
Szymon

Jack Moffitt

unread,
Jun 9, 2011, 9:36:58 PM6/9/11
to str...@googlegroups.com
> @ygit - in case of an external script, how does ejabberd know who's
> registered when I call "ejabberdctl registered_users localhost"?

registered_users doesn't work for external auth. It's kind of a silly
command anyway, since if your user base is huge it won't be very good
to enumerate them all :)

> @jack - do you have a link to a page describing how to hook up my own
> database to ejabberd (what's the db schema and so on)? Would it be possible
> to tell it to fetch just username and password from my db (e.g. from a view
> based on my current "users" table) and the rest from wherever ejabberd
> stores it by default?

The best I can do for you is show you my patch to change its format
that I made for chesspark for an old version of ejabberd:
http://metajack.im/2009/12/18/better-ejabberd-vhosts/

> 2. Attaching to existing BOSH session
> @jack - thanks a lot for this tip! The only problem is that I'd need
> something on the server side that talks BOSH, so I'd probably have to use
> strophe-ruby that looks a bit outdated... Do you know if it can work
> synchronously, so that I don't have to handle asynch callbacks on the server
> side?

Use your favorite http library and write your own?

jack.

Reply all
Reply to author
Forward
0 new messages