Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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/5876.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Replace `trust_identity_server_for_password_resets` config option with `account_threepid_delegate`.
27 changes: 14 additions & 13 deletions docs/sample_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -902,6 +902,20 @@ uploads_path: "DATADIR/uploads"
# - matrix.org
# - vector.im

# Handle threepid (email/phone etc) registration and password resets
# through a *trusted* identity server. Note that this allows the configured
# identity server to reset passwords for accounts.
#
# If this option is not defined and SMTP options have not been
# configured, registration by email and resetting user passwords via
# email will be disabled
#
# Otherwise, to enable set this option to the reachable domain name, including protocol
# definition, for an identity server
# (e.g "https://matrix.org", "http://localhost:8090")
#
#account_threepid_delegate: ""

# Users who register on this homeserver will automatically be joined
# to these rooms
#
Expand Down Expand Up @@ -1163,19 +1177,6 @@ password_config:
# #
# riot_base_url: "http://localhost/riot"
#
# # Enable sending password reset emails via the configured, trusted
# # identity servers
# #
# # IMPORTANT! This will give a malicious or overtaken identity server
# # the ability to reset passwords for your users! Make absolutely sure
# # that you want to do this! It is strongly recommended that password
# # reset emails be sent by the homeserver instead
# #
# # If this option is set to false and SMTP options have not been
# # configured, resetting user passwords via email will be disabled
# #
# #trust_identity_server_for_password_resets: false
#
# # Configure the time that a validation email or text message code
# # will expire after sending
# #
Expand Down
71 changes: 47 additions & 24 deletions synapse/config/emailconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
# This file can't be called email.py because if it is, we cannot:
import email.utils
import os
from enum import Enum

import pkg_resources

Expand Down Expand Up @@ -74,19 +75,39 @@ def read_config(self, config, **kwargs):
"renew_at"
)

email_trust_identity_server_for_password_resets = email_config.get(
"trust_identity_server_for_password_resets", False
self.email_threepid_behaviour = (
# Have Synapse handle the email sending if account_threepid_delegate
# is not defined
ThreepidBehaviour.REMOTE
if self.account_threepid_delegate
else ThreepidBehaviour.LOCAL
)
self.email_password_reset_behaviour = (
"remote" if email_trust_identity_server_for_password_resets else "local"
)
self.password_resets_were_disabled_due_to_email_config = False
if self.email_password_reset_behaviour == "local" and email_config == {}:
# Prior to Synapse v1.4.0, there was another option that defined whether Synapse would
# use an identity server to password reset tokens on its behalf. We now warn the user
# if they have this set and tell them to use the updated option, while using a default
# identity server in the process.
self.using_identity_server_from_trusted_list = False
if config.get("trust_identity_server_for_password_resets", False) is True:
# Use the first entry in self.trusted_third_party_id_servers instead
if self.trusted_third_party_id_servers:
self.account_threepid_delegate = self.trusted_third_party_id_servers[0]
self.using_identity_server_from_trusted_list = True
else:
raise ConfigError(
"Attempted to use an identity server from"
'"trusted_third_party_id_servers" but it is empty.'
)

self.local_threepid_emails_disabled_due_to_config = False
if (
self.email_threepid_behaviour == ThreepidBehaviour.LOCAL
and email_config == {}
):
# We cannot warn the user this has happened here
# Instead do so when a user attempts to reset their password
self.password_resets_were_disabled_due_to_email_config = True
self.local_threepid_emails_disabled_due_to_config = True

self.email_password_reset_behaviour = "off"
self.email_threepid_behaviour = ThreepidBehaviour.OFF

# Get lifetime of a validation token in milliseconds
self.email_validation_token_lifetime = self.parse_duration(
Expand All @@ -96,7 +117,7 @@ def read_config(self, config, **kwargs):
if (
self.email_enable_notifs
or account_validity_renewal_enabled
or self.email_password_reset_behaviour == "local"
or self.email_threepid_behaviour == ThreepidBehaviour.LOCAL
):
# make sure we can import the required deps
import jinja2
Expand All @@ -106,7 +127,7 @@ def read_config(self, config, **kwargs):
jinja2
bleach

if self.email_password_reset_behaviour == "local":
if self.email_threepid_behaviour == ThreepidBehaviour.LOCAL:
required = ["smtp_host", "smtp_port", "notif_from"]

missing = []
Expand Down Expand Up @@ -239,19 +260,6 @@ def generate_config_section(self, config_dir_path, server_name, **kwargs):
# #
# riot_base_url: "http://localhost/riot"
#
# # Enable sending password reset emails via the configured, trusted
# # identity servers
# #
# # IMPORTANT! This will give a malicious or overtaken identity server
# # the ability to reset passwords for your users! Make absolutely sure
# # that you want to do this! It is strongly recommended that password
# # reset emails be sent by the homeserver instead
# #
# # If this option is set to false and SMTP options have not been
# # configured, resetting user passwords via email will be disabled
# #
# #trust_identity_server_for_password_resets: false
#
# # Configure the time that a validation email or text message code
# # will expire after sending
# #
Expand Down Expand Up @@ -289,3 +297,18 @@ def generate_config_section(self, config_dir_path, server_name, **kwargs):
# #password_reset_template_success_html: password_reset_success.html
# #password_reset_template_failure_html: password_reset_failure.html
"""


class ThreepidBehaviour(Enum):
"""
Enum to define the behaviour of Synapse with regards to when it contacts an identity
server for 3pid registration and password resets

REMOTE = use an external server to send tokens
LOCAL = send tokens ourselves
OFF = disable registration via 3pid and password resets
"""

REMOTE = "remote"
LOCAL = "local"
OFF = "off"
15 changes: 15 additions & 0 deletions synapse/config/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ def read_config(self, config, **kwargs):
self.trusted_third_party_id_servers = config.get(
"trusted_third_party_id_servers", ["matrix.org", "vector.im"]
)
self.account_threepid_delegate = config.get("account_threepid_delegate")
self.default_identity_server = config.get("default_identity_server")
self.allow_guest_access = config.get("allow_guest_access", False)

Expand Down Expand Up @@ -269,6 +270,20 @@ def generate_config_section(self, generate_secrets=False, **kwargs):
# - matrix.org
# - vector.im

# Handle threepid (email/phone etc) registration and password resets
# through a *trusted* identity server. Note that this allows the configured
# identity server to reset passwords for accounts.
#
# If this option is not defined and SMTP options have not been
# configured, registration by email and resetting user passwords via
# email will be disabled
#
# Otherwise, to enable set this option to the reachable domain name, including protocol
# definition, for an identity server
# (e.g "https://matrix.org", "http://localhost:8090")
#
#account_threepid_delegate: ""

# Users who register on this homeserver will automatically be joined
# to these rooms
#
Expand Down
5 changes: 3 additions & 2 deletions synapse/handlers/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
UserDeactivatedError,
)
from synapse.api.ratelimiting import Ratelimiter
from synapse.config.emailconfig import ThreepidBehaviour
from synapse.logging.context import defer_to_thread
from synapse.module_api import ModuleApi
from synapse.types import UserID
Expand Down Expand Up @@ -460,10 +461,10 @@ def _check_threepid(self, medium, authdict, password_servlet=False, **kwargs):
logger.info("Getting validated threepid. threepidcreds: %r", (threepid_creds,))
if (
not password_servlet
or self.hs.config.email_password_reset_behaviour == "remote"
or self.hs.config.email_threepid_behaviour == ThreepidBehaviour.REMOTE
):
threepid = yield identity_handler.threepid_from_creds(threepid_creds)
elif self.hs.config.email_password_reset_behaviour == "local":
elif self.hs.config.email_threepid_behaviour == ThreepidBehaviour.LOCAL:
row = yield self.store.get_threepid_validation_session(
medium,
threepid_creds["client_secret"],
Expand Down
67 changes: 59 additions & 8 deletions synapse/handlers/identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def __init__(self, hs):

self.http_client = hs.get_simple_http_client()
self.federation_http_client = hs.get_http_client()
self.hs = hs

@defer.inlineCallbacks
def threepid_from_creds(self, creds):
Expand Down Expand Up @@ -199,19 +200,40 @@ def try_unbind_threepid_with_id_server(self, mxid, threepid, id_server):
def requestEmailToken(
self, id_server, email, client_secret, send_attempt, next_link=None
):
"""
Request an external server send an email on our behalf for the purposes of threepid
validation.

Args:
id_server (str): The identity server to proxy to
email (str): The email to send the message to
client_secret (str): The unique client_secret sends by the user
send_attempt (int): Which attempt this is
next_link: A link to redirect the user to once they submit the token

Returns:
The json response body from the server
"""
params = {
"email": email,
"client_secret": client_secret,
"send_attempt": send_attempt,
}

if next_link:
params.update({"next_link": next_link})
params["next_link"] = next_link

if self.hs.config.using_identity_server_from_trusted_list:
# Warn that a deprecated config option is in use
logger.warn(
'The config option "trust_identity_server_for_password_resets" '
'has been replaced by "account_threepid_delegate". '
"Please consult the sample config at docs/sample_config.yaml for "
"details and update your config file."
)

try:
data = yield self.http_client.post_json_get_json(
"https://%s%s"
% (id_server, "/_matrix/identity/api/v1/validate/email/requestToken"),
id_server + "/_matrix/identity/api/v1/validate/email/requestToken",
params,
)
return data
Expand All @@ -221,20 +243,49 @@ def requestEmailToken(

@defer.inlineCallbacks
def requestMsisdnToken(
self, id_server, country, phone_number, client_secret, send_attempt, **kwargs
self,
id_server,
country,
phone_number,
client_secret,
send_attempt,
next_link=None,
):
"""
Request an external server send an SMS message on our behalf for the purposes of
threepid validation.
Args:
id_server (str): The identity server to proxy to
country (str): The country code of the phone number
phone_number (str): The number to send the message to
client_secret (str): The unique client_secret sends by the user
send_attempt (int): Which attempt this is
next_link: A link to redirect the user to once they submit the token

Returns:
The json response body from the server
"""
params = {
"country": country,
"phone_number": phone_number,
"client_secret": client_secret,
"send_attempt": send_attempt,
}
params.update(kwargs)
if next_link:
params["next_link"] = next_link

if self.hs.config.using_identity_server_from_trusted_list:
# Warn that a deprecated config option is in use
logger.warn(
'The config option "trust_identity_server_for_password_resets" '
'has been replaced by "account_threepid_delegate". '
"Please consult the sample config at docs/sample_config.yaml for "
"details and update your config file."
)

try:
data = yield self.http_client.post_json_get_json(
"https://%s%s"
% (id_server, "/_matrix/identity/api/v1/validate/msisdn/requestToken"),
id_server + "/_matrix/identity/api/v1/validate/msisdn/requestToken",
params,
)
return data
Expand Down
Loading