Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Commit

Permalink
Honour AS ratelimit settings for /login requests
Browse files Browse the repository at this point in the history
Fixes #8846.
  • Loading branch information
erikjohnston committed Dec 10, 2020
1 parent 16f4451 commit d765e42
Showing 1 changed file with 14 additions and 4 deletions.
18 changes: 14 additions & 4 deletions synapse/rest/client/v1/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,22 +108,27 @@ def on_GET(self, request: SynapseRequest):
return 200, {"flows": flows}

async def on_POST(self, request: SynapseRequest):
self._address_ratelimiter.ratelimit(request.getClientIP())

login_submission = parse_json_object_from_request(request)

try:
if login_submission["type"] == LoginRestServlet.APPSERVICE_TYPE:
appservice = self.auth.get_appservice_by_req(request)

if appservice.is_rate_limited():
self._address_ratelimiter.ratelimit(request.getClientIP())

result = await self._do_appservice_login(login_submission, appservice)
elif self.jwt_enabled and (
login_submission["type"] == LoginRestServlet.JWT_TYPE
or login_submission["type"] == LoginRestServlet.JWT_TYPE_DEPRECATED
):
self._address_ratelimiter.ratelimit(request.getClientIP())
result = await self._do_jwt_login(login_submission)
elif login_submission["type"] == LoginRestServlet.TOKEN_TYPE:
self._address_ratelimiter.ratelimit(request.getClientIP())
result = await self._do_token_login(login_submission)
else:
self._address_ratelimiter.ratelimit(request.getClientIP())
result = await self._do_other_login(login_submission)
except KeyError:
raise SynapseError(400, "Missing JSON keys.")
Expand Down Expand Up @@ -162,7 +167,9 @@ async def _do_appservice_login(
if not appservice.is_interested_in_user(qualified_user_id):
raise LoginError(403, "Invalid access_token", errcode=Codes.FORBIDDEN)

return await self._complete_login(qualified_user_id, login_submission)
return await self._complete_login(
qualified_user_id, login_submission, ratelimit=appservice.is_rate_limited()
)

async def _do_other_login(self, login_submission: JsonDict) -> Dict[str, str]:
"""Handle non-token/saml/jwt logins
Expand Down Expand Up @@ -197,6 +204,7 @@ async def _complete_login(
login_submission: JsonDict,
callback: Optional[Callable[[Dict[str, str]], Awaitable[None]]] = None,
create_non_existent_users: bool = False,
ratelimit=True,
) -> Dict[str, str]:
"""Called when we've successfully authed the user and now need to
actually login them in (e.g. create devices). This gets called on
Expand All @@ -211,6 +219,7 @@ async def _complete_login(
callback: Callback function to run after login.
create_non_existent_users: Whether to create the user if they don't
exist. Defaults to False.
ratelimit: Whether to ratelimit the login request.
Returns:
result: Dictionary of account information after successful login.
Expand All @@ -219,7 +228,8 @@ async def _complete_login(
# Before we actually log them in we check if they've already logged in
# too often. This happens here rather than before as we don't
# necessarily know the user before now.
self._account_ratelimiter.ratelimit(user_id.lower())
if ratelimit:
self._account_ratelimiter.ratelimit(user_id.lower())

if create_non_existent_users:
canonical_uid = await self.auth_handler.check_user_exists(user_id)
Expand Down

0 comments on commit d765e42

Please sign in to comment.