Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Use account_threepid_delegate for 3pid validation #6011

Merged
merged 2 commits into from
Sep 10, 2019
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
1 change: 1 addition & 0 deletions changelog.d/6011.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Use account_threepid_delegate.email and account_threepid_delegate.msisdn for validating threepid sessions.
11 changes: 10 additions & 1 deletion synapse/handlers/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,16 @@ def _check_threepid(self, medium, authdict, **kwargs):

logger.info("Getting validated threepid. threepidcreds: %r", (threepid_creds,))
if self.hs.config.threepid_behaviour_email == ThreepidBehaviour.REMOTE:
threepid = yield identity_handler.threepid_from_creds(threepid_creds)
if medium == "email":
threepid = yield identity_handler.threepid_from_creds(
self.hs.config.account_threepid_delegate_email, threepid_creds
)
elif medium == "msisdn":
threepid = yield identity_handler.threepid_from_creds(
self.hs.config.account_threepid_delegate_msisdn, threepid_creds
)
else:
raise SynapseError(400, "Unrecognized threepid medium: %s" % (medium,))
elif self.hs.config.threepid_behaviour_email == ThreepidBehaviour.LOCAL:
row = yield self.store.get_threepid_validation_session(
medium,
Expand Down
73 changes: 33 additions & 40 deletions synapse/handlers/identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,59 +75,52 @@ def _extract_items_from_creds_dict(self, creds):
return client_secret, id_server, id_access_token

@defer.inlineCallbacks
def threepid_from_creds(self, creds, use_v2=True):
def threepid_from_creds(self, id_server, creds):
"""
Retrieve and validate a threepid identitier from a "credentials" dictionary
Retrieve and validate a threepid identifier from a "credentials" dictionary against a
given identity server

Args:
creds (dict[str, str]): Dictionary of credentials that contain the following keys:
id_server (str|None): The identity server to validate 3PIDs against. If None,
we will attempt to extract id_server creds

creds (dict[str, str]): Dictionary containing the following keys:
* id_server|idServer: An optional domain name of an identity server
* client_secret|clientSecret: A unique secret str provided by the client
* id_server|idServer: the domain of the identity server to query
* id_access_token: The access token to authenticate to the identity
server with. Required if use_v2 is true
use_v2 (bool): Whether to use v2 Identity Service API endpoints
* sid: The ID of the validation session

Returns:
Deferred[dict[str,str|int]|None]: A dictionary consisting of response params to
the /getValidated3pid endpoint of the Identity Service API, or None if the
threepid was not found
"""
client_secret, id_server, id_access_token = self._extract_items_from_creds_dict(
creds
)

# If an id_access_token is not supplied, force usage of v1
if id_access_token is None:
use_v2 = False

query_params = {"sid": creds["sid"], "client_secret": client_secret}

# Decide which API endpoint URLs and query parameters to use
if use_v2:
url = "https://%s%s" % (
id_server,
"/_matrix/identity/v2/3pid/getValidated3pid",
client_secret = creds.get("client_secret") or creds.get("clientSecret")
if not client_secret:
raise SynapseError(
400, "Missing param client_secret in creds", errcode=Codes.MISSING_PARAM
)
query_params["id_access_token"] = id_access_token
else:
url = "https://%s%s" % (
id_server,
"/_matrix/identity/api/v1/3pid/getValidated3pid",
session_id = creds.get("sid")
if not session_id:
raise SynapseError(
400, "Missing param session_id in creds", errcode=Codes.MISSING_PARAM
)
if not id_server:
# Attempt to get the id_server from the creds dict
id_server = creds.get("id_server") or creds.get("idServer")
if not id_server:
raise SynapseError(
400, "Missing param id_server in creds", errcode=Codes.MISSING_PARAM
)

query_params = {"sid": session_id, "client_secret": client_secret}

url = "https://%s%s" % (
id_server,
"/_matrix/identity/api/v1/3pid/getValidated3pid",
)

try:
data = yield self.http_client.get_json(url, query_params)
return data if "medium" in data else None
except HttpResponseException as e:
if e.code != 404 or not use_v2:
# Generic failure
logger.info("getValidated3pid failed with Matrix error: %r", e)
raise e.to_synapse_error()

# This identity server is too old to understand Identity Service API v2
# Attempt v1 endpoint
logger.info("Got 404 when POSTing JSON %s, falling back to v1 URL", url)
return (yield self.threepid_from_creds(creds, use_v2=False))
data = yield self.http_client.get_json(url, query_params)
return data if "medium" in data else None

@defer.inlineCallbacks
def bind_threepid(self, creds, mxid, use_v2=True):
Expand Down
3 changes: 2 additions & 1 deletion synapse/rest/client/v2_alpha/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,8 @@ def on_POST(self, request):
requester = yield self.auth.get_user_by_req(request)
user_id = requester.user.to_string()

threepid = yield self.identity_handler.threepid_from_creds(threepid_creds)
# Specify None as the identity server to retrieve it from the request body instead
threepid = yield self.identity_handler.threepid_from_creds(None, threepid_creds)

if not threepid:
raise SynapseError(400, "Failed to auth 3pid", Codes.THREEPID_AUTH_FAILED)
Expand Down