Difference between revisions of "Integration/XMPP/Prosody"

From diaspora* project wiki
Jump to: navigation, search
(Modified mod_auth_sql)
(Drop i18n template)
 
(25 intermediate revisions by 10 users not shown)
Line 1: Line 1:
 +
= Integrating Prosody with Diaspora =
  
= Integrating Prosody with Diaspora =
+
Here you will find all you need to install and set up a Prosody XMPP server integrated with your Diaspora user database.
 +
This guide was tested using Debian 7 and Archlinux, but it will probably work well for all GNU distributions.
 +
There are several steps and configurations you will need to perform, so read the instructions carefully.
  
Here you will find all you need to install and setup a Prosody XMPP server integrated with Diaspora users database.
+
'''See debian specific instructions at https://wiki.debian.org/Diaspora/XMPP'''
This tutorial was developed using Debain 7 but it probably will work well for all GNU Distributions.
 
There is several steps and configurations you will need to do, so watch it carefully.
 
  
 
= Understanding =
 
= Understanding =
  
The main goal is setup '''Prosody''' to be capable to compare the password received by the XMPP Client with the hashed password stored on '''Diaspora''' database.
+
The main goal is to set up Prosody to be capable of comparing the password received by the XMPP client with the hashed password stored on your pod's Diaspora database.
'''Diaspora''' password hash is done with bcrypt library, so we need to patch '''Prosody''' to do the same with the received password. To do so, we need to install a modified [https://code.google.com/p/prosody-modules/wiki/mod_auth_sql - mod_auth_sql] module available below.
+
Diasporas password hash is done using <tt>bcrypt</tt>, so we need to extend Prosody to do the same with the received password. To do so, we need to install a modified version of the [https://code.google.com/p/prosody-modules/wiki/mod_auth_sql - <tt>mod_auth_sql</tt>] module, available below.
 
 
On this setup '''Prosody''' will use it's own SQL database to store users data like friends, etc. and it will connect on '''Diaspora''' database just to compare passwords. Then two database configurations will be required.
 
  
Follow the tutorial and this should work well.
+
Since authentication methods can be set per host, you can use an existing Prosody instance with access to Diasporas database.
  
= SQL =
+
You can also pull in Diaspora contacts into the roster. They will only be updated on signing into the XMPP account and all modifications to them from the XMPP side will be lost.
 
 
Before install '''Prosody''' create a database and user for it. You can do it on the same '''Diaspora''' SQL Server.
 
Just as '''Diaspora''' you can choose between '''MySQL''' or '''PostgreSQL'''.
 
  
 
= Prosody =
 
= Prosody =
  
Prosody is a modern XMPP communication server. It aims to be easy to set up and configure, and efficient with system resources. Additionally, for developers it aims to be easy to extend and give a flexible system on which to rapidly develop added functionality, or prototype new protocols.
+
If you haven't  yet, install Prosody. This setup was tested against 0.9.8 and is known to be incompatible with the 0.8 series.
* [http://prosody.im Prosody] - XMPP Server
+
Follow the instructions described on their [http://prosody.im/download/start official site].
 
 
== Installing Prosody ==
 
 
 
To install '''Prosody''' follow the official instructions described on their official site - [http://prosody.im/download/start - Download]
 
 
 
Once '''Prosody''' is installed ten you can proceed.
 
 
 
== Setup prosody.cfg.lua ==
 
  
Separated by topics here you have what you need to do on this file:
+
Once Prosody is installed, you can proceed.
  
=== modules_enabled ===
+
== Install bcrypt Lua library ==
  
* Disable
+
Lua or Prosody don't ship with the bcrypt library. If it isn't in your repositories, you can install it with the following command:
  
 
<syntaxhighlight lang="bash">
 
<syntaxhighlight lang="bash">
"saslauth"
+
luarocks install bcrypt
 
</syntaxhighlight>
 
</syntaxhighlight>
  
* Enable
+
Prosody still depends on Lua 5.1, if your distribution is already on Lua 5.2 you may need to change the command to <tt>luarocks-5.1</tt> or something similar.
  
<syntaxhighlight lang="bash">
+
== Changes in <tt>prosody.cfg.lua</tt> ==
"bosh"
 
"legacyauth"
 
</syntaxhighlight>
 
  
=== Setup and configure SQL ===
+
There are a couple of required changes to your <tt>prosody.cfg.lua</tt>.
  
The default auth method is '''internal''' and it must be replaced by '''sql'''. But '''sql''' require some configurations like SQL Server, database, user and password to access '''Diaspora''' and '''Prosody''' databases.
+
=== Plugin path ===
  
* Modify
+
Since we're going to install a new module, you should pick a location where you want to store it, for example <tt>/etc/prosody/modules</tt>.
 +
Then tell Prosody to look for modules there:
  
<syntaxhighlight lang="bash">
+
<syntaxhighlight lang="lua">
authentication = "sql"
+
plugin_paths = { "/etc/prosody/modules" }
 
</syntaxhighlight>
 
</syntaxhighlight>
  
* Add
+
Don't worry, Prosody will continue looking for modules in the standard location.
  
<syntaxhighlight lang="bash">
+
Now download the module to your machine:
storage = "sql"
 
</syntaxhighlight>
 
 
 
'''MySQL Setup'''
 
  
 
<syntaxhighlight lang="bash">
 
<syntaxhighlight lang="bash">
sql = { driver = "MySQL", database = "prosody_xmpp", username = "prosody_xmpp", password = "pass", host = "localhost" }
+
curl https://gist.githubusercontent.com/jhass/948e8e8d87b9143f97ad/raw/mod_auth_diaspora.lua > /etc/prosody/modules/mod_auth_diaspora.lua
sql_dsp = { driver = "MySQL", database = "diaspora_production", username = "diaspora", password = "pass", host = "localhost" }
+
curl https://gist.githubusercontent.com/jhass/948e8e8d87b9143f97ad/raw/mod_diaspora_contacts.lua > /etc/prosody/modules/mod_diaspora_contacts.lua
 
</syntaxhighlight>
 
</syntaxhighlight>
  
'''PostgreSQL Setup'''
+
=== Add a virtual host for your pod ===
  
<syntaxhighlight lang="bash">
+
<syntaxhighlight lang="lua">
sql = { driver = "PostgreSQL", database = "prosody_xmpp", username = "prosody_xmpp", password = "pass", host = "localhost" }
+
VirtualHost "yourpod.example.org"
sql_dsp = { driver = "PostgreSQL", database = "diaspora_production", username = "diaspora", password = "pass", host = "localhost" }
+
  authentication = "diaspora"
 +
  -- Uncomment and adjust username and password for MySQL/MariaDB
 +
  --auth_diaspora = { driver = "MySQL", database = "diaspora_production", username = "diaspora", password = "pass", host = "localhost" }
 +
  -- Uncomment and adjust username and password for PostgreSQL
 +
  --auth_diaspora = { driver = "PostgreSQL", database = "diaspora_production", username = "diaspora", password = "pass", host = "localhost" }
 +
 
 +
  modules_enabled = {
 +
    "diaspora_contacts";
 +
  };
 
</syntaxhighlight>
 
</syntaxhighlight>
  
* sql
+
Replace <tt>yourpod.example.org</tt> with your pod's domain and adjust the username and password for the database connection. This is very important!
  
This is the '''Prosody''' database setup where '''Prosody''' will store users friends lists and it's personal setup. The database user must have wright permission on this;
+
Read in [http://prosody.im/doc/dns Prosodys official documentation] on how to correctly update your nameserver records afterwards.
 +
Also read about setting up the right [http://prosody.im/doc/certificates certificates] for your host.
  
* sql_dsp
+
=== Enable BOSH support ===
  
This is the '''Diaspora''' database setup where '''Prosody''' will search the user password. The database user only need read permission.
+
Uncomment following line inside '''modules_enabled''' to enable BOSH support:
 +
<syntaxhighlight lang="lua">
 +
"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"
 +
</syntaxhighlight>
  
=== Setup c2s_require_encryption ===
+
=== Other recommendations ===
  
Change it to true, like this:
+
* Since we have to transmit the password in plaintext to the server, we strongly recommend to require encryption:
 
+
:<syntaxhighlight lang="lua">
<syntaxhighlight lang="bash">
+
c2s_require_encryption = true
c2s_require_encryption = true
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
=== Add to the file ===
+
* You may also require server to server connections to be encrypted and validate server certificates (diaspora does this already), but your pod won't be able to talk to some xmpp servers which use self signed certificates.
  
<syntaxhighlight lang="bash">
+
:<syntaxhighlight lang="lua">
VirtualHost "your POD domain.foo"
+
s2s_require_encryption = true
 +
s2s_secure_auth = true
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Replace "your POD domain.foo" by your POD domain. This is very important!
+
* Adding a reverse proxy to Prosody's BOSH endpoint under your pods domain on the path <tt>/http-bind</tt>  is a good idea too (check the [https://wiki.diasporafoundation.org/Vines#Browser_blocks_mixed-content examples on Vines page]). If you have done so, set the <tt>proxy</tt> setting in <tt>diaspora.yml</tt> to <tt>true</tt> and add <tt>consider_bosh_secure = true</tt> to your Prosody configuration.
 
 
 
 
== Modified mod_auth_sql ==
 
 
 
Below you get the entire '''mod_auth_sql''' file.
 
Create a file called '''mod_auth_sql''' on '''Prosody''' modules directory and paste this in it.
 
On Debian 7 this is '''/usr/lib/prosody/modules/'''.
 
 
 
<syntaxhighlight lang="lua">
 
-- Simple SQL Authentication module for Prosody IM
 
-- Copyright (C) 2011 Tomasz Sterna <tomek@xiaoka.com>
 
-- Copyright (C) 2011 Waqas Hussain <waqas20@gmail.com>
 
--
 
-- Modified by Anahuac de Paula Gil - anahuac@anahuac.eu
 
-- This will make prosody able to use Diaspora database users and passwords
 
-- 25/05/2014
 
 
 
local log = require "util.logger".init("auth_sql");
 
local new_sasl = require "util.sasl".new;
 
local DBI = require "DBI"
 
 
 
local connection;
 
local params = module:get_option("auth_sql", module:get_option("sql_dsp"));
 
 
 
local resolve_relative_path = require "core.configmanager".resolve_relative_path;
 
 
 
local function test_connection()
 
        if not connection then return nil; end
 
        if connection:ping() then
 
                return true;
 
        else
 
                module:log("debug", "Database connection closed");
 
                connection = nil;
 
        end
 
end
 
local function connect()
 
        if not test_connection() then
 
                prosody.unlock_globals();
 
                local dbh, err = DBI.Connect(
 
                        params.driver, params.database,
 
                        params.username, params.password,
 
                        params.host, params.port
 
                );
 
                prosody.lock_globals();
 
                if not dbh then
 
                        module:log("debug", "Database connection failed: %s", tostring(err));
 
                        return nil, err;
 
                end
 
                module:log("debug", "Successfully connected to database");
 
                dbh:autocommit(true); -- don't run in transaction
 
                connection = dbh;
 
                return connection;
 
        end
 
end
 
 
 
do -- process options to get a db connection
 
        params = params or { driver = "SQLite3" };
 
 
 
        if params.driver == "SQLite3" then
 
                params.database = resolve_relative_path(prosody.paths.data or ".", params.database or "prosody.sqlite");
 
        end
 
 
 
        assert(params.driver and params.database, "Both the SQL driver and the database need to be specified");
 
 
 
        assert(connect());
 
end
 
 
 
local function getsql(sql, ...)
 
        if params.driver == "PostgreSQL" then
 
                sql = sql:gsub("`", "\"");
 
        end
 
        if not test_connection() then connect(); end
 
        -- do prepared statement stuff
 
        local stmt, err = connection:prepare(sql);
 
        if not stmt and not test_connection() then error("connection failed"); end
 
        if not stmt then module:log("error", "QUERY FAILED: %s %s", err, debug.traceback()); return nil, err; end
 
        -- run query
 
        local ok, err = stmt:execute(...);
 
        if not ok and not test_connection() then error("connection failed"); end
 
        if not ok then return nil, err; end
 
  
        return stmt;
+
* If you want to improve the experience of your users when connecting from mobile devices, install [https://wiki.debian.org/InstallingProsody#Useful_Modules_.28Mobile_support.29 modules listed on Debian's Prosody Installation guide].
end
 
  
local function mydebug(value,file)
+
* If you want to allow users to connect via HTTPS port (443) to bypass restrictive firewalls, follow [https://wiki.debian.org/InstallingProsody#XMPP_over_HTTPS steps documented at Debian's Prosody Installation guide].
        fho,err = io.open("/tmp/" .. file,"w")
 
        fho:write(value)
 
        fho:write("\n")
 
        fho:close()
 
end
 
  
local function mydebug2(value)
+
== Restart Prosody ==
        fho,err = io.open("/tmp/teste2","w")
 
        fho:write(value)
 
        fho:write("\n")
 
        fho:close()
 
end
 
  
local function getsql_dsp(sql, ...)
+
To complete the setup, just restart Prosody.
        if params.driver == "PostgreSQL" then
 
                sql = sql:gsub("`", "\"");
 
        end
 
        if not test_connection() then connect(); end
 
        -- do prepared statement stuff
 
        local stmt, err = connection:prepare(sql);
 
        if not stmt and not test_connection() then error("connection failed"); end
 
        if not stmt then module:log("error", "QUERY FAILED: %s %s", err, debug.traceback()); return nil, err; end
 
        -- run query
 
        local ok, err = stmt:execute(...);
 
        if not ok and not test_connection() then error("connection failed"); end
 
        if not ok then return nil, err; end
 
  
        return stmt;
+
= Testing =
end
 
  
 +
Just use your favorite XMPP client to connect to your pod using your regular Diaspora account and password.
  
local function get_password(username)
+
[[Category:Podmin]]
        local stmt, err = getsql_dsp("SELECT encrypted_password FROM users WHERE username = '" .. username .. "'");
 
        if stmt then
 
                for row in stmt:rows(true) do
 
                        return row.encrypted_password;
 
                end
 
        end
 
end
 
 
 
 
 
provider = {};
 
 
 
function provider.test_password(username, password)
 
        local bcrypt = require( "bcrypt" )
 
 
 
        -- pepper imported from diaspora/config/initializers/devise.rb
 
        local pepper = "065eb8798b181ff0ea2c5c16aee0ff8b70e04e2ee6bd6e08b49da46924223e39127d5335e466207d42bf2a045c12be5f90e92012a4f05f7fc6d9f3c875f4c95b"
 
        -- adding pepper to the regular password
 
        local pw_plus_pepper = password .. pepper
 
 
 
        -- Getting password from Diaspora database
 
        local pw_stored_dsp = get_password(username)
 
 
 
        -- Comparing password. If fail aborts
 
        return password and assert( bcrypt.verify( pw_plus_pepper, pw_stored_dsp ))
 
 
 
        --return password and get_password(username) == password;
 
end
 
function provider.get_password(username)
 
        return get_password(username);
 
end
 
function provider.set_password(username, password)
 
        return nil, "Setting password is not supported.";
 
end
 
function provider.user_exists(username)
 
        return get_password(username) and true;
 
end
 
function provider.create_user(username, password)
 
        return nil, "Account creation/modification not supported.";
 
end
 
function provider.get_sasl_handler()
 
        local profile = {
 
                plain = function(sasl, username, realm)
 
                        local password = get_password(username);
 
                        if not password then return "", nil; end
 
                        return password, true;
 
                end
 
        };
 
        return new_sasl(module.host, profile);
 
end
 
 
 
function provider.users()
 
        local stmt, err = getsql_dsp("SELECT username FROM user", module.host);
 
        if stmt then
 
                local next, state = stmt:rows(true)
 
                return function()
 
                        for row in next, state do
 
                                return row.username;
 
                        end
 
                end
 
        end
 
        return stmt, err;
 
end
 
 
 
 
 
module:provides("auth", provider);
 
</syntaxhighlight>
 
 
 
== Install bcrypt Lua lib ==
 
 
 
The modified '''mod_auth_sql''' require bcrypt lib available. To have so, ru the command below to install it
 
 
 
<syntaxhighlight lang="lua">
 
luarocks install bcrypt
 
</syntaxhighlight>
 

Latest revision as of 02:46, 15 October 2018

Integrating Prosody with Diaspora

Here you will find all you need to install and set up a Prosody XMPP server integrated with your Diaspora user database. This guide was tested using Debian 7 and Archlinux, but it will probably work well for all GNU distributions. There are several steps and configurations you will need to perform, so read the instructions carefully.

See debian specific instructions at https://wiki.debian.org/Diaspora/XMPP

Understanding

The main goal is to set up Prosody to be capable of comparing the password received by the XMPP client with the hashed password stored on your pod's Diaspora database. Diasporas password hash is done using bcrypt, so we need to extend Prosody to do the same with the received password. To do so, we need to install a modified version of the - mod_auth_sql module, available below.

Since authentication methods can be set per host, you can use an existing Prosody instance with access to Diasporas database.

You can also pull in Diaspora contacts into the roster. They will only be updated on signing into the XMPP account and all modifications to them from the XMPP side will be lost.

Prosody

If you haven't yet, install Prosody. This setup was tested against 0.9.8 and is known to be incompatible with the 0.8 series. Follow the instructions described on their official site.

Once Prosody is installed, you can proceed.

Install bcrypt Lua library

Lua or Prosody don't ship with the bcrypt library. If it isn't in your repositories, you can install it with the following command:

luarocks install bcrypt

Prosody still depends on Lua 5.1, if your distribution is already on Lua 5.2 you may need to change the command to luarocks-5.1 or something similar.

Changes in prosody.cfg.lua

There are a couple of required changes to your prosody.cfg.lua.

Plugin path

Since we're going to install a new module, you should pick a location where you want to store it, for example /etc/prosody/modules. Then tell Prosody to look for modules there:

plugin_paths = { "/etc/prosody/modules" }

Don't worry, Prosody will continue looking for modules in the standard location.

Now download the module to your machine:

curl https://gist.githubusercontent.com/jhass/948e8e8d87b9143f97ad/raw/mod_auth_diaspora.lua > /etc/prosody/modules/mod_auth_diaspora.lua
curl https://gist.githubusercontent.com/jhass/948e8e8d87b9143f97ad/raw/mod_diaspora_contacts.lua > /etc/prosody/modules/mod_diaspora_contacts.lua

Add a virtual host for your pod

VirtualHost "yourpod.example.org"
  authentication = "diaspora"
  -- Uncomment and adjust username and password for MySQL/MariaDB
  --auth_diaspora = { driver = "MySQL", database = "diaspora_production", username = "diaspora", password = "pass", host = "localhost" }
  -- Uncomment and adjust username and password for PostgreSQL
  --auth_diaspora = { driver = "PostgreSQL", database = "diaspora_production", username = "diaspora", password = "pass", host = "localhost" }
  
  modules_enabled = {
    "diaspora_contacts";
  };

Replace yourpod.example.org with your pod's domain and adjust the username and password for the database connection. This is very important!

Read in Prosodys official documentation on how to correctly update your nameserver records afterwards. Also read about setting up the right certificates for your host.

Enable BOSH support

Uncomment following line inside modules_enabled to enable BOSH support:

"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"

Other recommendations

  • Since we have to transmit the password in plaintext to the server, we strongly recommend to require encryption:
 c2s_require_encryption = true
  • You may also require server to server connections to be encrypted and validate server certificates (diaspora does this already), but your pod won't be able to talk to some xmpp servers which use self signed certificates.
s2s_require_encryption = true
s2s_secure_auth = true
  • Adding a reverse proxy to Prosody's BOSH endpoint under your pods domain on the path /http-bind is a good idea too (check the examples on Vines page). If you have done so, set the proxy setting in diaspora.yml to true and add consider_bosh_secure = true to your Prosody configuration.

Restart Prosody

To complete the setup, just restart Prosody.

Testing

Just use your favorite XMPP client to connect to your pod using your regular Diaspora account and password.