Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions changelogs/client_server/newsfragments/2083.clarification
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Clarify the format of third-party invites, including the fact that identity
server public keys can be encoded using standard or URL-safe base64.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Clarify that public keys can be encoded using standard or URL-safe base64.
2 changes: 2 additions & 0 deletions changelogs/server_server/newsfragments/2083.clarification
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Clarify the format of third-party invites, including the fact that identity
server public keys can be encoded using standard or URL-safe base64.
46 changes: 26 additions & 20 deletions content/client-server-api/modules/third_party_invites.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ This module adds in support for inviting new members to a room where
their Matrix user ID is not known, instead addressing them by a third-party
identifier such as an email address. There are two flows here; one
if a Matrix user ID is known for the third-party identifier, and one if
not. Either way, the client calls [`/invite`](#post_matrixclientv3roomsroomidinvite) with the details of the
third-party identifier.
not. Either way, the client calls [`/invite`](#thirdparty_post_matrixclientv3roomsroomidinvite)
with the details of the third-party identifier.

The homeserver asks the identity server whether a Matrix user ID is
known for that identifier:
Expand Down Expand Up @@ -37,10 +37,12 @@ A client asks a server to invite a user by their third-party identifier.

#### Server behaviour

Upon receipt of an [`/invite`](#post_matrixclientv3roomsroomidinvite), the server is expected to look up the
third-party identifier with the provided identity server. If the lookup
yields a result for a Matrix User ID then the normal invite process can
be initiated. This process ends up looking like this:
Upon receipt of an [`/invite`](#thirdparty_post_matrixclientv3roomsroomidinvite),
the server is expected to look up the third-party identifier with the provided
identity server by making a call to [`/_matrix/identity/v2/lookup`](/identity-service-api/#post_matrixidentityv2lookup).
If the lookup yields a result for a Matrix User ID then the normal [invite
process](/server-server-api/#inviting-to-a-room) can be initiated. This process
ends up looking like this:

```
+---------+ +-------------+ +-----------------+
Expand All @@ -66,10 +68,11 @@ be initiated. This process ends up looking like this:
| | |
```

However, if the lookup does not yield a bound User ID, the homeserver
must store the invite on the identity server and emit a valid
`m.room.third_party_invite` event to the room. This process ends up
looking like this:
However, if the lookup does not yield a bound User ID, the homeserver must store
the invite on the identity server with a call to
[`/_matrix/identity/v2/store-invite`](/identity-service-api/#post_matrixidentityv2store-invite)
and emit a valid [`m.room.third_party_invite`](#mroomthird_party_invite) event
to the room. This process ends up looking like this:

```
+---------+ +-------------+ +-----------------+
Expand Down Expand Up @@ -101,16 +104,19 @@ looking like this:
| | |
```

All homeservers MUST verify the signature in the event's
The third-party user will then need to verify their identity, which results in a
request to [`/_matrix/federation/v1/3pid/onbind`](/server-server-api/#put_matrixfederationv13pidonbind)
from the identity server to the homeserver that bound the third-party identifier
to a user. The homeserver then exchanges the `m.room.third_party_invite` event
in the room for a complete [`m.room.member`](#mroommember) event with
`content.membership: invite` and a `content.third_party_invite` property for the
user that has bound the third-party identifier. If the invitee is on a different
homeserver than the inviting user, the invitee's homeserver makes a request to
[`/_matrix/federation/v1/exchange_third_party_invite/{roomId}`](/server-server-api/#put_matrixfederationv1exchange_third_party_inviteroomid).

All homeservers MUST verify the signature in the `m.room.member` event's
`content.third_party_invite.signed` object.

The third-party user will then need to verify their identity, which
results in a call from the identity server to the homeserver that bound
the third-party identifier to a user. The homeserver then exchanges the
`m.room.third_party_invite` event in the room for a complete
`m.room.member` event for `membership: invite` for the user that has
bound the third-party identifier.

If a homeserver is joining a room for the first time because of an
`m.room.third_party_invite`, the server which is already participating
in the room (which is chosen as per the standard server-server
Expand Down Expand Up @@ -193,8 +199,8 @@ at any time - the completion is not shown in the diagram.

H1 MUST verify the request from H3 to ensure the `signed` property is
correct as well as the `key_validity_url` as still being valid. This is
done by making a request to the [identity server
/isvalid](/identity-service-api/#get_matrixidentityv2pubkeyisvalid)
done by making a request to the identity server's
[`/pubkey/isvalid`](/identity-service-api/#get_matrixidentityv2pubkeyisvalid)
endpoint, using the provided URL rather than constructing a new one. The
query string and response for the provided URL must match the Identity
Service Specification.
Expand Down
46 changes: 24 additions & 22 deletions content/server-server-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -970,9 +970,8 @@ the event to other servers in the room.
## Third-party invites

{{% boxes/note %}}
More information about third-party invites is available in the
[Client-Server API](/client-server-api) under
the Third-party Invites module.
More information about third-party invites is available in the Client-Server API
under the [Third-party invites](/client-server-api/#third-party-invites) module.
{{% /boxes/note %}}

When a user wants to invite another user in a room but doesn't know the
Expand All @@ -985,38 +984,41 @@ API](/identity-service-api).

### Cases where an association exists for a third-party identifier

If the third-party identifier is already bound to a Matrix ID, a lookup
request on the identity server will return it. The invite is then
processed by the inviting homeserver as a standard `m.room.member`
invite event. This is the simplest case.
If the third-party identifier is already bound to a Matrix ID, a [lookup
request](/identity-service-api/#post_matrixidentityv2lookup) on the identity
server will return it. The invite is then processed by the inviting homeserver
as a [standard `m.room.member` invite event](#inviting-to-a-room). This is the
simplest case.

### Cases where an association doesn't exist for a third-party identifier

If the third-party identifier isn't bound to any Matrix ID, the inviting
homeserver will request the identity server to store an invite for this
identifier and to deliver it to whoever binds it to its Matrix ID. It
will also send an `m.room.third_party_invite` event in the room to
specify a display name, a token and public keys the identity server
provided as a response to the invite storage request.

When a third-party identifier with pending invites gets bound to a
Matrix ID, the identity server will send a POST request to the ID's
homeserver as described in the [Invitation
Storage](/identity-service-api#invitation-storage)
section of the Identity Service API.
homeserver will request the identity server to [store an invite](/identity-service-api/#invitation-storage)
for this identifier and to deliver it to whoever binds it to its Matrix ID. It
will also send an [`m.room.third_party_invite`](/client-server-api/#mroomthird_party_invite)
event in the room to specify a display name, a token and public keys the
identity server provided as a response to the invite storage request.

When a third-party identifier with pending invites gets bound to a Matrix ID,
the identity server will send a request to the [`/3pid/onbind`](#put_matrixfederationv13pidonbind)
endpoint of the the ID's homeserver as described in the [Invitation
Storage](/identity-service-api#invitation-storage) section of the Identity
Service API.

The following process applies for each invite sent by the identity
server:

The invited homeserver will create an `m.room.member` invite event
containing a special `third_party_invite` section containing the token
and a signed object, both provided by the identity server.
The invited homeserver will create an [`m.room.member`](/client-server-api/#mroommember)
invite event containing a special `third_party_invite` section containing the
token and a `signed` object, both provided by the identity server.

If the invited homeserver is in the room the invite came from, it can
auth the event and send it.

However, if the invited homeserver isn't in the room the invite came
from, it will need to request the room's homeserver to auth the event.
from, it will need to request the inviting homeserver to auth the event
at the [`/exchange_third_party_invite`](#put_matrixfederationv1exchange_third_party_inviteroomid)
endpoint.

{{% http-api spec="server-server" api="third_party_invite" %}}

Expand Down
9 changes: 5 additions & 4 deletions data/api/client-server/third_party_membership.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,6 @@ paths:
- A signature of the token, signed with the identity server's private key

- The matrix user ID who invited them to the room

If a token is requested from the identity server, the homeserver will
append a `m.room.third_party_invite` event to the room.
operationId: inviteBy3PID
security:
- accessTokenQuery: []
Expand All @@ -72,6 +69,8 @@ paths:
example: "!d41d8cd:matrix.org"
schema:
type: string
format: mx-room-id
pattern: "^!"
requestBody:
content:
application/json:
Expand Down Expand Up @@ -120,7 +119,9 @@ paths:
value: {}
"403":
description: |-
You do not have permission to invite the user to the room. A meaningful `errcode` and description error text will be returned. Example reasons for rejections are:
You do not have permission to invite the user to the room. A
meaningful `errcode` and description error text will be returned.
Example reasons for rejections are:

- The invitee has been banned from the room.
- The invitee is already a member of the room.
Expand Down
15 changes: 12 additions & 3 deletions data/api/identity/v2_pubkey.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ paths:
properties:
public_key:
type: string
description: Unpadded Base64 encoded public key.
description: |-
[Unpadded Base64](/appendices/#unpadded-base64)-encoded public key.
required:
- public_key
examples:
Expand Down Expand Up @@ -74,7 +75,8 @@ paths:
- in: query
name: public_key
required: true
description: The unpadded base64-encoded public key to check.
description: |-
The [unpadded Base64](/appendices/#unpadded-base64)-encoded public key to check.
example: VXuGitF39UH5iRfvbIknlvlAVKgD1BsLDMvBf0pmp7c
schema:
type: string
Expand Down Expand Up @@ -105,7 +107,14 @@ paths:
- in: query
name: public_key
required: true
description: The unpadded base64-encoded public key to check.
description: |-
The [unpadded Base64](/appendices/#unpadded-base64)-encoded public
key to check.

This MUST be the exact same encoded string returned in the response
of the [`/store-invite`](/identity-service-api/#post_matrixidentityv2store-invite)
endpoint, or found in the corresponding [`m.room.third_party_invite`](/client-server-api/#mroomthird_party_invite)
event, so it may use the standard or URL-safe alphabets.
example: VXuGitF39UH5iRfvbIknlvlAVKgD1BsLDMvBf0pmp7c
schema:
type: string
Expand Down
14 changes: 12 additions & 2 deletions data/api/identity/v2_store_invite.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ paths:
(if present) from the request here.

Also, the generated ephemeral public key will be listed as valid on
requests to `/_matrix/identity/v2/pubkey/ephemeral/isvalid`.
requests to [`/_matrix/identity/v2/pubkey/ephemeral/isvalid`](/identity-service-api/#get_matrixidentityv2pubkeyephemeralisvalid).

Currently, invites may only be issued for 3pids of the `email` medium.

Expand Down Expand Up @@ -70,23 +70,31 @@ paths:
room_id:
type: string
description: The Matrix room ID to which the user is invited
format: mx-room-id
pattern: "^!"
example: "!something:example.org"
sender:
type: string
description: The Matrix user ID of the inviting user
format: mx-user-id
pattern: "^@"
example: "@bob:example.com"
room_alias:
type: string
description: |-
The Matrix room alias for the room to which the user is
invited. This should be retrieved from the `m.room.canonical_alias`
state event.
format: mx-room-alias
pattern: "^#"
example: "#somewhere:example.org"
room_avatar_url:
type: string
description: |-
The Content URI for the room to which the user is invited. This should
be retrieved from the `m.room.avatar` state event.
format: mx-mxc-uri
pattern: "^mxc:\\/\\/"
example: mxc://example.org/s0meM3dia
room_join_rules:
type: string
Expand All @@ -108,6 +116,8 @@ paths:
type: string
description: The Content URI for the avatar of the user ID initiating the
invite.
format: mx-mxc-uri
pattern: "^mxc:\\/\\/"
example: mxc://example.org/an0th3rM3dia
room_type:
type: string
Expand Down Expand Up @@ -146,7 +156,7 @@ paths:
public_key:
type: string
description: |
The public key, encoded using [unpadded Base64](/appendices/#unpadded-base64).
The public key, encoded using standard or URL-safe [unpadded Base64](/appendices/#unpadded-base64).
key_validity_url:
type: string
description: |
Expand Down
Loading