From dc3c02aff5ed34686dd62b39fcce72cae8065f5f Mon Sep 17 00:00:00 2001 From: Daniel Wagner-Hall Date: Thu, 8 Oct 2015 10:08:38 -0500 Subject: [PATCH] Review comments --- api/client-server/v1/membership.yaml | 31 +++++++------------ event-schemas/schema/v1/m.room.member | 4 +-- specification/modules/third_party_invites.rst | 29 ++++++++++++----- 3 files changed, 35 insertions(+), 29 deletions(-) diff --git a/api/client-server/v1/membership.yaml b/api/client-server/v1/membership.yaml index ff35fa35..efc82578 100644 --- a/api/client-server/v1/membership.yaml +++ b/api/client-server/v1/membership.yaml @@ -80,11 +80,6 @@ paths: They do not start participating in the room until they actually join the room. - This serves two purposes; firstly, to notify the user that the room - exists (and that their presence is requested). Secondly, some rooms can - only be joined if a user is invited to join it; sending the invite gives - that user permission to join the room. - Only users currently in a particular room can invite other users to join that room. @@ -142,20 +137,21 @@ paths: description: |- *Note that there are two forms of this API, which are documented separately. This version of the API does not require that the inviter know the Matrix - identifier of the invitee, and instead relies on third party identifiers.* + identifier of the invitee, and instead relies on third party identifiers. + The homeserver uses an identity server to perform the mapping from + third party identifier to a Matrix identifier.* This API invites a user to participate in a particular room. They do not start participating in the room until they actually join the room. - This serves two purposes; firstly, to notify the user that the room - exists (and that their presence is requested). Secondly, some rooms can - only be joined if a user is invited to join it; sending the invite gives - that user permission to join the room. - Only users currently in a particular room can invite other users to join that room. + If the identity server did know the Matrix user identifier for the + third party identifier, the home server will append a ``m.room.member`` + event to the room. + If the identity server does not know a Matrix user identifier for the passed third party identifier, the homeserver will issue an invitation which can be accepted upon providing proof of ownership of the third @@ -164,9 +160,9 @@ paths: add an ``m.room.third_party_invite`` event into the graph for the room, containing that token. - When a user binds the invited third party identifier to a Matrix user ID, - the identity server will give the user a list of pending invitations, - each containing: + When the invitee binds the invited third party identifier to a Matrix + user ID, the identity server will give the user a list of pending + invitations, each containing: - The room ID to which they were invited @@ -176,10 +172,6 @@ paths: - The matrix user ID who invited them to the room - If the identity server did know the Matrix user identifier for the - third party identifier, the home server will append a ``m.room.member`` - event to the room. - If a token is requested from the identity server, the home server will append a ``m.room.third_party_invite`` event to the room. security: @@ -209,7 +201,8 @@ paths: description: The hostname+port of the identity server which should be used for third party identifier lookups. medium: type: string - description: The kind of address being passed in the address field. + # TODO: Link to identity service spec when it eixsts + description: The kind of address being passed in the address field, for example ``email``. address: type: string description: The invitee's third party identifier. diff --git a/event-schemas/schema/v1/m.room.member b/event-schemas/schema/v1/m.room.member index 56104328..912f6cf3 100644 --- a/event-schemas/schema/v1/m.room.member +++ b/event-schemas/schema/v1/m.room.member @@ -1,7 +1,7 @@ { "type": "object", "title": "The current membership state of a user in the room.", - "description": "Adjusts the membership state for a user in a room. It is preferable to use the membership APIs (``/rooms//invite`` etc) when performing membership actions rather than adjusting the state directly as there are a restricted set of valid transformations. For example, user A cannot force user B to join a room, and trying to force this state change directly will fail. The token, public_key, key_validity_url, signature, and sender properties either must all or none be set - they are set if the invite was an ``m.room.third_party_invite`` event, and absent if the invite was an ``m.room.member`` event.", + "description": "Adjusts the membership state for a user in a room. It is preferable to use the membership APIs (``/rooms//invite`` etc) when performing membership actions rather than adjusting the state directly as there are a restricted set of valid transformations. For example, user A cannot force user B to join a room, and trying to force this state change directly will fail. The ``third_party_invite`` property will be set if the invite was an ``m.room.third_party_invite`` event, and absent if the invite was an ``m.room.member`` event.", "allOf": [{ "$ref": "core-event-schema/state_event.json" }], @@ -32,7 +32,7 @@ }, "key_validity_url": { "type": "string", - "description": "A URL which can be fetched, with querystring public_key=public_key, to validate whether the key has been revoked. The URL must return a JSON object containing a boolean property named 'valid'." + "description": "A URL which can be fetched, with querystring ``public_key=public_key``, to validate whether the key has been revoked. The URL must return a JSON object containing a boolean property named 'valid'." }, "public_key": { "type": "string", diff --git a/specification/modules/third_party_invites.rst b/specification/modules/third_party_invites.rst index 3365501e..9b3b52e1 100644 --- a/specification/modules/third_party_invites.rst +++ b/specification/modules/third_party_invites.rst @@ -8,7 +8,7 @@ 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 with the +identifier, and one if not. Either way, the client calls ``/invite`` with the details of the third party identifier. The homeserver asks the identity server whether a Matrix user ID is known for @@ -16,8 +16,8 @@ that identifier. If it is, an invite is simply issued for that user. If it is not, the homeserver asks the identity server to record the details of the invitation, and to notify the client of this pending invitation if it gets -a binding for this identifier in the future. The identity server returns to the -homeserver a token, as well as its public key. +a binding for this identifier in the future. The identity server returns a token +and public key to the homeserver. If a client then tries to join the room in the future, it will be allowed to if it presents both the token, and a signature of that token from the identity @@ -43,6 +43,8 @@ If a client of the current homeserver is joining by an key used for signing is still valid, by checking ``key_validity_url``. It does this by making an HTTP GET request to ``key_validity_url``: +.. TODO: Link to identity server spec when it exists + Schema:: => GET $key_validity_url?public_key=$public_key @@ -63,14 +65,16 @@ Example:: } with the querystring -?public_key=``public_key``. A JSON object will be returned, and the key is -considered valid if the object contains a key named ``valid`` whose value is -``true``. If this cannot be verified, the invitation must be rejected. +?public_key=``public_key``. A JSON object will be returned. +The invitation is valid if the object contains a key named ``valid`` which is +``true``. Otherwise, the invitation MUST be rejected. This request is +idempotent, and may be retried by the homeserver. 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 MUST validate that the public key used for signing is still valid, by -checking ``key_validity_url`` in the above described way. +room (which is chosen as per the standard server-server specification) MUST +validate that the public key used for signing is still valid, by checking +``key_validity_url`` in the above described way. No other homeservers may reject the joining of the room on the basis of ``key_validity_url``, this is so that all homeservers have a consistent view of @@ -98,3 +102,12 @@ sign(``token``, ``public_key``) = ``signature`` *and* check ``key_validity_url`` Having validated these things, H1 writes the join event to the room, and H3 begins participating in the room. H2 *must* accept this event. +The reason that no other homeserver may reject the event based on checking +``key_validity_url`` is that we must ensure event acceptance is deterministic. +If some other participating server doesn't have a network path to the keyserver, +or if the keyserver were to go offline, or revoke its keys, that other server +would reject the event and cause the participating servers' graphs to diverge. +This relies on participating servers trusting each other, but that trust is +already implied by the server-server protocol. Also, the public key signature +verification must still be performed, so the attack surface here is minimized. +