Skip to content

Commit c7f247a

Browse files
author
3np
committed
Revert "Drop support for delegating email validation (matrix-org#13192)"
This reverts commit fa71bb1.
1 parent 33788a0 commit c7f247a

File tree

11 files changed

+251
-102
lines changed

11 files changed

+251
-102
lines changed

docs/upgrade.md

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -91,19 +91,6 @@ process, for example:
9191
9292
# Upgrading to v1.64.0
9393
94-
## Delegation of email validation no longer supported
95-
96-
As of this version, Synapse no longer allows the tasks of verifying email address
97-
ownership, and password reset confirmation, to be delegated to an identity server.
98-
99-
To continue to allow users to add email addresses to their homeserver accounts,
100-
and perform password resets, make sure that Synapse is configured with a
101-
working email server in the `email` configuration section (including, at a
102-
minimum, a `notif_from` setting.)
103-
104-
Specifying an `email` setting under `account_threepid_delegates` will now cause
105-
an error at startup.
106-
10794
## Changes to the event replication streams
10895
10996
Synapse now includes a flag indicating if an event is an outlier when

docs/usage/configuration/config_documentation.md

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2200,26 +2200,30 @@ default_identity_server: https://matrix.org
22002200
---
22012201
### `account_threepid_delegates`
22022202

2203-
Delegate verification of phone numbers to an identity server.
2203+
Handle threepid (email/phone etc) registration and password resets through a set of
2204+
*trusted* identity servers. Note that this allows the configured identity server to
2205+
reset passwords for accounts!
22042206

2205-
When a user wishes to add a phone number to their account, we need to verify that they
2206-
actually own that phone number, which requires sending them a text message (SMS).
2207-
Currently Synapse does not support sending those texts itself and instead delegates the
2208-
task to an identity server. The base URI for the identity server to be used is
2209-
specified by the `account_threepid_delegates.msisdn` option.
2207+
Be aware that if `email` is not set, and SMTP options have not been
2208+
configured in the email config block, registration and user password resets via
2209+
email will be globally disabled.
22102210

2211-
If this is left unspecified, Synapse will not allow users to add phone numbers to
2212-
their account.
2211+
Additionally, if `msisdn` is not set, registration and password resets via msisdn
2212+
will be disabled regardless, and users will not be able to associate an msisdn
2213+
identifier to their account. This is due to Synapse currently not supporting
2214+
any method of sending SMS messages on its own.
22132215

2214-
(Servers handling the these requests must answer the `/requestToken` endpoints defined
2215-
by the Matrix Identity Service API
2216-
[specification](https://matrix.org/docs/spec/identity_service/latest).)
2216+
To enable using an identity server for operations regarding a particular third-party
2217+
identifier type, set the value to the URL of that identity server as shown in the
2218+
examples below.
22172219

2218-
*Updated in Synapse 1.64.0*: No longer accepts an `email` option.
2220+
Servers handling the these requests must answer the `/requestToken` endpoints defined
2221+
by the Matrix Identity Service API [specification](https://matrix.org/docs/spec/identity_service/latest).
22192222

22202223
Example configuration:
22212224
```yaml
22222225
account_threepid_delegates:
2226+
email: https://example.com # Delegate email sending to example.com
22232227
msisdn: http://localhost:8090 # Delegate SMS sending to this local process
22242228
```
22252229
---

synapse/app/homeserver.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
register_start,
4545
)
4646
from synapse.config._base import ConfigError, format_config_error
47+
from synapse.config.emailconfig import ThreepidBehaviour
4748
from synapse.config.homeserver import HomeServerConfig
4849
from synapse.config.server import ListenerConfig
4950
from synapse.federation.transport.server import TransportLayerServer
@@ -201,7 +202,7 @@ def _configure_named_resource(
201202
}
202203
)
203204

204-
if self.config.email.can_verify_email:
205+
if self.config.email.threepid_behaviour_email == ThreepidBehaviour.LOCAL:
205206
from synapse.rest.synapse.client.password_reset import (
206207
PasswordResetSubmitTokenResource,
207208
)

synapse/config/emailconfig.py

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import email.utils
1919
import logging
2020
import os
21+
from enum import Enum
2122
from typing import Any
2223

2324
import attr
@@ -135,22 +136,41 @@ def read_config(self, config: JsonDict, **kwargs: Any) -> None:
135136

136137
self.email_enable_notifs = email_config.get("enable_notifs", False)
137138

139+
self.threepid_behaviour_email = (
140+
# Have Synapse handle the email sending if account_threepid_delegates.email
141+
# is not defined
142+
# msisdn is currently always remote while Synapse does not support any method of
143+
# sending SMS messages
144+
ThreepidBehaviour.REMOTE
145+
if self.root.registration.account_threepid_delegate_email
146+
else ThreepidBehaviour.LOCAL
147+
)
148+
138149
if config.get("trust_identity_server_for_password_resets"):
139150
raise ConfigError(
140151
'The config option "trust_identity_server_for_password_resets" '
141-
"is no longer supported. Please remove it from the config file."
152+
'has been replaced by "account_threepid_delegate". '
153+
"Please consult the configuration manual at docs/usage/configuration/config_documentation.md for "
154+
"details and update your config file."
142155
)
143156

144-
# If we have email config settings, assume that we can verify ownership of
145-
# email addresses.
146-
self.can_verify_email = email_config != {}
157+
self.local_threepid_handling_disabled_due_to_email_config = False
158+
if (
159+
self.threepid_behaviour_email == ThreepidBehaviour.LOCAL
160+
and email_config == {}
161+
):
162+
# We cannot warn the user this has happened here
163+
# Instead do so when a user attempts to reset their password
164+
self.local_threepid_handling_disabled_due_to_email_config = True
165+
166+
self.threepid_behaviour_email = ThreepidBehaviour.OFF
147167

148168
# Get lifetime of a validation token in milliseconds
149169
self.email_validation_token_lifetime = self.parse_duration(
150170
email_config.get("validation_token_lifetime", "1h")
151171
)
152172

153-
if self.can_verify_email:
173+
if self.threepid_behaviour_email == ThreepidBehaviour.LOCAL:
154174
missing = []
155175
if not self.email_notif_from:
156176
missing.append("email.notif_from")
@@ -341,3 +361,18 @@ def read_config(self, config: JsonDict, **kwargs: Any) -> None:
341361
"Config option email.invite_client_location must be a http or https URL",
342362
path=("email", "invite_client_location"),
343363
)
364+
365+
366+
class ThreepidBehaviour(Enum):
367+
"""
368+
Enum to define the behaviour of Synapse with regards to when it contacts an identity
369+
server for 3pid registration and password resets
370+
371+
REMOTE = use an external server to send tokens
372+
LOCAL = send tokens ourselves
373+
OFF = disable registration via 3pid and password resets
374+
"""
375+
376+
REMOTE = "remote"
377+
LOCAL = "local"
378+
OFF = "off"

synapse/config/registration.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,6 @@
2020
from synapse.types import JsonDict, RoomAlias, UserID
2121
from synapse.util.stringutils import random_string_with_symbols, strtobool
2222

23-
NO_EMAIL_DELEGATE_ERROR = """\
24-
Delegation of email verification to an identity server is no longer supported. To
25-
continue to allow users to add email addresses to their accounts, and use them for
26-
password resets, configure Synapse with an SMTP server via the `email` setting, and
27-
remove `account_threepid_delegates.email`.
28-
"""
29-
3023

3124
class RegistrationConfig(Config):
3225
section = "registration"
@@ -58,9 +51,7 @@ def read_config(self, config: JsonDict, **kwargs: Any) -> None:
5851
self.bcrypt_rounds = config.get("bcrypt_rounds", 12)
5952

6053
account_threepid_delegates = config.get("account_threepid_delegates") or {}
61-
if "email" in account_threepid_delegates:
62-
raise ConfigError(NO_EMAIL_DELEGATE_ERROR)
63-
# self.account_threepid_delegate_email = account_threepid_delegates.get("email")
54+
self.account_threepid_delegate_email = account_threepid_delegates.get("email")
6455
self.account_threepid_delegate_msisdn = account_threepid_delegates.get("msisdn")
6556
self.default_identity_server = config.get("default_identity_server")
6657
self.allow_guest_access = config.get("allow_guest_access", False)

synapse/handlers/identity.py

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
SynapseError,
2727
)
2828
from synapse.api.ratelimiting import Ratelimiter
29+
from synapse.config.emailconfig import ThreepidBehaviour
2930
from synapse.http import RequestTimedOutError
3031
from synapse.http.client import SimpleHttpClient
3132
from synapse.http.site import SynapseRequest
@@ -415,6 +416,48 @@ async def send_threepid_validation(
415416

416417
return session_id
417418

419+
async def requestEmailToken(
420+
self,
421+
id_server: str,
422+
email: str,
423+
client_secret: str,
424+
send_attempt: int,
425+
next_link: Optional[str] = None,
426+
) -> JsonDict:
427+
"""
428+
Request an external server send an email on our behalf for the purposes of threepid
429+
validation.
430+
431+
Args:
432+
id_server: The identity server to proxy to
433+
email: The email to send the message to
434+
client_secret: The unique client_secret sends by the user
435+
send_attempt: Which attempt this is
436+
next_link: A link to redirect the user to once they submit the token
437+
438+
Returns:
439+
The json response body from the server
440+
"""
441+
params = {
442+
"email": email,
443+
"client_secret": client_secret,
444+
"send_attempt": send_attempt,
445+
}
446+
if next_link:
447+
params["next_link"] = next_link
448+
449+
try:
450+
data = await self.http_client.post_json_get_json(
451+
id_server + "/_matrix/identity/api/v1/validate/email/requestToken",
452+
params,
453+
)
454+
return data
455+
except HttpResponseException as e:
456+
logger.info("Proxied requestToken failed: %r", e)
457+
raise e.to_synapse_error()
458+
except RequestTimedOutError:
459+
raise SynapseError(500, "Timed out contacting identity server")
460+
418461
async def requestMsisdnToken(
419462
self,
420463
id_server: str,
@@ -488,7 +531,18 @@ async def validate_threepid_session(
488531
validation_session = None
489532

490533
# Try to validate as email
491-
if self.hs.config.email.can_verify_email:
534+
if self.hs.config.email.threepid_behaviour_email == ThreepidBehaviour.REMOTE:
535+
# Remote emails will only be used if a valid identity server is provided.
536+
assert (
537+
self.hs.config.registration.account_threepid_delegate_email is not None
538+
)
539+
540+
# Ask our delegated email identity server
541+
validation_session = await self.threepid_from_creds(
542+
self.hs.config.registration.account_threepid_delegate_email,
543+
threepid_creds,
544+
)
545+
elif self.hs.config.email.threepid_behaviour_email == ThreepidBehaviour.LOCAL:
492546
# Get a validated session matching these details
493547
validation_session = await self.store.get_threepid_validation_session(
494548
"email", client_secret, sid=sid, validated=True

synapse/handlers/ui_auth/checkers.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
from synapse.api.constants import LoginType
2121
from synapse.api.errors import Codes, LoginError, SynapseError
22+
from synapse.config.emailconfig import ThreepidBehaviour
2223
from synapse.util import json_decoder
2324

2425
if TYPE_CHECKING:
@@ -152,7 +153,7 @@ async def _check_threepid(self, medium: str, authdict: dict) -> dict:
152153

153154
logger.info("Getting validated threepid. threepidcreds: %r", (threepid_creds,))
154155

155-
# msisdns are currently always verified via the IS
156+
# msisdns are currently always ThreepidBehaviour.REMOTE
156157
if medium == "msisdn":
157158
if not self.hs.config.registration.account_threepid_delegate_msisdn:
158159
raise SynapseError(
@@ -163,7 +164,18 @@ async def _check_threepid(self, medium: str, authdict: dict) -> dict:
163164
threepid_creds,
164165
)
165166
elif medium == "email":
166-
if self.hs.config.email.can_verify_email:
167+
if (
168+
self.hs.config.email.threepid_behaviour_email
169+
== ThreepidBehaviour.REMOTE
170+
):
171+
assert self.hs.config.registration.account_threepid_delegate_email
172+
threepid = await identity_handler.threepid_from_creds(
173+
self.hs.config.registration.account_threepid_delegate_email,
174+
threepid_creds,
175+
)
176+
elif (
177+
self.hs.config.email.threepid_behaviour_email == ThreepidBehaviour.LOCAL
178+
):
167179
threepid = None
168180
row = await self.store.get_threepid_validation_session(
169181
medium,
@@ -215,7 +227,10 @@ def __init__(self, hs: "HomeServer"):
215227
_BaseThreepidAuthChecker.__init__(self, hs)
216228

217229
def is_enabled(self) -> bool:
218-
return self.hs.config.email.can_verify_email
230+
return self.hs.config.email.threepid_behaviour_email in (
231+
ThreepidBehaviour.REMOTE,
232+
ThreepidBehaviour.LOCAL,
233+
)
219234

220235
async def check_auth(self, authdict: dict, clientip: str) -> Any:
221236
return await self._check_threepid("email", authdict)

0 commit comments

Comments
 (0)