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:
parent
3f178332d6
commit
fa71bb18b5
|
@ -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)
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Drop support for delegating email verification to an external server.
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
```
|
```
|
||||||
---
|
---
|
||||||
|
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
|
@ -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"
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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,8 +72,7 @@ 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"
|
||||||
)
|
)
|
||||||
|
@ -129,18 +127,6 @@ 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:
|
|
||||||
assert self.hs.config.registration.account_threepid_delegate_email
|
|
||||||
|
|
||||||
# Have the configured identity server handle the request
|
|
||||||
ret = await self.identity_handler.requestEmailToken(
|
|
||||||
self.hs.config.registration.account_threepid_delegate_email,
|
|
||||||
email,
|
|
||||||
client_secret,
|
|
||||||
send_attempt,
|
|
||||||
next_link,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
# Send password reset emails from Synapse
|
# Send password reset emails from Synapse
|
||||||
sid = await self.identity_handler.send_threepid_validation(
|
sid = await self.identity_handler.send_threepid_validation(
|
||||||
email,
|
email,
|
||||||
|
@ -150,14 +136,12 @@ class EmailPasswordRequestTokenRestServlet(RestServlet):
|
||||||
next_link,
|
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,8 +342,7 @@ 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"
|
||||||
)
|
)
|
||||||
|
@ -413,19 +396,6 @@ 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:
|
|
||||||
assert self.hs.config.registration.account_threepid_delegate_email
|
|
||||||
|
|
||||||
# Have the configured identity server handle the request
|
|
||||||
ret = await self.identity_handler.requestEmailToken(
|
|
||||||
self.hs.config.registration.account_threepid_delegate_email,
|
|
||||||
email,
|
|
||||||
client_secret,
|
|
||||||
send_attempt,
|
|
||||||
next_link,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
# Send threepid validation emails from Synapse
|
|
||||||
sid = await self.identity_handler.send_threepid_validation(
|
sid = await self.identity_handler.send_threepid_validation(
|
||||||
email,
|
email,
|
||||||
client_secret,
|
client_secret,
|
||||||
|
@ -434,14 +404,12 @@ class EmailThreepidRequestTokenRestServlet(RestServlet):
|
||||||
next_link,
|
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)
|
||||||
|
|
|
@ -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,10 +82,7 @@ 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 (
|
|
||||||
self.hs.config.email.local_threepid_handling_disabled_due_to_email_config
|
|
||||||
):
|
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Email registration has been disabled due to lack of email config"
|
"Email registration has been disabled due to lack of email config"
|
||||||
)
|
)
|
||||||
|
@ -138,18 +134,6 @@ 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:
|
|
||||||
assert self.hs.config.registration.account_threepid_delegate_email
|
|
||||||
|
|
||||||
# Have the configured identity server handle the request
|
|
||||||
ret = await self.identity_handler.requestEmailToken(
|
|
||||||
self.hs.config.registration.account_threepid_delegate_email,
|
|
||||||
email,
|
|
||||||
client_secret,
|
|
||||||
send_attempt,
|
|
||||||
next_link,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
# Send registration emails from Synapse
|
# Send registration emails from Synapse
|
||||||
sid = await self.identity_handler.send_threepid_validation(
|
sid = await self.identity_handler.send_threepid_validation(
|
||||||
email,
|
email,
|
||||||
|
@ -159,14 +143,12 @@ class EmailRegisterRequestTokenRestServlet(RestServlet):
|
||||||
next_link,
|
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,8 +252,7 @@ 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"
|
||||||
)
|
)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue