Skip to content

Commit

Permalink
Add jitsi-meet modules and README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
ItsOnlyBinary committed Mar 1, 2021
1 parent 9957f73 commit 9990ce7
Show file tree
Hide file tree
Showing 8 changed files with 1,340 additions and 2 deletions.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Add the plugin javascript file to your kiwiirc `config.json` and configure the s
### Security note!
By default, this plugin uses Jisti's public servers. It should be noted that by using these public servers, your conference calls are not secure in that anybody can join them if they can guess the room name.

Note that the "secure" option enables JWT authentication, but will not work on Jitsi's public server.
Note that the "secure" option enables JWT authentication, but will not work on Jitsi's public server. For more information see [Running your own conference server](#Running-your-own-conference-server)

### Extra configuration
Jitsi Meet supports extra configuration to customise its interface and functions. You can configure these via the optional `interfaceConfigOverwrite` and `configOverwrite` config options.
Expand Down Expand Up @@ -103,7 +103,12 @@ You may also choose to hide the conference call icon in either channels or priva
}
```
### Running your own conference server
Running your own conference server allows you to secure your conference rooms. We make use of the Jitsi Meet server to handle the conference calls, the installation steps can be found here: https://github.com/jitsi/jitsi-meet/blob/master/doc/quick-install.md
Running your own conference server allows you to secure your conference rooms. We make use of the Jitsi Meet server to handle the conference calls, the installation steps can be found here: https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-quickstart

If docker is your preferred method then see here: https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-docker

For installing and configuring jitsi to support [IRCv3 EXTJWT](https://github.com/ircv3/ircv3-specifications/pull/341) documentation can can be found here: https://github.com/kiwiirc/plugin-conference/blob/master/jitsi-meet-modules/README.md


## License

Expand Down
116 changes: 116 additions & 0 deletions jitsi-meet-modules/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Jitsi Meet Kiwi IRC auth plugin

## About

This repository contains modified copy of Jitsi Meet's Prosody token authentication modules for use with [kiwiirc/plugin-conference].

The purpose of these files is to mirror the access control model and user identity from the IRC environment to the Jitsi conference room.

This auth method is necessary when using `{ "conference.secure": true }` in your KiwiIRC client config.

___

## Docker install

Follow the [jitsi documentation](https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-docker) for setting up jitsi docker

After setting up docker copy the contents of `plugins/` to `~/.jitsi-meet-cfg/prosody/prosody-plugins-custom`

### Editing the docker .env file

Uncomment and set the following settings

```
ENABLE_WELCOME_PAGE=0
ENABLE_AUTH=1
ENABLE_GUESTS=0
AUTH_TYPE=jwt
JWT_APP_ID=<hostname of your ircd as specified in startupOptions.server>
JWT_APP_SECRET=<your jwt secret>
XMPP_MUC_MODULES=kiwi_muc_role_from_jwt,kiwi_presence_identity
```

The following vars will require adding:

```
ENABLE_P2P=false
ENABLE_AUTO_OWNER=false
JWT_AUTH_TYPE=kiwi_token
JWT_TOKEN_AUTH_MODULE=kiwi_token_verification
```

___

## Native install

Before proceeding, you'll need to complete the installation of the Jitsi Meet backend. Using the apt repository mentioned in [Jitsi Meet's instructions](https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-quickstart), install the `jitsi-meet` and `jitsi-meet-tokens` packages. e.g. `apt-get install jitsi-meet jitsi-meet-tokens`.

> A few hints:
>
> - On Ubuntu 16.04 `jitsi-meet-tokens` currently has a dependency on `prosody-trunk`, rather than the `prosody` package available in the main repositories. See [Prosody's documentation] to add their apt repository as a package source on your system.
> - The Jitsi Meet packaging may have issues on Ubuntu 18.04.
> - Use an interactive shell when installing `jitsi-meet` because the packages will ask questions via debconf during installation and errors will occur if no debconf frontend is available.
> - Install `nginx` **before** `jitsi-meet` if you want the `jitsi-meet` package to automatically create an nginx site configuration for you.
> - On debian there is an issue building the dependencies at install time due to a difference in libssl packages. As a workaround, do `sudo apt-get install apt-transport-https libssl1.0-dev luarocks git && sudo luarocks install luacrypto` before trying to install the jitsi packages. `libssl1.0-dev` is needed to build luacrypto, but it will get uninstalled and replaced with `libssl-dev` due to the dependencies specified by jitsi packages later on.
> - On Ubuntu 20.04 / Debian 10 `liblua5.2-dev` package is required before installing `jitsi-meet-tokens`.
> - To restart jitsi services after editing configs you can use `sudo systemctl restart prosody.service jicofo.service jitsi-videobridge2.service`.
### Post install

After installing the required packages copy the contents of `plugins/` to `/usr/share/jitsi-meet-kiwi`

### Configuring

In `/etc/prosody/conf.d/<your jitsi domain>.cfg.lua`:

1. Edit `plugin_paths` to add the newly created `/usr/share/jitsi-meet-kiwi` directory.

2. At the top level of the config, add these two lines, replacing `<your jitsi domain>` with the appropriate value for your installation:

```lua
jitsi_meet_domain = "<your jitsi domain>";
jitsi_meet_focus_hostname = "auth.<your jitsi domain>";
```

3. `authentication = "kiwi_token"`

4. `app_secret` (referred to as `application secret` during the interactive debconf prompts) needs to match the secret set in your webircgateway config.

5. `app_id` (`application ID` in debconf) must match the hostname in the upstream section of your webircgateway config **as well as** the server hostname that the KiwiIRC *client* uses (i.e. `startupOptions.server` in the client `config.json`)

6. Remove `"token_verification"` and add `"kiwi_token_verification"; "kiwi_muc_role_from_jwt"; "kiwi_presence_identity";` to `modules_enabled` in `Component "conference.<your jitsi domain>" "muc"`.

7. If you're hosting Jitsi on a separate hostname from KiwiIRC, you will need to either add

```lua
cross_domain_bosh = true;
```

at the top level of the config or manually add CORS headers in your nginx config.

### Jicofo SIP Communicator properties

8. Open `/etc/jitsi/jicofo/sip-communicator.properties` and add the following line:

```ini
org.jitsi.jicofo.DISABLE_AUTO_OWNER=True
```

### Jitsi Meet config

9. You may also want to disable P2P connectivity in the videobridge's config file at `/etc/jitsi/meet/<your jitsi domain>-config.js`.

```js
p2p: { enabled: false }
```

See `/usr/share/doc/jitsi-meet-web-config/config.js` for an example of the configuration format.
149 changes: 149 additions & 0 deletions jitsi-meet-modules/mod_auth_kiwi_token.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
-- Token authentication
-- Copyright (C) 2015 Atlassian

local formdecode = require "util.http".formdecode;
local generate_uuid = require "util.uuid".generate;
local new_sasl = require "util.sasl".new;
local sasl = require "util.sasl";
local token_util = module:require "token/util_kiwi".new(module);
local sessions = prosody.full_sessions;

module:log("info", "kiwiirc patch active: prosody-plugins/mod_auth_kiwi_token.lua");

-- no token configuration
if token_util == nil then
return;
end

-- define auth provider
local provider = {};

local host = module.host;

-- Extract 'token' param from URL when session is created
function init_session(event)
local session, request = event.session, event.request;
local query = request.url.query;

if query ~= nil then
local params = formdecode(query);

-- The following fields are filled in the session, by extracting them
-- from the query and no validation is beeing done.
-- After validating auth_token will be cleaned in case of error and few
-- other fields will be extracted from the token and set in the session

session.auth_token = query and params.token or nil;
-- previd is used together with https://modules.prosody.im/mod_smacks.html
-- the param is used to find resumed session and re-use anonymous(random) user id
-- (see get_username_from_token)
session.previd = query and params.previd or nil;

-- The room name and optional prefix from the web query
session.jitsi_web_query_room = params.room;
session.jitsi_web_query_prefix = params.prefix or "";

-- Deprecated, you should use jitsi_web_query_room and jitsi_web_query_prefix
session.jitsi_bosh_query_room = session.jitsi_web_query_room;
session.jitsi_bosh_query_prefix = session.jitsi_web_query_prefix;
end
end

module:hook_global("bosh-session", init_session);
module:hook_global("websocket-session", init_session);

function provider.test_password(username, password)
return nil, "Password based auth not supported";
end

function provider.get_password(username)
return nil;
end

function provider.set_password(username, password)
return nil, "Set password not supported";
end

function provider.user_exists(username)
return nil;
end

function provider.create_user(username, password)
return nil;
end

function provider.delete_user(username)
return nil;
end

function provider.get_sasl_handler(session)

local function get_username_from_token(self, message)

-- retrieve custom public key from server and save it on the session
local pre_event_result = prosody.events.fire_event("pre-jitsi-authentication-fetch-key", session);
if pre_event_result ~= nil and pre_event_result.res == false then
log("warn",
"Error verifying token on pre authentication stage:%s, reason:%s", pre_event_result.error, pre_event_result.reason);
session.auth_token = nil;
return pre_event_result.res, pre_event_result.error, pre_event_result.reason;
end

local res, error, reason = token_util:process_and_verify_token(session);
if res == false then
log("warn",
"Error verifying token err:%s, reason:%s", error, reason);
session.auth_token = nil;
return res, error, reason;
end

local customUsername
= prosody.events.fire_event("pre-jitsi-authentication", session);

if (customUsername) then
self.username = customUsername;
elseif (session.previd ~= nil) then
for _, session1 in pairs(sessions) do
if (session1.resumption_token == session.previd) then
self.username = session1.username;
break;
end
end
else
self.username = message;
end

local post_event_result = prosody.events.fire_event("post-jitsi-authentication", session);
if post_event_result ~= nil and post_event_result.res == false then
log("warn",
"Error verifying token on post authentication stage :%s, reason:%s", post_event_result.error, post_event_result.reason);
session.auth_token = nil;
return post_event_result.res, post_event_result.error, post_event_result.reason;
end

return res;
end

return new_sasl(host, { anonymous = get_username_from_token });
end

module:provides("auth", provider);

local function anonymous(self, message)

local username = generate_uuid();

-- This calls the handler created in 'provider.get_sasl_handler(session)'
local result, err, msg = self.profile.anonymous(self, username, self.realm);

if result == true then
if (self.username == nil) then
self.username = username;
end
return "success";
else
return "failure", err, msg;
end
end

sasl.registerMechanism("ANONYMOUS", {"anonymous"}, anonymous);
92 changes: 92 additions & 0 deletions jitsi-meet-modules/mod_kiwi_muc_role_from_jwt.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@


local muc_service = module:depends("muc");
local room_mt = muc_service.room_mt;

--local occupant = muc_service.occupant_mt;
module:set_global();
--module:depends("c2s");
--local sessions = module:shared("c2s/sessions");
local sessions = module:shared("sessions");

local muc_util = module:require "muc/util";
local valid_affiliations = muc_util.valid_affiliations;

local jid_bare = require "util.jid".bare;
local jid_split = require "util.jid".split;

-- package.path = '?.lua;' .. package.path
-- local inspect = require('/usr/share/jitsi-meet/prosody-plugins/inspect');

module:log("info", "kiwiirc patch active: prosody-plugins/mod_kiwi_muc_role_from_jwt.lua");

function len(t)
local n = 0;
for _ in pairs(t) do
n = n + 1
end
return n
end

local seen={}

function dump(t,i)
module:log("debug", "dump table size: " .. len(t));
seen[t]=true
local s={}
local n=0
for k in pairs(t) do
n=n+1 s[n]=k
end
if pcall(function () table.sort(s); end) then
table.sort(s)
end
for k,v in ipairs(s) do
module:log("debug", "dump: " .. tostring(i) .. tostring(v))
v=t[v]
if type(v)=="table" and not seen[v] then
dump(v,i.."\t")
end
end
end

local jitsi_meet_focus_hostname = module:get_option("jitsi_meet_focus_hostname", os.getenv("XMPP_AUTH_DOMAIN"));

room_mt.get_affiliation = function(room, jid)
--module:log("debug", "--- entered get_affiliation: jid=" .. jid);
--module:log("debug", debug.traceback());
-- dump(_G,"");
-- dump(_G.full_sessions, "");
--module:log("debug", "sessions - " .. inspect(prosody.full_sessions));
local bare_jid = jid_bare(jid);
-- module:log("debug", "jid : " .. session);
--local sess = occupant:get_presence(jid);
--module.log("debug", "sess - " .. sess);
local affiliation = nil;

-- TODO: don't allow earlier sessions to override affiliation claim from later ones
for conn, session in pairs(prosody.full_sessions) do
--module:log("debug", "test session: " .. jid .. " - " .. session.full_jid);
if jid_bare(session.full_jid) == bare_jid then
--module:log("debug", "found session - " .. inspect(session));
--module:log("debug", "found session - " .. session.full_jid);
if valid_affiliations[session.jitsi_meet_room_affiliation] ~= nil then
affiliation = session.jitsi_meet_room_affiliation;
-- module:log("debug", "setting affil - " .. affiliation);
end
end
end
local default_focus_affil = "owner";
local node, host, resource = jid_split(jid);
if host == jitsi_meet_focus_hostname then
module:log("debug", "affil (focus): " .. default_focus_affil .. " jid: " .. jid);
return default_focus_affil;
end
local default_affil = "member";
if affiliation == nil then
module:log("debug", "affil (default): " .. default_affil .. " jid: " .. jid);
return default_affil;
end
module:log("debug", "affil: " .. affiliation .. " jid: " .. jid);
return affiliation;
end
Loading

0 comments on commit 9990ce7

Please sign in to comment.