authorization by JWT token
Connecting to a jitsi without authorization can become insecure. In order to avoid uninvited guests during a meeting, conference or personal conversation, you should think about authorization. Under the cut, I will tell you in detail how we can improve our jitsi-meet service using a JWT token.
Below I have described a step-by-step instruction for installing and configuring a JWT token on debian. The whole process can be carried out as on an already running service jitsi-jibri (from my mana it definitely works), and in a new installation after completing the jitsi setup.
apt install git cmake luarocks libssl-dev liblua5.2
wget http://packages.prosody.im/debian/pool/main/p/prosody-trunk/prosody-trunk_1nightly1273-1~buster_amd64.deb
dpkg -i prosody-trunk_1nightly1273-1~buster_amd64.deb
apt install prosody -y
echo deb http://packages.prosody.im/debian $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list
wget https://prosody.im/files/prosody-debian-packages.key -O- | sudo apt-key add -
apt update
apt upgrade
apt-get install jitsi-meet-tokens prosody-modules lua5.2 liblua5.2 luarocks libssl-dev
During the installation process, the Application ID and Application secret will be requested. We indicate them and be sure to remember them, they will be needed to generate a token (if you suddenly forgot them, then it’s okay, you can see / change them in the prosody configuration file)
luarocks install basexx
At the end of the /etc/prosody/prosody.cfg.lua file, add the line:
vim /etc/prosody/prosody.cfg.lua
Include "conf.d/*.cfg.lua"
We also find the line starting with “s2s_” and add before it:
c2s_require_encryption = false
We continue the installation:
luarocks download lua-cjson
luarocks unpack lua-cjson-2.1.0.6-1.src.rock
In the lua-cjson-2.1.0.6-1/lua-cjson/lua_cjson.c file, change line 743:
vim lua-cjson-2.1.0.6-1/lua-cjson/lua_cjson.c
len = lua_objlen(l, -1);
на
len = lua_rawlen(l, -1);
Save the file and continue with the installation:
cd lua-cjson-2.1.0.6-1/lua-cjson
luarocks make --force
cd ..
git clone https://github.com/ASolomatin/luajwt.git
cd luajwt/
Let’s make changes to the luajwtjitsi-1.3-7.rockspec file:
package = "luajwtjitsi"
version = "1.3-7"
source = {
url = "git://github.com/ASolomatin/luajwt/",
tag = "replace_luacrypto"
}
description = {
summary = "JSON Web Tokens for Lua",
detailed = "Very fast and compatible with pyjwt, php-jwt, ruby-jwt, node-jwt-simple and others",
homepage = "https://github.com/jitsi/luajwt/",
license = "MIT <http://opensource.org/licenses/MIT>"
}
dependencies = {
"lua >= 5.2",
"luaossl >= 20190731-0",
"lua-cjson >= 2.1.0",
"lbase64 >= 20120807-3"
}
build = {
type = "builtin",
modules = {
luajwtjitsi = "luajwtjitsi.lua"
}
}
We continue:
luarocks install luajwtjitsi 2.0-0
systemctl restart prosody
We check for errors, if there are, then we clean the file and restart the prosody:
vim /var/log/prosody/prosody.err
systemctl restart prosody
vim /var/log/prosody/prosody.err
To generate a token, you can go to website and there, setting the parameters to generate it, and then insert it into the URL in the format https:///name_room?jwt=token .
On the site enter the following data:
HEADER:ALGORITHM & TOKEN TYPE
{
"typ": "JWT",
"alg": "HS256"
}
PAYLOAD:DATA
{
"context": {
"user": {
"name": "<user>",
"id": "<user>@gmail.com", #optional
"email": "<user@gmail.com>", #optional
"avatar": "<link to user's avatar>" #optional
}
},
"aud": "jitsi",
"iss": "<Application_ID>",
"sub": "<FQDN>",
"room": "*",
"exp": 98753496345768,
"moderator": true
}
VERIFY SIGNATURE
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
<Application_secret>
) secret base64 encoded
Bring to this form with the substitution of your own value instead of <...>
After successfully installing the necessary infrastructure, you need to register the configuration for correct operation. We received the basic configuration during the installation process, and the settings that I will give below are optional.
Editing prosody virtual hosts. In order for participants to connect to our conference at the invitation of a moderator without a token, we will create a guest host. By default, we installed the moderator module, but this module does not allow you to transfer moderator rights, we will change it to another one. We will also install a module that includes the lobby by default. This feature will allow the administrator to control who enters the room, and they, in turn, will have to “introduce themselves”.
vim /etc/prosody/conf.avail/<FQDN>.cfg.lua
We find our virtual host and bring it to the following value:
VirtualHost "<FQDN>"
authentication = "token"
app_id="<APP_ID>"
app_secret="<APP_SECRET>"
allow_empty_token = false
allow_unencrypted_plain_auth = true
…
ssl = {
key = "/etc/prosody/certs/<FQDN>.key";
certificate = "/etc/prosody/certs/<FQDN>.crt";
}
av_moderation_component = "avmoderation.<FQDN>"
speakerstats_component = "speakerstats.<FQDN>"
conference_duration_component = "conferenceduration.<FQDN>"
-- we need bosh
modules_enabled = {
"bosh";
"pubsub";
"ping"; -- Enable mod_ping
"speakerstats";
"external_services";
"conference_duration";
"muc_lobby_rooms";
"muc_breakout_rooms";
"presence_identity";
"av_moderation";
}
c2s_require_encryption = false
lobby_muc = "lobby.<FQDN>"
breakout_rooms_muc = "breakout.<FQDN>"
main_muc = "conference.<FQDN>"
muc_lobby_whitelist = { "recorder.<FQDN>" } -- Here we can whitelist jibri to enter lobby enabled rooms
VirtualHost "guest.<FQDN>"
authentication = "anonymous"
modules_enabled = {
"bosh";
"pubsub";
"ping"; -- Enable mod_ping
"speakerstats";
"conference_duration";
}
c2s_require_encryption = false
Component "conference.<FQDN>" "muc"
restrict_room_creation = true
storage = "memory"
modules_enabled = {
"muc_meeting_id";
"muc_domain_mapper";
"polls";
"token_verification";
"token_moderation";
"muc_rate_limit";
}
admins = { "focus@auth.<FQDN>" }
muc_room_locking = false
muc_room_default_public_jids = true
Component "breakout.<FQDN>" "muc"
restrict_room_creation = true
storage = "memory"
modules_enabled = {
"muc_meeting_id";
"muc_domain_mapper";
"token_verification";
"muc_rate_limit";
"polls";
}
admins = { "focus@auth.<FQDN>" }
muc_room_locking = false
muc_room_default_public_jids = true
-- internal muc component
Component "internal.auth.<FQDN>" "muc"
storage = "memory"
modules_enabled = {
"ping";
}
admins = { "focus@auth.<FQDN>", "jvb@auth.<FQDN>" }
muc_room_locking = false
muc_room_default_public_jids = true
muc_room_cache_size = 1000
VirtualHost "auth.<FQDN>"
ssl = {
key = "/etc/prosody/certs/auth.<FQDN>.key";
certificate = "/etc/prosody/certs/auth.<FQDN>.crt";
}
modules_enabled = {
"limits_exception";
}
authentication = "internal_hashed"
-- Proxy to jicofo's user JID, so that it doesn't have to register as a component.
Component "focus.<FQDN>" "client_proxy"
target_address = "focus@auth.<FQDN>"
Component "speakerstats.<FQDN>" "speakerstats_component"
muc_component = "conference.<FQDN>"
Component "conferenceduration.<FQDN>" "conference_duration_component"
muc_component = "conference.<FQDN>"
Component "avmoderation.<FQDN>" "av_moderation_component"
muc_component = "conference.<FQDN>"
Component "lobby.<FQDN>" "muc"
storage = "memory"
restrict_room_creation = true
muc_room_locking = false
muc_room_default_public_jids = true
modules_enabled = {
"muc_rate_limit";
"polls";
}
В конец файла добавляем следующее (это понадобится для jibri)
-- internal muc component, meant to enable pools of jibri and jigasi clients
-- Component "internal.auth.<FQDN>" "muc" -- Данный блок уже может быть выше в конфиге
-- modules_enabled = {
-- "ping";
-- }
-- storage = "memory"
-- muc_room_cache_size = 1000
VirtualHost "recorder.<FQDN>"
modules_enabled = {
"ping";
}
authentication = "internal_plain"
Clone the repository with modules and install:
cd ~
git clone https://github.com/nvonahsen/jitsi-token-moderation-plugin.git
mv jitsi-token-moderation-plugin/mod_token_moderation.lua /usr/share/jitsi-meet/prosody-plugins/bak.mod_token_moderation.lua
git clone https://github.com/dumasti/jitsi_mods.git
mv /usr/share/jitsi-meet/prosody-plugins/mod_muc_lobby_rooms.lua /usr/share/jitsi-meet/prosody-plugins/bak.mod_muc_lobby_rooms.lua
mv jitsi_mods/*.lua /usr/share/jitsi-meet/prosody-plugins/
mv /usr/share/jitsi-meet/prosody-plugins/mod_token_moderation_grand.lua /usr/share/jitsi-meet/prosody-plugins/mod_token_moderation.lua
Change the settings in the /etc/jitsi/meet/-config.js file to enable the guest host and other usefulness (optional).
cp /etc/jitsi/meet/<FQDN>-config.js /etc/jitsi/meet/bak.<FQDN>-config.js
vim /etc/jitsi/meet/<FQDN>-config.js
/* eslint-disable no-unused-vars, no-var */
var config = {
hosts: {
domain: '<FQDN>',
anonymousdomain: 'guest.<FQDN>',
muc: 'conference.<FQDN>'
},
bosh: '//<FQDN>/http-bind',
testing: {
},
flags: {
},
enableNoAudioDetection: true,
enableNoisyMicDetection: true,
startAudioOnly: true,
startWithAudioMuted: false,
resolution: 1080,
constraints: {
video: {
height: {
ideal: 720,
max: 1080,
min: 360
}
}
},
disableSimulcast: true,
fileRecordingsEnabled: true,
liveStreamingEnabled: true,
hiddenDomain: 'recorder.<FQDN>',
channelLastN: -1,
enableWelcomePage: true,
defaultLanguage: 'en',
enableUserRolesBasedOnToken: true,
p2p: {
enabled: true,
stunServers: [
{ urls: 'stun:meet-jit-si-turnrelay.jitsi.net:443' }
]
},
analytics: {
},
deploymentInfo: {
},
mouseMoveCallbackInterval: 1000,
makeJsonParserHappy: 'even if last key had a trailing comma'
};
/* eslint-enable no-unused-vars, no-var */
vim /etc/jitsi/jicofo/sip-communicator.properties
org.jitsi.jicofo.jibri.BREWERY=JibriBrewery@internal.auth.<FQDN>
org.jitsi.jicofo.jibri.PENDING_TIMEOUT=90
org.jitsi.jicofo.auth.URL=EXT_JWT:<FQDN>
systemctl restart jitsi-videobridge2 jicofo prosody
All is ready. Let’s go check.
If jibri is not yet installed, but you need to be able to record or broadcast conferences, then go here and continue installing jibri.
Thank you for attention!
Thanks for the editorial Daria Gulkovich. I also express my gratitude for the technical support (pendal in the right direction) to Nikita Suklich.