Currently, onboarding users to the Matrix Fediverse has more points of friction than its peers. The timeline for an existing Matrix user to on-board a new user to their space, and/or room by extension, is significantly longer than what it could be from the invitee's perspective:
Currently, onboarding users to the Matrix Fediverse has more points of friction than its peers. The timeline
for an existing Matrix user to on-board a new user to their space, and/or room by extension, is significantly
longer than what it could be from the invitee's perspective:
> 1. Ask friend to join matrix/homeserver
@ -20,7 +22,9 @@ Versus the flow for onboarding an invitee in other services, and what this MSC a
> 3. Hand them invite code/link
> 4. They join your room/space
Where in the improved flow, there is no necessity for exessive back-and-forth between the inviter and invitee. With pre-generated invites, points 1 and 3 could realistically be condensed into a single event from the invitee's point of view.
Where in the improved flow, there is no necessity for exessive back-and-forth between the inviter and invitee.
With pre-generated invites, points 1 and 3 could realistically be condensed into a single event from the invitee's
point of view.
## Proposal
@ -70,16 +74,21 @@ Example:
This example is using a sha-265 hash of the string `inviteme!` for the hash.
A user attempted to join a room via providing a secret will have it hashed and compared against the stored hash to determine if they may use the specific invite room event to join.
A user attempted to join a room via providing a secret will have it hashed and compared against the stored hash
to determine if they may use the specific invite room event to join.
The burden of remembering the secret key will be on the person who created the invite, however this is acceptable as clients could generate an extended room ID with the state key and provided/generated secret.
The burden of remembering the secret key will be on the person who created the invite, however this is acceptable
as clients could generate an extended room ID with the state key and provided/generated secret.
### 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:
`[string]:[server_name]#[state_key]/[secret_key]` so that a client can interpret the state and secret keys from the URI and allow a join request to be made with the identifying information needed for the homeserver to add the user to the room's member list.
Optionally clients could also ask a user for a state_key and secret key when one or both is not provided, and the room they are are attempting to join is rejecting their join request.
`[string]:[server_name]#[state_key]/[secret_key]` so that a client can interpret the state and secret keys
from the URI and allow a join request to be made with the identifying information needed for the homeserver
to add the user to the room's member list.
Optionally clients could also ask a user for a state_key and secret key when one or both is not provided,
and the room they are are attempting to join is rejecting their join request.
For example, the following invite URI could be generated by a user's client:
@ -88,9 +97,10 @@ For example, the following invite URI could be generated by a user's client:
```
and subsequently handed over to a https://matrix.to or equivalent redirection service to create clickable links such as:
[`https://matrix.to/#/!irs2iosct:example.com#MwhqK12Rs4/inviteme!`](https://matrix.to/#/!irs2iosct:example.com#MwhqK12Rs4/inviteme!) (This link goes nowhere)
While not as pretty as some of Matrix's peers' invite urls, it would fulfill the basic function of allowing a user to join a private room without have their specific user account explicitly invited to participate.
While not as pretty as some of Matrix's peers' invite urls, it would fulfill the basic function of allowing a
user to join a private room without have their specific user account explicitly invited to participate.
### Extend the `m.room.power_levels` state event
@ -105,14 +115,20 @@ Add new content items for managing and creating invites.
### New API endpoints to get room invites
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.
Get the invites created for a room. This endpoint should be restricted by a user's power level in a room to prevent leaking invite keys to default or lower power members in a restricted room.
Get the invites created for a room. This endpoint should be restricted by a user's power level in a room to
prevent leaking invite keys to default or lower power members in a restricted room.
| Rate-limited | No |
| ----------------------- | --- |
@ -136,7 +152,8 @@ Get the invites created for a room. This endpoint should be restricted by a user
Array of [`ClientEvent`](https://spec.matrix.org/v1.7/client-server-api/#room-event-format)
If a user has sufficient power to list either their own invites, or that of other users, but none exist, respond with an empty array.
If a user has sufficient power to list either their own invites, or that of other users, but none exist,
respond with an empty array.
###### 403 Response
@ -192,7 +209,8 @@ Add extra content fields to allow a user submit their *state_key* and *secret ke
Create another optional block for when the user has provided the necessary information to join a room via pre-generated invite code, modeled after the existing *Third-party Signed* block.
Create another optional block for when the user has provided the necessary information
to join a room via pre-generated invite code, modeled after the existing *Third-party Signed* block.
| Pre-generated key | | |
@ -255,11 +273,18 @@ can follow.
### Generate and store invites differently
Much of the complexity arises from storing, authenticating and transmitting invites while trying to minimize new additions. Alternatively invites could be removed entirely from the event history and put directly in the database of the resident homeserver, as well as allow powerful room members to request an invite code and generate a url directly from the resident homeserver.
Much of the complexity arises from storing, authenticating and transmitting invites while trying to minimize new
additions. Alternatively invites could be removed entirely from the event history and put directly in the
database of the resident homeserver, as well as allow powerful room members to request an invite code and
generate a url directly from the resident homeserver.
Instead of URIs that look like `!irs2iosct:example.com#MwhqK12Rs4/inviteme!` as proposed by the MSC, this could instead yield much prettier urls such as `https://invite.example.com/invitecode` and cleaner invite codes like `invitecode:example.com`
Instead of URIs that look like `!irs2iosct:example.com#MwhqK12Rs4/inviteme!` as proposed by the MSC,
this could instead yield much prettier urls such as `https://invite.example.com/invitecode`
and cleaner invite codes like `invitecode:example.com`
A stopgap between these two could be an integration or extension of homeserver services that serves as a url shortener such as bit.ly, to avoid needing a deeper rewrite of the spec while maintaining url readability of Matrix's competitor.
A stopgap between these two could be an integration or extension of homeserver services that
serves as a url shortener such as bit.ly, to avoid needing a deeper rewrite of the spec while
maintaining url readability of Matrix's competitor.
## Security considerations
@ -267,13 +292,19 @@ A stopgap between these two could be an integration or extension of homeserver s
### Unintentionally leaking the secret key
The method of authenticating an invite code here would expose the raw *secret key* to a user's homeserver and possibly the redirection service used by a user's client. Specifically this may expose *secret key*s to [https://matrix.to](https://matrix.to) as it is Element's default url redirector.
The method of authenticating an invite code here would expose the raw *secret key* to a user's homeserver
and possibly the redirection service used by a user's client. Specifically this may expose *secret key*s to
[https://matrix.to](https://matrix.to) as it is Element's default url redirector.
Since it is unavoidable to expose the secret key to a user's personal homeserver, it will be assumed a user's homeserver is trusted.
Since it is unavoidable to expose the secret key to a user's personal homeserver, it will be assumed a user's
homeserver is trusted.
In this case, a remedy to this issue would allowing the user's homeserver to define a something along the lines of a `redirection_provider` in the `.well-known/matrix/client` that overrides the client's default redirection service. This way an invitee would have to intentionally attach the invite credentials to an untrusted redirection provider.
In this case, a remedy to this issue would allowing the user's homeserver to define a something along the lines
of a `redirection_provider` in the `.well-known/matrix/client` that overrides the client's default redirection
service. This way an invitee would have to intentionally attach the invite credentials to an untrusted redirection provider.
Alternatively the process of generating valid invite links (not invite codes) could be offloaded to the resident homeserver itself. See alternatives above.
Alternatively the process of generating valid invite links (not invite codes) could be offloaded to the resident