diff --git a/synapse/api/constants.py b/synapse/api/constants.py index 46013cde15a4..28f8285da959 100644 --- a/synapse/api/constants.py +++ b/synapse/api/constants.py @@ -57,6 +57,7 @@ class JoinRules: class LoginType: PASSWORD = "m.login.password" + APPSERVICE = "uk.half-shot.unstable.login.appservice" EMAIL_IDENTITY = "m.login.email.identity" MSISDN = "m.login.msisdn" RECAPTCHA = "m.login.recaptcha" diff --git a/synapse/rest/client/v1/login.py b/synapse/rest/client/v1/login.py index a14618ac84fb..e8b5fc9a4ed6 100644 --- a/synapse/rest/client/v1/login.py +++ b/synapse/rest/client/v1/login.py @@ -16,8 +16,10 @@ import logging from typing import Awaitable, Callable, Dict, Optional +from synapse.api.constants import LoginType from synapse.api.errors import Codes, LoginError, SynapseError from synapse.api.ratelimiting import Ratelimiter +from synapse.appservice import ApplicationService from synapse.handlers.auth import ( convert_client_dict_legacy_fields_to_identifier, login_id_phone_to_thirdparty, @@ -61,6 +63,8 @@ def __init__(self, hs): self.cas_enabled = hs.config.cas_enabled self.oidc_enabled = hs.config.oidc_enabled + self.auth = hs.get_auth() + self.auth_handler = self.hs.get_auth_handler() self.registration_handler = hs.get_registration_handler() self.handlers = hs.get_handlers() @@ -116,6 +120,11 @@ async def on_POST(self, request: SynapseRequest): self._address_ratelimiter.ratelimit(request.getClientIP()) login_submission = parse_json_object_from_request(request) + + appservice = None + if self.auth.has_access_token(request): + appservice = self.auth.get_appservice_by_req(request) + try: if self.jwt_enabled and ( login_submission["type"] == LoginRestServlet.JWT_TYPE @@ -125,7 +134,7 @@ async def on_POST(self, request: SynapseRequest): elif login_submission["type"] == LoginRestServlet.TOKEN_TYPE: result = await self._do_token_login(login_submission) else: - result = await self._do_other_login(login_submission) + result = await self._do_other_login(login_submission, appservice) except KeyError: raise SynapseError(400, "Missing JSON keys.") @@ -134,7 +143,9 @@ async def on_POST(self, request: SynapseRequest): result["well_known"] = well_known_data return 200, result - async def _do_other_login(self, login_submission: JsonDict) -> Dict[str, str]: + async def _do_other_login( + self, login_submission: JsonDict, appservice: ApplicationService + ) -> Dict[str, str]: """Handle non-token/saml/jwt logins Args: @@ -229,6 +240,10 @@ async def _do_other_login(self, login_submission: JsonDict) -> Dict[str, str]: else: qualified_user_id = UserID(identifier["user"], self.hs.hostname).to_string() + if login_submission["type"] == LoginType.APPSERVICE and appservice is not None: + result = await self._complete_login(qualified_user_id, login_submission) + return result + # Check if we've hit the failed ratelimit (but don't update it) self._failed_attempts_ratelimiter.ratelimit( qualified_user_id.lower(), update=False