idaa/video_conferences: issue JWT to all verified Novi users

Previously only moderators received a JWT; non-moderators joined
anonymously. Now all verified Novi users get a JWT with the
is_moderator flag set appropriately, allowing the Jitsi server to
enforce authentication and respect context.user.moderator for
all participants.

Also adds JWT payload decode logging (client-side, signature not
verified) so the moderator flag and user identity can be confirmed
in the browser console during testing.
This commit is contained in:
Scott Idem
2026-04-02 12:51:05 -04:00
parent 75d85bf904
commit fd5d5e371b

View File

@@ -841,30 +841,33 @@ async function init_jitsi() {
const url_params = data.params; const url_params = data.params;
// --- Initialize Jitsi --- // --- Initialize Jitsi ---
// TODO: Issue JWT to all verified Novi users once Jitsi server is configured to enforce // Issue JWT to all verified Novi users. The token's moderator flag controls
// JWT auth and respect context.user.moderator (set allow_empty_token = false in Prosody). // whether the user gets host privileges in the Jitsi room.
// For now, only moderators get a JWT — non-moderators join anonymously. console.log(`Jitsi: Attempting to get JWT (is_moderator=${is_moderator})...`);
let jwt_token = null; const jwt_token = await get_jitsi_jwt(
if (is_moderator) { display_name,
console.log('Jitsi: Attempting to get JWT for moderator...'); email,
jwt_token = await get_jitsi_jwt( is_moderator,
display_name, room_name,
email, user_id
is_moderator, );
room_name, if (!jwt_token) {
user_id const container = document.getElementById(jitsi_container_id);
); if (container)
if (!jwt_token) { container.innerHTML =
const container = document.getElementById(jitsi_container_id); '<h1>Authentication Failed. Please try again.</h1>';
if (container) console.error('Jitsi: Authentication failed. JWT not received.');
container.innerHTML = return;
'<h1>Authentication Failed. Please try again.</h1>'; }
console.error('Jitsi: Authentication failed. JWT not received.'); console.log('Jitsi: Successfully received JWT.');
return; try {
} // Decode JWT payload (base64url → JSON) for debug verification.
console.log('Jitsi: Successfully received JWT.'); // This does NOT verify the signature — for logging only.
} else { const jwt_payload = JSON.parse(atob(jwt_token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/')));
console.log('Jitsi: Non-moderator joining without JWT (temporary — pending Jitsi server config fix).'); console.log('%cJitsi JWT decoded payload:', 'font-weight:bold;color:#4f8ef7', jwt_payload);
console.log(`Jitsi JWT: user=${jwt_payload?.context?.user?.name ?? jwt_payload?.name}, moderator=${jwt_payload?.context?.user?.moderator ?? jwt_payload?.user?.moderator}, room=${jwt_payload?.room ?? jwt_payload?.context?.room}`);
} catch (e) {
console.warn('Jitsi: Could not decode JWT payload for debug logging.', e);
} }
const disabled_sounds = [ const disabled_sounds = [