Skip to content
Snippets Groups Projects
Commit a0c3e029 authored by Dominik Kaminski's avatar Dominik Kaminski :fire:
Browse files

Merge branch 'feat/hybrid-matrix-token' into 'main'

feat(sovereign-workplace-jitsi): Add hybrid-matrix-token support

See merge request souvap/tooling/charts/sovereign-workplace-jitsi!1
parents ac8423a9 88c09904
No related branches found
No related tags found
No related merge requests found
-- SPDX-FileCopyrightText: 2023 Bundesministerium des Innern und für Heimat, PG ZenDiS "Projektgruppe für Aufbau ZenDiS"
-- SPDX-License-Identifier: Apache-2.0
{{ $ENABLE_AUTH := .Env.ENABLE_AUTH | default "0" | toBool -}}
{{ $AUTH_TYPE := .Env.AUTH_TYPE | default "internal" -}}
{{ $PROSODY_AUTH_TYPE := .Env.PROSODY_AUTH_TYPE | default $AUTH_TYPE -}}
{{ $ENABLE_GUEST_DOMAIN := and $ENABLE_AUTH (.Env.ENABLE_GUESTS | default "0" | toBool) -}}
{{ $ENABLE_RECORDING := .Env.ENABLE_RECORDING | default "0" | toBool -}}
{{ $JIBRI_XMPP_USER := .Env.JIBRI_XMPP_USER | default "jibri" -}}
{{ $JIGASI_XMPP_USER := .Env.JIGASI_XMPP_USER | default "jigasi" -}}
{{ $JVB_AUTH_USER := .Env.JVB_AUTH_USER | default "jvb" -}}
{{ $JWT_ASAP_KEYSERVER := .Env.JWT_ASAP_KEYSERVER | default "" -}}
{{ $JWT_ALLOW_EMPTY := .Env.JWT_ALLOW_EMPTY | default "0" | toBool -}}
{{ $JWT_AUTH_TYPE := .Env.JWT_AUTH_TYPE | default "token" -}}
{{ $JWT_ENABLE_DOMAIN_VERIFICATION := .Env.JWT_ENABLE_DOMAIN_VERIFICATION | default "false" | toBool -}}
{{ $MATRIX_UVS_ISSUER := .Env.MATRIX_UVS_ISSUER | default "issuer" -}}
{{ $MATRIX_UVS_SYNC_POWER_LEVELS := .Env.MATRIX_UVS_SYNC_POWER_LEVELS | default "0" | toBool -}}
{{ $JWT_TOKEN_AUTH_MODULE := .Env.JWT_TOKEN_AUTH_MODULE | default "token_verification" -}}
{{ $ENABLE_LOBBY := .Env.ENABLE_LOBBY | default "true" | toBool -}}
{{ $ENABLE_AV_MODERATION := .Env.ENABLE_AV_MODERATION | default "true" | toBool -}}
{{ $ENABLE_BREAKOUT_ROOMS := .Env.ENABLE_BREAKOUT_ROOMS | default "true" | toBool -}}
{{ $ENABLE_END_CONFERENCE := .Env.ENABLE_END_CONFERENCE | default "true" | toBool -}}
{{ $ENABLE_XMPP_WEBSOCKET := .Env.ENABLE_XMPP_WEBSOCKET | default "1" | toBool -}}
{{ $ENABLE_JAAS_COMPONENTS := .Env.ENABLE_JAAS_COMPONENTS | default "0" | toBool -}}
{{ $ENABLE_RATE_LIMITS := .Env.PROSODY_ENABLE_RATE_LIMITS | default "0" | toBool -}}
{{ $PUBLIC_URL := .Env.PUBLIC_URL | default "https://localhost:8443" -}}
{{ $PUBLIC_URL_DOMAIN := $PUBLIC_URL | trimPrefix "https://" | trimSuffix "/" -}}
{{ $TURN_HOST := .Env.TURN_HOST | default "" -}}
{{ $TURN_HOSTS := splitList "," $TURN_HOST -}}
{{ $TURN_PORT := .Env.TURN_PORT | default "443" -}}
{{ $TURN_TRANSPORT := .Env.TURN_TRANSPORT | default "tcp" -}}
{{ $TURN_TRANSPORTS := splitList "," $TURN_TRANSPORT -}}
{{ $TURNS_HOST := .Env.TURNS_HOST | default "" -}}
{{ $TURNS_HOSTS := splitList "," $TURNS_HOST -}}
{{ $TURNS_PORT := .Env.TURNS_PORT | default "443" -}}
{{ $XMPP_AUTH_DOMAIN := .Env.XMPP_AUTH_DOMAIN | default "auth.meet.jitsi" -}}
{{ $XMPP_DOMAIN := .Env.XMPP_DOMAIN | default "meet.jitsi" -}}
{{ $XMPP_GUEST_DOMAIN := .Env.XMPP_GUEST_DOMAIN | default "guest.meet.jitsi" -}}
{{ $XMPP_INTERNAL_MUC_DOMAIN := .Env.XMPP_INTERNAL_MUC_DOMAIN | default "internal-muc.meet.jitsi" -}}
{{ $XMPP_MUC_DOMAIN := .Env.XMPP_MUC_DOMAIN | default "muc.meet.jitsi" -}}
{{ $XMPP_MUC_DOMAIN_PREFIX := (split "." $XMPP_MUC_DOMAIN)._0 -}}
{{ $XMPP_RECORDER_DOMAIN := .Env.XMPP_RECORDER_DOMAIN | default "recorder.meet.jitsi" -}}
{{ $JIBRI_RECORDER_USER := .Env.JIBRI_RECORDER_USER | default "recorder" -}}
{{ $JIGASI_TRANSCRIBER_USER := .Env.JIGASI_TRANSCRIBER_USER | default "transcriber" -}}
{{ $DISABLE_POLLS := .Env.DISABLE_POLLS | default "false" | toBool -}}
{{ $ENABLE_SUBDOMAINS := .Env.ENABLE_SUBDOMAINS | default "true" | toBool -}}
{{ $PROSODY_RESERVATION_ENABLED := .Env.PROSODY_RESERVATION_ENABLED | default "false" | toBool -}}
{{ $PROSODY_RESERVATION_REST_BASE_URL := .Env.PROSODY_RESERVATION_REST_BASE_URL | default "" -}}
{{ $RATE_LIMIT_LOGIN_RATE := .Env.PROSODY_RATE_LIMIT_LOGIN_RATE | default "3" -}}
{{ $RATE_LIMIT_SESSION_RATE := .Env.PROSODY_RATE_LIMIT_SESSION_RATE | default "200" -}}
{{ $RATE_LIMIT_TIMEOUT := .Env.PROSODY_RATE_LIMIT_TIMEOUT | default "60" -}}
{{ $RATE_LIMIT_ALLOW_RANGES := .Env.PROSODY_RATE_LIMIT_ALLOW_RANGES | default "10.0.0.0/8" -}}
{{ $RATE_LIMIT_CACHE_SIZE := .Env.PROSODY_RATE_LIMIT_CACHE_SIZE | default "10000" -}}
{{ $ENV := .Env -}}
admins = {
{{ if .Env.JIGASI_XMPP_PASSWORD }}
"{{ $JIGASI_XMPP_USER }}@{{ $XMPP_AUTH_DOMAIN }}",
{{ end }}
{{ if .Env.JIBRI_XMPP_PASSWORD }}
"{{ $JIBRI_XMPP_USER }}@{{ $XMPP_AUTH_DOMAIN }}",
{{ end }}
"focus@{{ $XMPP_AUTH_DOMAIN }}",
"{{ $JVB_AUTH_USER }}@{{ $XMPP_AUTH_DOMAIN }}"
}
unlimited_jids = {
"focus@{{ $XMPP_AUTH_DOMAIN }}",
"{{ $JVB_AUTH_USER }}@{{ $XMPP_AUTH_DOMAIN }}"
}
plugin_paths = { "/prosody-plugins/", "/prosody-plugins-custom" }
muc_mapper_domain_base = "{{ $XMPP_DOMAIN }}";
muc_mapper_domain_prefix = "{{ $XMPP_MUC_DOMAIN_PREFIX }}";
http_default_host = "{{ $XMPP_DOMAIN }}"
{{ if .Env.TURN_CREDENTIALS -}}
external_service_secret = "{{.Env.TURN_CREDENTIALS}}";
{{- end }}
{{ if or .Env.TURN_HOST .Env.TURNS_HOST -}}
external_services = {
{{ if $TURN_HOST -}}
{{- range $idx1, $host := $TURN_HOSTS -}}
{{- range $idx2, $transport := $TURN_TRANSPORTS -}}
{{- if or $idx1 $idx2 -}},{{- end }}
{ type = "turn", host = "{{ $host }}", port = {{ $TURN_PORT }}, transport = "{{ $transport }}", secret = true, ttl = 86400, algorithm = "turn" }
{{- end -}}
{{- end -}}
{{- end -}}
{{- if $TURNS_HOST -}}
{{- range $idx, $host := $TURNS_HOSTS -}}
{{- if or $TURN_HOST $idx -}},{{- end }}
{ type = "turns", host = "{{ $host }}", port = {{ $TURNS_PORT }}, transport = "tcp", secret = true, ttl = 86400, algorithm = "turn" }
{{- end }}
{{- end }}
};
{{- end }}
{{ if and $ENABLE_AUTH (or (eq $PROSODY_AUTH_TYPE "jwt") (eq $PROSODY_AUTH_TYPE "hybrid_matrix_token")) .Env.JWT_ACCEPTED_ISSUERS }}
asap_accepted_issuers = { "{{ join "\",\"" (splitList "," .Env.JWT_ACCEPTED_ISSUERS) }}" }
{{ end }}
{{ if and $ENABLE_AUTH (or (eq $PROSODY_AUTH_TYPE "jwt") (eq $PROSODY_AUTH_TYPE "hybrid_matrix_token")) .Env.JWT_ACCEPTED_AUDIENCES }}
asap_accepted_audiences = { "{{ join "\",\"" (splitList "," .Env.JWT_ACCEPTED_AUDIENCES) }}" }
{{ end }}
consider_bosh_secure = true;
consider_websocket_secure = true;
{{ if $ENABLE_JAAS_COMPONENTS }}
VirtualHost "jigasi.meet.jitsi"
modules_enabled = {
"ping";
"bosh";
"muc_password_check";
}
authentication = "token"
app_id = "jitsi";
asap_key_server = "https://jaas-public-keys.jitsi.net/jitsi-components/prod-8x8"
asap_accepted_issuers = { "jaas-components" }
asap_accepted_audiences = { "jigasi.{{ $PUBLIC_URL_DOMAIN }}" }
{{ end }}
VirtualHost "{{ $XMPP_DOMAIN }}"
{{ if $ENABLE_AUTH }}
{{ if eq $PROSODY_AUTH_TYPE "jwt" }}
authentication = "{{ $JWT_AUTH_TYPE }}"
app_id = "{{ .Env.JWT_APP_ID }}"
app_secret = "{{ .Env.JWT_APP_SECRET }}"
allow_empty_token = {{ $JWT_ALLOW_EMPTY }}
{{ if $JWT_ASAP_KEYSERVER }}
asap_key_server = "{{ .Env.JWT_ASAP_KEYSERVER }}"
{{ end }}
enable_domain_verification = {{ $JWT_ENABLE_DOMAIN_VERIFICATION }}
{{ else if eq $PROSODY_AUTH_TYPE "ldap" }}
authentication = "cyrus"
cyrus_application_name = "xmpp"
allow_unencrypted_plain_auth = true
{{ else if eq $PROSODY_AUTH_TYPE "matrix" }}
authentication = "matrix_user_verification"
app_id = "{{ $MATRIX_UVS_ISSUER }}"
uvs_base_url = "{{ .Env.MATRIX_UVS_URL }}"
{{ if .Env.MATRIX_UVS_AUTH_TOKEN }}
uvs_auth_token = "{{ .Env.MATRIX_UVS_AUTH_TOKEN }}"
{{ end }}
{{ if $MATRIX_UVS_SYNC_POWER_LEVELS }}
uvs_sync_power_levels = true
{{ end }}
{{ else if eq $PROSODY_AUTH_TYPE "hybrid_matrix_token" }}
authentication = "hybrid_matrix_token"
app_id = "{{ .Env.JWT_APP_ID }}"
app_secret = "{{ .Env.JWT_APP_SECRET }}"
allow_empty_token = {{ $JWT_ALLOW_EMPTY }}
enable_domain_verification = {{ $JWT_ENABLE_DOMAIN_VERIFICATION }}
uvs_base_url = "{{ .Env.MATRIX_UVS_URL }}"
{{ if .Env.MATRIX_UVS_ISSUER }}
uvs_issuer = "{{ .Env.MATRIX_UVS_ISSUER }}"
{{ end }}
{{ if .Env.MATRIX_UVS_AUTH_TOKEN }}
uvs_auth_token = "{{ .Env.MATRIX_UVS_AUTH_TOKEN }}"
{{ end }}
{{ else if eq $PROSODY_AUTH_TYPE "internal" }}
authentication = "internal_hashed"
{{ end }}
{{ else }}
authentication = "jitsi-anonymous"
{{ end }}
ssl = {
key = "/config/certs/{{ $XMPP_DOMAIN }}.key";
certificate = "/config/certs/{{ $XMPP_DOMAIN }}.crt";
}
modules_enabled = {
"bosh";
{{ if $ENABLE_XMPP_WEBSOCKET }}
"websocket";
"smacks"; -- XEP-0198: Stream Management
{{ end }}
"pubsub";
"ping";
"speakerstats";
"conference_duration";
"room_metadata";
{{ if $ENABLE_END_CONFERENCE }}
"end_conference";
{{ end }}
{{ if or .Env.TURN_HOST .Env.TURNS_HOST }}
"external_services";
{{ end }}
{{ if $ENABLE_LOBBY }}
"muc_lobby_rooms";
{{ end }}
{{ if $ENABLE_BREAKOUT_ROOMS }}
"muc_breakout_rooms";
{{ end }}
{{ if $ENABLE_AV_MODERATION }}
"av_moderation";
{{ end }}
{{ if .Env.XMPP_MODULES }}
"{{ join "\";\n\"" (splitList "," .Env.XMPP_MODULES) }}";
{{ end }}
{{ if and $ENABLE_AUTH (eq $PROSODY_AUTH_TYPE "ldap") }}
"auth_cyrus";
{{end}}
{{ if $PROSODY_RESERVATION_ENABLED }}
"reservations";
{{ end }}
}
main_muc = "{{ $XMPP_MUC_DOMAIN }}"
{{ if $ENABLE_LOBBY }}
lobby_muc = "lobby.{{ $XMPP_DOMAIN }}"
{{ if $ENABLE_RECORDING }}
muc_lobby_whitelist = { "{{ $XMPP_RECORDER_DOMAIN }}" }
{{ end }}
{{ end }}
{{ if $PROSODY_RESERVATION_ENABLED }}
reservations_api_prefix = "{{ $PROSODY_RESERVATION_REST_BASE_URL }}"
{{ end }}
{{ if $ENABLE_BREAKOUT_ROOMS }}
breakout_rooms_muc = "breakout.{{ $XMPP_DOMAIN }}"
{{ end }}
speakerstats_component = "speakerstats.{{ $XMPP_DOMAIN }}"
conference_duration_component = "conferenceduration.{{ $XMPP_DOMAIN }}"
{{ if $ENABLE_END_CONFERENCE }}
end_conference_component = "endconference.{{ $XMPP_DOMAIN }}"
{{ end }}
{{ if $ENABLE_AV_MODERATION }}
av_moderation_component = "avmoderation.{{ $XMPP_DOMAIN }}"
{{ end }}
c2s_require_encryption = false
{{ if $ENABLE_GUEST_DOMAIN }}
VirtualHost "{{ $XMPP_GUEST_DOMAIN }}"
authentication = "jitsi-anonymous"
c2s_require_encryption = false
{{ end }}
VirtualHost "{{ $XMPP_AUTH_DOMAIN }}"
ssl = {
key = "/config/certs/{{ $XMPP_AUTH_DOMAIN }}.key";
certificate = "/config/certs/{{ $XMPP_AUTH_DOMAIN }}.crt";
}
modules_enabled = {
"limits_exception";
}
authentication = "internal_hashed"
{{ if $ENABLE_RECORDING }}
VirtualHost "{{ $XMPP_RECORDER_DOMAIN }}"
modules_enabled = {
"ping";
}
authentication = "internal_hashed"
{{ end }}
Component "{{ $XMPP_INTERNAL_MUC_DOMAIN }}" "muc"
storage = "memory"
modules_enabled = {
"ping";
{{ if .Env.XMPP_INTERNAL_MUC_MODULES -}}
"{{ join "\";\n\"" (splitList "," .Env.XMPP_INTERNAL_MUC_MODULES) }}";
{{ end -}}
}
restrict_room_creation = true
muc_room_locking = false
muc_room_default_public_jids = true
Component "{{ $XMPP_MUC_DOMAIN }}" "muc"
restrict_room_creation = true
storage = "memory"
modules_enabled = {
"muc_meeting_id";
{{ if .Env.XMPP_MUC_MODULES -}}
"{{ join "\";\n\"" (splitList "," .Env.XMPP_MUC_MODULES) }}";
{{ end -}}
{{ if and $ENABLE_AUTH (or (eq $PROSODY_AUTH_TYPE "jwt") (eq $PROSODY_AUTH_TYPE "hybrid_matrix_token")) -}}
"{{ $JWT_TOKEN_AUTH_MODULE }}";
{{ end }}
{{ if and $ENABLE_AUTH (eq $PROSODY_AUTH_TYPE "matrix") $MATRIX_UVS_SYNC_POWER_LEVELS -}}
"matrix_power_sync";
{{ end -}}
{{ if and $ENABLE_AUTH (eq $PROSODY_AUTH_TYPE "hybrid_matrix_token") $MATRIX_UVS_SYNC_POWER_LEVELS -}}
"matrix_affiliation";
{{ end -}}
{{ if not $DISABLE_POLLS -}}
"polls";
{{ end -}}
{{ if $ENABLE_SUBDOMAINS -}}
"muc_domain_mapper";
{{ end -}}
{{ if $ENABLE_RATE_LIMITS -}}
"muc_rate_limit";
"rate_limit";
{{ end -}}
{{ if .Env.MAX_PARTICIPANTS }}
"muc_max_occupants";
{{ end }}
"muc_password_whitelist";
}
{{ if $ENABLE_RATE_LIMITS -}}
-- Max allowed join/login rate in events per second.
rate_limit_login_rate = {{ $RATE_LIMIT_LOGIN_RATE }};
-- The rate to which sessions from IPs exceeding the join rate will be limited, in bytes per second.
rate_limit_session_rate = {{ $RATE_LIMIT_SESSION_RATE }};
-- The time in seconds, after which the limit for an IP address is lifted.
rate_limit_timeout = {{ $RATE_LIMIT_TIMEOUT }};
-- List of regular expressions for IP addresses that are not limited by this module.
rate_limit_whitelist = {
"127.0.0.1";
{{ range $index, $cidr := (splitList "," $RATE_LIMIT_ALLOW_RANGES) -}}
"{{ $cidr }}";
{{ end -}}
};
rate_limit_whitelist_jids = {
"{{ $JIBRI_RECORDER_USER }}@{{ $XMPP_RECORDER_DOMAIN }}",
"{{ $JIGASI_TRANSCRIBER_USER }}@{{ $XMPP_RECORDER_DOMAIN }}"
}
{{ end -}}
-- The size of the cache that saves state for IP addresses
rate_limit_cache_size = {{ $RATE_LIMIT_CACHE_SIZE }};
muc_room_cache_size = 1000
muc_room_locking = false
muc_room_default_public_jids = true
{{ if .Env.XMPP_MUC_CONFIGURATION -}}
{{ join "\n" (splitList "," .Env.XMPP_MUC_CONFIGURATION) }}
{{ end -}}
{{ if .Env.MAX_PARTICIPANTS }}
muc_access_whitelist = { "focus@{{ .Env.XMPP_AUTH_DOMAIN }}" }
muc_max_occupants = "{{ .Env.MAX_PARTICIPANTS }}"
{{ end }}
muc_password_whitelist = {
"focus@{{ .Env.XMPP_AUTH_DOMAIN }}"
}
Component "focus.{{ $XMPP_DOMAIN }}" "client_proxy"
target_address = "focus@{{ $XMPP_AUTH_DOMAIN }}"
Component "speakerstats.{{ $XMPP_DOMAIN }}" "speakerstats_component"
muc_component = "{{ $XMPP_MUC_DOMAIN }}"
Component "conferenceduration.{{ $XMPP_DOMAIN }}" "conference_duration_component"
muc_component = "{{ $XMPP_MUC_DOMAIN }}"
{{ if $ENABLE_END_CONFERENCE }}
Component "endconference.{{ $XMPP_DOMAIN }}" "end_conference"
muc_component = "{{ $XMPP_MUC_DOMAIN }}"
{{ end }}
{{ if $ENABLE_AV_MODERATION }}
Component "avmoderation.{{ $XMPP_DOMAIN }}" "av_moderation_component"
muc_component = "{{ $XMPP_MUC_DOMAIN }}"
{{ end }}
{{ if $ENABLE_LOBBY }}
Component "lobby.{{ $XMPP_DOMAIN }}" "muc"
storage = "memory"
restrict_room_creation = true
muc_room_locking = false
muc_room_default_public_jids = true
modules_enabled = {
{{ if $ENABLE_RATE_LIMITS -}}
"muc_rate_limit";
{{ end -}}
}
{{ end }}
{{ if $ENABLE_BREAKOUT_ROOMS }}
Component "breakout.{{ $XMPP_DOMAIN }}" "muc"
storage = "memory"
restrict_room_creation = true
muc_room_locking = false
muc_room_default_public_jids = true
modules_enabled = {
"muc_meeting_id";
{{ if $ENABLE_SUBDOMAINS -}}
"muc_domain_mapper";
{{ end -}}
{{ if not $DISABLE_POLLS -}}
"polls";
{{ end -}}
{{ if $ENABLE_RATE_LIMITS -}}
"muc_rate_limit";
{{ end -}}
}
{{ end }}
Component "metadata.{{ $XMPP_DOMAIN }}" "room_metadata_component"
muc_component = "{{ $XMPP_MUC_DOMAIN }}"
breakout_rooms_component = "breakout.{{ $XMPP_DOMAIN }}"
-- SPDX-FileCopyrightText: 2023 Bundesministerium des Innern und für Heimat, PG ZenDiS "Projektgruppe für Aufbau ZenDiS"
-- SPDX-License-Identifier: Apache-2.0
-- -----------------------------------------------------------------------------
-- Hybrid Matrix-Token authentication
-- -----------------------------------------------------------------------------
-- This module is an authentication provider for Prosody which supports Matrix
-- and standard Jitsi token at the same time. It senses the type of the token
-- and handles it depending on its type.
-- -----------------------------------------------------------------------------
local async = require "util.async"
local basexx = require 'basexx'
local cjson_safe = require 'cjson.safe'
local formdecode = require "util.http".formdecode
local generate_uuid = require "util.uuid".generate
local http = require "net.http"
local json = require "util.json"
local new_sasl = require "util.sasl".new
local sasl = require "util.sasl"
local sessions = prosody.full_sessions
local token_util = module:require "token/util".new(module)
-- no token configuration
if token_util == nil then
return
end
module:depends("jitsi_session")
local uvsIssuer = {"*"}
local issuer = module:get_option("uvs_issuer", nil)
if issuer then
uvsIssuer = { string.format("%s", issuer) }
end
local uvsUrl = module:get_option("uvs_base_url", nil)
if uvsUrl == nil then
module:log("warn", "Missing 'uvs_base_url' config")
end
local uvsAuthToken = module:get_option("uvs_auth_token", nil)
if uvsAuthToken == nil then
module:log(
"info",
"No uvs_auth_token supplied, not sending authentication headers"
)
end
-- define auth provider
local provider = {}
local host = module.host
-- Extract 'token' and 'room' params 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)
session.auth_token = params and params.token or nil
session.jitsi_room = params and params.room or nil
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
local function split_token(token)
local segments = {}
for seg in string.gmatch(token, "([^.]+)") do
table.insert(segments, seg)
end
return segments
end
local function parse_token(token)
if type(token) ~= "string" then return nil, nil, nil end
local segments = split_token(token)
if #segments ~= 3 then return nil, nil, nil end
local header, err1 = cjson_safe.decode(basexx.from_url64(segments[1]))
if err1 then return nil, nil, nil end
local payload, err2 = cjson_safe.decode(basexx.from_url64(segments[2]))
if err2 then return nil, nil, nil end
local sign, err3 = basexx.from_url64(segments[3])
if err3 then return nil, nil, nil end
return header, payload, sign
end
local function get_options(matrixPayload)
local options = {}
options.method = "POST"
options.headers = {
["Content-Type"] = "application/json",
["User-Agent"] = string.format("Prosody (%s)", prosody.version)
}
if uvsAuthToken ~= nil then
options.headers["Authorization"] = string.format(
"Bearer %s", uvsAuthToken
)
end
local body = {
["token"] = matrixPayload["token"],
["room_id"] = matrixPayload["room_id"]
}
if matrixPayload.server_name then
body["matrix_server_name"] = matrixPayload.server_name
end
options.body = json.encode(body)
return options
end
local function is_user_in_room(session, matrixPayload)
local url = string.format("%s/verify/user_in_room", uvsUrl)
local options = get_options(matrixPayload)
local wait, done = async.waiter()
local httpRes
local function cb(resBody, resCode, _req, _res)
if resCode == 200 then
httpRes = json.decode(resBody)
end
done()
end
http.request(url, options, cb)
wait()
-- no result
if not (httpRes and httpRes.results) then
return false
end
-- not a member of Matrix room
if not (httpRes.results.user and httpRes.results.room_membership) then
return false
end
-- set affiliation as session value according to their power level
session.matrix_affiliation = "member"
session.auth_matrix_user_verification_is_owner = false
if
httpRes.power_levels and httpRes.power_levels.user and
httpRes.power_levels.room and httpRes.power_levels.room.state_default and
httpRes.power_levels.user >= httpRes.power_levels.room.state_default
then
session.matrix_affiliation = "owner"
session.auth_matrix_user_verification_is_owner = true
end
return true
end
local function matrix_handler(session, payload)
if uvsUrl == nil then
module:log("warn", "Missing 'uvs_base_url' config")
session.auth_token = nil
return false, "access-denied", "missing Matrix UVS address"
end
session.public_key = "notused"
local res, error, reason = token_util:process_and_verify_token(
session,
uvsIssuer
)
if res == false then
module:log(
"warn",
"Error verifying token err:%s, reason:%s", error, reason
)
session.auth_token = nil
return res, error, reason
end
if payload.context.matrix.room_id == nil then
module:log("warn", "Missing Matrix room_id in token")
session.auth_token = nil
return false, "bad-request", "Matrix room ID must be given"
end
local decodedRoomId = basexx.from_base32(session.jitsi_room)
if decodedRoomId ~= payload.context.matrix.room_id then
module:log("warn", "Jitsi and Matrix rooms don't match")
session.auth_token = nil
return false, "access-denied", "Jitsi room does not match Matrix room"
end
if not is_user_in_room(session, payload.context.matrix) then
module:log("warn", "Matrix token is invalid or user does not in room")
session.auth_token = nil
return false, "access-denied", "Matrix token invalid or not in room"
end
session.jitsi_meet_context_matrix = payload.context.matrix
return true, nil, nil
end
local function token_handler(session)
-- retrieve custom public key from server and save it on the session
local preEvent = prosody.events.fire_event(
"pre-jitsi-authentication-fetch-key",
session
)
if preEvent ~= nil and preEvent.res == false then
module:log(
"warn",
"Error verifying token on pre authentication stage:%s, reason:%s",
preEvent.error,
preEvent.reason
)
session.auth_token = nil
return preEvent.res, preEvent.error, preEvent.reason
end
local res, error, reason = token_util:process_and_verify_token(session)
if res == false then
module:log(
"warn",
"Error verifying token err:%s, reason:%s", error, reason
)
session.auth_token = nil
return res, error, reason
end
return true, nil, nil
end
local function common_handler(self, session, message)
local shouldAllow = prosody.events.fire_event(
"jitsi-access-ban-check",
session
)
if shouldAllow == false then
module:log("warn", "user is banned")
return false, "not-allowed", "user is banned"
end
local customUsername = prosody.events.fire_event(
"pre-jitsi-authentication",
session
)
if (customUsername) then
self.username = customUsername
elseif (session.previd ~= nil) then
for _, s in pairs(sessions) do
if (s.resumption_token == session.previd) then
self.username = s.username
break
end
end
else
self.username = message
end
local postEvent = prosody.events.fire_event(
"post-jitsi-authentication",
session
)
if postEvent ~= nil and postEvent.res == false then
module:log(
"warn",
"Error verifying token on post authentication :%s, reason:%s",
postEvent.error,
postEvent.reason
)
session.auth_token = nil
return postEvent.res, postEvent.error, postEvent.reason
end
return true, nil, nil
end
function provider.get_sasl_handler(session)
local function handler(self, message)
local payload
if session.auth_token then
_, payload, _ = parse_token(session.auth_token)
end
if payload and payload.context and payload.context.matrix then
module:log("info", "Matrix authentication handler is selected")
local res, error, reason = matrix_handler(session, payload)
if res == false then
return res, error, reason
end
else
module:log("info", "Token authentication handler is selected")
local res, error, reason = token_handler(session)
if res == false then
return res, error, reason
end
end
local res, error, reason = common_handler(self, session, message)
if res == false then
return res, error, reason
end
return true
end
return new_sasl(host, { anonymous = handler })
end
module:provides("auth", provider)
local function anonymous(self, message)
module:log("debug", "Message in anonymous: %s", 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)
-- SPDX-FileCopyrightText: 2023 Bundesministerium des Innern und für Heimat, PG ZenDiS "Projektgruppe für Aufbau ZenDiS"
-- SPDX-License-Identifier: Apache-2.0
-- -----------------------------------------------------------------------------
-- Matrix Affiliation (downgrade only)
-- -----------------------------------------------------------------------------
-- This module updates the affiliation of participants if the room is created
-- by Element's Jitsi widget. This module checks Jitsi room name to understand
-- if this room is created by widget or not...
--
-- base32.decode(jitsi_room_name) should match "!.*:.*[.].*" (regex) for related
-- rooms.
--
-- This module assumes that the authentication is already enabled on Jicofo. So
-- every participants who have a valid token will become moderator (owner) by
-- default (this is not what we want).
--
-- This module downgrades the affiliation level (from owner to member) of
-- the participant if she is not an admin in the related Matrix room.
-- -----------------------------------------------------------------------------
local basexx = require 'basexx'
local is_admin = require "core.usermanager".is_admin
local is_healthcheck_room = module:require "util".is_healthcheck_room
local jid_split = require "util.jid".split
local timer = require "util.timer"
local LOGLEVEL = "debug"
local function _is_admin(jid)
return is_admin(jid, module.host)
end
module:hook("muc-occupant-joined", function (event)
local room, occupant = event.room, event.occupant
if is_healthcheck_room(room.jid) or _is_admin(occupant.jid) then
module:log(LOGLEVEL, "skip affiliation, %s", occupant.jid)
return
end
if not event.origin.auth_token then
module:log(LOGLEVEL, "skip affiliation, no token")
return
end
local roomName, _ = jid_split(room.jid)
local roomId = basexx.from_base32(roomName)
if not roomId then
module:log(LOGLEVEL, "skip affiliation, cannot decode the room name")
return
end
local isMatrixRoom = string.match(roomId, "!.*:.*[.].*")
if not isMatrixRoom then
module:log(LOGLEVEL, "skip affiliation, not a Matrix room")
return
end
if event.origin.matrix_affiliation == "owner" then
module:log(LOGLEVEL, "skip downgrading, valid Matrix owner")
return
end
-- All users who have a valid token are set as owner by jicofo when
-- auhentication is enabled on jicofo. Downgrade the affiliation for all
-- users who are not a Matrix owner (even they have a valid token).
-- A timer is used because Jicofo will update the affiliation after this
-- internal authentication phase is completed. It should be overwritten.
local i = 0.0
while (i < 2.0) do
timer.add_task(i, function()
room:set_affiliation(true, occupant.bare_jid, "member")
end)
i = i + 0.2
end
module:log( "info",
"affiliation is downgraded, occupant: %s",
occupant.bare_jid
)
end)
......@@ -50,4 +50,18 @@ data:
{{- end }}
kubectl rollout restart deployment jitsi-jvb
{{- end }}
---
kind: "ConfigMap"
apiVersion: "v1"
metadata:
name: "prosody-swp"
data:
{{ (.Files.Glob "files/prosody/jitsi-meet.cfg.lua").AsConfig | nindent 2 }}
---
kind: "ConfigMap"
apiVersion: "v1"
metadata:
name: "prosody-plugins-swp"
data:
{{ (.Files.Glob "files/prosody/prosody-plugins-custom/*").AsConfig | nindent 2 }}
...
......@@ -176,7 +176,7 @@ jitsi:
web:
replicaCount: 1
image:
tag: "stable-8615"
tag: "stable-8719"
pullPolicy: "IfNotPresent"
extraVolumes:
- name: "jitsi-meet-swp"
......@@ -222,18 +222,36 @@ jitsi:
prosody:
image:
tag: "stable-8615"
tag: "stable-8719"
pullPolicy: "IfNotPresent"
extraEnvs:
- name: "AUTH_TYPE"
value: "jwt"
extraVolumes:
- name: "prosody-swp"
configMap:
name: "prosody-swp"
items:
- key: "jitsi-meet.cfg.lua"
path: "jitsi-meet.cfg.lua"
- name: "prosody-plugins-custom"
configMap:
name: "prosody-plugins-swp"
extraVolumeMounts:
- name: "prosody-swp"
mountPath: "/defaults/conf.d/jitsi-meet.cfg.lua"
subPath: "jitsi-meet.cfg.lua"
- name: "prosody-plugins-custom"
mountPath: "/prosody-plugins-custom"
jicofo:
image:
tag: "stable-8615"
tag: "stable-8719"
pullPolicy: "IfNotPresent"
extraEnvs:
AUTH_TYPE: "xmpp"
ENABLE_AUTO_LOGIN: "false"
JICOFO_AUTH_LIFETIME: "100 milliseconds"
extraEnvFrom:
- secretRef:
name: "{{ include 'prosody.fullname' . }}-jicofo"
......@@ -246,9 +264,9 @@ jitsi:
jvb:
image:
tag: "stable-8615"
tag: "stable-8719"
pullPolicy: "IfNotPresent"
replicaCount: 2
replicaCount: 1
service:
externalTrafficPolicy: ""
enabled: true
......@@ -259,7 +277,7 @@ jitsi:
recording: true
livestreaming: true
image:
tag: "stable-8615"
tag: "stable-8719"
pullPolicy: "IfNotPresent"
readinessProbe:
initialDelaySeconds: 15
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment

Consent

On this website, we use the web analytics service Matomo to analyze and review the use of our website. Through the collected statistics, we can improve our offerings and make them more appealing for you. Here, you can decide whether to allow us to process your data and set corresponding cookies for these purposes, in addition to technically necessary cookies. Further information on data protection—especially regarding "cookies" and "Matomo"—can be found in our privacy policy. You can withdraw your consent at any time.