Video-room : Restrict a token to be used only for a subscriber/publisher role

229 views
Skip to first unread message

Jordan Breton

unread,
Sep 19, 2021, 5:00:00 AM9/19/21
to meetecho-janus
I'm using Janus and the Video-Room plugin to create a RPG plateform. Some users are publishers (they play to the game), other users are only subscribers (they watch participants playing). 

I use the token, admin_secret + pin system to restrict access on rooms. My node.js backend is the only one who can create tokens and manage rooms. But the thing is that with an access token, one can decide to publish and participate in the game, even if he is only supposed to be a subscriber and watch.

Is there any way to restrict a token/ a user to only be either a participant or a subscriber to prevent that someone overcome his role by client-side manipulations ?

Lorenzo Miniero

unread,
Sep 20, 2021, 2:08:25 AM9/20/21
to meetecho-janus
Use RTP forwarding to relay a VideoRoom publisher to a Streaming plugin mountoint, and have subscribers get the media there. This way, they won't need to be in the room to get the media, meaning they won't have a pin to join that. Mountpoints can have pins too if you want to restrict subscription access as well.

Lorenzo

Jordan Breton

unread,
Sep 21, 2021, 7:10:42 AM9/21/21
to meetecho-janus
Thank you for your answer and sorry to publish mine so late. The problem is that using RTP forwarding to relay all publishers on streaming mountpoints introduce a lot of burden to manage new publishers in the rooms, both for UI and backend. I would have to maintain a constant sync with the janus server, to manage a mainly UI related concern, while it's only a videoroom's current ACL limitation.

On the other hand, a subscriber mechanism with ACL would be perfect : someone would join the room as a special "publisher" with let's say a subscriber_only flag, and with an ACL that distinguish between subscribers_only and real publishers, we would just have users that join a videoroom in both cases, that recieve the same events and updates using the same js API, but subscribers_only publishers would not be able to publish anything. Only getting room infos, room publishers and feeds, etc, without any additional code needed for UI and backend. The backend would just have to tweek room configs and to manage room's ACL to add/revoke tokens.

I took a look at the videoroom plugin code. It's been a long time since I didn't wrote any C code (and that was really basic one at that time...), but with few tests I have been able to achieve this in about 350 code lines (including ACL persistence in room config). It seems to work pretty well, without introducing any breaking change with respect to the current ACL mechanism. 

I would be glad to write a detailed PR if it sounds intresting to you. If not, I'll maintain this on my own and patch future videoroom updates manually, since it really save me a lot of work to do it in janus side instead of backend + UI.

PS: I would like to thank you for your amazing work on this project, it's a real pleasure to work with ! 

Lorenzo Miniero

unread,
Sep 21, 2021, 7:22:09 AM9/21/21
to meetecho-janus
If you have a PR to share, we'd be glad to review it, even though 350 lines seems quite a lot. Please notice there's no guarantee we'd merge it, though, especially if we detect potential issues.

L.

Moez Fehri

unread,
Sep 21, 2021, 8:27:03 AM9/21/21
to meetecho-janus
interesting, but are you creating an other ACL for that or using the one already in place ? 
i wonder, why don't you listen to "publish" events and mute the feed if user is not allowed  to publish?

Jordan Breton

unread,
Sep 21, 2021, 10:48:55 AM9/21/21
to meetecho-janus
Yes I'll share the PR probably tomorow. Since I'm not a C guru, I think that my modifications are not fully optimal and some refactorisation may be required. 

I use the same ACL with the same API, I just differenciate between lists.

- allowed (the current one) will serve it's initial purpose : a token there will allow a user to publish/subscribe.
- allowed_subscribers : the user that provide a token in this list will only be allowed to join the room as a publisher with the 'subscribe_only' flag. WIthout that flag, the user will be rejected.
- allowed_publishers : the user that provide a token in this list will only be allowed to  join as a publisher and to publish, but not to subscribe to any feed. I need it in some scenarios where some users are blind. They can join the room, all subscribers will see them but they will not be able to subscribe to any feed. 

In basic use cases, you populate the allowed list for publishers, and the allowed_subscribers for subscriber_only publishers. You can use the ACL API to add token in the list you want : 

     "request" : "allowed", 
     "secret" : "<room secret, mandatory if configured>", 
     "action" : "enable|disable|add|remove", 
     "room" : <unique numeric ID of the room to update>, 
     "allowed" : [ // Array of strings (tokens users might pass in "join", only for add|remove) ],
     "allowed_subscribers" : [ // Array of strings (tokens users might pass in "join", only for add|remove) Will only be able to join the room as subscriber_only ],
     "allowed_publishers" : [ // Array of strings (tokens users might pass in "join", only for add|remove) Will not be able to subscribe to any feed in the room ]
}   

And when you have to join as a subscriber_only, you send a join request like : 

    "request" : "join",
    "ptype" : "publisher", 
    "room" : <unique ID of the room to join>, 
    "id" : <unique ID to register for the publisher; optional, will be chosen by the plugin if missing>, 
    "display" : "<display name for the publisher; optional>",
    "token" : "<invitation token, in case the room has an ACL; optional>", 
    "subscriber_only" : "<boolean>"
}

If you don't provide subscriber_only : true, the videoroom keep it's default behavior and will assume that you must be a publisher, and will check the token against allowed or allowed_publishers. 

And to answer this question : "i wonder, why don't you listen to "publish" events and mute the feed if user is not allowed  to publish?" :
Because there is two ways to do it : client side, but I want to prevent client-side manipulation so it doesn't help.
And server side, but I have a multi-backend architecture with several nodes by server and several servers, watching each room for event can become very tricky and may run out of sync if one node stop for whatever reason. The worst part of it is : I will have several janus instances accross several servers too. The amount of work to enforce this server side policy become really painfull outside of the videoroom plugin. And with the streaming mountpoints solutions, it's not better, since I must care about janus events too.

If the videoroom plugin just handle that with ACL, I have no more work to do : just grant access to a user as a subscriber_only and voilà. If the user then disconnects, my backend can just revoke it's tokens. Tokens desappear with the room when it is destroyed. If one of my server must be taken down for maintenance or whatever, it can be. If janus instance is lost and restart, it reload all rooms whith their tokens and ACL ready as if nothing happened. Everyone is happy.   

Since I need room persistence, and I don't want to have to recreate all tokens if a janus server restart or crash, you can use these lists in the videroom config files. The ACL will not be enabled if you not enable it explicitly with check_allowed = "yes" or if you don't enable ACL with an allowed request. 

I added a way differenciate max_publishers too : max_publishers doen't count publisher that are subscribers_only. So a new conf is added : max_subscribers_only, with no limit by default (must be discussed). The idea is that we often want a fixed number of real publishers, and another (greater) fixed number of viewers.

The goal is to avoid as much as possible to have to maintain a state depending on Janus or a connection whith it where it's not needed and to just use native videoroom plugins implementation and JS API to achieve what we want without changing too much code. I hope it's clear, I'm not an english native and I wrote that as it comes :/

Lorenzo Miniero

unread,
Sep 21, 2021, 10:55:22 AM9/21/21
to meetecho-janus
Mh I don't like the approach much, especially the one which requires a user to in advance state if a handle will be used just to subscribe or not. A publisher role is always a potential publisher, and that doesn't need to change. What you can enforce are checks when such a publisher tries to publish later on: if the token they provided was not one that could be used for publishing, that's where the rejection can take place.

L.

Jordan Breton

unread,
Sep 21, 2021, 11:58:29 AM9/21/21
to meetecho-janus
Yes your right. In fact, thinking about it, the subscriber_only flag passed by the client is totaly useless. I'll work upon that before writing the PR. Thanks.

Jordan Breton

unread,
Sep 26, 2021, 12:30:00 PM9/26/21
to meetecho-janus
So, I submited a PR for those who are intrested in. I struggled a lot to achieve what I wanted, since I didn't wrote a line of C since my CS degree, but after some tests it seems to work pretty well. It fit for my use case, at least. I plan to add some more features later (like a way to close PeerConnection for revoked tokens/permissions and maybe some more permissions).

Lorenzo Miniero

unread,
Sep 27, 2021, 9:09:43 AM9/27/21
to meetecho-janus
Thanks, saw that! It definitely wins the prize for most thorough description, which is a rear feat :-D

I haven't gone through it yet, but from a quick glance I think it adds too many changes for what's supposed to be a simpler requirement. With the multistream branch merge so close, I'm hesitant to consider such a big refactoring, which would introduce a ton of conflicts (and probably a feature that would be hard to adapt to its new streams management). I'll need some time to review, so once I have a clearer idea I'll see what can be done.

Lorenzo

Jordan Breton

unread,
Sep 27, 2021, 10:06:48 AM9/27/21
to meetecho-janus

I think that I'm maybe too verbose/chatty sometimes ^^'

Ok, I understand. In any case, since I really need this feature I will maintain it. And as I'll want the multistream too, I'll have to adapt it anyway in the future. I'll take a look at the multistream branch to see what's going on. Do you now approximately when it will be merged ? 
Reply all
Reply to author
Forward
0 new messages