From 9b0c05b80c8a64bb577d7ba6909d0848eeeca6b4 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Tue, 31 Mar 2026 17:53:09 -0400 Subject: [PATCH] fix(idaa): require JWT for all Novi users, remove embed meeting button - Issue JWT to all verified Novi users, not just moderators; unauthenticated URL access no longer sufficient to join an IDAA video conference - Remove 'embedmeeting' from Jitsi toolbar via explicit toolbarButtons whitelist; the embed dialog exposed the Jitsi host/room URL violating IDAA privacy rules Co-Authored-By: Claude Sonnet 4.6 --- .../(idaa)/video_conferences/+page.svelte | 54 +++++++++++-------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/src/routes/idaa/(idaa)/video_conferences/+page.svelte b/src/routes/idaa/(idaa)/video_conferences/+page.svelte index 9120b759..ea5a5321 100644 --- a/src/routes/idaa/(idaa)/video_conferences/+page.svelte +++ b/src/routes/idaa/(idaa)/video_conferences/+page.svelte @@ -836,28 +836,26 @@ async function init_jitsi() { const url_params = data.params; // --- Initialize Jitsi --- - let jwt_token = null; - if (is_moderator) { - console.log('Jitsi: Attempting to get JWT for moderator...'); - jwt_token = await get_jitsi_jwt( - display_name, - email, - is_moderator, - room_name, - user_id - ); - if (!jwt_token) { - const container = document.getElementById(jitsi_container_id); - if (container) - container.innerHTML = - '

Authentication Failed. Please try again.

'; - console.error('Jitsi: Authentication failed. JWT not received.'); - return; - } - console.log('Jitsi: Successfully received JWT.'); - } else { - console.log('Jitsi: Not a moderator, proceeding without JWT.'); + // All verified Novi users get a JWT — not just moderators. + // Without JWT enforcement, the room URL alone is enough to join, which violates IDAA privacy. + // is_moderator is encoded in the token payload by get_jitsi_jwt(). + console.log('Jitsi: Attempting to get JWT...'); + const jwt_token = await get_jitsi_jwt( + display_name, + email, + is_moderator, + room_name, + user_id + ); + if (!jwt_token) { + const container = document.getElementById(jitsi_container_id); + if (container) + container.innerHTML = + '

Authentication Failed. Please try again.

'; + console.error('Jitsi: Authentication failed. JWT not received.'); + return; } + console.log('Jitsi: Successfully received JWT.'); const disabled_sounds = [ disable_incoming_msg_sound ? 'INCOMING_MSG_SOUND' : null, @@ -879,7 +877,19 @@ async function init_jitsi() { startWithVideoMuted: true, enableLobby: is_moderator, disableReactionsModeration: false, - disabledSounds: disabled_sounds + disabledSounds: disabled_sounds, + // Explicit toolbar whitelist — omitting 'embedmeeting' entirely. + // "Embed Meeting" exposes the Jitsi host/room URL and must never appear + // for IDAA users (authenticated or not) — privacy requirement. + toolbarButtons: [ + 'camera', 'chat', 'closedcaptions', 'desktop', 'download', + 'etherpad', 'feedback', 'filmstrip', 'fullscreen', 'hangup', + 'help', 'invite', 'livestreaming', 'microphone', + 'mute-everyone', 'mute-video-everyone', 'participants-pane', + 'profile', 'raisehand', 'recording', 'security', + 'select-background', 'settings', 'shareaudio', 'sharedvideo', + 'shortcuts', 'stats', 'tileview', 'toggle-camera', 'videoquality' + ] }, interfaceConfigOverwrite: { DISABLE_JOIN_LEAVE_NOTIFICATIONS: true,