Skip to content

collective/collective.converse

Repository files navigation

Introduction

collective.converse integrates converse.js and the Prosody XMPP server into Plone.

https://raw.githubusercontent.com/collective/collective.converse/master/images/screenshot.png

Installation

Installing dependencies

Before running buildout, you'll need to install various libraries needed by Prosody:

- lua5.1: The Lua 5.1 interpreter
- liblua5.1: Lua 5.1 library
- libssl 0.9.8 or later: OpenSSL
- libidn11: GNU libidn library, version 1.1
- libevent

These can be installed on Debian/Ubuntu with apt-get:

sudo apt-get install lua5.1 liblua5.1-dev libidn11-dev libssl-dev luarocks libevent-dev

On Mac, if you use brew:

brew install libidn libevent openssl lua51

Note

It could happen that lua51 installs into /usr/local/Cellar/lua@5.1. If so, then symlink it to /usr/local/Cellar/lua51.

and if you use MacPorts:

sudo port install libidn libevent openssl lua51* luarocks*

Note

luarocks and lua51 need to be fixed on macports (luarocks to use lua5.1 instead of the latest, and lua5.1 to use default lua CFLAGS instead of overriding them).

Running buildout

To integrate collective.converse into your own project, you'll want to include prosody.cfg from this repo in your bulidout config.:

[buildout]
extends = /path/to/prosody.cfg

Then you'll need to create a secrets.cfg file, with the following format:

[prosody.cfg.lua]
# TODO: don't use these values, they're for demonstration purposes only,
# generate your own OR YOU WILL BE HACKED!
otp_seed = XVGR73KMZH2M4XMY
token_secret = JYXEX4IQOEYFYQ2S3MC5P4ZT4SDHYEA7

[instance]
zope-conf-additional +=
    <product-config collective.converse>
        instance_name Plone
        xmpp_domain example.org
        auto_subscribe 1
        bosh_url http://example.org:5280/http-bind
        otp_seed XVGR73KMZH2M4XMY
        token_secret JYXEX4IQOEYFYQ2S3MC5P4ZT4SDHYEA7
        debug 0
    </product-config>

Don't use the secrets values in the example above, generate your own. Read the section User Authentication below to see how to do that.

The zope-conf-additional additional section above lets you configure your XMPP settings via buildout. In the very least you'll need to provide the otp_seed and token_secret values because they can't be configured from within Plone itself (for security reasons).

However the other values can be configured at the ${plone}/@@xmpp-settings URL once you've installed collective.converse.

To find out what the configuration settings are for, go read their descriptions at ${plone}/@@xmpp-settings.

Be aware that the values in secrets.cfg will override any manually configured settings whenever you restart Plone. If you want to avoid that, then don't put those value in secrets.cfg.

Once you've configured secrets.cfg, you can run buildout.

User Authentication

Plone generates HMAC tokens which contain time-based one-time-pin (TOTP) tokens and are hashed with SHA256.

Converse.js, the JavaScript XMPP client receives this token and then passes it on to Prosody which verifies the tokens authenticity, i.e. it checks whether the token was really generated by Plone.

For this to work, Plone and Prosody need to share a common secret key and a secret OTP seed.

We use a Prosody modules mod_sasl_hmac_md to register a custom SASL authentication mechanism (called "SASL-HMAC") and mod_auth_hmac_md to create an authentication provider that accepts signed TOTP tokens.

Generating the secret key for the HMAC token

The tokens are in HMAC-SHA256 format and are generated by Plone when a client wants to sign in to Prosody (the XMPP server).

A private key needs to be generated that will be shared between Plone and Prosody. This key is used in the HMAC token construction in Plone and by mod_auth_hmac.lua in Prosody to verify the HMAC token.

Your key needs to be 32 bytes (the HMAC specification recommends that the key length is at least as long as the output of the hash function used, in our case sha256 which outputs 32 byte strings).

You can generate the key as follows:

>>> import pyotp
>>> pyotp.random_base32(length=32)
u'JYXEX4IQOEYFYQ2S3MC5P4ZT4SDHYEA7'

The key then needs to be added to secrets.cfg.

prosody_token_secret = JYXEX4IQOEYFYQ2S3MC5P4ZT4SDHYEA7

Generating the TOTP secret

Each token contains a TOTP (time-based one-time-pin) which restricts that token's validity to a specific time window which is usually a few minutes starting from token creation.

For the TOTP we also need a shared secret key between Plone and Prosody. This can be generated with [pyotp](https://pypi.python.org/pypi/pyotp).

>>> import pyotp
>>> pyotp.random_base32()
u'XVGR73KMZH2M4XMY'

The key then needs to be added to secrets.cfg.

prosody_otp_seed = XVGR73KMZH2M4XMY