Many websites enrich their visitors’ experience by providing them with communication options.
From a simple shoutbox to live chats and forums, chat facilities allow users to interact with the company and each-other.
The quality of that experience matters.
In order to fully control what is going on in the chat a dedicated server is necessary and here MongooseIM fits in.
Why use MongooseIM for your web chat?
It supports both BOSH and Websocket connection.
It is easy to integrate with various CMS authentication methods.
It supports a server-side message archive.
It is stable and scalable in heavily-loaded systems.
User authentication in a MongooseIM based webchat
The chat application integrates with the website and uses its data to authenticate users.
This benefits the users who generally prefer to have a single login and password to both the website and chat facility. It is common for modern content management systems to use session keys stored in the database or generated with specific algorithm, so the XMPP server uses this key for authenticating user.
Bosh and Websockets
The most common and widely supported protocol for Web-XMPP communication is BOSH: Bidirectional-streams Over Synchronous HTTP.
In this communication channel every XMPP request is encapsulated in a HTTP request, making it easy to use in web applications. Unfortunately, this solution is not performance oriented.
The alternative is using Websockets (RFC 6455). They are supported by most modern browsers and introduce much smaller overhead. They do not specify any session resumption procedure, therefore they should be used either with a XEP-0198 or only for chat windows limited to single, non-reloading page (Websockets connections are closed by browser on page reload).
MongooseIM supports both BOSH and Websockets to provide maximum flexibility in your application design.
Case study: Wordpress & Erlang Central
In Wordpress the session key is not stored on the server side since it is generated using a deterministic algorithm, which requires a username, a part of password hash and a session expiration timestamp on input. The non-invasive integration involves logging onto the XMPP server with a Wordpress username and a Wordpress cookie as a password.
With ejabberd_auth_wordpress enabled, MongooseIM will parse the cookie and validate the session key. This applies to BOSH and Websockets connections.
It is also possible to login with ordinary Wordpress password over a native XMPP connection. In this case, MongooseIM will process the password the same way Wordpress does, and compare it with the hash stored in the database.
These solutions have been applied in the Erlang Central (www.erlangcentral.org) Cafe chat - a global chat room for all Erlang Central visitors.
The anatomy of the server side integration
Developing an authentication module for MongooseIM doesn’t take much skill. Any auth module can be used as a template - the simplest one to begin with is ejabberd_auth_wordpress.erl. The only function that must be implemented is check_password/3. Then it’s just a matter of implementing a specific algorithm used by the CMS in Erlang.
In case of Wordpress it was a matter of reverse-engineering wp_validate_auth_cookie function from wp-includes/pluggable.php.
The hashing method is defined:
frag := passwordHash[8:11]
hmacKey := concat(loggedInKey, loggedInSalt)
hmacData := concat(username, frag, ‘|’, expirationTimestamp)
hmacRes := hmac(‘md5’, hmacData, hmacKey)
magicHash := hmac(‘md5’, concat(username, ‘|’, expirationTimestamp), hmacRes)
In case of the native XMPP connections, a library called PHPass had to be implemented in Erlang (phpass.erl) in order to create hashes that could be matched against the values stored in the database.
Session key in Drupal
In this case using session key is trivial, as it is kept in the database. One of the PHP files (includes/session.inc) provides some convenient SQL queries for fetching sessions from the table: “SELECT u.name FROM users as u INNER JOIN sessions as s ON u.uid = s.uid WHERE s.ssid = ‘” + Sid + “’”.