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

Replace trust_identity_server_for_password_resets with account_threepid_delegate #5876

Merged
merged 23 commits into from
Aug 21, 2019
Merged
Show file tree
Hide file tree
Changes from 12 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
72 changes: 48 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,40 @@ 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.
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]
else:
raise ConfigError(
'The config option "trust_identity_server_for_password_resets" '
'has been replaced by "account_threepid_delegate". Attempted to use an '
'identity server from "trusted_third_party_id_servers" but it is empty. '
"Please consult the sample config at docs/sample_config.yaml for "
"details and update your config file."
)

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 +118,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 +128,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 +261,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 +298,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
69 changes: 63 additions & 6 deletions synapse/handlers/identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,19 +199,46 @@ 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|None): The identity server to send this through. If None,
use the server specified by the account_threepid_delegate config option
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["next_link"] = next_link

if next_link:
params.update({"next_link": next_link})

if not id_server:
if not self.hs.config.account_threepid_delegate:
raise SynapseError(
400, "No id_server provided and none configured on the " "server"
)
id_server = self.hs.config.account_threepid_delegate
else:
# Assume "https://" is the protocol we're using to contact the id_server
# provided by the client
id_server = "https://" + id_server

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 +248,50 @@ 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:
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 not id_server:
if not self.hs.config.account_threepid_delegate:
raise SynapseError(
400, "No id_server provided and none configured on the " "server"
)
id_server = self.hs.config.account_threepid_delegate
else:
# Assume "https://" is the protocol we're using to contact the id_server
# provided by the client
id_server = "https://" + id_server

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