#!/bin/bash # JWT Mode Setup # SwITNet Ltd © - 2025, https://switnet.net/ # GPLv3 or later. while getopts m: option do case "${option}" in m) MODE=${OPTARG};; \?) echo "Usage: sudo bash ./$0 [-m debug]" && exit;; esac done #DEBUG if [ "$MODE" = "debug" ]; then set -x fi DOMAIN="$(find /etc/prosody/conf.d/ -name \*.lua|awk -F'.cfg' '!/localhost/{print $1}'|xargs basename)" MEET_CONF="/etc/jitsi/meet/$DOMAIN-config.js" JICOFO_SIP="/etc/jitsi/jicofo/sip-communicator.properties" JICOFO_CONF="/etc/jitsi/jicofo/jicofo.conf" PROSODY_FILE="/etc/prosody/conf.d/$DOMAIN.cfg.lua" PROSODY_SYS="/etc/prosody/prosody.cfg.lua" APP_ID="$(tr -dc "a-zA-Z0-9" < /dev/urandom | fold -w 16 | head -n1)" SECRET_APP="$(tr -dc "a-zA-Z0-9" < /dev/urandom | fold -w 64 | head -n1)" ROOM="Two-Hour-Test-Room" SRP_STR="$(grep -n "VirtualHost \"$DOMAIN\"" "$PROSODY_FILE" | head -n1 | cut -d ":" -f1)" SRP_END="$((SRP_STR + 10))" # Prosody 0.12{,.*} only if command -v prosodyctl >/dev/null 2>&1; then PROSODY_VER="$(prosodyctl about 2>/dev/null | sed -n 's/^Prosody //p' | awk '{print $1}')" case "$PROSODY_VER" in 0.12) : ;; # 22.04 0.12.*) : ;; # 24.04 *) echo "Prosody $PROSODY_VER NO supported for JWT mode (required 0.12.x)" exit 1 ;; esac fi # Custom 5.4 lua workaround for prosody 0.12 echo "Warning: Ubuntu 22.04/24.04 don't ship the required lua inspect module 5.4," echo " so, we work arround it, be careful on further upgrades or changes." install -d -m 755 /usr/share/lua/5.4 ln -sf /usr/share/lua/5.3/inspect.lua /usr/share/lua/5.4/inspect.lua systemctl restart prosody jicofo jitsi-videobridge2 sleep .1 # Install dependencies apt-get -y install python3-jwt echo "set jitsi-meet-tokens/appid string $APP_ID" | debconf-set-selections echo "set jitsi-meet-tokens/appsecret password $SECRET_APP" | debconf-set-selections apt-get install -y jitsi-meet-tokens # Setting up prosody sed -i "s|c2s_require_encryption = true|c2s_require_encryption = false|" "$PROSODY_SYS" #- sed -i "$SRP_STR,$SRP_END{s|authentication = \"jitsi-anonymous\"|authentication = \"token\"|}" "$PROSODY_FILE" sed -i "s|--app_id=\"example_app_id\"|app_id=\"$APP_ID\"|" "$PROSODY_FILE" sed -i "s|--app_secret=\"example_app_secret\"|app_secret=\"$SECRET_APP\"|" "$PROSODY_FILE" sed -i "/app_secret/a \\\\" "$PROSODY_FILE" ## Only token owners can create, open the room and become moderators, ## but require jibri: `allow_empty_token = true` ## other participants are redirected authentication to guest. sed -i "/app_secret/a \ \ \ \ allow_empty_token = true" "$PROSODY_FILE" sed -i "/app_secret/a \\\\" "$PROSODY_FILE" sed -i "/app_secret/a \ \ \ \ asap_accepted_issuers = { \"$APP_ID\" }" "$PROSODY_FILE" sed -i "/app_secret/a \ \ \ \ asap_accepted_audiences = { \"$APP_ID\" }" "$PROSODY_FILE" sed -i "/app_secret/a \\\\" "$PROSODY_FILE" sed -i "s|--allow_empty_token =.*|allow_empty_token = true|" "$PROSODY_FILE" sed -i 's|--"token_verification"|"token_verification"|' "$PROSODY_FILE" sed -i "/muc_lobby_rooms/a \ \ \ \ \ \ \ \ \"persistent_lobby\";" "$PROSODY_FILE" sed -i "/token_verification/a \ \ \ \ \ \ \ \ \"muc_wait_for_host\";" "$PROSODY_FILE" # Set JWT and Guest settings ## Harden JWT auth, preventing "free" moderator by racing into room, ## only participants with token with moderator:true. # Custom 'token_moderator_owner' module for passing JWT claim cp files/mod_token_moderator_owner.lua /usr/share/jitsi-meet/prosody-plugins/ sed -i '/"muc_password_whitelist"/a \ \ \ \ \ \ \ \ \"token_moderator_owner";' "$PROSODY_FILE" envsubst < \ patches/prosody/001-enable_wait_for_host_disable_auto_owners.patch | \ patch --no-backup-if-mismatch -d / -p1 hocon set jicofo.conference.enable-auto-owner false -f "$JICOFO_CONF" ## config.js sed -i "s|// anonymousdomain: 'guest.example.com'|anonymousdomain: \'guest.$DOMAIN\'|" "$MEET_CONF" awk ' BEGIN{done=0} /^[[:space:]]*var[[:space:]]+config[[:space:]]*=[[:space:]]*{\s*$/ && !done{ print print " enableFeaturesBasedOnToken: true," print " enableUserRolesBasedOnToken: true," done=1 next } {print} ' "$MEET_CONF" > "${MEET_CONF}.new" && mv "${MEET_CONF}.new" "$MEET_CONF" # Setup guests and lobby cat << P_SR >> "$PROSODY_FILE" -- jwt setup -QJI VirtualHost "guest.$DOMAIN" authentication = "anonymous" c2s_require_encryption = false speakerstats_component = "speakerstats.$DOMAIN" modules_enabled = { "speakerstats"; -- "conference_duration"; } P_SR echo -e "\nUse the following for your App (e.g. Rocket.Chat):\n" echo -e "\nAPP_ID: $APP_ID" && \ echo -e "SECRET_APP: $SECRET_APP\n" echo -e "You can test JWT authentication with the following token for the next 2 hours:\n" python3 tools/jwt/jitsi_token_maker_features.py \ --app-id "$APP_ID" --secret "$SECRET_APP" \ --domain "$DOMAIN" --room "$ROOM" \ --username "Moderator Token Test User" --moderator --features-all \ --minutes 120 --nbf-offset 300 --include-iat \ --url "https://$DOMAIN/" read -n 1 -s -r -p $'\n'"Press any key to continue..."$'\n'