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

Commit 7739f23

Browse files
Replace trust_identity_server_for_password_resets with account_threepid_delegate (#5876)
Replaces the trust_identity_server_for_password_resets boolean option with a account_threepid_delegate str option that defines which identity server to use to handle password resets and registration if the homeserver does not want to or is unable to handle these tasks itself. Having this option being something other than null or "" gives the same indication as True for trust_identity_server_for_password_resets. The domain of the identity server is actually used in #5835
1 parent 8a3175f commit 7739f23

File tree

8 files changed

+290
-91
lines changed

8 files changed

+290
-91
lines changed

changelog.d/5876.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Replace `trust_identity_server_for_password_resets` config option with `account_threepid_delegate`.

docs/sample_config.yaml

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,20 @@ uploads_path: "DATADIR/uploads"
902902
# - matrix.org
903903
# - vector.im
904904

905+
# Handle threepid (email/phone etc) registration and password resets
906+
# through a *trusted* identity server. Note that this allows the configured
907+
# identity server to reset passwords for accounts.
908+
#
909+
# If this option is not defined and SMTP options have not been
910+
# configured, registration by email and resetting user passwords via
911+
# email will be disabled
912+
#
913+
# Otherwise, to enable set this option to the reachable domain name, including protocol
914+
# definition, for an identity server
915+
# (e.g "https://matrix.org", "http://localhost:8090")
916+
#
917+
#account_threepid_delegate: ""
918+
905919
# Users who register on this homeserver will automatically be joined
906920
# to these rooms
907921
#
@@ -1163,19 +1177,6 @@ password_config:
11631177
# #
11641178
# riot_base_url: "http://localhost/riot"
11651179
#
1166-
# # Enable sending password reset emails via the configured, trusted
1167-
# # identity servers
1168-
# #
1169-
# # IMPORTANT! This will give a malicious or overtaken identity server
1170-
# # the ability to reset passwords for your users! Make absolutely sure
1171-
# # that you want to do this! It is strongly recommended that password
1172-
# # reset emails be sent by the homeserver instead
1173-
# #
1174-
# # If this option is set to false and SMTP options have not been
1175-
# # configured, resetting user passwords via email will be disabled
1176-
# #
1177-
# #trust_identity_server_for_password_resets: false
1178-
#
11791180
# # Configure the time that a validation email or text message code
11801181
# # will expire after sending
11811182
# #

synapse/config/emailconfig.py

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
# This file can't be called email.py because if it is, we cannot:
2121
import email.utils
2222
import os
23+
from enum import Enum
2324

2425
import pkg_resources
2526

@@ -74,19 +75,39 @@ def read_config(self, config, **kwargs):
7475
"renew_at"
7576
)
7677

77-
email_trust_identity_server_for_password_resets = email_config.get(
78-
"trust_identity_server_for_password_resets", False
78+
self.email_threepid_behaviour = (
79+
# Have Synapse handle the email sending if account_threepid_delegate
80+
# is not defined
81+
ThreepidBehaviour.REMOTE
82+
if self.account_threepid_delegate
83+
else ThreepidBehaviour.LOCAL
7984
)
80-
self.email_password_reset_behaviour = (
81-
"remote" if email_trust_identity_server_for_password_resets else "local"
82-
)
83-
self.password_resets_were_disabled_due_to_email_config = False
84-
if self.email_password_reset_behaviour == "local" and email_config == {}:
85+
# Prior to Synapse v1.4.0, there was another option that defined whether Synapse would
86+
# use an identity server to password reset tokens on its behalf. We now warn the user
87+
# if they have this set and tell them to use the updated option, while using a default
88+
# identity server in the process.
89+
self.using_identity_server_from_trusted_list = False
90+
if config.get("trust_identity_server_for_password_resets", False) is True:
91+
# Use the first entry in self.trusted_third_party_id_servers instead
92+
if self.trusted_third_party_id_servers:
93+
self.account_threepid_delegate = self.trusted_third_party_id_servers[0]
94+
self.using_identity_server_from_trusted_list = True
95+
else:
96+
raise ConfigError(
97+
"Attempted to use an identity server from"
98+
'"trusted_third_party_id_servers" but it is empty.'
99+
)
100+
101+
self.local_threepid_emails_disabled_due_to_config = False
102+
if (
103+
self.email_threepid_behaviour == ThreepidBehaviour.LOCAL
104+
and email_config == {}
105+
):
85106
# We cannot warn the user this has happened here
86107
# Instead do so when a user attempts to reset their password
87-
self.password_resets_were_disabled_due_to_email_config = True
108+
self.local_threepid_emails_disabled_due_to_config = True
88109

89-
self.email_password_reset_behaviour = "off"
110+
self.email_threepid_behaviour = ThreepidBehaviour.OFF
90111

91112
# Get lifetime of a validation token in milliseconds
92113
self.email_validation_token_lifetime = self.parse_duration(
@@ -96,7 +117,7 @@ def read_config(self, config, **kwargs):
96117
if (
97118
self.email_enable_notifs
98119
or account_validity_renewal_enabled
99-
or self.email_password_reset_behaviour == "local"
120+
or self.email_threepid_behaviour == ThreepidBehaviour.LOCAL
100121
):
101122
# make sure we can import the required deps
102123
import jinja2
@@ -106,7 +127,7 @@ def read_config(self, config, **kwargs):
106127
jinja2
107128
bleach
108129

109-
if self.email_password_reset_behaviour == "local":
130+
if self.email_threepid_behaviour == ThreepidBehaviour.LOCAL:
110131
required = ["smtp_host", "smtp_port", "notif_from"]
111132

112133
missing = []
@@ -239,19 +260,6 @@ def generate_config_section(self, config_dir_path, server_name, **kwargs):
239260
# #
240261
# riot_base_url: "http://localhost/riot"
241262
#
242-
# # Enable sending password reset emails via the configured, trusted
243-
# # identity servers
244-
# #
245-
# # IMPORTANT! This will give a malicious or overtaken identity server
246-
# # the ability to reset passwords for your users! Make absolutely sure
247-
# # that you want to do this! It is strongly recommended that password
248-
# # reset emails be sent by the homeserver instead
249-
# #
250-
# # If this option is set to false and SMTP options have not been
251-
# # configured, resetting user passwords via email will be disabled
252-
# #
253-
# #trust_identity_server_for_password_resets: false
254-
#
255263
# # Configure the time that a validation email or text message code
256264
# # will expire after sending
257265
# #
@@ -289,3 +297,18 @@ def generate_config_section(self, config_dir_path, server_name, **kwargs):
289297
# #password_reset_template_success_html: password_reset_success.html
290298
# #password_reset_template_failure_html: password_reset_failure.html
291299
"""
300+
301+
302+
class ThreepidBehaviour(Enum):
303+
"""
304+
Enum to define the behaviour of Synapse with regards to when it contacts an identity
305+
server for 3pid registration and password resets
306+
307+
REMOTE = use an external server to send tokens
308+
LOCAL = send tokens ourselves
309+
OFF = disable registration via 3pid and password resets
310+
"""
311+
312+
REMOTE = "remote"
313+
LOCAL = "local"
314+
OFF = "off"

synapse/config/registration.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ def read_config(self, config, **kwargs):
9999
self.trusted_third_party_id_servers = config.get(
100100
"trusted_third_party_id_servers", ["matrix.org", "vector.im"]
101101
)
102+
self.account_threepid_delegate = config.get("account_threepid_delegate")
102103
self.default_identity_server = config.get("default_identity_server")
103104
self.allow_guest_access = config.get("allow_guest_access", False)
104105

@@ -269,6 +270,20 @@ def generate_config_section(self, generate_secrets=False, **kwargs):
269270
# - matrix.org
270271
# - vector.im
271272
273+
# Handle threepid (email/phone etc) registration and password resets
274+
# through a *trusted* identity server. Note that this allows the configured
275+
# identity server to reset passwords for accounts.
276+
#
277+
# If this option is not defined and SMTP options have not been
278+
# configured, registration by email and resetting user passwords via
279+
# email will be disabled
280+
#
281+
# Otherwise, to enable set this option to the reachable domain name, including protocol
282+
# definition, for an identity server
283+
# (e.g "https://matrix.org", "http://localhost:8090")
284+
#
285+
#account_threepid_delegate: ""
286+
272287
# Users who register on this homeserver will automatically be joined
273288
# to these rooms
274289
#

synapse/handlers/auth.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
UserDeactivatedError,
3939
)
4040
from synapse.api.ratelimiting import Ratelimiter
41+
from synapse.config.emailconfig import ThreepidBehaviour
4142
from synapse.logging.context import defer_to_thread
4243
from synapse.module_api import ModuleApi
4344
from synapse.types import UserID
@@ -460,10 +461,10 @@ def _check_threepid(self, medium, authdict, password_servlet=False, **kwargs):
460461
logger.info("Getting validated threepid. threepidcreds: %r", (threepid_creds,))
461462
if (
462463
not password_servlet
463-
or self.hs.config.email_password_reset_behaviour == "remote"
464+
or self.hs.config.email_threepid_behaviour == ThreepidBehaviour.REMOTE
464465
):
465466
threepid = yield identity_handler.threepid_from_creds(threepid_creds)
466-
elif self.hs.config.email_password_reset_behaviour == "local":
467+
elif self.hs.config.email_threepid_behaviour == ThreepidBehaviour.LOCAL:
467468
row = yield self.store.get_threepid_validation_session(
468469
medium,
469470
threepid_creds["client_secret"],

synapse/handlers/identity.py

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def __init__(self, hs):
3636

3737
self.http_client = hs.get_simple_http_client()
3838
self.federation_http_client = hs.get_http_client()
39+
self.hs = hs
3940

4041
@defer.inlineCallbacks
4142
def threepid_from_creds(self, creds):
@@ -199,19 +200,40 @@ def try_unbind_threepid_with_id_server(self, mxid, threepid, id_server):
199200
def requestEmailToken(
200201
self, id_server, email, client_secret, send_attempt, next_link=None
201202
):
203+
"""
204+
Request an external server send an email on our behalf for the purposes of threepid
205+
validation.
206+
207+
Args:
208+
id_server (str): The identity server to proxy to
209+
email (str): The email to send the message to
210+
client_secret (str): The unique client_secret sends by the user
211+
send_attempt (int): Which attempt this is
212+
next_link: A link to redirect the user to once they submit the token
213+
214+
Returns:
215+
The json response body from the server
216+
"""
202217
params = {
203218
"email": email,
204219
"client_secret": client_secret,
205220
"send_attempt": send_attempt,
206221
}
207-
208222
if next_link:
209-
params.update({"next_link": next_link})
223+
params["next_link"] = next_link
224+
225+
if self.hs.config.using_identity_server_from_trusted_list:
226+
# Warn that a deprecated config option is in use
227+
logger.warn(
228+
'The config option "trust_identity_server_for_password_resets" '
229+
'has been replaced by "account_threepid_delegate". '
230+
"Please consult the sample config at docs/sample_config.yaml for "
231+
"details and update your config file."
232+
)
210233

211234
try:
212235
data = yield self.http_client.post_json_get_json(
213-
"https://%s%s"
214-
% (id_server, "/_matrix/identity/api/v1/validate/email/requestToken"),
236+
id_server + "/_matrix/identity/api/v1/validate/email/requestToken",
215237
params,
216238
)
217239
return data
@@ -221,20 +243,49 @@ def requestEmailToken(
221243

222244
@defer.inlineCallbacks
223245
def requestMsisdnToken(
224-
self, id_server, country, phone_number, client_secret, send_attempt, **kwargs
246+
self,
247+
id_server,
248+
country,
249+
phone_number,
250+
client_secret,
251+
send_attempt,
252+
next_link=None,
225253
):
254+
"""
255+
Request an external server send an SMS message on our behalf for the purposes of
256+
threepid validation.
257+
Args:
258+
id_server (str): The identity server to proxy to
259+
country (str): The country code of the phone number
260+
phone_number (str): The number to send the message to
261+
client_secret (str): The unique client_secret sends by the user
262+
send_attempt (int): Which attempt this is
263+
next_link: A link to redirect the user to once they submit the token
264+
265+
Returns:
266+
The json response body from the server
267+
"""
226268
params = {
227269
"country": country,
228270
"phone_number": phone_number,
229271
"client_secret": client_secret,
230272
"send_attempt": send_attempt,
231273
}
232-
params.update(kwargs)
274+
if next_link:
275+
params["next_link"] = next_link
276+
277+
if self.hs.config.using_identity_server_from_trusted_list:
278+
# Warn that a deprecated config option is in use
279+
logger.warn(
280+
'The config option "trust_identity_server_for_password_resets" '
281+
'has been replaced by "account_threepid_delegate". '
282+
"Please consult the sample config at docs/sample_config.yaml for "
283+
"details and update your config file."
284+
)
233285

234286
try:
235287
data = yield self.http_client.post_json_get_json(
236-
"https://%s%s"
237-
% (id_server, "/_matrix/identity/api/v1/validate/msisdn/requestToken"),
288+
id_server + "/_matrix/identity/api/v1/validate/msisdn/requestToken",
238289
params,
239290
)
240291
return data

0 commit comments

Comments
 (0)