50
50
parse_json_object_from_request ,
51
51
parse_string ,
52
52
)
53
- from synapse .http .site import SynapseRequest
53
+ from synapse .http .site import RequestInfo , SynapseRequest
54
54
from synapse .rest .client ._base import client_patterns
55
55
from synapse .rest .well_known import WellKnownBuilder
56
56
from synapse .types import JsonDict , UserID
@@ -114,6 +114,7 @@ def __init__(self, hs: "HomeServer"):
114
114
self .auth_handler = self .hs .get_auth_handler ()
115
115
self .registration_handler = hs .get_registration_handler ()
116
116
self ._sso_handler = hs .get_sso_handler ()
117
+ self ._spam_checker = hs .get_module_api_callbacks ().spam_checker
117
118
118
119
self ._well_known_builder = WellKnownBuilder (hs )
119
120
self ._address_ratelimiter = Ratelimiter (
@@ -197,6 +198,8 @@ async def on_POST(self, request: SynapseRequest) -> Tuple[int, LoginResponse]:
197
198
self ._refresh_tokens_enabled and client_requested_refresh_token
198
199
)
199
200
201
+ request_info = request .request_info ()
202
+
200
203
try :
201
204
if login_submission ["type" ] == LoginRestServlet .APPSERVICE_TYPE :
202
205
requester = await self .auth .get_user_by_req (request )
@@ -216,6 +219,7 @@ async def on_POST(self, request: SynapseRequest) -> Tuple[int, LoginResponse]:
216
219
login_submission ,
217
220
appservice ,
218
221
should_issue_refresh_token = should_issue_refresh_token ,
222
+ request_info = request_info ,
219
223
)
220
224
elif (
221
225
self .jwt_enabled
@@ -227,6 +231,7 @@ async def on_POST(self, request: SynapseRequest) -> Tuple[int, LoginResponse]:
227
231
result = await self ._do_jwt_login (
228
232
login_submission ,
229
233
should_issue_refresh_token = should_issue_refresh_token ,
234
+ request_info = request_info ,
230
235
)
231
236
elif login_submission ["type" ] == LoginRestServlet .TOKEN_TYPE :
232
237
await self ._address_ratelimiter .ratelimit (
@@ -235,6 +240,7 @@ async def on_POST(self, request: SynapseRequest) -> Tuple[int, LoginResponse]:
235
240
result = await self ._do_token_login (
236
241
login_submission ,
237
242
should_issue_refresh_token = should_issue_refresh_token ,
243
+ request_info = request_info ,
238
244
)
239
245
else :
240
246
await self ._address_ratelimiter .ratelimit (
@@ -243,6 +249,7 @@ async def on_POST(self, request: SynapseRequest) -> Tuple[int, LoginResponse]:
243
249
result = await self ._do_other_login (
244
250
login_submission ,
245
251
should_issue_refresh_token = should_issue_refresh_token ,
252
+ request_info = request_info ,
246
253
)
247
254
except KeyError :
248
255
raise SynapseError (400 , "Missing JSON keys." )
@@ -265,6 +272,8 @@ async def _do_appservice_login(
265
272
login_submission : JsonDict ,
266
273
appservice : ApplicationService ,
267
274
should_issue_refresh_token : bool = False ,
275
+ * ,
276
+ request_info : RequestInfo ,
268
277
) -> LoginResponse :
269
278
identifier = login_submission .get ("identifier" )
270
279
logger .info ("Got appservice login request with identifier: %r" , identifier )
@@ -300,10 +309,15 @@ async def _do_appservice_login(
300
309
# The user represented by an appservice's configured sender_localpart
301
310
# is not actually created in Synapse.
302
311
should_check_deactivated = qualified_user_id != appservice .sender ,
312
+ request_info = request_info ,
303
313
)
304
314
305
315
async def _do_other_login (
306
- self , login_submission : JsonDict , should_issue_refresh_token : bool = False
316
+ self ,
317
+ login_submission : JsonDict ,
318
+ should_issue_refresh_token : bool = False ,
319
+ * ,
320
+ request_info : RequestInfo ,
307
321
) -> LoginResponse :
308
322
"""Handle non-token/saml/jwt logins
309
323
@@ -333,6 +347,7 @@ async def _do_other_login(
333
347
login_submission ,
334
348
callback ,
335
349
should_issue_refresh_token = should_issue_refresh_token ,
350
+ request_info = request_info ,
336
351
)
337
352
return result
338
353
@@ -347,6 +362,8 @@ async def _complete_login(
347
362
should_issue_refresh_token : bool = False ,
348
363
auth_provider_session_id : Optional [str ] = None ,
349
364
should_check_deactivated : bool = True ,
365
+ * ,
366
+ request_info : RequestInfo ,
350
367
) -> LoginResponse :
351
368
"""Called when we've successfully authed the user and now need to
352
369
actually login them in (e.g. create devices). This gets called on
@@ -371,6 +388,7 @@ async def _complete_login(
371
388
372
389
This exists purely for appservice's configured sender_localpart
373
390
which doesn't have an associated user in the database.
391
+ request_info: The user agent/IP address of the user.
374
392
375
393
Returns:
376
394
Dictionary of account information after successful login.
@@ -417,6 +435,22 @@ async def _complete_login(
417
435
)
418
436
419
437
initial_display_name = login_submission .get ("initial_device_display_name" )
438
+ spam_check = await self ._spam_checker .check_login_for_spam (
439
+ user_id ,
440
+ device_id = device_id ,
441
+ initial_display_name = initial_display_name ,
442
+ request_info = [(request_info .user_agent , request_info .ip )],
443
+ auth_provider_id = auth_provider_id ,
444
+ )
445
+ if spam_check != self ._spam_checker .NOT_SPAM :
446
+ logger .info ("Blocking login due to spam checker" )
447
+ raise SynapseError (
448
+ 403 ,
449
+ msg = "Login was blocked by the server" ,
450
+ errcode = spam_check [0 ],
451
+ additional_fields = spam_check [1 ],
452
+ )
453
+
420
454
(
421
455
device_id ,
422
456
access_token ,
@@ -451,7 +485,11 @@ async def _complete_login(
451
485
return result
452
486
453
487
async def _do_token_login (
454
- self , login_submission : JsonDict , should_issue_refresh_token : bool = False
488
+ self ,
489
+ login_submission : JsonDict ,
490
+ should_issue_refresh_token : bool = False ,
491
+ * ,
492
+ request_info : RequestInfo ,
455
493
) -> LoginResponse :
456
494
"""
457
495
Handle token login.
@@ -474,10 +512,15 @@ async def _do_token_login(
474
512
auth_provider_id = res .auth_provider_id ,
475
513
should_issue_refresh_token = should_issue_refresh_token ,
476
514
auth_provider_session_id = res .auth_provider_session_id ,
515
+ request_info = request_info ,
477
516
)
478
517
479
518
async def _do_jwt_login (
480
- self , login_submission : JsonDict , should_issue_refresh_token : bool = False
519
+ self ,
520
+ login_submission : JsonDict ,
521
+ should_issue_refresh_token : bool = False ,
522
+ * ,
523
+ request_info : RequestInfo ,
481
524
) -> LoginResponse :
482
525
"""
483
526
Handle the custom JWT login.
@@ -496,6 +539,7 @@ async def _do_jwt_login(
496
539
login_submission ,
497
540
create_non_existent_users = True ,
498
541
should_issue_refresh_token = should_issue_refresh_token ,
542
+ request_info = request_info ,
499
543
)
500
544
501
545
0 commit comments