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).
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:
- Get user password from DB (in its hashed string form, no processing needed)
- Get characters 9-12 from password
- Create HMAC key from concatenating WordPress logged in key & salt
- Data for HMAC is concatenation of: username, password fragment, ‘|’, expiration time in string form
- Do md5 HMAC with key from 3. on data from 4.
- Convert result from 5. to hexadecimal, string representation of hash (remember about zero-padding bytes lesser than 16)
- Do md5 HMAC with 6 as a key and concatenation of username, ‘|’ and expiration in string form as data
- 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.
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.