Drop support for delegating email validation (#13192)

* Drop support for delegating email validation

Delegating email validation to an IS is insecure (since it allows the owner of
the IS to do a password reset on your HS), and has long been deprecated. It
will now cause a config error at startup.

* Update unit test which checks for email verification

Give it an `email` config instead of a threepid delegate

* Remove unused method `requestEmailToken`

* Simplify config handling for email verification

Rather than an enum and a boolean, all we need here is a single bool, which
says whether we are or are not doing email verification.

* update docs

* changelog

* upgrade.md: fix typo

* update version number

this will be in 1.64, not 1.63

* update version number

this one too
This commit is contained in:
Richard van der Hoff 2022-07-12 19:18:53 +01:00 committed by GitHub
parent 3f178332d6
commit fa71bb18b5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 110 additions and 253 deletions

View file

@ -1,3 +1,8 @@
Synapse vNext
=============
As of this release, Synapse no longer allows the tasks of verifying email address ownership, and password reset confirmation, to be delegated to an identity server. For more information, see the [upgrade notes](https://github.com/matrix-org/synapse/blob/release-v1.63/docs/upgrade.md#upgrading-to-v1630).
Synapse 1.63.0rc1 (2022-07-12) Synapse 1.63.0rc1 (2022-07-12)
============================== ==============================
@ -73,7 +78,6 @@ Internal Changes
- More aggressively rotate push actions. ([\#13211](https://github.com/matrix-org/synapse/issues/13211)) - More aggressively rotate push actions. ([\#13211](https://github.com/matrix-org/synapse/issues/13211))
- Add `max_line_length` setting for Python files to the `.editorconfig`. Contributed by @sumnerevans @ Beeper. ([\#13228](https://github.com/matrix-org/synapse/issues/13228)) - Add `max_line_length` setting for Python files to the `.editorconfig`. Contributed by @sumnerevans @ Beeper. ([\#13228](https://github.com/matrix-org/synapse/issues/13228))
Synapse 1.62.0 (2022-07-05) Synapse 1.62.0 (2022-07-05)
=========================== ===========================
@ -81,7 +85,6 @@ No significant changes since 1.62.0rc3.
Authors of spam-checker plugins should consult the [upgrade notes](https://github.com/matrix-org/synapse/blob/release-v1.62/docs/upgrade.md#upgrading-to-v1620) to learn about the enriched signatures for spam checker callbacks, which are supported with this release of Synapse. Authors of spam-checker plugins should consult the [upgrade notes](https://github.com/matrix-org/synapse/blob/release-v1.62/docs/upgrade.md#upgrading-to-v1620) to learn about the enriched signatures for spam checker callbacks, which are supported with this release of Synapse.
Synapse 1.62.0rc3 (2022-07-04) Synapse 1.62.0rc3 (2022-07-04)
============================== ==============================

View file

@ -0,0 +1 @@
Drop support for delegating email verification to an external server.

View file

@ -89,6 +89,21 @@ process, for example:
dpkg -i matrix-synapse-py3_1.3.0+stretch1_amd64.deb dpkg -i matrix-synapse-py3_1.3.0+stretch1_amd64.deb
``` ```
# Upgrading to v1.64.0
## Delegation of email validation no longer supported
As of this version, Synapse no longer allows the tasks of verifying email address
ownership, and password reset confirmation, to be delegated to an identity server.
To continue to allow users to add email addresses to their homeserver accounts,
and perform password resets, make sure that Synapse is configured with a
working email server in the `email` configuration section (including, at a
minimum, a `notif_from` setting.)
Specifying an `email` setting under `account_threepid_delegates` will now cause
an error at startup.
# Upgrading to v1.62.0 # Upgrading to v1.62.0
## New signatures for spam checker callbacks ## New signatures for spam checker callbacks

View file

@ -2168,30 +2168,26 @@ default_identity_server: https://matrix.org
--- ---
### `account_threepid_delegates` ### `account_threepid_delegates`
Handle threepid (email/phone etc) registration and password resets through a set of Delegate verification of phone numbers to an identity server.
*trusted* identity servers. Note that this allows the configured identity server to
reset passwords for accounts!
Be aware that if `email` is not set, and SMTP options have not been When a user wishes to add a phone number to their account, we need to verify that they
configured in the email config block, registration and user password resets via actually own that phone number, which requires sending them a text message (SMS).
email will be globally disabled. Currently Synapse does not support sending those texts itself and instead delegates the
task to an identity server. The base URI for the identity server to be used is
specified by the `account_threepid_delegates.msisdn` option.
Additionally, if `msisdn` is not set, registration and password resets via msisdn If this is left unspecified, Synapse will not allow users to add phone numbers to
will be disabled regardless, and users will not be able to associate an msisdn their account.
identifier to their account. 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 (Servers handling the these requests must answer the `/requestToken` endpoints defined
identifier type, set the value to the URL of that identity server as shown in the by the Matrix Identity Service API
examples below. [specification](https://matrix.org/docs/spec/identity_service/latest).)
Servers handling the these requests must answer the `/requestToken` endpoints defined *Updated in Synapse 1.64.0*: No longer accepts an `email` option.
by the Matrix Identity Service API [specification](https://matrix.org/docs/spec/identity_service/latest).
Example configuration: Example configuration:
```yaml ```yaml
account_threepid_delegates: account_threepid_delegates:
email: https://example.com # Delegate email sending to example.com
msisdn: http://localhost:8090 # Delegate SMS sending to this local process msisdn: http://localhost:8090 # Delegate SMS sending to this local process
``` ```
--- ---

View file

@ -44,7 +44,6 @@ from synapse.app._base import (
register_start, register_start,
) )
from synapse.config._base import ConfigError, format_config_error from synapse.config._base import ConfigError, format_config_error
from synapse.config.emailconfig import ThreepidBehaviour
from synapse.config.homeserver import HomeServerConfig from synapse.config.homeserver import HomeServerConfig
from synapse.config.server import ListenerConfig from synapse.config.server import ListenerConfig
from synapse.federation.transport.server import TransportLayerServer from synapse.federation.transport.server import TransportLayerServer
@ -202,7 +201,7 @@ class SynapseHomeServer(HomeServer):
} }
) )
if self.config.email.threepid_behaviour_email == ThreepidBehaviour.LOCAL: if self.config.email.can_verify_email:
from synapse.rest.synapse.client.password_reset import ( from synapse.rest.synapse.client.password_reset import (
PasswordResetSubmitTokenResource, PasswordResetSubmitTokenResource,
) )

View file

@ -18,7 +18,6 @@
import email.utils import email.utils
import logging import logging
import os import os
from enum import Enum
from typing import Any from typing import Any
import attr import attr
@ -131,41 +130,22 @@ class EmailConfig(Config):
self.email_enable_notifs = email_config.get("enable_notifs", False) self.email_enable_notifs = email_config.get("enable_notifs", False)
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.root.registration.account_threepid_delegate_email
else ThreepidBehaviour.LOCAL
)
if config.get("trust_identity_server_for_password_resets"): if config.get("trust_identity_server_for_password_resets"):
raise ConfigError( raise ConfigError(
'The config option "trust_identity_server_for_password_resets" ' 'The config option "trust_identity_server_for_password_resets" '
'has been replaced by "account_threepid_delegate". ' "is no longer supported. Please remove it from the config file."
"Please consult the configuration manual at docs/usage/configuration/config_documentation.md for "
"details and update your config file."
) )
self.local_threepid_handling_disabled_due_to_email_config = False # If we have email config settings, assume that we can verify ownership of
if ( # email addresses.
self.threepid_behaviour_email == ThreepidBehaviour.LOCAL self.can_verify_email = email_config != {}
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_email = ThreepidBehaviour.OFF
# Get lifetime of a validation token in milliseconds # Get lifetime of a validation token in milliseconds
self.email_validation_token_lifetime = self.parse_duration( self.email_validation_token_lifetime = self.parse_duration(
email_config.get("validation_token_lifetime", "1h") email_config.get("validation_token_lifetime", "1h")
) )
if self.threepid_behaviour_email == ThreepidBehaviour.LOCAL: if self.can_verify_email:
missing = [] missing = []
if not self.email_notif_from: if not self.email_notif_from:
missing.append("email.notif_from") missing.append("email.notif_from")
@ -356,18 +336,3 @@ class EmailConfig(Config):
"Config option email.invite_client_location must be a http or https URL", "Config option email.invite_client_location must be a http or https URL",
path=("email", "invite_client_location"), path=("email", "invite_client_location"),
) )
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"

View file

@ -20,6 +20,13 @@ from synapse.config._base import Config, ConfigError
from synapse.types import JsonDict, RoomAlias, UserID from synapse.types import JsonDict, RoomAlias, UserID
from synapse.util.stringutils import random_string_with_symbols, strtobool from synapse.util.stringutils import random_string_with_symbols, strtobool
NO_EMAIL_DELEGATE_ERROR = """\
Delegation of email verification to an identity server is no longer supported. To
continue to allow users to add email addresses to their accounts, and use them for
password resets, configure Synapse with an SMTP server via the `email` setting, and
remove `account_threepid_delegates.email`.
"""
class RegistrationConfig(Config): class RegistrationConfig(Config):
section = "registration" section = "registration"
@ -51,7 +58,9 @@ class RegistrationConfig(Config):
self.bcrypt_rounds = config.get("bcrypt_rounds", 12) self.bcrypt_rounds = config.get("bcrypt_rounds", 12)
account_threepid_delegates = config.get("account_threepid_delegates") or {} account_threepid_delegates = config.get("account_threepid_delegates") or {}
self.account_threepid_delegate_email = account_threepid_delegates.get("email") if "email" in account_threepid_delegates:
raise ConfigError(NO_EMAIL_DELEGATE_ERROR)
# self.account_threepid_delegate_email = account_threepid_delegates.get("email")
self.account_threepid_delegate_msisdn = account_threepid_delegates.get("msisdn") self.account_threepid_delegate_msisdn = account_threepid_delegates.get("msisdn")
self.default_identity_server = config.get("default_identity_server") self.default_identity_server = config.get("default_identity_server")
self.allow_guest_access = config.get("allow_guest_access", False) self.allow_guest_access = config.get("allow_guest_access", False)

View file

@ -26,7 +26,6 @@ from synapse.api.errors import (
SynapseError, SynapseError,
) )
from synapse.api.ratelimiting import Ratelimiter from synapse.api.ratelimiting import Ratelimiter
from synapse.config.emailconfig import ThreepidBehaviour
from synapse.http import RequestTimedOutError from synapse.http import RequestTimedOutError
from synapse.http.client import SimpleHttpClient from synapse.http.client import SimpleHttpClient
from synapse.http.site import SynapseRequest from synapse.http.site import SynapseRequest
@ -434,48 +433,6 @@ class IdentityHandler:
return session_id return session_id
async def requestEmailToken(
self,
id_server: str,
email: str,
client_secret: str,
send_attempt: int,
next_link: Optional[str] = None,
) -> JsonDict:
"""
Request an external server send an email on our behalf for the purposes of threepid
validation.
Args:
id_server: The identity server to proxy to
email: The email to send the message to
client_secret: The unique client_secret sends by the user
send_attempt: 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
try:
data = await self.http_client.post_json_get_json(
id_server + "/_matrix/identity/api/v1/validate/email/requestToken",
params,
)
return data
except HttpResponseException as e:
logger.info("Proxied requestToken failed: %r", e)
raise e.to_synapse_error()
except RequestTimedOutError:
raise SynapseError(500, "Timed out contacting identity server")
async def requestMsisdnToken( async def requestMsisdnToken(
self, self,
id_server: str, id_server: str,
@ -549,18 +506,7 @@ class IdentityHandler:
validation_session = None validation_session = None
# Try to validate as email # Try to validate as email
if self.hs.config.email.threepid_behaviour_email == ThreepidBehaviour.REMOTE: if self.hs.config.email.can_verify_email:
# Remote emails will only be used if a valid identity server is provided.
assert (
self.hs.config.registration.account_threepid_delegate_email is not None
)
# Ask our delegated email identity server
validation_session = await self.threepid_from_creds(
self.hs.config.registration.account_threepid_delegate_email,
threepid_creds,
)
elif self.hs.config.email.threepid_behaviour_email == ThreepidBehaviour.LOCAL:
# Get a validated session matching these details # Get a validated session matching these details
validation_session = await self.store.get_threepid_validation_session( validation_session = await self.store.get_threepid_validation_session(
"email", client_secret, sid=sid, validated=True "email", client_secret, sid=sid, validated=True

View file

@ -19,7 +19,6 @@ from twisted.web.client import PartialDownloadError
from synapse.api.constants import LoginType from synapse.api.constants import LoginType
from synapse.api.errors import Codes, LoginError, SynapseError from synapse.api.errors import Codes, LoginError, SynapseError
from synapse.config.emailconfig import ThreepidBehaviour
from synapse.util import json_decoder from synapse.util import json_decoder
if TYPE_CHECKING: if TYPE_CHECKING:
@ -153,7 +152,7 @@ class _BaseThreepidAuthChecker:
logger.info("Getting validated threepid. threepidcreds: %r", (threepid_creds,)) logger.info("Getting validated threepid. threepidcreds: %r", (threepid_creds,))
# msisdns are currently always ThreepidBehaviour.REMOTE # msisdns are currently always verified via the IS
if medium == "msisdn": if medium == "msisdn":
if not self.hs.config.registration.account_threepid_delegate_msisdn: if not self.hs.config.registration.account_threepid_delegate_msisdn:
raise SynapseError( raise SynapseError(
@ -164,18 +163,7 @@ class _BaseThreepidAuthChecker:
threepid_creds, threepid_creds,
) )
elif medium == "email": elif medium == "email":
if ( if self.hs.config.email.can_verify_email:
self.hs.config.email.threepid_behaviour_email
== ThreepidBehaviour.REMOTE
):
assert self.hs.config.registration.account_threepid_delegate_email
threepid = await identity_handler.threepid_from_creds(
self.hs.config.registration.account_threepid_delegate_email,
threepid_creds,
)
elif (
self.hs.config.email.threepid_behaviour_email == ThreepidBehaviour.LOCAL
):
threepid = None threepid = None
row = await self.store.get_threepid_validation_session( row = await self.store.get_threepid_validation_session(
medium, medium,
@ -227,10 +215,7 @@ class EmailIdentityAuthChecker(UserInteractiveAuthChecker, _BaseThreepidAuthChec
_BaseThreepidAuthChecker.__init__(self, hs) _BaseThreepidAuthChecker.__init__(self, hs)
def is_enabled(self) -> bool: def is_enabled(self) -> bool:
return self.hs.config.email.threepid_behaviour_email in ( return self.hs.config.email.can_verify_email
ThreepidBehaviour.REMOTE,
ThreepidBehaviour.LOCAL,
)
async def check_auth(self, authdict: dict, clientip: str) -> Any: async def check_auth(self, authdict: dict, clientip: str) -> Any:
return await self._check_threepid("email", authdict) return await self._check_threepid("email", authdict)

View file

@ -28,7 +28,6 @@ from synapse.api.errors import (
SynapseError, SynapseError,
ThreepidValidationError, ThreepidValidationError,
) )
from synapse.config.emailconfig import ThreepidBehaviour
from synapse.handlers.ui_auth import UIAuthSessionDataConstants from synapse.handlers.ui_auth import UIAuthSessionDataConstants
from synapse.http.server import HttpServer, finish_request, respond_with_html from synapse.http.server import HttpServer, finish_request, respond_with_html
from synapse.http.servlet import ( from synapse.http.servlet import (
@ -64,7 +63,7 @@ class EmailPasswordRequestTokenRestServlet(RestServlet):
self.config = hs.config self.config = hs.config
self.identity_handler = hs.get_identity_handler() self.identity_handler = hs.get_identity_handler()
if self.config.email.threepid_behaviour_email == ThreepidBehaviour.LOCAL: if self.config.email.can_verify_email:
self.mailer = Mailer( self.mailer = Mailer(
hs=self.hs, hs=self.hs,
app_name=self.config.email.email_app_name, app_name=self.config.email.email_app_name,
@ -73,11 +72,10 @@ class EmailPasswordRequestTokenRestServlet(RestServlet):
) )
async def on_POST(self, request: SynapseRequest) -> Tuple[int, JsonDict]: async def on_POST(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
if self.config.email.threepid_behaviour_email == ThreepidBehaviour.OFF: if not self.config.email.can_verify_email:
if self.config.email.local_threepid_handling_disabled_due_to_email_config: logger.warning(
logger.warning( "User password resets have been disabled due to lack of email config"
"User password resets have been disabled due to lack of email config" )
)
raise SynapseError( raise SynapseError(
400, "Email-based password resets have been disabled on this server" 400, "Email-based password resets have been disabled on this server"
) )
@ -129,35 +127,21 @@ class EmailPasswordRequestTokenRestServlet(RestServlet):
raise SynapseError(400, "Email not found", Codes.THREEPID_NOT_FOUND) raise SynapseError(400, "Email not found", Codes.THREEPID_NOT_FOUND)
if self.config.email.threepid_behaviour_email == ThreepidBehaviour.REMOTE: # Send password reset emails from Synapse
assert self.hs.config.registration.account_threepid_delegate_email sid = await self.identity_handler.send_threepid_validation(
email,
# Have the configured identity server handle the request client_secret,
ret = await self.identity_handler.requestEmailToken( send_attempt,
self.hs.config.registration.account_threepid_delegate_email, self.mailer.send_password_reset_mail,
email, next_link,
client_secret, )
send_attempt,
next_link,
)
else:
# Send password reset emails from Synapse
sid = await self.identity_handler.send_threepid_validation(
email,
client_secret,
send_attempt,
self.mailer.send_password_reset_mail,
next_link,
)
# Wrap the session id in a JSON object
ret = {"sid": sid}
threepid_send_requests.labels(type="email", reason="password_reset").observe( threepid_send_requests.labels(type="email", reason="password_reset").observe(
send_attempt send_attempt
) )
return 200, ret # Wrap the session id in a JSON object
return 200, {"sid": sid}
class PasswordRestServlet(RestServlet): class PasswordRestServlet(RestServlet):
@ -349,7 +333,7 @@ class EmailThreepidRequestTokenRestServlet(RestServlet):
self.identity_handler = hs.get_identity_handler() self.identity_handler = hs.get_identity_handler()
self.store = self.hs.get_datastores().main self.store = self.hs.get_datastores().main
if self.config.email.threepid_behaviour_email == ThreepidBehaviour.LOCAL: if self.config.email.can_verify_email:
self.mailer = Mailer( self.mailer = Mailer(
hs=self.hs, hs=self.hs,
app_name=self.config.email.email_app_name, app_name=self.config.email.email_app_name,
@ -358,11 +342,10 @@ class EmailThreepidRequestTokenRestServlet(RestServlet):
) )
async def on_POST(self, request: SynapseRequest) -> Tuple[int, JsonDict]: async def on_POST(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
if self.config.email.threepid_behaviour_email == ThreepidBehaviour.OFF: if not self.config.email.can_verify_email:
if self.config.email.local_threepid_handling_disabled_due_to_email_config: logger.warning(
logger.warning( "Adding emails have been disabled due to lack of an email config"
"Adding emails have been disabled due to lack of an email config" )
)
raise SynapseError( raise SynapseError(
400, "Adding an email to your account is disabled on this server" 400, "Adding an email to your account is disabled on this server"
) )
@ -413,35 +396,20 @@ class EmailThreepidRequestTokenRestServlet(RestServlet):
raise SynapseError(400, "Email is already in use", Codes.THREEPID_IN_USE) raise SynapseError(400, "Email is already in use", Codes.THREEPID_IN_USE)
if self.config.email.threepid_behaviour_email == ThreepidBehaviour.REMOTE: sid = await self.identity_handler.send_threepid_validation(
assert self.hs.config.registration.account_threepid_delegate_email email,
client_secret,
# Have the configured identity server handle the request send_attempt,
ret = await self.identity_handler.requestEmailToken( self.mailer.send_add_threepid_mail,
self.hs.config.registration.account_threepid_delegate_email, next_link,
email, )
client_secret,
send_attempt,
next_link,
)
else:
# Send threepid validation emails from Synapse
sid = await self.identity_handler.send_threepid_validation(
email,
client_secret,
send_attempt,
self.mailer.send_add_threepid_mail,
next_link,
)
# Wrap the session id in a JSON object
ret = {"sid": sid}
threepid_send_requests.labels(type="email", reason="add_threepid").observe( threepid_send_requests.labels(type="email", reason="add_threepid").observe(
send_attempt send_attempt
) )
return 200, ret # Wrap the session id in a JSON object
return 200, {"sid": sid}
class MsisdnThreepidRequestTokenRestServlet(RestServlet): class MsisdnThreepidRequestTokenRestServlet(RestServlet):
@ -534,26 +502,19 @@ class AddThreepidEmailSubmitTokenServlet(RestServlet):
self.config = hs.config self.config = hs.config
self.clock = hs.get_clock() self.clock = hs.get_clock()
self.store = hs.get_datastores().main self.store = hs.get_datastores().main
if self.config.email.threepid_behaviour_email == ThreepidBehaviour.LOCAL: if self.config.email.can_verify_email:
self._failure_email_template = ( self._failure_email_template = (
self.config.email.email_add_threepid_template_failure_html self.config.email.email_add_threepid_template_failure_html
) )
async def on_GET(self, request: Request) -> None: async def on_GET(self, request: Request) -> None:
if self.config.email.threepid_behaviour_email == ThreepidBehaviour.OFF: if not self.config.email.can_verify_email:
if self.config.email.local_threepid_handling_disabled_due_to_email_config: logger.warning(
logger.warning( "Adding emails have been disabled due to lack of an email config"
"Adding emails have been disabled due to lack of an email config" )
)
raise SynapseError( raise SynapseError(
400, "Adding an email to your account is disabled on this server" 400, "Adding an email to your account is disabled on this server"
) )
elif self.config.email.threepid_behaviour_email == ThreepidBehaviour.REMOTE:
raise SynapseError(
400,
"This homeserver is not validating threepids. Use an identity server "
"instead.",
)
sid = parse_string(request, "sid", required=True) sid = parse_string(request, "sid", required=True)
token = parse_string(request, "token", required=True) token = parse_string(request, "token", required=True)

View file

@ -31,7 +31,6 @@ from synapse.api.errors import (
) )
from synapse.api.ratelimiting import Ratelimiter from synapse.api.ratelimiting import Ratelimiter
from synapse.config import ConfigError from synapse.config import ConfigError
from synapse.config.emailconfig import ThreepidBehaviour
from synapse.config.homeserver import HomeServerConfig from synapse.config.homeserver import HomeServerConfig
from synapse.config.ratelimiting import FederationRateLimitConfig from synapse.config.ratelimiting import FederationRateLimitConfig
from synapse.config.server import is_threepid_reserved from synapse.config.server import is_threepid_reserved
@ -74,7 +73,7 @@ class EmailRegisterRequestTokenRestServlet(RestServlet):
self.identity_handler = hs.get_identity_handler() self.identity_handler = hs.get_identity_handler()
self.config = hs.config self.config = hs.config
if self.hs.config.email.threepid_behaviour_email == ThreepidBehaviour.LOCAL: if self.hs.config.email.can_verify_email:
self.mailer = Mailer( self.mailer = Mailer(
hs=self.hs, hs=self.hs,
app_name=self.config.email.email_app_name, app_name=self.config.email.email_app_name,
@ -83,13 +82,10 @@ class EmailRegisterRequestTokenRestServlet(RestServlet):
) )
async def on_POST(self, request: SynapseRequest) -> Tuple[int, JsonDict]: async def on_POST(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
if self.hs.config.email.threepid_behaviour_email == ThreepidBehaviour.OFF: if not self.hs.config.email.can_verify_email:
if ( logger.warning(
self.hs.config.email.local_threepid_handling_disabled_due_to_email_config "Email registration has been disabled due to lack of email config"
): )
logger.warning(
"Email registration has been disabled due to lack of email config"
)
raise SynapseError( raise SynapseError(
400, "Email-based registration has been disabled on this server" 400, "Email-based registration has been disabled on this server"
) )
@ -138,35 +134,21 @@ class EmailRegisterRequestTokenRestServlet(RestServlet):
raise SynapseError(400, "Email is already in use", Codes.THREEPID_IN_USE) raise SynapseError(400, "Email is already in use", Codes.THREEPID_IN_USE)
if self.config.email.threepid_behaviour_email == ThreepidBehaviour.REMOTE: # Send registration emails from Synapse
assert self.hs.config.registration.account_threepid_delegate_email sid = await self.identity_handler.send_threepid_validation(
email,
# Have the configured identity server handle the request client_secret,
ret = await self.identity_handler.requestEmailToken( send_attempt,
self.hs.config.registration.account_threepid_delegate_email, self.mailer.send_registration_mail,
email, next_link,
client_secret, )
send_attempt,
next_link,
)
else:
# Send registration emails from Synapse
sid = await self.identity_handler.send_threepid_validation(
email,
client_secret,
send_attempt,
self.mailer.send_registration_mail,
next_link,
)
# Wrap the session id in a JSON object
ret = {"sid": sid}
threepid_send_requests.labels(type="email", reason="register").observe( threepid_send_requests.labels(type="email", reason="register").observe(
send_attempt send_attempt
) )
return 200, ret # Wrap the session id in a JSON object
return 200, {"sid": sid}
class MsisdnRegisterRequestTokenRestServlet(RestServlet): class MsisdnRegisterRequestTokenRestServlet(RestServlet):
@ -260,7 +242,7 @@ class RegistrationSubmitTokenServlet(RestServlet):
self.clock = hs.get_clock() self.clock = hs.get_clock()
self.store = hs.get_datastores().main self.store = hs.get_datastores().main
if self.config.email.threepid_behaviour_email == ThreepidBehaviour.LOCAL: if self.config.email.can_verify_email:
self._failure_email_template = ( self._failure_email_template = (
self.config.email.email_registration_template_failure_html self.config.email.email_registration_template_failure_html
) )
@ -270,11 +252,10 @@ class RegistrationSubmitTokenServlet(RestServlet):
raise SynapseError( raise SynapseError(
400, "This medium is currently not supported for registration" 400, "This medium is currently not supported for registration"
) )
if self.config.email.threepid_behaviour_email == ThreepidBehaviour.OFF: if not self.config.email.can_verify_email:
if self.config.email.local_threepid_handling_disabled_due_to_email_config: logger.warning(
logger.warning( "User registration via email has been disabled due to lack of email config"
"User registration via email has been disabled due to lack of email config" )
)
raise SynapseError( raise SynapseError(
400, "Email-based registration is disabled on this server" 400, "Email-based registration is disabled on this server"
) )

View file

@ -17,7 +17,6 @@ from typing import TYPE_CHECKING, Tuple
from twisted.web.server import Request from twisted.web.server import Request
from synapse.api.errors import ThreepidValidationError from synapse.api.errors import ThreepidValidationError
from synapse.config.emailconfig import ThreepidBehaviour
from synapse.http.server import DirectServeHtmlResource from synapse.http.server import DirectServeHtmlResource
from synapse.http.servlet import parse_string from synapse.http.servlet import parse_string
from synapse.util.stringutils import assert_valid_client_secret from synapse.util.stringutils import assert_valid_client_secret
@ -46,9 +45,6 @@ class PasswordResetSubmitTokenResource(DirectServeHtmlResource):
self.clock = hs.get_clock() self.clock = hs.get_clock()
self.store = hs.get_datastores().main self.store = hs.get_datastores().main
self._local_threepid_handling_disabled_due_to_email_config = (
hs.config.email.local_threepid_handling_disabled_due_to_email_config
)
self._confirmation_email_template = ( self._confirmation_email_template = (
hs.config.email.email_password_reset_template_confirmation_html hs.config.email.email_password_reset_template_confirmation_html
) )
@ -59,8 +55,8 @@ class PasswordResetSubmitTokenResource(DirectServeHtmlResource):
hs.config.email.email_password_reset_template_failure_html hs.config.email.email_password_reset_template_failure_html
) )
# This resource should not be mounted if threepid behaviour is not LOCAL # This resource should only be mounted if email validation is enabled
assert hs.config.email.threepid_behaviour_email == ThreepidBehaviour.LOCAL assert hs.config.email.can_verify_email
async def _async_render_GET(self, request: Request) -> Tuple[int, bytes]: async def _async_render_GET(self, request: Request) -> Tuple[int, bytes]:
sid = parse_string(request, "sid", required=True) sid = parse_string(request, "sid", required=True)

View file

@ -592,9 +592,9 @@ class RegisterRestServletTestCase(unittest.HomeserverTestCase):
"require_at_registration": True, "require_at_registration": True,
}, },
"account_threepid_delegates": { "account_threepid_delegates": {
"email": "https://id_server",
"msisdn": "https://id_server", "msisdn": "https://id_server",
}, },
"email": {"notif_from": "Synapse <synapse@example.com>"},
} }
) )
def test_advertised_flows_captcha_and_terms_and_3pids(self) -> None: def test_advertised_flows_captcha_and_terms_and_3pids(self) -> None: