Excalidraw data decrypt error / Whiteboard not working on anonymous domains?

The Whiteboard works for me on Domains with authentication but on an anonymous domain it fails with “can’t decrypt data”. Using “muc_allowners”, when creating a whiteboard it does not appear for a fellow jitster → if that person clicks/selects the whiteboard himself, the “can’t decrypt data” error occurs.

prosody shows no errors. when running in debug + debug_stanza this error is shown after the whiteboard is first activated (even though it seems the metadata_room is initialised normaly on startup?)

Dec 09 21:04:41 c2s563526009820 debug   RECV: <message to='metadata.meet.domain.tld'><room_metadata xmlns='http://jitsi.org/jitmeet' room='whiteboardroom@conference.meet.domain.tld'>{&quot;key&quot;:&quot;whiteboard&quot;,&quot;data&quot;:{&quot;collabServerUrl&quot;:&quot;https://meet.domain.tld/?room=3419054546d9af6484dfa71443d30ceb&quot;,&quot;collabDetails&quot;:{&quot;roomId&quot;:&quot;whiteboardroom&quot;,&quot;roomKey&quot;:&quot;jSK2BqdP3XeR6z9zXUK-wg&quot;}},&quot;type&quot;:&quot;room_metadata&quot;}</room_metadata></message>
Dec 09 21:04:41 c2s563526009820 debug   Received[c2s]: <message to='metadata.meet.domain.tld'>
Dec 09 21:04:41 c2s563526009820 debug   Sending[c2s]: <message to='zigtfykchqkphydl@meet.domain.tld/p06m1fHC' type='error' from='metadata.meet.domain.tld'>
Dec 09 21:04:41 c2s563526009820 debug   SEND: <message to='zigtfykchqkphydl@meet.domain.tld/p06m1fHC' type='error' from='metadata.meet.domain.tld'><error type='cancel'><service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/></error></message>

→ but no idea why the service is unavailable.
when not running in debug, no errors are shown.

a similiar setup (+lobby/breakoutrooms as only difference) with authentication works as expected → thats why I am focusing on this difference, albeit it might be entirely unrelated :see_no_evil:

If someone can confirm that Whiteboards are working with anonymous/no authentication → that would already be good to know.

prosody configuration:

muc_mapper_domain_base = "meet.domain.tld";
plugin_paths = { "/usr/share/jitsi-meet/prosody-plugins/" }
external_service_secret = "***";

external_services = {
     { type = "stun", host = "turn.domain.tld", port = 5349 },
     { type = "turn", host = "turn.domain.tld", port = 5349, transport = "udp", secret = true, ttl = 86400, algorithm = "turn" },
     { type = "turns", host = "turn.domain.tld", port = 5349, transport = "tcp", secret = true, ttl = 86400, algorithm = "turn" }
};

ssl = {
    protocol = "tlsv1_2+";
    ciphers = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"
}

unlimited_jids = {
    "focusUser@auth.meet.domain.tld",
    "jvb@auth.meet.domain.tld"
}

cross_domain_bosh = false;
consider_bosh_secure = true;
cross_domain_websocket = true;
consider_websocket_secure = true;

VirtualHost "meet.domain.tld"
        authentication = "anonymous"
        ssl = {
                key = "/etc/prosody/certs/meet.domain.tld.key";
                certificate = "/etc/prosody/certs/meet.domain.tld.crt";
        }
        speakerstats_component = "speakerstats.meet.domain.tld"
        conference_duration_component = "conferenceduration.meet.domain.tld"
        modules_enabled = {
            "bosh";
            "pubsub";
            "ping";
            "speakerstats";
            "external_services";
            "conference_duration";
            "websocket";
            "smacks";
            "room_metadata";
            --"stanza_debug";
        }
        lobby_muc = "lobby.meet.domain.tld"
        main_muc = "conference.meet.domain.tld"
        room_metadata_component = "metadata.meet.domain.tld"
        c2s_require_encryption = false
        smacks_max_unacked_stanzas = 5;
        smacks_hibernation_time = 60;
        smacks_max_hibernated_sessions = 1;
        smacks_max_old_sessions = 1;


Component "conference.meet.domain.tld" "muc"
    storage = "memory"
    modules_enabled = {
        "muc_meeting_id";
        "muc_domain_mapper";
        "polls";
        "muc_allowners";
    }
    admins = { "focus@auth.meet.domain.tld" }
    muc_room_locking = false
    muc_room_default_public_jids = true

Component "internal.auth.meet.domain.tld" "muc"
    storage = "memory"
    modules_enabled = {
      "ping";
    }
    admins = { "focus@auth.meet.domain.tld", "jvb@auth.meet.domain.tld" }
    muc_room_locking = false
    muc_room_default_public_jids = true

VirtualHost "auth.meet.domain.tld"
    ssl = {
        key = "/etc/prosody/certs/auth.meet.domain.tld.key";
        certificate = "/etc/prosody/certs/auth.meet.domain.tld.crt";
    }
    modules_enabled = {
        "limits_exception";
    }
    authentication = "internal_hashed"

Component "focus.meet.domain.tld" "client_proxy"
    target_address = "focus@auth.meet.domain.tld"

Component "speakerstats.meet.domain.tld" "speakerstats_component"
    muc_component = "conference.meet.domain.tld"

Component "conferenceduration.meet.domain.tld" "conference_duration_component"
    muc_component = "conference.meet.domain.tld"

Component "metadata.meet.domain.tld" "room_metadata_component"
    muc_component = "conference.meet.domain.tld"

Try to replace the auth from anonymous to jitsi-anonymous.

Hello @saghul Thanks for the Input! tried with jitsi-anonymous but the overal behavior did not change.

Did you restart prosody after making the change?

yes. I restartet even the entire stack (jvb/jicofo) just to be sure as well

however, there is no indication in the prosody.log that it uses the mod_auth_jitsi-anonymous.lua → i suppose that is normal though? have not tried with debug yet

edit: it does show when running in debug:

Dec 12 09:31:49 usermanager debug Host ‘meet.domain.tld’ now set to use user provider ‘jitsi-anonymous’

Do you see the room metadata plugin related logs when prosody starts up?

Can confirm it’s working OK here with anonymous auth and muc_allowners. One possibly notable difference, the stack I tested on has the breakout component (which the room_metadata component has a configuration option pointing at).

grepping for metadata in prosdy startup:

Dec 12 09:31:49 hostmanager     debug   Activated host: metadata.meet.domain.tld
Dec 12 09:31:49 metadata.meet.domain.tld:room_metadata_component     info    Starting room metadata for conference.meet.domain.tld
Dec 12 09:31:49 metadata.meet.domain.tld:room_metadata_component     debug   Main muc loaded
Dec 12 09:31:49 metadata.meet.domain.tld:room_metadata_component     info    Hook to muc events on conference.meet.domain.tld
Dec 12 09:31:49 metadata.meet.domain.tld:tls debug   Creating context for c2s
Dec 12 09:31:49 certmanager     debug   Searching /etc/prosody/certs for a key and certificate for metadata.meet.domain.tld...
Dec 12 09:31:49 certmanager     debug   No certificate/key found for metadata.meet.domain.tld
Dec 12 09:31:49 metadata.meet.domain.tld:tls debug   Creating context for s2sout
Dec 12 09:31:49 certmanager     debug   Searching /etc/prosody/certs for a key and certificate for metadata.meet.domain.tld...
Dec 12 09:31:49 certmanager     debug   No certificate/key found for metadata.meet.domain.tld
Dec 12 09:31:49 metadata.meet.domain.tld:tls debug   Creating context for s2sin
Dec 12 09:31:49 certmanager     debug   Searching /etc/prosody/certs for a key and certificate for metadata.meet.domain.tld...
Dec 12 09:31:49 certmanager     debug   No certificate/key found for metadata.meet.domain.tld
Dec 12 09:31:49 metadata.meet.domain.tld:tls info    Certificates loaded
Dec 12 09:31:49 conference.meet.domain.tld:muc_domain_mapper info    Loading mod_muc_domain_mapper for host metadata.meet.domain.tld!

so that seems to initialise. One more thing, that system has 2 ip addresses but pretty much all services are configured/pointed at localhost. name resolving for meet.domain.tld is also pointing to the correct IP (also listening on * )

thanks, that is very good to know. So it must be something in my config

thanks for the hint @jbg !
thanks for the help @saghul !

Adding the breakout room → and it works … I never needed breakout rooms on that Instance and i was thinking about adding for testing but … next time :slight_smile:

It works when the breakout.domain.tld component/muc is configured

so, for whiteboard the breakout rooms are mandatory, no good reason to not configure them anyways … :see_no_evil:

1 Like

Oh, interesting! That was certainly not intentional, so we should fix it I reckon. At the same time, it’d be very hard to give a proper error if it’s actually necessary, because breakout rooms are enabled…

Sorry to bother but can you be very specific here or perhaps send your config? I’m not understanding fully and I’m 48 hours into trying to get this whiteboard to work. I have it on the screen but it’s not shared between people yet. I’m so close. I think I just need your config to see what you guys mean by the breakout settings.

sure, here is the diff/config from above with the enabled breakout rooms:

muc_mapper_domain_base = "meet.domain.tld";

plugin_paths = { "/usr/share/jitsi-meet/prosody-plugins/" }

external_service_secret = "***";

external_services = {
     { type = "stun", host = "stun.domain.tld", port = 443 },
     { type = "turn", host = "stun.domain.tld", port = 443, transport = "udp", secret = true, ttl = 86400, algorithm = "turn" },
     { type = "turns", host = "stun.domain.tld", port = 443, transport = "tcp", secret = true, ttl = 86400, algorithm = "turn" }
};

ssl = {
    protocol = "tlsv1_2+";
    ciphers = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"
}

unlimited_jids = {
    "focusUser@auth.meet.domain.tld",
    "jvb@auth.meet.domain.tld"
}

cross_domain_bosh = false;
consider_bosh_secure = true;
cross_domain_websocket = true;
consider_websocket_secure = true;

VirtualHost "meet.domain.tld"
        authentication = "jitsi-anonymous"
        ssl = {
                key = "/etc/prosody/certs/meet.domain.tld.key";
                certificate = "/etc/prosody/certs/meet.domain.tld.crt";
        }
        speakerstats_component = "speakerstats.meet.domain.tld"
        conference_duration_component = "conferenceduration.meet.domain.tld"
        --av_moderation_component = "avmoderation.meet.domain.tld"
        breakout_rooms_muc = "breakout.meet.domain.tld"
        --end_conference_component = "endconference.meet.domain.tld."
        -- we need bosh
        modules_enabled = {
            "bosh";
            "pubsub";
            "ping";
            "speakerstats";
            "external_services";
            "conference_duration";
            "websocket";
            "smacks";
            --"av_moderation";
            "muc_breakout_rooms";
            "presence_identity";
            "room_metadata";
            --"stanza_debug";
        }
        lobby_muc = "lobby.meet.domain.tld"
        main_muc = "conference.meet.domain.tld"
        room_metadata_component = "metadata.meet.domain.tld"
        c2s_require_encryption = false
        smacks_max_unacked_stanzas = 5;
        smacks_hibernation_time = 60;
        smacks_max_hibernated_sessions = 1;
        smacks_max_old_sessions = 1;


Component "conference.meet.domain.tld" "muc"
    storage = "memory"
    modules_enabled = {
        "muc_meeting_id";
        "muc_domain_mapper";
        "polls";
        "muc_allowners";
        --"token_verification";
    }
    admins = { "focus@auth.meet.domain.tld" }
    muc_room_locking = false
    muc_room_default_public_jids = true

-- internal muc component
-- Note: This is also used from jibris
Component "internal.auth.meet.domain.tld" "muc"
    storage = "memory"
    modules_enabled = {
      "ping";
    }
    admins = { "focus@auth.meet.domain.tld", "jvb@auth.meet.domain.tld" }
    muc_room_locking = false
    muc_room_default_public_jids = true

VirtualHost "auth.meet.domain.tld"
    ssl = {
        key = "/etc/prosody/certs/auth.meet.domain.tld.key";
        certificate = "/etc/prosody/certs/auth.meet.domain.tld.crt";
    }
    modules_enabled = {
        "limits_exception";
    }
    authentication = "internal_hashed"

Component "focus.meet.domain.tld" "client_proxy"
    target_address = "focus@auth.meet.domain.tld"

Component "speakerstats.meet.domain.tld" "speakerstats_component"
    muc_component = "conference.meet.domain.tld"

Component "conferenceduration.meet.domain.tld" "conference_duration_component"
    muc_component = "conference.meet.domain.tld"

Component "breakout.meet.domain.tld" "muc"
    restrict_room_creation = true
    storage = "memory"
    admins = { "focus@auth.meet.domain.tld" }
    muc_room_locking = false
    muc_room_default_public_jids = true


Component "metadata.meet.domain.tld" "room_metadata_component"
    muc_component = "conference.meet.domain.tld"
    breakout_rooms_component = "breakout.meet.domain.tld"

esentially you need to add it to the virtualhost:
breakout_rooms_muc = "breakout.meet.domain.tld"

to the modules_enabled:
"muc_breakout_rooms";

then the component itself:

Component "breakout.meet.domain.tld" "muc"
    restrict_room_creation = true
    storage = "memory"
    admins = { "focus@auth.meet.domain.tld" }
    muc_room_locking = false
    muc_room_default_public_jids = true

and also add it to the metadata component:

Component "metadata.meet.domain.tld" "room_metadata_component"
    muc_component = "conference.meet.domain.tld"
    breakout_rooms_component = "breakout.meet.domain.tld"

hope that helps!

assuming its the same cause/error. obviously one also needs the excalidraw nodejs service running and configured/pointed to in the jitsi-meet config.js

Hey thanks a lot for your help by the way. Being a real Linux amateur, I had to learn everything from the ground up to get this working and I eventually did. Now I kind of want to make a tutorial to maybe help others get it up and running.

2 Likes