Jitsi meet: no user authentication with Secure Domain setup

Hi,

Please correct me if I’m wrong, but there seems to be a contradiction in the quickstart manual at Self-Hosting Guide - Debian/Ubuntu server · Jitsi Meet Handbook.
It states right at the beginning that one of the required packages is nginx-full. However, further down under “Install Jitsi Meet” it also states that “The installer will check if Nginx or Apache are present”.
The last time I struggled to install Jitsi Meet on a server was in Jan. 2020, and I used apache instead of nginx.
I am now trying to install an updated server and having trouble getting user authentication to work. I was wondering if using nginx or apache made any difference (I don’t think so).

On my older server (Jan. 2020) I have user authentication enabled with ldap2, and it’s working great.

On my new server, unauthed/default installation works fine with Apache2. However, if I enable authentication as per Secure Domain setup · Jitsi Meet Handbook there’s simply no user login page. Any user can open a room. However, if more than one user opens the same room, they do not see each other (they are alone).

I see no errors anywhere (server logs and client browser consoles). The only thing I do see is that the client browsers report:
[modules/xmpp/strophe.util.js] <Object.r.Strophe.log>: Strophe: Server did not yet offer a supported authentication mechanism. Sending a blank poll request.
I also see a cert error message in prosody, but it has been said over and over that Jitsi Meet does not use it and can be ignored:
portmanager error Error binding encrypted port for https: No certificate present in SSL/TLS configuration for https port 5281

Here are my config files (using jitsi-meet “stable” on Debian 10):

# cat /etc/prosody/conf.avail/meet.mydomain.org.cfg.lua
plugin_paths = { "/usr/share/jitsi-meet/prosody-plugins/" }

-- domain mapper options, must at least have domain base set to use the mapper
muc_mapper_domain_base = "meet.mydomain.org";

turncredentials_secret = "aF9VS2uVJEzkDCDk";

turncredentials = {
    { type = "stun", host = "meet.mydomain.org", port = "3478" },
    { type = "turn", host = "meet.mydomain.org", port = "3478", transport = "udp" },
    { type = "turns", host = "meet.mydomain.org", port = "5349", transport = "tcp" }
};

cross_domain_bosh = false;
consider_bosh_secure = true;
-- https_ports = { }; -- Remove this line to prevent listening on port 5284

-- https://ssl-config.mozilla.org/#server=haproxy&version=2.1&config=intermediate&openssl=1.1.0g&guideline=5.4
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"
}

VirtualHost "meet.mydomain.org"
    -- enabled = false -- Remove this line to enable this host
    authentication = "internal_hashed"
    -- Properties below are modified by jitsi-meet-tokens package config
    -- and authentication above is switched to "token"
    --app_id="example_app_id"
    --app_secret="example_app_secret"
    -- Assign this host a certificate for TLS, otherwise it would use the one
    -- set in the global section (if any).
    -- Note that old-style SSL on port 5223 only supports one certificate, and will always
    -- use the global one.
    ssl = {
        key = "/etc/prosody/certs/meet.mydomain.org.key";
        certificate = "/etc/prosody/certs/meet.mydomain.org.crt";
    }
    speakerstats_component = "speakerstats.meet.mydomain.org"
    conference_duration_component = "conferenceduration.meet.mydomain.org"
    -- we need bosh
    modules_enabled = {
        "bosh";
        "pubsub";
        "ping"; -- Enable mod_ping
        "speakerstats";
        "turncredentials";
        "conference_duration";
        "muc_lobby_rooms";
    }
    c2s_require_encryption = false
    lobby_muc = "lobby.meet.mydomain.org"
    main_muc = "conference.meet.mydomain.org"
    -- muc_lobby_whitelist = { "recorder.meet.mydomain.org" } -- Here we can whitelist jibri to enter lobby enabled rooms

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

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

VirtualHost "auth.meet.mydomain.org"
    ssl = {
        key = "/etc/prosody/certs/auth.meet.mydomain.org.key";
        certificate = "/etc/prosody/certs/auth.meet.mydomain.org.crt";
    }
    authentication = "internal_plain"

Component "focus.meet.mydomain.org"
    component_secret = "4pSePkRM"

Component "speakerstats.meet.mydomain.org" "speakerstats_component"
    muc_component = "conference.meet.mydomain.org"

Component "conferenceduration.meet.mydomain.org" "conference_duration_component"
    muc_component = "conference.meet.mydomain.org"

Component "lobby.meet.mydomain.org" "muc"
    storage = "memory"
    restrict_room_creation = true
    muc_room_locking = false
    muc_room_default_public_jids = true

VirtualHost "guest.meet.mydomain.org"
    authentication = "anonymous"
    c2s_require_encryption = false

# sudo prosodyctl register testuser meet.mydomain.org testpwd

# ls -l /etc/prosody/conf.d/
total 0
lrwxrwxrwx 1 root root 31 Feb 20 00:23 localhost.cfg.lua -> ../conf.avail/localhost.cfg.lua
lrwxrwxrwx 1 root root 56 Feb 20 00:23 meet.mydomain.org.cfg.lua -> /etc/prosody/conf.avail/meet.mydomain.org.cfg.lua

# cat /etc/jitsi/jicofo/sip-communicator.properties
org.jitsi.jicofo.BRIDGE_MUC=JvbBrewery@internal.auth.meet.mydomain.org
org.jitsi.jicofo.auth.URL=XMPP:meet.mydomain.org

# cat /etc/jitsi/meet/meet.mydomain.org-config.js (well, only the first part of the file as I believe it's the only relevant section and the file is long to post here)
/* eslint-disable no-unused-vars, no-var */

var config = {
    // Connection
    //

    hosts: {
        // XMPP domain.
        domain: 'meet.mydomain.org',

        // When using authentication, domain for guest users.
        anonymousdomain: 'guest.mydomain.org',

        // Domain for authenticated users. Defaults to <domain>.
        // authdomain: 'meet.mydomain.org',

        // Focus component domain. Defaults to focus.<domain>.
        // focus: 'focus.meet.mydomain.org',

        // XMPP MUC domain. FIXME: use XEP-0030 to discover it.
        muc: 'conference.meet.mydomain.org'
    },

    // BOSH URL. FIXME: use XEP-0156 to discover it.
    bosh: '//meet.mydomain.org/http-bind',

    // Websocket URL
    // websocket: 'wss://meet.mydomain.org/xmpp-websocket',

    // The name of client node advertised in XEP-0115 'c' stanza
    clientNode: 'http://jitsi.org/jitsimeet',

[...]

This is probably irrelevant, but I’d rather post it anyway:

# cat /etc/jitsi/videobridge/sip-communicator.properties
org.ice4j.ice.harvest.DISABLE_AWS_HARVESTER=true
org.ice4j.ice.harvest.STUN_MAPPING_HARVESTER_ADDRESSES=meet-jit-si-turnrelay.jitsi.net:443
org.jitsi.videobridge.ENABLE_STATISTICS=true
org.jitsi.videobridge.STATISTICS_TRANSPORT=muc
org.jitsi.videobridge.xmpp.user.shard.HOSTNAME=localhost
org.jitsi.videobridge.xmpp.user.shard.DOMAIN=auth.meet.mydomain.org
org.jitsi.videobridge.xmpp.user.shard.USERNAME=jvb
org.jitsi.videobridge.xmpp.user.shard.PASSWORD=gnY0Ym9o
org.jitsi.videobridge.xmpp.user.shard.MUC_JIDS=JvbBrewery@internal.auth.meet.mydomain.org
org.jitsi.videobridge.xmpp.user.shard.MUC_NICKNAME=1c5e46a2-7322-4cfd-b099-c4a8783d98e0

I rebooted the server, but there’s simply no authentication presented to the client.

I also tried explicitly setting
authdomain: 'meet.mydomain.org',
in /etc/jitsi/meet/meet.mydomain.org-config.js, but that didn’t make any difference.

I’m clueless.
My older 2020 server authenticates just fine, but the new one doesn’t for some odd reason.

Any ideas?

Thanks

PS: can I or should I enable websockets with ‘wss://meet.mydomain.org/xmpp-websocket’?
Why is it disabled by default?

If you want a quick answer, may I suggest you install, on a separate server(or reinstall) using this script and check if it works as expected.

One thing, the config.js should have guest.meet.mydomain.org, for anonymousdomain

either this is wrong, or you have done a very bad job while anonymising your domain.

Well, this is embarrassing. You’re both right. My anonymousdomain value was wrong. I fixed it, and now I am properly presented with a login for. the internal_hashed user is authenticated as expected. I guess I’ll need a new pair of glasses…

However, my goal was to enable LDAP authentication instead of internal_hashed. If I change to “ldap2” I do not get a login form. Instead, the user just creates the room as a guest.

So here’s the only change in config.js:

anonymousdomain: 'guest.meet.mydomain.org',

And this is all that’s been modified in prosody:

# cat /etc/prosody/conf.d/meet.mydomain.org.cfg.lua
[...]
VirtualHost "meet.mydomain.org"
    authentication = "ldap2"
[...]

This is for the ldap2 auth module:

# cat /etc/prosody/conf.d/ldap.cfg.lua
authentication = 'ldap2'

ldap = {
    -- hostname = '10.215.144.35:389',
    hostname = '10.215.144.35',
    bind_dn = 'cn=ldapbind,cn=Users,dc=mydomain,dc=org',
    bind_password = 'whatever',
    -- use_tls = true,
    user = {
        basedn = 'cn=Users,dc=mydomain,dc=org',
        filter = '(&(objectClass=User)(|(memberOf=CN=MEET,CN=Users,DC=mydomain,DC=org)(distinguishedName=CN=meet1,CN=Users,DC=mydomain,DC=org)))',
        usernamefield = 'sAMAccountName',
        namefield = 'cn',
    },
}

No outstanding errors in the xmpp log:

# cat /var/log/prosody/prosody.log
Feb 21 10:33:07 startup info    Hello and welcome to Prosody version 0.11.2
Feb 21 10:33:07 startup info    Prosody is using the select backend for connection handling
Feb 21 10:33:07 general info    Starting speakerstats for conference.meet.mydomain.org
Feb 21 10:33:07 speakerstats.meet.mydomain.org:speakerstats_component    info    No muc component found, will listen for it: conference.meet.mydomain.org
Feb 21 10:33:07 portmanager     info    Activated service 's2s' on [*]:5269, [::]:5269
Feb 21 10:33:08 conference.meet.mydomain.org:muc_domain_mapper   info    Loading mod_muc_domain_mapper for host internal.auth.meet.mydomain.org!
Feb 21 10:33:08 conference.meet.mydomain.org:muc_domain_mapper   info    Loading mod_muc_domain_mapper for host conference.meet.mydomain.org!
Feb 21 10:33:08 conference.meet.mydomain.org:muc_domain_mapper   info    Loading mod_muc_domain_mapper for host speakerstats.meet.mydomain.org!
Feb 21 10:33:08 speakerstats.meet.mydomain.org:speakerstats_component    info    Hook to muc events on conference.meet.mydomain.org
Feb 21 10:33:08 portmanager     info    Activated service 'c2s' on [*]:5222, [::]:5222
Feb 21 10:33:08 portmanager     info    Activated service 'legacy_ssl' on no ports
Feb 21 10:33:08 portmanager     info    Activated service 'http' on [*]:5280, [::]:5280
Feb 21 10:33:08 portmanager     error   Error binding encrypted port for https: No certificate present in SSL/TLS configuration for https port 5281
Feb 21 10:33:08 portmanager     error   Error binding encrypted port for https: No certificate present in SSL/TLS configuration for https port 5281
Feb 21 10:33:08 portmanager     info    Activated service 'https' on no ports
Feb 21 10:33:08 conference.meet.mydomain.org:muc_domain_mapper   info    Loading mod_muc_domain_mapper for host meet.mydomain.org!
Feb 21 10:33:08 conference.meet.mydomain.org:muc_domain_mapper   info    Loading mod_muc_domain_mapper for host auth.meet.mydomain.org!
Feb 21 10:33:08 conference.meet.mydomain.org:muc_domain_mapper   info    Loading mod_muc_domain_mapper for host guest.meet.mydomain.org!
Feb 21 10:33:08 general info    Starting conference duration timer for conference.meet.mydomain.org
Feb 21 10:33:08 conferenceduration.meet.mydomain.org:conference_duration_component       info    Hook to muc events on conference.meet.mydomain.org
Feb 21 10:33:08 conference.meet.mydomain.org:muc_domain_mapper   info    Loading mod_muc_domain_mapper for host conferenceduration.meet.mydomain.org!
Feb 21 10:33:08 meet.mydomain.org:muc_lobby_rooms        info    Lobby component loaded lobby.meet.mydomain.org
Feb 21 10:33:08 conference.meet.mydomain.org:muc_domain_mapper   info    Loading mod_muc_domain_mapper for host lobby.meet.mydomain.org!
Feb 21 10:33:08 portmanager     info    Activated service 'component' on [::1]:5347, [127.0.0.1]:5347
Feb 21 10:33:08 conference.meet.mydomain.org:muc_domain_mapper   info    Loading mod_muc_domain_mapper for host focus.meet.mydomain.org!
Feb 21 10:33:08 conference.meet.mydomain.org:muc_domain_mapper   info    Loading mod_muc_domain_mapper for host localhost!
Feb 21 10:33:11 c2s55e1fd530810 info    Client connected
Feb 21 10:33:11 c2s55e1fd530810 info    Stream encrypted (TLSv1.3 with TLS_AES_256_GCM_SHA384)
Feb 21 10:33:11 c2s55e1fd530810 info    Authenticated as jvb@auth.meet.mydomain.org
Feb 21 10:33:11 c2s55e1fd5c4050 info    Client connected
Feb 21 10:33:12 c2s55e1fd5c4050 info    Stream encrypted (TLSv1.3 with TLS_AES_256_GCM_SHA384)
Feb 21 10:33:12 c2s55e1fd5c4050 info    Authenticated as focus@auth.meet.mydomain.org
Feb 21 10:33:16 mod_bosh        info    Client tried to use sid '327b5df7-c600-4431-840f-4fe2e01422ed' which we don't know about
Feb 21 10:33:16 mod_bosh        info    Client tried to use sid '327b5df7-c600-4431-840f-4fe2e01422ed' which we don't know about
Feb 21 10:33:16 jcp55e1fd66a2c0 info    Incoming Jabber component connection
Feb 21 10:33:16 focus.meet.mydomain.org:component        info    External component successfully authenticated
Feb 21 10:33:27 mod_bosh        info    New BOSH session, assigned it sid 'fc8da5cc-c4bf-44ce-8a5c-e2c60e76fed5'
Feb 21 10:33:27 boshfc8da5cc-c4bf-44ce-8a5c-e2c60e76fed5        info    Authenticated as korwhtratdplhagm@guest.meet.mydomain.org

Any more ideas?

Thanks!

[EDIT]
BTW same thing happens if I enable an “external” auth type:

VirtualHost "meet.mydomain.org"
    -- authentication = "ldap2"
    authentication = "external"
    external_auth_command = "/etc/prosody/conf.avail/my_prosody_auth.sh"

Prosody log:

Feb 21 10:57:21 startup info    Hello and welcome to Prosody version 0.11.2
Feb 21 10:57:21 startup info    Prosody is using the select backend for connection handling
Feb 21 10:57:21 general info    Starting conference duration timer for conference.meet.mydomain.org
Feb 21 10:57:21 conferenceduration.meet.mydomain.org:conference_duration_component       info    No muc component found, will listen for it: conference.meet.mydomain.org
Feb 21 10:57:21 portmanager     info    Activated service 's2s' on [*]:5269, [::]:5269
Feb 21 10:57:21 portmanager     info    Activated service 'component' on [::1]:5347, [127.0.0.1]:5347
Feb 21 10:57:21 portmanager     info    Activated service 'c2s' on [*]:5222, [::]:5222
Feb 21 10:57:21 portmanager     info    Activated service 'legacy_ssl' on no ports
Feb 21 10:57:21 portmanager     info    Activated service 'http' on [*]:5280, [::]:5280
Feb 21 10:57:21 portmanager     error   Error binding encrypted port for https: No certificate present in SSL/TLS configuration for https port 5281
Feb 21 10:57:21 portmanager     error   Error binding encrypted port for https: No certificate present in SSL/TLS configuration for https port 5281
Feb 21 10:57:21 portmanager     info    Activated service 'https' on no ports
Feb 21 10:57:21 general info    Starting speakerstats for conference.meet.mydomain.org
Feb 21 10:57:21 speakerstats.meet.mydomain.org:speakerstats_component    info    No muc component found, will listen for it: conference.meet.mydomain.org
Feb 21 10:57:21 meet.mydomain.org:muc_lobby_rooms        info    Lobby component loaded lobby.meet.mydomain.org
Feb 21 10:57:21 conferenceduration.meet.mydomain.org:conference_duration_component       info    Hook to muc events on conference.meet.mydomain.org
Feb 21 10:57:21 conference.meet.mydomain.org:muc_domain_mapper   info    Loading mod_muc_domain_mapper for host conferenceduration.meet.mydomain.org!
Feb 21 10:57:21 conference.meet.mydomain.org:muc_domain_mapper   info    Loading mod_muc_domain_mapper for host internal.auth.meet.mydomain.org!
Feb 21 10:57:21 conference.meet.mydomain.org:muc_domain_mapper   info    Loading mod_muc_domain_mapper for host focus.meet.mydomain.org!
Feb 21 10:57:21 conference.meet.mydomain.org:muc_domain_mapper   info    Loading mod_muc_domain_mapper for host meet.mydomain.org!
Feb 21 10:57:21 conference.meet.mydomain.org:muc_domain_mapper   info    Loading mod_muc_domain_mapper for host speakerstats.meet.mydomain.org!
Feb 21 10:57:21 conference.meet.mydomain.org:muc_domain_mapper   info    Loading mod_muc_domain_mapper for host conference.meet.mydomain.org!
Feb 21 10:57:21 conference.meet.mydomain.org:muc_domain_mapper   info    Loading mod_muc_domain_mapper for host auth.meet.mydomain.org!
Feb 21 10:57:21 conference.meet.mydomain.org:muc_domain_mapper   info    Loading mod_muc_domain_mapper for host localhost!
Feb 21 10:57:21 conference.meet.mydomain.org:muc_domain_mapper   info    Loading mod_muc_domain_mapper for host lobby.meet.mydomain.org!
Feb 21 10:57:21 conference.meet.mydomain.org:muc_domain_mapper   info    Loading mod_muc_domain_mapper for host guest.meet.mydomain.org!
Feb 21 10:57:21 speakerstats.meet.mydomain.org:speakerstats_component    info    Hook to muc events on conference.meet.mydomain.org
Feb 21 10:57:21 c2s55afe18160b0 info    Client connected
Feb 21 10:57:21 c2s55afe18160b0 info    Stream encrypted (TLSv1.3 with TLS_AES_256_GCM_SHA384)
Feb 21 10:57:21 c2s55afe18160b0 info    Authenticated as jvb@auth.meet.mydomain.org
Feb 21 10:57:25 c2s55afe1b83e40 info    Client connected
Feb 21 10:57:25 c2s55afe1b83e40 info    Stream encrypted (TLSv1.3 with TLS_AES_256_GCM_SHA384)
Feb 21 10:57:25 c2s55afe1b83e40 info    Authenticated as focus@auth.meet.mydomain.org
Feb 21 10:57:26 jcp55afe1bca470 info    Incoming Jabber component connection
Feb 21 10:57:26 focus.meet.mydomain.org:component        info    External component successfully authenticated
Feb 21 10:57:38 mod_bosh        info    New BOSH session, assigned it sid '399a96f5-a8ea-4860-99b3-e9dcf8075ad1'
Feb 21 10:57:38 bosh399a96f5-a8ea-4860-99b3-e9dcf8075ad1        info    Authenticated as 7m1ce8ms3a2zegy2@guest.meet.mydomain.org
Feb 21 10:58:05 speakerstats.meet.mydomain.org:speakerstats_component    warn    A module has been configured that triggers external events.
Feb 21 10:58:05 speakerstats.meet.mydomain.org:speakerstats_component    warn    Implement this lib to trigger external events.
Feb 21 10:58:05 bosh399a96f5-a8ea-4860-99b3-e9dcf8075ad1        info    BOSH client disconnected: session close

So, is “internal_hashed” the only supported auth type?

On an older Jitsi Meet server I have ldap2 authentication working as expected so I don’t know what I’m doing wrong in the new server.

well… ldap was not the original subject, so don’t expect people already replying to you to be knowledgeable in it. I know nil about it. Did you take a look at the (old and possibly outdated) ldap wiki page ? See also the github issue about unpleasantness with email as a login. It’s a general problem with email as a login in XMPP systems.

The title of this thread is about “user authentication” so it really doesn’t matter which authentication type is used. There was however one tiny config line I was missing in my ldap lua file… I had to consider BOSH secure. My setup is now working with ldap2. I also managed to fix the “external” authentication type as I was using an older version of the mod_auth_external script. Updating it from upstream solved the issue.

So big thanks to all here!

BTW @Prashanth thanks for sharing your setup script, but I’d really like to know why you “forcefully” install nginx? I know the jitsi manual also mentions nginx-full, but it also mentions that one can use either Apache2 or nginx. So I’m wondering if anyone knows if nginx is a “better option” for Jitsi Meet and why.

Yes apache can be used too. I chose nginx as I got my setup working with it and it didn’t occur to me, till now, to consider apache. I might add it as an option too, if more people choose to install via that script and need apache.