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 39 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, create_id_access_token_header | ||
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 | ||
|
||
|
@@ -626,7 +628,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): | ||
|
@@ -638,7 +640,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) | ||
|
@@ -661,7 +671,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( | ||
|
@@ -673,9 +688,47 @@ 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 id_access_token is not None: | ||
anoadragon453 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
try: | ||
results = yield self._lookup_3pid_v2( | ||
id_server, id_access_token, medium, address | ||
) | ||
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. | ||
|
@@ -685,10 +738,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), | ||
|
@@ -702,9 +751,116 @@ 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): | ||
"""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]"). | ||
|
||
Returns: | ||
Deferred[str|None]: the matrix ID of the 3pid, or None if it is not recognised. | ||
""" | ||
# Check what hashing details are supported by this identity server | ||
hash_details = yield self.simple_http_client.get_json( | ||
"%s%s/_matrix/identity/v2/hash_details" % (id_server_scheme, id_server), | ||
{"access_token": id_access_token}, | ||
) | ||
|
||
if not isinstance(hash_details, dict): | ||
logger.warning( | ||
"Got non-dict object when checking hash details of %s%s: %s", | ||
id_server_scheme, | ||
id_server, | ||
hash_details, | ||
) | ||
raise SynapseError( | ||
400, | ||
"Non-dict object from %s%s during v2 hash_details request: %s" | ||
% (id_server_scheme, id_server, hash_details), | ||
) | ||
|
||
# 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
|
||
400, | ||
"Invalid hash details received from identity server %s%s: %s" | ||
% (id_server_scheme, id_server, hash_details), | ||
) | ||
|
||
# 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.", | ||
) | ||
|
||
# Authenticate with identity server given the access token from the client | ||
headers = {"Authorization": create_id_access_token_header(id_access_token)} | ||
|
||
try: | ||
lookup_results = yield self.simple_http_client.post_json_get_json( | ||
"%s%s/_matrix/identity/v2/lookup" % (id_server_scheme, id_server), | ||
{ | ||
"addresses": [lookup_value], | ||
"algorithm": lookup_algorithm, | ||
"pepper": lookup_pepper, | ||
}, | ||
headers=headers, | ||
) | ||
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.warning("No results from 3pid lookup") | ||
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"]: | ||
|
@@ -844,7 +1000,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, | ||
|
@@ -862,7 +1017,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 | ||
|
@@ -1049,7 +1203,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.