WordPress, MongooseIM and Websocket-based chat

Yeah, it’s almost certain that someone will say that this post is just a one, big MongooseIM advertisement. Maybe in small part it is, but my main goal here is to not let my effort remain undocumented. Yes, it’s been quite a challenging task to tap into WordPress session, in order to use it in MongooseIM.

But first things first. Have you already visited Erlang Central? Last Thursday & Friday we had an occasion to give new feature a test drive, which is/was Erlang Factory live streaming. San Francisco Erlang Factory, to be more precise. When you open streaming subpage (“Erlang Factory Live”), you can see the chat below streaming window (obviously stream is inactive now). It is embedded, quite heavily modified version of MUCkl Jabber client designed for group chats. Original version features status changing, list of all participants, choosing nick and combo box with rooms to choose. All of these were removed due to concept of one room per WordPress page (which means removing combo box), automatic user login (don’t need to ask for nick), and focusing only on what people say, not who is logged in (no roster frame -> no use for status changing).

JavaScript and HTML were the easy part – remove few lines here and there and there you go – simpler, nice client. But what about automatic login?

I decided it would be a quite messy solution to write some PHP script and make MongooseIM use it as external authentication option. I wanted native support for WordPress session in Jabber server. The first natural step was to check what cookie contains session data in case of wordpress. It is wp_logged_in_[site name hash] and consists of following parts:
First one is obvious. Second one is the cookie expiration time in form of Unix timestamp. The third one is created as combination of user name, expiration date and user password. Yes, session cookie in WordPress is pretty deterministic, no random numbers. It wasn’t easy though to reconstruct PHP functions in Erlang. Here are the steps used to generate logged_in cookie:

  1. Get user password from DB (in its hashed string form, no processing needed)
  2. Get characters 9-12 from password
  3. Create HMAC key from concatenating WordPress logged in key & salt
  4. Data for HMAC is concatenation of: username, password fragment, ‘|’, expiration time in string form
  5. Do md5 HMAC with key from 3. on data from 4.
  6. Convert result from 5. to hexadecimal, string representation of hash (remember about zero-padding bytes lesser than 16)
  7. Do md5 HMAC with 6 as a key and concatenation of username, ‘|’ and expiration in string form as data
  8. There you go! Just convert the result to hexadecimal string and you can compare it with cookie

Sounds simple, right? It wasn’t. It wasn’t difficult either, just required some guessing and executing PHP code to figure out how it represents data in all intermediate steps.

No, it’s not over. We embedded MUCkl as iframe in WordPress page, since we didn’t have enough time to properly integrate it with all the JavaScript WordPress has inside. Too great risk of some conflicts.We put it also in different domain (stream.erlang-solutions.com), so it forced me to create some hack to pass logged_in cookie to MUCkl page. JavaScript was a dead end – this cookie is HttpOnly, meaning it can’t be accessed by scripts running in the page. The solution was to create small redirect page within erlangcentral.org domain to just read cookie and pass it further as HTTP parameter to MUCkl. Done! MUCkl just had to pass cookie value as user password to MongooseIM and custom ejabberd_auth checked it against algorithm described earlier. That’s how current solution works.

As a conclusion I would like to state that if not for complicated WordPress cookie creation, incorporating multi-user chat in own website with MongooseIM is a very pleasant stuff. Traffic was not that high last weekend but good performance and stability of such combination is one step more towards sending BOSH to (un)deserved retirement. Especially given that all modern browsers support Websockets, even the mobile ones.

This entry was posted in Erlang and tagged , , , , . Bookmark the permalink.

1 Response to WordPress, MongooseIM and Websocket-based chat

  1. Pingback: Erlang Factory is coming. | erlang:get_cookie().

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s