@@ -210,7 +210,8 @@ def __init__(self, hs: "HomeServer"):
210210
211211 self .hs = hs # FIXME better possibility to access registrationHandler later?
212212 self .macaroon_gen = hs .get_macaroon_generator ()
213- self ._password_enabled = hs .config .auth .password_enabled
213+ self ._password_enabled_for_login = hs .config .auth .password_enabled_for_login
214+ self ._password_enabled_for_reauth = hs .config .auth .password_enabled_for_reauth
214215 self ._password_localdb_enabled = hs .config .auth .password_localdb_enabled
215216 self ._third_party_rules = hs .get_third_party_event_rules ()
216217
@@ -387,13 +388,13 @@ def get_new_session_data() -> JsonDict:
387388 return params , session_id
388389
389390 async def _get_available_ui_auth_types (self , user : UserID ) -> Iterable [str ]:
390- """Get a list of the authentication types this user can use"""
391+ """Get a list of the user-interactive authentication types this user can use. """
391392
392393 ui_auth_types = set ()
393394
394395 # if the HS supports password auth, and the user has a non-null password, we
395396 # support password auth
396- if self ._password_localdb_enabled and self ._password_enabled :
397+ if self ._password_localdb_enabled and self ._password_enabled_for_reauth :
397398 lookupres = await self ._find_user_id_and_pwd_hash (user .to_string ())
398399 if lookupres :
399400 _ , password_hash = lookupres
@@ -402,7 +403,7 @@ async def _get_available_ui_auth_types(self, user: UserID) -> Iterable[str]:
402403
403404 # also allow auth from password providers
404405 for t in self .password_auth_provider .get_supported_login_types ().keys ():
405- if t == LoginType .PASSWORD and not self ._password_enabled :
406+ if t == LoginType .PASSWORD and not self ._password_enabled_for_reauth :
406407 continue
407408 ui_auth_types .add (t )
408409
@@ -710,7 +711,7 @@ async def _check_auth_dict(
710711 return res
711712
712713 # fall back to the v1 login flow
713- canonical_id , _ = await self .validate_login (authdict )
714+ canonical_id , _ = await self .validate_login (authdict , is_reauth = True )
714715 return canonical_id
715716
716717 def _get_params_recaptcha (self ) -> dict :
@@ -1064,7 +1065,7 @@ def can_change_password(self) -> bool:
10641065 Returns:
10651066 Whether users on this server are allowed to change or set a password
10661067 """
1067- return self ._password_enabled and self ._password_localdb_enabled
1068+ return self ._password_enabled_for_login and self ._password_localdb_enabled
10681069
10691070 def get_supported_login_types (self ) -> Iterable [str ]:
10701071 """Get a the login types supported for the /login API
@@ -1089,9 +1090,9 @@ def get_supported_login_types(self) -> Iterable[str]:
10891090 # that comes first, where it's present.
10901091 if LoginType .PASSWORD in types :
10911092 types .remove (LoginType .PASSWORD )
1092- if self ._password_enabled :
1093+ if self ._password_enabled_for_login :
10931094 types .insert (0 , LoginType .PASSWORD )
1094- elif self ._password_localdb_enabled and self ._password_enabled :
1095+ elif self ._password_localdb_enabled and self ._password_enabled_for_login :
10951096 types .insert (0 , LoginType .PASSWORD )
10961097
10971098 return types
@@ -1100,6 +1101,7 @@ async def validate_login(
11001101 self ,
11011102 login_submission : Dict [str , Any ],
11021103 ratelimit : bool = False ,
1104+ is_reauth : bool = False ,
11031105 ) -> Tuple [str , Optional [Callable [["LoginResponse" ], Awaitable [None ]]]]:
11041106 """Authenticates the user for the /login API
11051107
@@ -1110,6 +1112,9 @@ async def validate_login(
11101112 login_submission: the whole of the login submission
11111113 (including 'type' and other relevant fields)
11121114 ratelimit: whether to apply the failed_login_attempt ratelimiter
1115+ is_reauth: whether this is part of a User-Interactive Authorisation
1116+ flow to reauthenticate for a privileged action (rather than a
1117+ new login)
11131118 Returns:
11141119 A tuple of the canonical user id, and optional callback
11151120 to be called once the access token and device id are issued
@@ -1132,8 +1137,14 @@ async def validate_login(
11321137 # special case to check for "password" for the check_password interface
11331138 # for the auth providers
11341139 password = login_submission .get ("password" )
1140+
11351141 if login_type == LoginType .PASSWORD :
1136- if not self ._password_enabled :
1142+ if is_reauth :
1143+ passwords_allowed_here = self ._password_enabled_for_reauth
1144+ else :
1145+ passwords_allowed_here = self ._password_enabled_for_login
1146+
1147+ if not passwords_allowed_here :
11371148 raise SynapseError (400 , "Password login has been disabled." )
11381149 if not isinstance (password , str ):
11391150 raise SynapseError (400 , "Bad parameter: password" , Codes .INVALID_PARAM )
0 commit comments