diff options
-rw-r--r-- | synapse/handlers/identity.py | 23 | ||||
-rw-r--r-- | synapse/handlers/room.py | 4 | ||||
-rw-r--r-- | synapse/handlers/room_member.py | 91 | ||||
-rw-r--r-- | synapse/rest/client/v1/room.py | 1 |
4 files changed, 102 insertions, 17 deletions
diff --git a/synapse/handlers/identity.py b/synapse/handlers/identity.py index 622597c863..d081f88fc5 100644 --- a/synapse/handlers/identity.py +++ b/synapse/handlers/identity.py @@ -289,7 +289,7 @@ class IdentityHandler(BaseHandler): raise e.to_synapse_error() @defer.inlineCallbacks - def lookup_3pid(self, id_server, medium, address): + def lookup_3pid(self, id_server, medium, address, id_access_token=None): """Looks up a 3pid in the passed identity server. Args: @@ -297,16 +297,23 @@ class IdentityHandler(BaseHandler): of the identity server to use. medium (str): The type of the third party identifier (e.g. "email"). address (str): The third party identifier (e.g. "foo@example.com"). + id_access_token (str|None): The access token to authenticate to the identity + server with Returns: str: the matrix ID of the 3pid, or None if it is not recognized. """ + # If an access token is present, add it to the query params of the hash_details request + query_params = {} + if id_access_token is not None: + query_params["id_access_token"] = id_access_token + # Check what hashing details are supported by this identity server use_v1 = False hash_details = None try: hash_details = yield self.http_client.get_json( - "%s/_matrix/identity/v2/hash_details" % id_server + "%s/_matrix/identity/v2/hash_details" % id_server, query_params ) except (HttpResponseException, ValueError) as e: # Catch HttpResponseExcept for a non-200 response code @@ -323,7 +330,11 @@ class IdentityHandler(BaseHandler): if use_v1: return (yield self._lookup_3pid_v1(id_server, medium, address)) - return (yield self._lookup_3pid_v2(id_server, medium, address, hash_details)) + return ( + yield self._lookup_3pid_v2( + id_server, id_access_token, medium, address, hash_details + ) + ) @defer.inlineCallbacks def _lookup_3pid_v1(self, id_server, medium, address): @@ -356,12 +367,15 @@ class IdentityHandler(BaseHandler): return None @defer.inlineCallbacks - def _lookup_3pid_v2(self, id_server, medium, address, hash_details): + def _lookup_3pid_v2( + self, id_server, id_access_token, medium, address, hash_details + ): """Looks up a 3pid in the passed identity server using v2 lookup. Args: id_server (str): The server name (including protocol and port, if required) of the identity server to use. + id_access_token (str): The access token to authenticate to the identity server with medium (str): The type of the third party identifier (e.g. "email"). address (str): The third party identifier (e.g. "foo@example.com"). hash_details (dict[str, str|list]): A dictionary containing hashing information @@ -406,6 +420,7 @@ class IdentityHandler(BaseHandler): lookup_results = yield self.http_client.post_json_get_json( "%s/_matrix/identity/v2/lookup" % id_server, { + "id_access_token": id_access_token, "addresses": [lookup_value], "algorithm": lookup_algorithm, "pepper": lookup_pepper, diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index a509e11d69..970be3c846 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -579,8 +579,8 @@ class RoomCreationHandler(BaseHandler): room_id = yield self._generate_room_id(creator_id=user_id, is_public=is_public) + directory_handler = self.hs.get_handlers().directory_handler if room_alias: - directory_handler = self.hs.get_handlers().directory_handler yield directory_handler.create_association( requester=requester, room_id=room_id, @@ -665,6 +665,7 @@ class RoomCreationHandler(BaseHandler): for invite_3pid in invite_3pid_list: id_server = invite_3pid["id_server"] + id_access_token = invite_3pid.get("id_access_token") # optional address = invite_3pid["address"] medium = invite_3pid["medium"] yield self.hs.get_room_member_handler().do_3pid_invite( @@ -675,6 +676,7 @@ class RoomCreationHandler(BaseHandler): id_server, requester, txn_id=None, + id_access_token=id_access_token, ) result = {"room_id": room_id} diff --git a/synapse/handlers/room_member.py b/synapse/handlers/room_member.py index 3883bcdc97..3160e5fda1 100644 --- a/synapse/handlers/room_member.py +++ b/synapse/handlers/room_member.py @@ -643,7 +643,15 @@ class RoomMemberHandler(object): @defer.inlineCallbacks def do_3pid_invite( - self, room_id, inviter, medium, address, id_server, requester, txn_id + self, + room_id, + inviter, + medium, + address, + id_server, + requester, + txn_id, + id_access_token=None, ): if self.config.block_non_admin_invites: is_requester_admin = yield self.auth.is_server_admin(requester.user) @@ -673,7 +681,7 @@ class RoomMemberHandler(object): id_server_url = id_server_scheme + id_server invitee = yield self.identity_handler.lookup_3pid( - id_server_url, medium, address + id_server_url, medium, address, id_access_token ) if invitee: @@ -682,12 +690,27 @@ class RoomMemberHandler(object): ) else: yield self._make_and_store_3pid_invite( - requester, id_server, medium, address, room_id, inviter, txn_id=txn_id + requester, + id_server, + medium, + address, + room_id, + inviter, + txn_id=txn_id, + id_access_token=id_access_token, ) @defer.inlineCallbacks def _make_and_store_3pid_invite( - self, requester, id_server, medium, address, room_id, user, txn_id + self, + requester, + id_server, + medium, + address, + room_id, + user, + txn_id, + id_access_token=None, ): room_state = yield self.state_handler.get_current_state(room_id) @@ -736,6 +759,7 @@ class RoomMemberHandler(object): room_name=room_name, inviter_display_name=inviter_display_name, inviter_avatar_url=inviter_avatar_url, + id_access_token=id_access_token, ) ) @@ -773,6 +797,7 @@ class RoomMemberHandler(object): room_name, inviter_display_name, inviter_avatar_url, + id_access_token=None, ): """ Asks an identity server for a third party invite. @@ -792,6 +817,8 @@ class RoomMemberHandler(object): inviter_display_name (str): The current display name of the inviter. inviter_avatar_url (str): The URL of the inviter's avatar. + id_access_token (str|None): The access token to authenticate to the identity + server with Returns: A deferred tuple containing: @@ -802,12 +829,6 @@ class RoomMemberHandler(object): display_name (str): A user-friendly name to represent the invited user. """ - - is_url = "%s%s/_matrix/identity/api/v1/store-invite" % ( - id_server_scheme, - id_server, - ) - invite_config = { "medium": medium, "address": address, @@ -821,11 +842,39 @@ class RoomMemberHandler(object): "sender_avatar_url": inviter_avatar_url, } + # Add the identity service access token to the JSON body and use the v2 + # Identity Service endpoints if id_access_token is present + if id_access_token: + invite_config["id_access_token"] = id_access_token + is_url = "%s%s/_matrix/identity/v2/store-invite" % ( + id_server_scheme, + id_server, + ) + key_validity_url = "%s%s/_matrix/identity/v2/pubkey/isvalid" % ( + id_server_scheme, + id_server, + ) + else: + is_url = "%s%s/_matrix/identity/api/v1/store-invite" % ( + id_server_scheme, + id_server, + ) + key_validity_url = "%s%s/_matrix/identity/api/v1/pubkey/isvalid" % ( + id_server_scheme, + id_server, + ) + + fallback_to_v1 = False try: data = yield self.simple_http_client.post_json_get_json( is_url, invite_config ) except HttpResponseException as e: + if id_access_token and e.code == 404: + # This identity server does not support v2 endpoints + # Fallback to v1 endpoints + fallback_to_v1 = True + # Some identity servers may only support application/x-www-form-urlencoded # types. This is especially true with old instances of Sydent, see # https://github.com/matrix-org/sydent/pull/170 @@ -838,14 +887,32 @@ class RoomMemberHandler(object): is_url, invite_config ) + if fallback_to_v1: + return ( + yield self._ask_id_server_for_third_party_invite( + requester, + id_server, + medium, + address, + room_id, + inviter_user_id, + room_alias, + room_avatar_url, + room_join_rules, + room_name, + inviter_display_name, + inviter_avatar_url, + id_access_token=None, # force using v1 endpoints + ) + ) + # TODO: Check for success token = data["token"] public_keys = data.get("public_keys", []) if "public_key" in data: fallback_public_key = { "public_key": data["public_key"], - "key_validity_url": "%s%s/_matrix/identity/api/v1/pubkey/isvalid" - % (id_server_scheme, id_server), + "key_validity_url": key_validity_url, } else: fallback_public_key = public_keys[0] diff --git a/synapse/rest/client/v1/room.py b/synapse/rest/client/v1/room.py index 3582259026..a6a7b3b57e 100644 --- a/synapse/rest/client/v1/room.py +++ b/synapse/rest/client/v1/room.py @@ -701,6 +701,7 @@ class RoomMembershipRestServlet(TransactionRestServlet): content["id_server"], requester, txn_id, + content.get("id_access_token"), ) return 200, {} |