How do you query if a room has a password or not?

I am working on adding the password header so asterisk can connect the user to a password protected room.
Is there any way to query a room to see if there is a password set or not ? I am trying to avoid asking a user through the phone to enter a password if there is not really one.

I was able to figure this out with help of several posts from this forum… its not as straight forward as you think. Even doesn’t handle incoming calls with passwords in a good way. So I would say, there is no official solution out there.
Here is my tweak/hackie way of handling incoming calls with password, or calls to meetings that haven’t started yet.

First need to modify prosody’s /yourdomain.cfg.lua and add the muc_size module

VirtualHost "meet.jitsi"
    authentication = "anonymous"
    ssl = {
        key = "/config/certs/meet.jitsi.key";
        certificate = "/config/certs/meet.jitsi.crt";
    modules_enabled = {
    c2s_require_encryption = false

Then add the following block of code to mod_muc_size.lua inside prosody’s plugin folder: This code will allow you to curl http://your.jitsi.url:5280/all-rooms?domain=your.jitsi.domain. and get back number of rooms, room names, participants and which room has a password set or not. (you might have to expose port 5280 to make this work.

function handle_get_all_rooms(event)
        if (not event.request.url.query) then
                return { status_code = 400; };

        local params = parse(event.request.url.query);
        local domain_name = params["domain"];

        local raw_rooms = get_raw_rooms(domain_name);

        local rooms_json = array();

        for room in raw_rooms do

                local room_jid = room.jid;
        --      local room_everything = room;
                local participant_count = 0;
                local occupants_json = array();
                local occupants = room._occupants;
                local data = room._data;
                if occupants then
                        for _, occupant in room:each_occupant() do
                                -- filter focus as we keep it as hidden participant
                                if string.sub(occupant.nick,-string.len("/focus"))~="/focus" then
                                        for _, pr in occupant:each_session() do
                                                participant_count = participant_count + 1;
                                                local nick = pr:get_child_text("nick", "") or "";
                                                local email = pr:get_child_text("email") or "";
                                                        jid = tostring(occupant.nick),
                                                        email = tostring(email),
                                                        display_name = tostring(nick)});
                        jid = room_jid,
                        password = data.password,
                        participant_count = participant_count,
                        participants = occupants_json


        local result_json={
                rooms = rooms_json;
        -- create json response
        return { status_code = 200; body = json.encode(result_json); };

function module.load()
        module:provides("http", {
                default_path = "/";
                route = {
                        ["GET room-size"] = function (event) return async_handler_wrapper(event,handle_get_room_size) end;
                        ["GET sessions"] = function () return tostring(it.count(it.keys(prosody.full_sessions))); end;
                        ["GET room"] = function (event) return async_handler_wrapper(event,handle_get_room) end;
                        ["GET all-rooms"] = function (event) return async_handler_wrapper(event,handle_get_all_rooms) end;

I am also using a docker version of jitsi & jigasi. I had to add the following lines to the jigasi’s file

#This will prevent call to drop after 32 seconds and avoid calls that keep rining and never connect

To be able to add the dial in numbers and pin system to the meeting rooms, you have to add these lines to web’s config.js file

//you have to come up with your own list of numbers (json format and place it in your webserver under /var/www/html/ is a json file example
dialInNumbersUrl: 'https://your.jitsi.url/phoneNumberList',
dialInConfCodeUrl:  '',

I am using asterisk 17 (PJSIP conf) in my company with the following architecture
Client cellphone -> PSTN -> Cisco unified callmanager - (trunk) -> asterisk - (sip client) -> jigasi

in your Asterisk server, place the following 2 scripts inside /var/lib/asterisk/agi-bin/


jit_rm=$(curl -x -v$1 | cut -d \, -f 3 | cut -d \: -f 2 | cut -d \" -f 2 | cut -d \@ -f 1)

echo "SET VARIABLE JITSI \"$jit_rm\" "


jsonResponse=$(curl --silent --noproxy "*" http://your.jitsi.url:5280/all-rooms? | jq -r '.rooms[]')

for row in $(echo "${jsonResponse}" | jq -r '. | @base64' ); do
    _jq() {
        echo ${row} | base64 --decode | jq -r ${1}
    entry=$(echo $(_jq '.'))
    for variable in $(echo "${entry}" | jq -r '. | @base64' ); do
        _jq() {
            echo ${variable} | base64 --decode | jq -r ${1}
        roomName=$(echo $(_jq '.jid'))
        if [ ${roomName} == $1"" ]; then
            roomPassword=$(echo $(_jq '.password'))

if [ -z "${roomPassword}" ]; then
    if [ ${roomPassword} == "null" ]; then
echo "SET VARIABLE JITSIPassword ${roomPassword}"

This is how my extensions.conf file looks like. I am using from-external context because calls are coming from call manager, if you only have asterisk, you context will be from-internal and you will have just an extension instead of _[0-9].


exten => addheader,1,Set(PJSIP_HEADER(add,X-Room-Name)=${ARG1})
exten => addheader,n,Set(PJSIP_HEADER(add,X-Room-Name-Pass)=${ARG2})

exten => _[0-9].,1,Set(__RINGTIMER={IF([${DB(AMPUSER/6000/ringtimer)} > 0]?{DB(AMPUSER/6000/ringtimer)}:{RINGTIMER_DEFAULT})})
exten => _[0-9].,n,Playback(conf-getconfno)
;get conference pin
exten => _[0-9].,n(getmeeting),Read(Pin,beep,20)
exten => _[0-9].,n,Verbose(result is: ${Pin})
;Run meeting pin cript
exten => _[0-9].,n,AGI(,${Pin})
exten => _[0-9].,n,Verbose(Meeting Name: ${JITSI})
exten => _[0-9].,n,GotoIf($[${JITSI} = false}]?invalidnum:checkForPassword)
exten => _[0-9].,n(invalidnum),Playback(conf-invalid)
exten => _[0-9].,n,Goto(getmeeting)
;Run password script
exten => _[0-9].,n(checkForPassword),AGI(,${JITSI})
exten => _[0-9].,n,Verbose(Jitsi Password return: ${JITSIPassword})
exten => _[0-9].,n,GotoIf($[${JITSIPassword} = ConfDidNotStartYet]?hangUpandTryAgain:checkforPassword)
;meeting has a password, check if password matches
exten => _[0-9].,n(checkforPassword),GotoIf($[${JITSIPassword} = NoPassword]?joinmeeting:askForPassword)
exten => _[0-9].,n(askForPassword),Playback(agent-pass)
exten => _[0-9].,n,Read(Password,beep,20)
exten => _[0-9].,n,Verbose(Meeting password: ${Password})
exten => _[0-9].,n,GotoIf($[${JITSIPassword} = ${Password}]?joinmeeting:invalidPassword)
exten => _[0-9].,n(invalidPassword),Playback(vm-invalidpassword)
exten => _[0-9].,n,Goto(askForPassword)
;everything is good, join meeting
exten => _[0-9].,n(joinmeeting),Playback(auth-thankyou)
exten => _[0-9].,n,playback(conf-placeintoconf)
exten => _[0-9].,n,Dial(PJSIP/9729956000,,b(handler^addheader^1(${JITSI},${Password})))
exten => _[0-9].,n(hangUpandTryAgain),Playback(conf-onlyperson)
exten => _[0-9].,n,Playback(hangup-try-again)

Thank you for sharing :slight_smile:

I’m trying to set up this (docker-container). Configs are written/modified. (Sip is already running)
But i get no answer on port 5280.
Is there a another trick to enable it in prosody-container?

Greetings, Peter

have you mapped the ports in docker-compose.yml?

    #image: jitsi/prosody
    build: ./prosody
        - '5222'
        - '5347'
        - '5280'
        - '5222:5222'
        - '5347:5347'
        - '5280:5280'
        - ${CONFIG}/prosody:/config
1 Like

Ok. in default config (git docker image) the mapping ports missing.
Thank you, I’ll test it

# XMPP server
    image: jitsi/prosody
    restart: ${RESTART_POLICY}
        - '5222'
        - '5347'
        - '5280'
        - ${CONFIG}/prosody:/config
1 Like

Thank you, now the port 5280 answers.

Now i can call the url, but there is a error. Is this a missing modul?

startup warn Attempt to read a non-existent global ‘get_raw_rooms’
stack traceback:
/prosody-plugins/mod_muc_size.lua:209: in function ‘handler’
/prosody-plugins/util.lib.lua:75: in function ‘func’
/usr/lib/prosody/util/async.lua:127: in function </usr/lib/prosody/util/async.lua:125>
runnernDo1PMGs error Encountered error: /prosody-plugins/mod_muc_size.lua:209: attempt to call global ‘get_raw_rooms’ (a nil value)
stack traceback:
/prosody-plugins/mod_muc_size.lua:209: in function ‘handler’
/prosody-plugins/util.lib.lua:75: in function ‘func’
/usr/lib/prosody/util/async.lua:127: in function </usr/lib/prosody/util/async.lua:125>
http.server error Traceback[httpserver]: /usr/lib/prosody/util/async.lua:137: /prosody-plugins/mod_muc_size.lua:209: attempt to call global ‘get_raw_rooms’ (a nil value)
stack traceback:
/prosody-plugins/mod_muc_size.lua:209: in function ‘handler’
/prosody-plugins/util.lib.lua:75: in function ‘func’
/usr/lib/prosody/util/async.lua:127: in function </usr/lib/prosody/util/async.lua:125>
stack traceback:
[C]: in function ‘error’
/usr/lib/prosody/util/async.lua:137: in function ‘handler’
/usr/lib/prosody/util/async.lua:211: in function ‘run’
/prosody-plugins/util.lib.lua:98: in function </prosody-plugins/util.lib.lua:62>
(…tail calls…)
/usr/lib/prosody/util/events.lua:79: in function </usr/lib/prosody/util/events.lua:75>
(…tail calls…)
/usr/lib/prosody/net/http/server.lua:248: in function </usr/lib/prosody/net/http/server.lua:176>
[C]: in function ‘xpcall’
/usr/lib/prosody/net/http/server.lua:108: in function ‘process_next’
/usr/lib/prosody/net/http/server.lua:124: in function ‘success_cb’
/usr/lib/prosody/net/http/parser.lua:177: in function ‘feed’
/usr/lib/prosody/net/http/server.lua:155: in function </usr/lib/prosody/net/http/server.lua:154>
[C]: in function ‘pcall’
/usr/lib/prosody/net/server_epoll.lua:159: in function ‘on’
/usr/lib/prosody/net/server_epoll.lua:348: in function ‘onreadable’
/usr/lib/prosody/net/server_epoll.lua:734: in function </usr/lib/prosody/net/server_epoll.lua:726>
[C]: in function ‘xpcall’
/usr/bin/prosody:76: in function ‘loop’
/usr/bin/prosody:86: in main chunk
[C]: in ?

Did you add the module “muc_size” to meet.jitsi.cfg.lua?
Did you copy the block of code inside mod_muc_size.lua?

If you did all this, please share your meet.jitsi.cfg.lua, mod_muc_lua and docker-compose files

A good test to see if your code deployed correctly is running this command.

docker-compose exec prosody bash -c "cat /prosody-plugins/mod_muc_size.lua"

if you are able to see your custom code inside that file, then it made it to the container. Otherwise, you will have to tweak your docker-compose file

I see that your image is getting build remotely every time.
try changing these lines in your docker-compose file, remove jitsi-meet-cfg/ folder and try again.

XMPP server

# image: jitsi/prosody
build: ./prosody
restart: ${RESTART_POLICY}

To set the build option is no good idea. So i lost a part my configuration and bosh take errors (I’ve test it and now i test my vmware-snapshot :wink: ) The configuration-files of prosodoy lies partly outside the Docker-Container. In the /prosody-plugin path is already a plugin mod-muc_size. I can overide it when i connect the bash in container. This works well.
Now i do the muc_size setup again.

1 Like