summary refs log tree commit diff
path: root/synapse/handlers/auth.py
diff options
context:
space:
mode:
Diffstat (limited to 'synapse/handlers/auth.py')
-rw-r--r--synapse/handlers/auth.py80
1 files changed, 52 insertions, 28 deletions
diff --git a/synapse/handlers/auth.py b/synapse/handlers/auth.py
index acae4d9e0d..93d8ac0e04 100644
--- a/synapse/handlers/auth.py
+++ b/synapse/handlers/auth.py
@@ -77,6 +77,12 @@ class AuthHandler(BaseHandler):
         self.hs = hs  # FIXME better possibility to access registrationHandler later?
         self.device_handler = hs.get_device_handler()
         self.macaroon_gen = hs.get_macaroon_generator()
+        self._password_enabled = hs.config.password_enabled
+
+        login_types = set()
+        if self._password_enabled:
+            login_types.add(LoginType.PASSWORD)
+        self._supported_login_types = frozenset(login_types)
 
     @defer.inlineCallbacks
     def check_auth(self, flows, clientdict, clientip):
@@ -266,10 +272,11 @@ class AuthHandler(BaseHandler):
 
         user_id = authdict["user"]
         password = authdict["password"]
-        if not user_id.startswith('@'):
-            user_id = UserID(user_id, self.hs.hostname).to_string()
 
-        return self._check_password(user_id, password)
+        return self.validate_login(user_id, {
+            "type": LoginType.PASSWORD,
+            "password": password,
+        })
 
     @defer.inlineCallbacks
     def _check_recaptcha(self, authdict, clientip):
@@ -398,23 +405,6 @@ class AuthHandler(BaseHandler):
 
         return self.sessions[session_id]
 
-    def validate_password_login(self, user_id, password):
-        """
-        Authenticates the user with their username and password.
-
-        Used only by the v1 login API.
-
-        Args:
-            user_id (str): complete @user:id
-            password (str): Password
-        Returns:
-            defer.Deferred: (str) canonical user id
-        Raises:
-            StoreError if there was a problem accessing the database
-            LoginError if there was an authentication problem.
-        """
-        return self._check_password(user_id, password)
-
     @defer.inlineCallbacks
     def get_access_token_for_user_id(self, user_id, device_id=None,
                                      initial_display_name=None):
@@ -501,26 +491,60 @@ class AuthHandler(BaseHandler):
             )
         defer.returnValue(result)
 
+    def get_supported_login_types(self):
+        """Get a the login types supported for the /login API
+
+        By default this is just 'm.login.password' (unless password_enabled is
+        False in the config file), but password auth providers can provide
+        other login types.
+
+        Returns:
+            Iterable[str]: login types
+        """
+        return self._supported_login_types
+
     @defer.inlineCallbacks
-    def _check_password(self, user_id, password):
-        """Authenticate a user against the LDAP and local databases.
+    def validate_login(self, user_id, login_submission):
+        """Authenticates the user for the /login API
 
-        user_id is checked case insensitively against the local database, but
-        will throw if there are multiple inexact matches.
+        Also used by the user-interactive auth flow to validate
+        m.login.password auth types.
 
         Args:
-            user_id (str): complete @user:id
+            user_id (str): user_id supplied by the user
+            login_submission (dict): the whole of the login submission
+                (including 'type' and other relevant fields)
         Returns:
-            (str) the canonical_user_id
+            Deferred[str]: canonical user id
         Raises:
-            LoginError if login fails
+            StoreError if there was a problem accessing the database
+            SynapseError if there was a problem with the request
+            LoginError if there was an authentication problem.
         """
+
+        if not user_id.startswith('@'):
+            user_id = UserID(
+                user_id, self.hs.hostname
+            ).to_string()
+
+        login_type = login_submission.get("type")
+
+        if login_type != LoginType.PASSWORD:
+            raise SynapseError(400, "Bad login type.")
+        if not self._password_enabled:
+            raise SynapseError(400, "Password login has been disabled.")
+        if "password" not in login_submission:
+            raise SynapseError(400, "Missing parameter: password")
+
+        password = login_submission["password"]
         for provider in self.password_providers:
             is_valid = yield provider.check_password(user_id, password)
             if is_valid:
                 defer.returnValue(user_id)
 
-        canonical_user_id = yield self._check_local_password(user_id, password)
+        canonical_user_id = yield self._check_local_password(
+            user_id, password,
+        )
 
         if canonical_user_id:
             defer.returnValue(canonical_user_id)