Restricting room membership via spaces

pull/977/head
Richard van der Hoff 4 years ago
parent 29b07c11ad
commit ae71a6219a

@ -187,7 +187,8 @@ TODO: this could also be done via pinned messages. Failing that
### Managing power levels via spaces ### Managing power levels via spaces
XXX: this section still in progress TODO: much of this is orthogonal to the headline feature of "spaces", and
should be moved to a separate MSC.
One use-case for spaces is to help manage power levels across a group of One use-case for spaces is to help manage power levels across a group of
rooms. For example: "Jim has just joined the management team at my company. He rooms. For example: "Jim has just joined the management team at my company. He
@ -283,22 +284,97 @@ access to it is itself restricted via `power_levels`. This could be enforced by
the admin bot so that no `m.room.power_levels` events are generated unless the admin bot so that no `m.room.power_levels` events are generated unless
`power_level_mappings` is appropriately restricted. `power_level_mappings` is appropriately restricted.
### Membership restrictions ### Restricting room membership based on space membership
A desirable feature is to give room admins the power to restrict membership of A desirable feature is to give room admins the power to restrict membership of
their room based on the membership of spaces (for example, "only members of the their room based on the membership of spaces (for example, "members of the
#doglovers space can join this room"<sup id="a1">[1](#f1)</sup>). #doglovers space can join this room without an invitation"<sup id="a1">[1](#f1)</sup>).
XXX can we maybe do this with invites generated on demand? If not, we probably We could represent the allowed spaces with additional content in the
need some sort of "silent invite" state for each user, `m.room.join_rules` event. For example:
By implication, when a user leaves the required space, they should be ejected ```js
from the room. {
"type": "m.room.join_rules",
XXX: how do we implement the ejection? We could leave it up to the ejectee's "state_key": "",
server, but what happens if it doesn't play the game? So we probably need to "content": {
enact a ban... but then, which server has responisiblity, and which user is used? "join_rule": "public",
"allowed_spaces": [
{
"space": "!mods:example.org",
"via": ["example.org"],
},
{
"space": "!users:example.org",
"via": ["example.org"],
}
]
}
}
```
XXX: would it be better to put it in a separate event? Doing so would probably
require us to come up with a new `join_rule` state to tell servers to go and
look for the allowed spaces.
The `allowed_spaces` key applies a restriction to the `public` join rule, so
that only users in those spaces should be allowed to join. Additionally, users
who have received an explicit `invite` event are allowed to join<sup
id="a2">[2](#f2)</sup>. If the `allowed_spaces` key is an empty list (or not a
list at all), no users are allowed to join without an invite.
Unlike the regular `invite` join rule, the restriction cannot be enforced over
federation by event authorization, so servers in the room are trusted not to
allow invalid users to join.<sup id="a3">[3](#f3)</sup>
When a server receives a `/join` request from a client or a
`/make_join`/`/send_join` request from a server, the request should only be
permitted if the user has a valid invite or is in one of the listed spaces
(established by peeking).
XXX: redacting the join_rules above will reset the room to public, which feels dangerous?
A new room version is not absolutely required here, but may be advisable to
ensure that servers that do not support `allowed_spaces` do not join the room
(and would also allow us to tweak the redaction rules to avoid the foot-gun).
#### Kicking users out when they leave the allowed_space
In the above example, suppose `@bob:server.example` leaves `!users:example.org`:
they should be removed from the room. One option is to leave the departure up
to Bob's server `server.example`, but this places a relatively high level of trust
in that server. Additionally, if `server.example` were offline, other users in
the room would still see Bob in the room (and their servers would attempt to
send message traffic to it).
Instead, we make the removal the responsibility of the room's admin bot (see
above): the bot is expected to peek into any `allowed_spaces` and kick any
users who are members of the room and leave the union of the allowed
spaces.
(XXX: should users in a space be kicked when that space is removed from the
`allowed_spaces` list? We think not, by analogy with what happens when you
switch the join rules from `public` to `invite`.)
One problem here is that it will lead to users who joined via an invite being
kicked. For example:
* `@bob:server.example` creates an invite-only room.
* Later, the `join_rules` are switched to `public`, with an `allowed_space` of
`!users:example.org`, of which Bob happens to be a member.
* Later still, Bob leaves `!users:example.org`.
* Bob is kicked from his own room.
Fixing this is thorny. Some sort of annotation on the membership events might
help. but it's unclear what the desired semantics are:
* Assuming that users in a given space are *not* kicked when that space is
removed from `allowed_spaces`, are those users then given a pass to remain
in the room indefinitely? What happens if the space is added back to
`allowed_spaces` and *then* the user leaves it?
* Suppose a user joins a room via a space (SpaceA). Later, SpaceB is added to
the `allowed_spaces` list and SpaceA is removed. What should happen when the
user leaves SpaceB? Are they exempt from the kick?
## Future extensions ## Future extensions
@ -370,6 +446,13 @@ These dependencies are shared with profiles-as-rooms
* The peek server has significant power. TODO: expand. * The peek server has significant power. TODO: expand.
* The `allowed_spaces` feature places increased trust in the servers in the
room. We consider this acceptable: if you don't want evil servers randomly
joining spurious users into your rooms, then a) don't let evil servers in
your room in the first place, b) don't use `allowed_spaces` lists, given the
expansion increases the attack surface anyway by letting members in other
rooms dictate who's allowed into your room".
## Tradeoffs ## Tradeoffs
* If the membership of a space would be large (for example: an organisation of * If the membership of a space would be large (for example: an organisation of
@ -442,3 +525,14 @@ of the '#catlovers' space" is less useful since (a) users in the banned space
could simply leave it at any time; (b) this functionality is already somewhat could simply leave it at any time; (b) this functionality is already somewhat
provided by [Moderation policy provided by [Moderation policy
lists](https://matrix.org/docs/spec/client_server/r0.6.1#moderation-policy-lists). [](#a1) lists](https://matrix.org/docs/spec/client_server/r0.6.1#moderation-policy-lists). [](#a1)
<a id="f2"/>[2]: Note that there is nothing stopping users sending and
receiving invites in `public` rooms today, and they work as you might
expect. The only difference is that you are not *required* to hold an `invite`
when joining the room. [](#a2)
<a id="f3"/>[3]: This is a marginal decrease in security from the current
situation with invite-only rooms. Currently, a misbehaving server can allow
unauthorized users to join an invite-only room by first issuing an invite to
that user. In theory that can be prevented by raising the PL required to send
an invite, but in practice that is rarely done. [](#a2)

Loading…
Cancel
Save