Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSC4031: Pre-generating invites and room invite codes #4031

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

mdnwvn
Copy link

@mdnwvn mdnwvn commented Jun 18, 2023

@mdnwvn mdnwvn changed the title Pre generate invites MSC4031: Pre-generating invites and room invite codes Jun 18, 2023
@turt2live turt2live added proposal A matrix spec change proposal client-server Client-Server API kind:feature MSC for not-core and not-maintenance stuff needs-implementation This MSC does not have a qualifying implementation for the SCT to review. The MSC cannot enter FCP. labels Jun 18, 2023
@turt2live
Copy link
Member

@mdnwvn when you get a chance, please sign off on your changes. This will be required before the MSC can enter FCP.

Comment on lines +118 to +123
Ideally, invites *should not* be exposed by the
[`/_matrix/client/v3/rooms/{roomId}/state`](https://spec.matrix.org/v1.7/client-server-api/#get_matrixclientv3roomsroomidstate)
endpoint *unless* the requesting user has the power level required to list invites. Any invites
created by the requesting user *should* be returned, regardless of the user's power level. It is
assumed that a user with invites has, or had the power level required to create their own invites,
so they should remain accessible to them until they expire or a higher power user manually redacts them.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this restriction only applied to the client-server API? If so, anyone self-hosting a server could still view the invites, which makes the restriction fairly pointless.

If it's supposed to apply to federation too, that should be specified explicitly and it probably also needs details on how it works exactly in terms of state resolution and the event graph. I don't think there's any precedent for withholding events from other servers

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I agree that withholding invites in the client-server api is pointless, increases implementation complexity, and it doesn't really provide any real security benefit when using an invite still requires knowing the secret key. The disclosure restrictions should probably just be stripped from the MSC since they provide nothing useful in practice.


### Extend the room URI when using inline invite keys

Currently room uris take the form of `[string]:[server_name]`, and they could be extended to:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extending room IDs like this doesn't make much sense. The MSC should probably just define query parameters for matrix: URIs and matrix.to URLs instead of this weird custom syntax. Something like ?join_key=..., so the URI becomes matrix:roomid/abc:example.com?join_key=... or https://matrix.to/#/!abc:example.com?join_key=.... The spec for Matrix URIs is https://spec.matrix.org/v1.7/appendices/#uris, there are a few existing parameters already.

Copy link
Author

@mdnwvn mdnwvn Jun 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MSC relies on being able to find which invite a secret key belongs to via the state_key, so two new query parameters would need to be created in its current form.

To bring it down to a single key, perhaps the hash of the secret could be used as the invite identifier as well, and the handling of invites could be condensed down into a single state event that gets updated, much like how m.room.power_levels only has one copy and gets updated. For example:

{
	"event_id": "$event_id",
	"type": "m.room.invites",
	"state_key": "",
	"content": {
		"aac88f2747be898998cb3d2793e2d71a93bb4902fd77de507bd0e8ee92e5b05f": {
			"created_by": "@example:example.org",
			"not_after": "1234567890",
			"good_for": 5,
			"uses": 3
		},
		"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08": {
			"created_by": "@example:example.org",
			"not_after": "12345678911",
			"good_for": 6,
			"uses": 2
		},

	}
}

Then, if the server cannot find an invite with the hash of the secret key in the invite event, the Join is rejected.

Additionally, if the hashed secrets become the invite identifiers as well, then invite codes could possibly be renamed to "ticket"s to reduce confusion with the existing direct invites that are in the spec.

Comment on lines +53 to +55
If `good_for` is greater than or equal to 1, it *must* be decremented each time a user is accepted using a given invite.

If `good_for` is currently 0 or has just been decremented to 0, it *must* be redacted by the server.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably specify who is doing the decrementing and how exactly. I'd assume it at least requires the joins to be done through a server which has a user with the power level necessary to send the state event, similar to how space-restricted joins can only be done through a server which has a user with invite permissions.

Also, this seems like it has a very high risk of conflicts. What if a room has admins from two servers and they decrement the count simultaneously? Currently state resolution would just pick one of the events and ignore the other, but that would mean the use count was only decremented by one rather than two. Temporary federation issues could cause bigger gaps than a single decrement.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what the best way to implement limited use would be currently. Condensing the invites down into a single event that gets updated, like the m.room.power_levels event is my best idea for a starting place. But that still has the issue of keeping decrements in sync.

Perhaps uses can be stored as separate state events, and count is calculated for a given invite on use? I worry that might get wasteful in rooms with thousands of members, needing to sift through and tally up an invite's uses to check if it's lower than the max allowed. This may be mitigate-able by limiting the maximum uses for limited invites to say, 50 or 100, and only beginning to count uses if the server has confirmed the invite code exists and is valid in the first place. This would allow for two admins to use an invite at the same time while recording both uses though.

On the other hand, the question of what happens if multiple simultaneous uses causes the count to go negative, but the users have already been accepted? Do we accept all the users? Or do we force the late users in the timeline to Leave and rejoin using new secret key or with a direct invite?

@mdnwvn
Copy link
Author

mdnwvn commented Jun 18, 2023

The MSC doesn't describe how to handle the privacy setting "Members only (since they were invited) in rooms. Maybe the datetime a user joins via the invite code should be used in place of not having an invite timestamp?

@InezMc
Copy link

InezMc commented Jun 19, 2023

@mdnwvn when you get a chance, please sign off on your changes. This will be required before the MSC can enter FCP.

Signoff request recieved.

endpoint *unless* the requesting user has the power level required to list invites. Any invites
created by the requesting user *should* be returned, regardless of the user's power level. It is
assumed that a user with invites has, or had the power level required to create their own invites,
so they should remain accessible to them until they expire or a higher power user manually redacts them.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is assumed that a user with invites has, or had the power level required to create their own invites, so they should remain accessible to them until they expire or a higher power user manually redacts them.

I wonder (since I don't use many others), how do other chat systems handle shared ability to manage invite links?

Background:
We should store the creator of an invite, because only they know the secret key. It makes sense to communicate this fact to other room members with membership management permissions, as long as no other way is found to share it between them automatically in a secret way.

Options:

  • If on top this approach is modeled in a way that invites are "bound" to their creator, it would make sense to redact them when they lose their invite permission.
  • If is is modeled such that invites are considered owned by the team of members with invite permissions, then it makes sense to decouple them from the creator losing their permissions. (The UI should still suggest to review their invite codes, but that's more of a client issue.)

Suggestion:
I think a better reasoning to keep invites in spite of demoting the creator (= the latter option) is the fact that other users with appropriate power level shall be able to modify existing invite codes, similar how one room admin can ban a user that was formerly invited by another admin. I think that would make for not quite perfect UX, since other admins don't necessarily know the secret key, but acceptable.

I don't think this MSC explicitly states this yet, but perhaps it should.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
client-server Client-Server API kind:feature MSC for not-core and not-maintenance stuff needs-implementation This MSC does not have a qualifying implementation for the SCT to review. The MSC cannot enter FCP. proposal A matrix spec change proposal
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants