TUTORIAL/EXAMPLE: JWT Authentication + Lobby

I recently set up JWT Authentication with Jitsi’s Lobby Feature. I struggled to piece together the correct implementation steps and configuration options, so I thought I would post my consolidated steps and relevant config file modifications here in case they would help anyone. Please let me know if I can clarify any points or correct any issues!

For the purposes of this post, our relevant requirements were:

  1. Authenticate all users with JWTs issued by our own HTTP server
  2. Designate some users as moderators, others as non-moderators using claims included on the JWT
  3. Automatically initialize the lobby feature when a moderator joins, and allow other moderators (or the first) to bypass the lobby when they join/rejoin

Below are the steps that I used to configure an instance of Jitsi that meets the above requirements. Most of the relevant changes to the linked config files below will be made in the course of following these steps, but I’ve attached them to this post as a reference point.


  1. Configure a new Jitsi server according to the Self-Hosting Guide

  2. Follow the instructions to set up the JWT token authentication Prosody plugin
    a. I recommend you go through the Manual Plugin Configuration steps after you’ve finished the installation to verify everything is correct
    b. The prosody configuration file can be found at /etc/prosody/conf.avail/.cfg.lua

  3. As of writing, the above steps resulted in errors in the Prosody logs indicating that the module “luajwtjitsi” couldn’t be found. This can be fixed using these instructions

  4. Add the mod_token_affiliation plugin using these instructions. This allows Prosody to determine moderation status according to the contents of the JWT

  5. Update /usr/share/jitsi-meet/prosody-plugins/mod_muc_lobby_rooms.lua according to this post. This will allow moderators to bypass the lobby when joining the meeting. An example of this file with the modification is included below. Note that this is a customization to a standard file in the jitsi repository, and may break in future versions

  6. Restart prosody, jicofo, and jitsi-videobridge2 using the “service <serviceName> restart” command

  7. Now configure your HTTP server to generate appropriate JWTs and send them to your client. The method of doing this will depend on your platform, but I’ve included a sample function in the links below to do this in Node.js based on my implementation

  8. Now configure your client to include the JWT in the options passed to the JitsiMeetExternalAPI constructor. Again, I’ve included a sample initialization in the links below

  9. Start the Lobby whenever a moderator joins the meeting using the toggleLobby API command. This is included in the example initialization below


  1. These steps were last successfully performed on jitsi-meet version 2.0.6726-1

  2. DO NOT perform the Secure Domain setup steps. These configuration changes conflict with the setup to authenticate users using JWTs

  3. The “enableUserRolesBasedOnToken” config option that comes up a lot in this forum has been deprecated and removed. You may see a similarly named config option, called “enableFeaturesBasedOnToken”. This setting can be used to enable certain UI features on a per-user basis, controlled by claims on the JWT. Documentation on these features can be found in the “features” section of 8x8’s JWT documentation.

  4. When working with the example config files, don’t forget to adjust your domain and application secret accordingly

  5. Users are sent to the Lobby if they join after a moderator has enabled it (in this case, via the iframe API). The Lobby is a distinct concept from the “Waiting for host to arrive” screen that appears on Secure Domain instances if a guest tries to join a conference before a moderator has arrived. There is no official way to enable the “Waiting for host to arrive” screen using JWT authentication, although some people appear to have unofficially made it work (example).

  6. In the JWT plugin setup step (2 above), you have a choice to specify the “room” claim on the JWT. You can either specify a single name (e.g. “roomName” in https://meet.example.com/roomName), or “*” to indicate that the JWT should give the user access to any room. Currently, you will NOT be able to use the Breakout Rooms feature if you specify a room name in the JWT.

Example configuration files (Github repo) and their standard locations in the Jitsi filesystem:


We used to have both, but we removed the enableUserRolesBasedOnToken, it no longer exist.
enableFeaturesBasedOnToken is a setting whether the UI to respect settings for feature coming in the jwt token, these are things like transcription, recording, livestreaming, full list you can check here The Jitsi JSON Web Token (JWT) under features.

@Gkleinereva Thanks for sharing!

I’ve updated my post to reflect this comment, thank you for the clarification!

One other point I’d like to definitively comment on in this post: Lobby vs. Waiting Room.

My current understanding is:

The Lobby is where new users joining the meeting are sent once a moderator has enabled it (or in the case of the instructions above, once it’s been enabled via call to the Jitsi iframe API). These users have to “Ask to join” the meeting, which prompts the moderator to accept or deny their request to join.

The Waiting Room is where guests wait for an authenticated moderator to join a room on an instance that has been set up with a Secure Domain. Guests see the “Waiting for Host to Arrive” dialog, and then automatically join the meeting once an authenticated moderator enters the room.

In essence, the Lobby covers the case where a moderator joins before guests. The Waiting Room covers the case where guests join before the moderator.

And my question is:

Is there a good way to enable both the Lobby and the Waiting Room when authenticating all users with JWTs?

Technically there is no such thing as a waiting room. When you try to join unauthenticated and that room does not exist on jicofo side, it just returns the error and the client shows that UI retrying every 5 seconds or so, and once the moderator joins(the authenticated user) there is no error coming from jicofo and the guest joins. This error and behavior of jicofo is specific to Secure Domain configuration and has nothing to do with jwt, sorry.
People reported that were able to make it work, I don’t know the details. But the fact it works is a coincidence and is not something we expect and test and keep it working, it may stop working anytime.

Thanks for the clarification @damencho , I added it to the notes above.

@Freddie I reviewed your documentation on breakout rooms here. When I try to use breakout rooms with the above setup (where the JWT is issued for a specific room name), Prosody blocks users from entering the breakout rooms with an error “Token <token> not allowed to join <room>”, since the breakout rooms technically have different names (?). I suspect that the only way around this is to issue JWTs that are valid for all rooms (*). Can you confirm this is correct, or point me towards a workaround if one exists? Thanks!

I think using a multi-room token is the best option for the moment because, yes, each breakout room is actually a new room and can have security set at its level. And since you’re using JWT for authentication, I suppose each room created under that hierarchy will be expecting tokens for access.

  • Add the mod_token_affiliation plugin using these instructions. This allows Prosody to determine moderation status according to the contents of the JWT

I this token_affiliation plugin OK? Because in the documentation there is no affiliaton key mentioned. Is this some legacy key?

mod_token_affiliation and its instructions are for those with own Jitsi deployment that want to add that feature.

If you’re using JaaS, they would have implemented the feature differently in which case you want to use the JWT claims listed in their docs. I believe there is a context.user.moderator claim for JWT used with JaaS.


Thanks @Freddie, I added that consideration to the notes in the post.

Yes - but it’s important to note that this is specific to your use case, I think (all users are JWT-authenticated, guests are not allowed). In the case where unauthenticated users (guests) are allowed, I believe you can still use a single-room token (for the moderators).

Thanks, noted. However, if allow_empty_tokens = true is set in the Prosody configuration, and a token is sent with a specific room name, that user will still not be allowed to join breakout rooms (I tested and verified this). So I feel like it’s more of a consequence of the “room” claim on the JWT, rather than the setting of allow_empty_tokens.

Thanks for verifying that. I’ll have to check on my end when I get a chance. I have some thoughts, but need to verify them.

Hello @Gkleinereva

I tried your changes to mod_muc_lobby_rooms.lua , but with lobby disabled. In that scenario 2 users join one with affiliation as owner and another as member. However when they join in conference they both join as moderators. Somewhere in the code, the user who is just a member is still able to join as moderator. I see that the token shows one user as “affiliation” : “owner” and another as “affiliation” : “member”. The browser console logs show both as “affiliation” : “owner” though and both join as moderator. Please let me know if I am missing anything.


IIUC this is a Dockerized setup. I have no idea about it