This repository was archived by the owner on Apr 26, 2024. It is now read-only.
  
  
  - 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 2.1k
Use the v2 Identity Service API for lookups (MSC2134 + MSC2140) #5976
          
     Merged
      
      
    
  
     Merged
                    Changes from 31 commits
      Commits
    
    
            Show all changes
          
          
            40 commits
          
        
        Select commit
          Hold shift + click to select a range
      
      1954438
              
                Use the v2 lookup API
              
              
                anoadragon453 24ee3ae
              
                lint
              
              
                anoadragon453 902ef39
              
                add changelog
              
              
                anoadragon453 3a114fe
              
                linter fight
              
              
                anoadragon453 5426e13
              
                Merge branch 'develop' into anoa/v2_lookup
              
              
                anoadragon453 73fb6f3
              
                Continue to support v1 lookup
              
              
                anoadragon453 2472e2e
              
                lint
              
              
                anoadragon453 7bfccad
              
                Address review comments
              
              
                anoadragon453 75ef0f8
              
                lint
              
              
                anoadragon453 e68d648
              
                small fixes and remove unnecessary Enum
              
              
                anoadragon453 38dac27
              
                Warn user when the id_server they chose does not support any of the h…
              
              
                anoadragon453 8f1346d
              
                Apply suggestions from code review
              
              
                anoadragon453 4dc0849
              
                lint
              
              
                anoadragon453 849d8dc
              
                Merge branch 'anoa/v2_lookup' of github.com:matrix-org/synapse into a…
              
              
                anoadragon453 d9d156b
              
                Merge branch 'develop' into anoa/v2_lookup
              
              
                anoadragon453 42b11bd
              
                use v2 identity service api endpoints for 3pid invites and lookup
              
              
                anoadragon453 83021d9
              
                Merge branch 'develop' of github.com:matrix-org/synapse into anoa/v2_…
              
              
                anoadragon453 07154ea
              
                Merge branch 'develop' of github.com:matrix-org/synapse into anoa/v2_…
              
              
                anoadragon453 f4b7f7f
              
                id_access_token support
              
              
                anoadragon453 29c3489
              
                Apply suggestions from code review
              
              
                anoadragon453 ff5f6a0
              
                Address review comments
              
              
                anoadragon453 a5153af
              
                Merge branch 'anoa/v2_lookup' of github.com:matrix-org/synapse into a…
              
              
                anoadragon453 7f647bc
              
                Revert moving lookup stuff to IdentityHandler
              
              
                anoadragon453 f8bb859
              
                Fix issues with moving stuff back to RoomMemberHandler
              
              
                anoadragon453 1c59243
              
                Factor our v2 invite things
              
              
                anoadragon453 1b20928
              
                lint
              
              
                anoadragon453 db1d161
              
                whoops
              
              
                anoadragon453 9f92c3e
              
                Change lookup_3pid back to a private method
              
              
                anoadragon453 07169b1
              
                Apply suggestions from code review
              
              
                anoadragon453 5b852c2
              
                Address review comments
              
              
                anoadragon453 0d968c0
              
                liiiiiiiiiiiint
              
              
                anoadragon453 f18f3f1
              
                address review comments
              
              
                anoadragon453 18671b0
              
                lint
              
              
                anoadragon453 649dcbe
              
                id_access_token -> access_token in query params
              
              
                anoadragon453 b4520ea
              
                Merge branch 'develop' of github.com:matrix-org/synapse into anoa/v2_…
              
              
                anoadragon453 79f5c4f
              
                Address review comments.
              
              
                anoadragon453 cf8dbea
              
                Merge branch 'develop' of github.com:matrix-org/synapse into anoa/v2_…
              
              
                anoadragon453 7008c79
              
                Send id access_token via Authorization headers, not JSON body
              
              
                anoadragon453 ffb284e
              
                Merge branch 'develop' of github.com:matrix-org/synapse into anoa/v2_…
              
              
                anoadragon453 317dff6
              
                Update changelog.d/5897.feature
              
              
                anoadragon453 File filter
Filter by extension
Conversations
          Failed to load comments.   
        
        
          
      Loading
        
  Jump to
        
          Jump to file
        
      
      
          Failed to load files.   
        
        
          
      Loading
        
  Diff view
Diff view
There are no files selected for viewing
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Switch to the v2 lookup API for 3PID invites. Implements MSC2134 plus id_access_token authentication for v2 Identity Service APIs from MSC2140. | ||
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -29,9 +29,11 @@ | |
| from synapse import types | ||
| from synapse.api.constants import EventTypes, Membership | ||
| from synapse.api.errors import AuthError, Codes, HttpResponseException, SynapseError | ||
| from synapse.handlers.identity import LookupAlgorithm | ||
| from synapse.types import RoomID, UserID | ||
| from synapse.util.async_helpers import Linearizer | ||
| from synapse.util.distributor import user_joined_room, user_left_room | ||
| from synapse.util.hash import sha256_and_url_safe_base64 | ||
|  | ||
| from ._base import BaseHandler | ||
|  | ||
|  | @@ -523,7 +525,7 @@ def send_membership_event( | |
| event (SynapseEvent): The membership event. | ||
| context: The context of the event. | ||
| is_guest (bool): Whether the sender is a guest. | ||
| room_hosts ([str]): Homeservers which are likely to already be in | ||
| remote_room_hosts (list[str]|None): Homeservers which are likely to already be in | ||
| the room, and could be danced with in order to join this | ||
| homeserver for the first time. | ||
| ratelimit (bool): Whether to rate limit this request. | ||
|  | @@ -634,7 +636,7 @@ def lookup_room_alias(self, room_alias): | |
| servers.remove(room_alias.domain) | ||
| servers.insert(0, room_alias.domain) | ||
|  | ||
| return (RoomID.from_string(room_id), servers) | ||
| return RoomID.from_string(room_id), servers | ||
|  | ||
| @defer.inlineCallbacks | ||
| def _get_inviter(self, user_id, room_id): | ||
|  | @@ -646,7 +648,15 @@ def _get_inviter(self, user_id, room_id): | |
|  | ||
| @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) | ||
|  | @@ -669,7 +679,12 @@ def do_3pid_invite( | |
| Codes.FORBIDDEN, | ||
| ) | ||
|  | ||
| invitee = yield self._lookup_3pid(id_server, medium, address) | ||
| if not self._enable_lookup: | ||
| raise SynapseError( | ||
| 403, "Looking up third-party identifiers is denied from this server" | ||
| ) | ||
|  | ||
| invitee = yield self._lookup_3pid(id_server, medium, address, id_access_token) | ||
|  | ||
| if invitee: | ||
| yield self.update_membership( | ||
|  | @@ -681,9 +696,65 @@ def do_3pid_invite( | |
| ) | ||
|  | ||
| @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: | ||
| id_server (str): The server name (including port, if required) | ||
| 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. "[email protected]"). | ||
| id_access_token (str|None): The access token to authenticate to the identity | ||
| server with | ||
|  | ||
| Returns: | ||
| str|None: 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 | ||
|         
                  anoadragon453 marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
| query_params = {} | ||
| if id_access_token is not None: | ||
|         
                  anoadragon453 marked this conversation as resolved.
              Show resolved
            Hide resolved | ||
| query_params["id_access_token"] = id_access_token | ||
|  | ||
| # Check what hashing details are supported by this identity server | ||
| try: | ||
| hash_details = yield self.simple_http_client.get_json( | ||
| "%s%s/_matrix/identity/v2/hash_details" | ||
| % (id_server_scheme, id_server), | ||
| query_params, | ||
| ) | ||
| if not isinstance(hash_details, dict): | ||
| logger.warning( | ||
| "Got non-dict object when checking hash details of %s: %s", | ||
| id_server, | ||
| hash_details, | ||
| ) | ||
| return None | ||
|  | ||
| results = yield self._lookup_3pid_v2( | ||
| id_server, id_access_token, medium, address, hash_details | ||
| ) | ||
| return results | ||
|  | ||
| except Exception as e: | ||
| # Catch HttpResponseExcept for a non-200 response code | ||
| # Check if this identity server does not know about v2 lookups | ||
| if isinstance(e, HttpResponseException) and e.code == 404: | ||
| # This is an old identity server that does not yet support v2 lookups | ||
| logger.warning( | ||
| "Attempted v2 lookup on v1 identity server %s. Falling " | ||
| "back to v1", | ||
| id_server, | ||
| ) | ||
| else: | ||
| logger.warning("Error when looking up hashing details: %s", e) | ||
| return None | ||
|  | ||
| return (yield self._lookup_3pid_v1(id_server, medium, address)) | ||
|  | ||
| @defer.inlineCallbacks | ||
| def _lookup_3pid_v1(self, id_server, medium, address): | ||
| """Looks up a 3pid in the passed identity server using v1 lookup. | ||
|  | ||
| Args: | ||
| id_server (str): The server name (including port, if required) | ||
| of the identity server to use. | ||
|  | @@ -693,10 +764,6 @@ def _lookup_3pid(self, id_server, medium, address): | |
| Returns: | ||
| str: the matrix ID of the 3pid, or None if it is not recognized. | ||
| """ | ||
| if not self._enable_lookup: | ||
| raise SynapseError( | ||
| 403, "Looking up third-party identifiers is denied from this server" | ||
| ) | ||
| try: | ||
| data = yield self.simple_http_client.get_json( | ||
| "%s%s/_matrix/identity/api/v1/lookup" % (id_server_scheme, id_server), | ||
|  | @@ -710,9 +777,96 @@ def _lookup_3pid(self, id_server, medium, address): | |
| return data["mxid"] | ||
|  | ||
| except IOError as e: | ||
| logger.warn("Error from identity server lookup: %s" % (e,)) | ||
| logger.warning("Error from v1 identity server lookup: %s" % (e,)) | ||
|  | ||
| return None | ||
|  | ||
| @defer.inlineCallbacks | ||
| 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 port, if required) | ||
| of the identity server to use. | ||
| id_access_token (str): The access token to authenticate to the identity server with | ||
|         
                  richvdh marked this conversation as resolved.
              Show resolved
            Hide resolved | ||
| medium (str): The type of the third party identifier (e.g. "email"). | ||
| address (str): The third party identifier (e.g. "[email protected]"). | ||
| hash_details (dict[str, str|list]): A dictionary containing hashing information | ||
| provided by an identity server. | ||
|  | ||
| Returns: | ||
| Deferred[str|None]: the matrix ID of the 3pid, or None if it is not recognised. | ||
| """ | ||
| # Extract information from hash_details | ||
| supported_lookup_algorithms = hash_details.get("algorithms") | ||
| lookup_pepper = hash_details.get("lookup_pepper") | ||
| if ( | ||
| not supported_lookup_algorithms | ||
| or not isinstance(supported_lookup_algorithms, list) | ||
| or not lookup_pepper | ||
| or not isinstance(lookup_pepper, str) | ||
| ): | ||
| raise SynapseError( | ||
|         
                  richvdh marked this conversation as resolved.
              Show resolved
            Hide resolved | ||
| 500, "Invalid hash details received from identity server: %s, %s" | ||
|         
                  anoadragon453 marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
| ) | ||
|  | ||
| # Check if any of the supported lookup algorithms are present | ||
| if LookupAlgorithm.SHA256 in supported_lookup_algorithms: | ||
|         
                  anoadragon453 marked this conversation as resolved.
              Show resolved
            Hide resolved | ||
| # Perform a hashed lookup | ||
| lookup_algorithm = LookupAlgorithm.SHA256 | ||
|  | ||
| # Hash address, medium and the pepper with sha256 | ||
| to_hash = "%s %s %s" % (address, medium, lookup_pepper) | ||
| lookup_value = sha256_and_url_safe_base64(to_hash) | ||
|  | ||
| elif LookupAlgorithm.NONE in supported_lookup_algorithms: | ||
| # Perform a non-hashed lookup | ||
| lookup_algorithm = LookupAlgorithm.NONE | ||
|  | ||
| # Combine together plaintext address and medium | ||
| lookup_value = "%s %s" % (address, medium) | ||
|  | ||
| else: | ||
| logger.warning( | ||
| "None of the provided lookup algorithms of %s are supported: %s", | ||
| id_server, | ||
| supported_lookup_algorithms, | ||
| ) | ||
| raise SynapseError( | ||
| 400, | ||
|         
                  anoadragon453 marked this conversation as resolved.
              Show resolved
            Hide resolved | ||
| "Provided identity server does not support any v2 lookup " | ||
| "algorithms that this homeserver supports.", | ||
| ) | ||
|  | ||
| try: | ||
| lookup_results = yield self.simple_http_client.post_json_get_json( | ||
| "%s%s/_matrix/identity/v2/lookup" % (id_server_scheme, id_server), | ||
| { | ||
| "id_access_token": id_access_token, | ||
| "addresses": [lookup_value], | ||
| "algorithm": lookup_algorithm, | ||
| "pepper": lookup_pepper, | ||
| }, | ||
| ) | ||
| except Exception as e: | ||
| logger.warning("Error when performing a v2 3pid lookup: %s", e) | ||
| raise SynapseError( | ||
|         
                  anoadragon453 marked this conversation as resolved.
              Show resolved
            Hide resolved | ||
| 500, "Unknown error occurred during identity server lookup" | ||
| ) | ||
|  | ||
| # Check for a mapping from what we looked up to an MXID | ||
| if "mappings" not in lookup_results or not isinstance( | ||
| lookup_results["mappings"], dict | ||
| ): | ||
| logger.debug("No results from 3pid lookup") | ||
|         
                  anoadragon453 marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
| return None | ||
|  | ||
| # Return the MXID if it's available, or None otherwise | ||
| mxid = lookup_results["mappings"].get(lookup_value) | ||
| return mxid | ||
|  | ||
| @defer.inlineCallbacks | ||
| def _verify_any_signature(self, data, server_hostname): | ||
| if server_hostname not in data["signatures"]: | ||
|  | @@ -852,7 +1006,6 @@ def _ask_id_server_for_third_party_invite( | |
| 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, | ||
|  | @@ -870,7 +1023,6 @@ def _ask_id_server_for_third_party_invite( | |
| "sender_display_name": inviter_display_name, | ||
| "sender_avatar_url": inviter_avatar_url, | ||
| } | ||
|  | ||
| try: | ||
| data = yield self.simple_http_client.post_json_get_json( | ||
| is_url, invite_config | ||
|  | @@ -1057,7 +1209,7 @@ def _remote_reject_invite(self, requester, remote_room_hosts, room_id, target): | |
| # The 'except' clause is very broad, but we need to | ||
| # capture everything from DNS failures upwards | ||
| # | ||
| logger.warn("Failed to reject invite: %s", e) | ||
| logger.warning("Failed to reject invite: %s", e) | ||
|  | ||
| yield self.store.locally_reject_invite(target.to_string(), room_id) | ||
| return {} | ||
|  | ||
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| # -*- coding: utf-8 -*- | ||
|  | ||
| # Copyright 2019 The Matrix.org Foundation C.I.C. | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|  | ||
| import hashlib | ||
|  | ||
| import unpaddedbase64 | ||
|  | ||
|  | ||
| def sha256_and_url_safe_base64(input_text): | ||
|         
                  anoadragon453 marked this conversation as resolved.
              Show resolved
            Hide resolved | ||
| """SHA256 hash an input string, encode the digest as url-safe base64, and | ||
| return | ||
| :param input_text: string to hash | ||
| :type input_text: str | ||
| :returns a sha256 hashed and url-safe base64 encoded digest | ||
| :rtype: str | ||
| """ | ||
| digest = hashlib.sha256(input_text.encode()).digest() | ||
| return unpaddedbase64.encode_base64(digest, urlsafe=True) | ||
  Add this suggestion to a batch that can be applied as a single commit.
  This suggestion is invalid because no changes were made to the code.
  Suggestions cannot be applied while the pull request is closed.
  Suggestions cannot be applied while viewing a subset of changes.
  Only one suggestion per line can be applied in a batch.
  Add this suggestion to a batch that can be applied as a single commit.
  Applying suggestions on deleted lines is not supported.
  You must change the existing code in this line in order to create a valid suggestion.
  Outdated suggestions cannot be applied.
  This suggestion has been applied or marked resolved.
  Suggestions cannot be applied from pending reviews.
  Suggestions cannot be applied on multi-line comments.
  Suggestions cannot be applied while the pull request is queued to merge.
  Suggestion cannot be applied right now. Please check back later.
  
    
  
    
Uh oh!
There was an error while loading. Please reload this page.