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

[2/2] Allow homeservers to send registration emails | Accepting the verification #5940

Merged
merged 14 commits into from
Sep 5, 2019
Merged
Show file tree
Hide file tree
Changes from 5 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
32 changes: 17 additions & 15 deletions UPGRADE.rst
Original file line number Diff line number Diff line change
Expand Up @@ -66,21 +66,23 @@ its own, phone-based password resets and registration will be disabled. For Syna
emails, the ``email`` block of the config must be filled out. If not, then password resets and
registration via email will be disabled entirely.

This release also deprecates the ``email.trust_identity_server_for_password_resets`` option
and replaces it with ``account_threepid_delegate``. This option defines whether the homeserver
should delegate an external server (typically an `identity server
<https://matrix.org/docs/spec/identity_service/r0.2.1>`_) to handle sending password reset
or registration messages via email or SMS.

If ``email.trust_identity_server_for_password_resets`` was changed from its default to
``true``, and ``account_threepid_delegate`` is not set to an identity server domain, then the
server handling password resets and registration via third-party addresses will be set to the
first entry in the Synapse config's ``trusted_third_party_id_servers`` entry. If no domains are
configured, Synapse will throw an error on startup.

If ``email.trust_identity_server_for_password_resets`` is not set to ``true`` and
``account_threepid_delegate`` is not set to a domain, then Synapse will attempt to send
password reset and registration messages itself.
This release also deprecates the ``email.trust_identity_server_for_password_resets`` option and
replaces it with the ``account_threepid_delegates`` dictionary. This option defines whether the
homeserver should delegate an external server (typically an `identity server
<https://matrix.org/docs/spec/identity_service/r0.2.1>`_) to handle sending password reset or
registration messages via email and SMS.

Specifically for email, if ``email.trust_identity_server_for_password_resets`` was changed from
its default to ``true``, and ``account_threepid_delegates.email`` is not set, then the server
handling password resets and registration via third-party addresses will be set to the first
entry in the Synapse config's ``trusted_third_party_id_servers`` entry. This is to ensure that
people who set up an external server for handling these tasks before v1.4.0 will not have their
setups mysteriously stop working. However, if no trusted identity server domains are
configured, Synapse will throw an error.

If ``email.trust_identity_server_for_password_resets`` is not set to ``true`` and a type in
``account_threepid_delegates`` is not set to a domain, then Synapse will attempt to send
password reset and registration messages itself for that type.

Email templates
---------------
Expand Down
1 change: 1 addition & 0 deletions changelog.d/5940.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add the ability to send registration emails from the homeserver rather than delegating to an identity server.
37 changes: 24 additions & 13 deletions docs/sample_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -903,19 +903,30 @@ 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: ""
# Handle threepid (email/phone etc) registration and password resets through a set of
# *trusted* identity servers. Note that this allows the configured identity server to
# reset passwords for accounts!
#
# Also be aware that if email is not set to a domain, and SMTP options have not been
# configured in the email config block, registration and resetting user passwords via
# email will be globally disabled.
#
# Additionally, if msisdn is not set to a domain, registration and password resets via
# msisdn will be disabled regardless. This is due to Synapse currently not supporting
# any method of sending SMS messages on its own.
#
# To enable using an identity server for operations regarding a particular third-party
# identifier type, set the value to the reachable domain name of that identity server,
# including protocol definition, e.g:
# email: "https://matrix.org" # Let matrix.org handle sending emails for my users
# msisdn: "http://localhost:8090" # Delegate contacting SMS numbers to this process
#
# Servers handling the above requests must answer the .../requestToken endpoints
# defined by the Matrix Identity Service API specification:
# https://matrix.org/docs/spec/identity_service/latest
#account_threepid_delegates:
# email: ""
# msisdn: ""

# Users who register on this homeserver will automatically be joined
# to these rooms
Expand Down
27 changes: 17 additions & 10 deletions synapse/config/emailconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,13 @@ def read_config(self, config, **kwargs):
"renew_at"
)

self.threepid_behaviour = (
# Have Synapse handle the email sending if account_threepid_delegate
self.threepid_behaviour_email = (
# Have Synapse handle the email sending if account_threepid_delegates.email
# is not defined
# msisdn is currently always remote while Synapse does not support any method of
# sending SMS messages
ThreepidBehaviour.REMOTE
if self.account_threepid_delegate
if self.account_threepid_delegate_email
else ThreepidBehaviour.LOCAL
)
# Prior to Synapse v1.4.0, there was another option that defined whether Synapse would
Expand All @@ -88,14 +90,16 @@ def read_config(self, config, **kwargs):
# identity server in the process.
self.using_identity_server_from_trusted_list = False
if (
not self.account_threepid_delegate
not self.account_threepid_delegate_email
and 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:
# XXX: It's a little confusing that account_threepid_delegate is modifed
# XXX: It's a little confusing that account_threepid_delegates is modified
# both in RegistrationConfig and here. We should factor this bit out
self.account_threepid_delegate = self.trusted_third_party_id_servers[0]
self.account_threepid_delegate_email = self.trusted_third_party_id_servers[
0
]
self.using_identity_server_from_trusted_list = True
else:
raise ConfigError(
Expand All @@ -104,12 +108,15 @@ def read_config(self, config, **kwargs):
)

self.local_threepid_handling_disabled_due_to_email_config = False
if self.threepid_behaviour == ThreepidBehaviour.LOCAL and email_config == {}:
if (
self.threepid_behaviour_email == 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.local_threepid_handling_disabled_due_to_email_config = True

self.threepid_behaviour = ThreepidBehaviour.OFF
self.threepid_behaviour_email = ThreepidBehaviour.OFF

# Get lifetime of a validation token in milliseconds
self.email_validation_token_lifetime = self.parse_duration(
Expand All @@ -119,7 +126,7 @@ def read_config(self, config, **kwargs):
if (
self.email_enable_notifs
or account_validity_renewal_enabled
or self.threepid_behaviour == ThreepidBehaviour.LOCAL
or self.threepid_behaviour_email == ThreepidBehaviour.LOCAL
):
# make sure we can import the required deps
import jinja2
Expand All @@ -129,7 +136,7 @@ def read_config(self, config, **kwargs):
jinja2
bleach

if self.threepid_behaviour == ThreepidBehaviour.LOCAL:
if self.threepid_behaviour_email == ThreepidBehaviour.LOCAL:
required = ["smtp_host", "smtp_port", "notif_from"]

missing = []
Expand Down
45 changes: 34 additions & 11 deletions synapse/config/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,19 @@ 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")
account_threepid_delegates = config.get(
"account_threepid_delegates", {"email": "", "msisdn": ""}
)
self.account_threepid_delegate_email = account_threepid_delegates.get("email")
self.account_threepid_delegate_msisdn = account_threepid_delegates.get("msisdn")
if (
self.account_threepid_delegate_email is None
or self.account_threepid_delegate_msisdn is None
):
raise ConfigError(
"account_threepid_delegates must contain fields: email, msisdn"
)

self.default_identity_server = config.get("default_identity_server")
self.allow_guest_access = config.get("allow_guest_access", False)

Expand Down Expand Up @@ -270,19 +282,30 @@ 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.
# Handle threepid (email/phone etc) registration and password resets through a set of
# *trusted* identity servers. Note that this allows the configured identity server to
# reset passwords for accounts!
#
# Also be aware that if email is not set to a domain, and SMTP options have not been
# configured in the email config block, registration and resetting user passwords via
# email will be globally disabled.
#
# 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
# Additionally, if msisdn is not set to a domain, registration and password resets via
# msisdn will be disabled regardless. This is due to Synapse currently not supporting
# any method of sending SMS messages on its own.
#
# 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")
# To enable using an identity server for operations regarding a particular third-party
# identifier type, set the value to the reachable domain name of that identity server,
# including protocol definition, e.g:
# email: "https://matrix.org" # Let matrix.org handle sending emails for my users
# msisdn: "http://localhost:8090" # Delegate contacting SMS numbers to this process
#
#account_threepid_delegate: ""
# Servers handling the above requests must answer the .../requestToken endpoints
# defined by the Matrix Identity Service API specification:
# https://matrix.org/docs/spec/identity_service/latest
#account_threepid_delegates:
# email: ""
# msisdn: ""

# Users who register on this homeserver will automatically be joined
# to these rooms
Expand Down
31 changes: 7 additions & 24 deletions synapse/handlers/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def validate_user_via_ui_auth(self, requester, request_body, clientip):
return params

@defer.inlineCallbacks
def check_auth(self, flows, clientdict, clientip, password_servlet=False):
def check_auth(self, flows, clientdict, clientip):
"""
Takes a dictionary sent by the client in the login / registration
protocol and handles the User-Interactive Auth flow.
Expand All @@ -183,16 +183,6 @@ def check_auth(self, flows, clientdict, clientip, password_servlet=False):

clientip (str): The IP address of the client.

password_servlet (bool): Whether the request originated from
PasswordRestServlet.
XXX: This is a temporary hack to distinguish between checking
for threepid validations locally (in the case of password
resets) and using the identity server (in the case of binding
a 3PID during registration). Once we start using the
homeserver for both tasks, this distinction will no longer be
necessary.


Returns:
defer.Deferred[dict, dict, str]: a deferred tuple of
(creds, params, session_id).
Expand Down Expand Up @@ -248,9 +238,7 @@ def check_auth(self, flows, clientdict, clientip, password_servlet=False):
if "type" in authdict:
login_type = authdict["type"]
try:
result = yield self._check_auth_dict(
authdict, clientip, password_servlet=password_servlet
)
result = yield self._check_auth_dict(authdict, clientip)
if result:
creds[login_type] = result
self._save_session(session)
Expand Down Expand Up @@ -357,7 +345,7 @@ def get_session_data(self, session_id, key, default=None):
return sess.setdefault("serverdict", {}).get(key, default)

@defer.inlineCallbacks
def _check_auth_dict(self, authdict, clientip, password_servlet=False):
def _check_auth_dict(self, authdict, clientip):
"""Attempt to validate the auth dict provided by a client

Args:
Expand All @@ -377,9 +365,7 @@ def _check_auth_dict(self, authdict, clientip, password_servlet=False):
if checker is not None:
# XXX: Temporary workaround for having Synapse handle password resets
anoadragon453 marked this conversation as resolved.
Show resolved Hide resolved
# See AuthHandler.check_auth for further details
res = yield checker(
authdict, clientip=clientip, password_servlet=password_servlet
)
res = yield checker(authdict, clientip=clientip)
return res

# build a v1-login-style dict out of the authdict and fall back to the
Expand Down Expand Up @@ -450,7 +436,7 @@ def _check_terms_auth(self, authdict, **kwargs):
return defer.succeed(True)

@defer.inlineCallbacks
def _check_threepid(self, medium, authdict, password_servlet=False, **kwargs):
def _check_threepid(self, medium, authdict, **kwargs):
if "threepid_creds" not in authdict:
raise LoginError(400, "Missing threepid_creds", Codes.MISSING_PARAM)

Expand All @@ -459,12 +445,9 @@ def _check_threepid(self, medium, authdict, password_servlet=False, **kwargs):
identity_handler = self.hs.get_handlers().identity_handler

logger.info("Getting validated threepid. threepidcreds: %r", (threepid_creds,))
if (
not password_servlet
or self.hs.config.threepid_behaviour == ThreepidBehaviour.REMOTE
):
if self.hs.config.threepid_behaviour_email == ThreepidBehaviour.REMOTE:
threepid = yield identity_handler.threepid_from_creds(threepid_creds)
elif self.hs.config.threepid_behaviour == ThreepidBehaviour.LOCAL:
elif self.hs.config.threepid_behaviour_email == ThreepidBehaviour.LOCAL:
row = yield self.store.get_threepid_validation_session(
medium,
threepid_creds["client_secret"],
Expand Down
Loading