Integration/XMPP/Prosody
Integrating Prosody with Diaspora
Here you will find all you need to install and setup a Prosody XMPP server integrated with Diaspora users database. 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
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. 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 - mod_auth_sql 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.
SQL
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 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.
- Prosody - XMPP Server
Installing Prosody
To install Prosody follow the official instructions described on their official site - - 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:
modules_enabled
- Disable
"saslauth"
- Enable
"bosh"
"legacyauth"
Setup and configure SQL
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.
- Modify
authentication = "sql"
- Add
storage = "sql"
MySQL Setup
sql = { driver = "MySQL", database = "prosody_xmpp", username = "prosody_xmpp", password = "pass", host = "localhost" }
sql_dsp = { driver = "MySQL", database = "diaspora_production", username = "diaspora", password = "pass", host = "localhost" }
PostgreSQL Setup
sql = { driver = "PostgreSQL", database = "prosody_xmpp", username = "prosody_xmpp", password = "pass", host = "localhost" }
sql_dsp = { driver = "PostgreSQL", database = "diaspora_production", username = "diaspora", password = "pass", host = "localhost" }
- sql
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;
- sql_dsp
This is the Diaspora database setup where Prosody will search the user password. The database user only need read permission.
Setup c2s_require_encryption
Change it to true, like this:
c2s_require_encryption = true
Add to the file
VirtualHost "your POD domain.foo"
Replace "your POD domain.foo" by your POD domain. This is very important!
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/.
-- 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;
end
local function mydebug(value,file)
fho,err = io.open("/tmp/" .. file,"w")
fho:write(value)
fho:write("\n")
fho:close()
end
local function mydebug2(value)
fho,err = io.open("/tmp/teste2","w")
fho:write(value)
fho:write("\n")
fho:close()
end
local function getsql_dsp(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;
end
local function get_password(username)
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);
Install bcrypt Lua lib
The modified mod_auth_sql require bcrypt lib available. To have so, ru the command below to install it
luarocks install bcrypt
Restart Prosody
To end it all, just restart Prosody
/etc/init.d/prosody restart
Testing
Just use your favorite XMMP Client to connect on your Diaspora POD using your regular account and password.