diff --git a/synapse/handlers/identity.py b/synapse/handlers/identity.py
index 9571d461c8..e5afe84df9 100644
--- a/synapse/handlers/identity.py
+++ b/synapse/handlers/identity.py
@@ -26,6 +26,7 @@ from synapse.api.errors import (
SynapseError,
)
from synapse.api.ratelimiting import Ratelimiter
+from synapse.config.emailconfig import ThreepidBehaviour
from synapse.http import RequestTimedOutError
from synapse.http.client import SimpleHttpClient
from synapse.http.site import SynapseRequest
@@ -415,6 +416,48 @@ class IdentityHandler:
return session_id
+ async def request_email_token(
+ 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(
self,
id_server: str,
@@ -488,7 +531,18 @@ class IdentityHandler:
validation_session = None
# Try to validate as email
- if self.hs.config.email.can_verify_email:
+ if self.hs.config.email.threepid_behaviour_email == ThreepidBehaviour.REMOTE:
+ # 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
validation_session = await self.store.get_threepid_validation_session(
"email", client_secret, sid=sid, validated=True
diff --git a/synapse/handlers/ui_auth/checkers.py b/synapse/handlers/ui_auth/checkers.py
index a744d68c64..05cebb5d4d 100644
--- a/synapse/handlers/ui_auth/checkers.py
+++ b/synapse/handlers/ui_auth/checkers.py
@@ -19,6 +19,7 @@ from twisted.web.client import PartialDownloadError
from synapse.api.constants import LoginType
from synapse.api.errors import Codes, LoginError, SynapseError
+from synapse.config.emailconfig import ThreepidBehaviour
from synapse.util import json_decoder
if TYPE_CHECKING:
@@ -152,7 +153,7 @@ class _BaseThreepidAuthChecker:
logger.info("Getting validated threepid. threepidcreds: %r", (threepid_creds,))
- # msisdns are currently always verified via the IS
+ # msisdns are currently always ThreepidBehaviour.REMOTE
if medium == "msisdn":
if not self.hs.config.registration.account_threepid_delegate_msisdn:
raise SynapseError(
@@ -163,7 +164,18 @@ class _BaseThreepidAuthChecker:
threepid_creds,
)
elif medium == "email":
- if self.hs.config.email.can_verify_email:
+ if (
+ 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
row = await self.store.get_threepid_validation_session(
medium,
@@ -215,7 +227,10 @@ class EmailIdentityAuthChecker(UserInteractiveAuthChecker, _BaseThreepidAuthChec
_BaseThreepidAuthChecker.__init__(self, hs)
def is_enabled(self) -> bool:
- return self.hs.config.email.can_verify_email
+ return self.hs.config.email.threepid_behaviour_email in (
+ ThreepidBehaviour.REMOTE,
+ ThreepidBehaviour.LOCAL,
+ )
async def check_auth(self, authdict: dict, clientip: str) -> Any:
return await self._check_threepid("email", authdict)
|