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

Commit d765e42

Browse files
committed
Honour AS ratelimit settings for /login requests
Fixes #8846.
1 parent 16f4451 commit d765e42

File tree

1 file changed

+14
-4
lines changed

1 file changed

+14
-4
lines changed

synapse/rest/client/v1/login.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,22 +108,27 @@ def on_GET(self, request: SynapseRequest):
108108
return 200, {"flows": flows}
109109

110110
async def on_POST(self, request: SynapseRequest):
111-
self._address_ratelimiter.ratelimit(request.getClientIP())
112-
113111
login_submission = parse_json_object_from_request(request)
114112

115113
try:
116114
if login_submission["type"] == LoginRestServlet.APPSERVICE_TYPE:
117115
appservice = self.auth.get_appservice_by_req(request)
116+
117+
if appservice.is_rate_limited():
118+
self._address_ratelimiter.ratelimit(request.getClientIP())
119+
118120
result = await self._do_appservice_login(login_submission, appservice)
119121
elif self.jwt_enabled and (
120122
login_submission["type"] == LoginRestServlet.JWT_TYPE
121123
or login_submission["type"] == LoginRestServlet.JWT_TYPE_DEPRECATED
122124
):
125+
self._address_ratelimiter.ratelimit(request.getClientIP())
123126
result = await self._do_jwt_login(login_submission)
124127
elif login_submission["type"] == LoginRestServlet.TOKEN_TYPE:
128+
self._address_ratelimiter.ratelimit(request.getClientIP())
125129
result = await self._do_token_login(login_submission)
126130
else:
131+
self._address_ratelimiter.ratelimit(request.getClientIP())
127132
result = await self._do_other_login(login_submission)
128133
except KeyError:
129134
raise SynapseError(400, "Missing JSON keys.")
@@ -162,7 +167,9 @@ async def _do_appservice_login(
162167
if not appservice.is_interested_in_user(qualified_user_id):
163168
raise LoginError(403, "Invalid access_token", errcode=Codes.FORBIDDEN)
164169

165-
return await self._complete_login(qualified_user_id, login_submission)
170+
return await self._complete_login(
171+
qualified_user_id, login_submission, ratelimit=appservice.is_rate_limited()
172+
)
166173

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

224234
if create_non_existent_users:
225235
canonical_uid = await self.auth_handler.check_user_exists(user_id)

0 commit comments

Comments
 (0)