From 006b4dad7a8270c21f98150154cd30ad02989052 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Wed, 11 Mar 2020 15:12:32 -0400 Subject: [PATCH] Add additional information to the session dictionary about what is being authenticated. --- synapse/handlers/auth.py | 33 +++++++++++++++++++++--- synapse/rest/client/v2_alpha/account.py | 20 +++++++++++--- synapse/rest/client/v2_alpha/devices.py | 12 +++++++-- synapse/rest/client/v2_alpha/keys.py | 2 +- synapse/rest/client/v2_alpha/register.py | 6 ++++- 5 files changed, 62 insertions(+), 11 deletions(-) diff --git a/synapse/handlers/auth.py b/synapse/handlers/auth.py index 3a69aa020920..d6d9eeea7a20 100644 --- a/synapse/handlers/auth.py +++ b/synapse/handlers/auth.py @@ -125,7 +125,12 @@ def __init__(self, hs): @defer.inlineCallbacks def validate_user_via_ui_auth( - self, requester: Requester, request_body: dict, clientip: str + self, + requester: Requester, + request_body: dict, + clientip: str, + action_type, + action_id, ): """ Checks that the user is who they claim to be, via a UI auth. @@ -172,7 +177,9 @@ def validate_user_via_ui_auth( flows = [[login_type] for login_type in self._supported_login_types] try: - result, params, _ = yield self.check_auth(flows, request_body, clientip) + result, params, _ = yield self.check_auth( + flows, request_body, clientip, action_type, action_id + ) except LoginError: # Update the ratelimite to say we failed (`can_do_action` doesn't raise). self._failed_uia_attempts_ratelimiter.can_do_action( @@ -210,7 +217,14 @@ def get_enabled_auth_types(self): return self.checkers.keys() @defer.inlineCallbacks - def check_auth(self, flows: List[List[str]], clientdict: dict, clientip: str): + def check_auth( + self, + flows: List[List[str]], + clientdict: dict, + clientip: str, + action_type, + action_id, + ): """ Takes a dictionary sent by the client in the login / registration protocol and handles the User-Interactive Auth flow. @@ -275,6 +289,19 @@ def check_auth(self, flows: List[List[str]], clientdict: dict, clientip: str): elif "clientdict" in session: clientdict = session["clientdict"] + # If ui_auth exists in the session this is a returning UI auth request. + # Validate that none of the requested information has changed. + if "ui_auth" not in session: + session["ui_auth"] = { + "action_type": action_type, + "action_id": action_id, + } + elif ( + session["ui_auth"]["action_type"] != action_type + or session["ui_auth"]["action_id"] != action_id + ): + raise SynapseError(403, "Foobar") + if not authdict: raise InteractiveAuthIncompleteError( self._auth_dict_for_flows(flows, session) diff --git a/synapse/rest/client/v2_alpha/account.py b/synapse/rest/client/v2_alpha/account.py index e40136f2f3b2..1f15e1a7adef 100644 --- a/synapse/rest/client/v2_alpha/account.py +++ b/synapse/rest/client/v2_alpha/account.py @@ -234,13 +234,21 @@ async def on_POST(self, request): if self.auth.has_access_token(request): requester = await self.auth.get_user_by_req(request) params = await self.auth_handler.validate_user_via_ui_auth( - requester, body, self.hs.get_ip_from_request(request) + requester, + body, + self.hs.get_ip_from_request(request), + "modify_password", + "", # TODO ) user_id = requester.user.to_string() else: requester = None result, params, _ = await self.auth_handler.check_auth( - [[LoginType.EMAIL_IDENTITY]], body, self.hs.get_ip_from_request(request) + [[LoginType.EMAIL_IDENTITY]], + body, + self.hs.get_ip_from_request(request), + "modify_password", + "", # TODO ) if LoginType.EMAIL_IDENTITY in result: @@ -305,7 +313,11 @@ async def on_POST(self, request): return 200, {} await self.auth_handler.validate_user_via_ui_auth( - requester, body, self.hs.get_ip_from_request(request) + requester, + body, + self.hs.get_ip_from_request(request), + "deactivate", + requester.user.to_string(), ) result = await self._deactivate_account_handler.deactivate_account( requester.user.to_string(), erase, id_server=body.get("id_server") @@ -663,7 +675,7 @@ async def on_POST(self, request): assert_valid_client_secret(client_secret) await self.auth_handler.validate_user_via_ui_auth( - requester, body, self.hs.get_ip_from_request(request) + requester, body, self.hs.get_ip_from_request(request), "add_3pid", user_id ) validation_session = await self.identity_handler.validate_threepid_session( diff --git a/synapse/rest/client/v2_alpha/devices.py b/synapse/rest/client/v2_alpha/devices.py index 94ff73f384e1..2ef5ec19a63a 100644 --- a/synapse/rest/client/v2_alpha/devices.py +++ b/synapse/rest/client/v2_alpha/devices.py @@ -81,7 +81,11 @@ async def on_POST(self, request): assert_params_in_dict(body, ["devices"]) await self.auth_handler.validate_user_via_ui_auth( - requester, body, self.hs.get_ip_from_request(request) + requester, + body, + self.hs.get_ip_from_request(request), + "delete_devices", + "", # TODO ) await self.device_handler.delete_devices( @@ -127,7 +131,11 @@ async def on_DELETE(self, request, device_id): raise await self.auth_handler.validate_user_via_ui_auth( - requester, body, self.hs.get_ip_from_request(request) + requester, + body, + self.hs.get_ip_from_request(request), + "delete_device", + device_id, ) await self.device_handler.delete_device(requester.user.to_string(), device_id) diff --git a/synapse/rest/client/v2_alpha/keys.py b/synapse/rest/client/v2_alpha/keys.py index f7ed4daf90a7..0e9cf8172937 100644 --- a/synapse/rest/client/v2_alpha/keys.py +++ b/synapse/rest/client/v2_alpha/keys.py @@ -263,7 +263,7 @@ async def on_POST(self, request): body = parse_json_object_from_request(request) await self.auth_handler.validate_user_via_ui_auth( - requester, body, self.hs.get_ip_from_request(request) + requester, body, self.hs.get_ip_from_request(request), "add_keys", user_id ) result = await self.e2e_keys_handler.upload_signing_keys_for_user(user_id, body) diff --git a/synapse/rest/client/v2_alpha/register.py b/synapse/rest/client/v2_alpha/register.py index a09189b1b469..950177075ec2 100644 --- a/synapse/rest/client/v2_alpha/register.py +++ b/synapse/rest/client/v2_alpha/register.py @@ -499,7 +499,11 @@ async def on_POST(self, request): ) auth_result, params, session_id = await self.auth_handler.check_auth( - self._registration_flows, body, self.hs.get_ip_from_request(request) + self._registration_flows, + body, + self.hs.get_ip_from_request(request), + "register", + "", # TODO ) # Check that we're not trying to register a denied 3pid.