summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Cloke <clokep@users.noreply.github.com>2020-08-28 08:56:36 -0400
committerGitHub <noreply@github.com>2020-08-28 08:56:36 -0400
commitb055dc93220217fe55f8f4d28945f86353c2f3a8 (patch)
tree99e69481c40dffd9e60a816f74a03d46beda9c2d
parentConvert additional database code to async/await. (#8195) (diff)
downloadsynapse-b055dc93220217fe55f8f4d28945f86353c2f3a8.tar.xz
Ensure that the OpenID Connect remote ID is a string. (#8190)
-rw-r--r--changelog.d/8190.bugfix1
-rw-r--r--synapse/handlers/oidc_handler.py3
-rw-r--r--tests/handlers/test_oidc.py41
3 files changed, 43 insertions, 2 deletions
diff --git a/changelog.d/8190.bugfix b/changelog.d/8190.bugfix
new file mode 100644
index 0000000000..bf6717ab28
--- /dev/null
+++ b/changelog.d/8190.bugfix
@@ -0,0 +1 @@
+Fix logging in via OpenID Connect with a provider that uses integer user IDs.
diff --git a/synapse/handlers/oidc_handler.py b/synapse/handlers/oidc_handler.py
index c5bd2fea68..1b06f3173f 100644
--- a/synapse/handlers/oidc_handler.py
+++ b/synapse/handlers/oidc_handler.py
@@ -869,6 +869,9 @@ class OidcHandler:
             raise MappingException(
                 "Failed to extract subject from OIDC response: %s" % (e,)
             )
+        # Some OIDC providers use integer IDs, but Synapse expects external IDs
+        # to be strings.
+        remote_user_id = str(remote_user_id)
 
         logger.info(
             "Looking for existing mapping for user %s:%s",
diff --git a/tests/handlers/test_oidc.py b/tests/handlers/test_oidc.py
index f92f3b8c15..89ec5fcb31 100644
--- a/tests/handlers/test_oidc.py
+++ b/tests/handlers/test_oidc.py
@@ -75,7 +75,17 @@ COMMON_CONFIG = {
 COOKIE_NAME = b"oidc_session"
 COOKIE_PATH = "/_synapse/oidc"
 
-MockedMappingProvider = Mock(OidcMappingProvider)
+
+class TestMappingProvider(OidcMappingProvider):
+    @staticmethod
+    def parse_config(config):
+        return
+
+    def get_remote_user_id(self, userinfo):
+        return userinfo["sub"]
+
+    async def map_user_attributes(self, userinfo, token):
+        return {"localpart": userinfo["username"], "display_name": None}
 
 
 def simple_async_mock(return_value=None, raises=None):
@@ -123,7 +133,7 @@ class OidcHandlerTestCase(HomeserverTestCase):
         oidc_config["issuer"] = ISSUER
         oidc_config["scopes"] = SCOPES
         oidc_config["user_mapping_provider"] = {
-            "module": __name__ + ".MockedMappingProvider"
+            "module": __name__ + ".TestMappingProvider",
         }
         config["oidc_config"] = oidc_config
 
@@ -580,3 +590,30 @@ class OidcHandlerTestCase(HomeserverTestCase):
         with self.assertRaises(OidcError) as exc:
             yield defer.ensureDeferred(self.handler._exchange_code(code))
         self.assertEqual(exc.exception.error, "some_error")
+
+    def test_map_userinfo_to_user(self):
+        """Ensure that mapping the userinfo returned from a provider to an MXID works properly."""
+        userinfo = {
+            "sub": "test_user",
+            "username": "test_user",
+        }
+        # The token doesn't matter with the default user mapping provider.
+        token = {}
+        mxid = self.get_success(
+            self.handler._map_userinfo_to_user(
+                userinfo, token, "user-agent", "10.10.10.10"
+            )
+        )
+        self.assertEqual(mxid, "@test_user:test")
+
+        # Some providers return an integer ID.
+        userinfo = {
+            "sub": 1234,
+            "username": "test_user_2",
+        }
+        mxid = self.get_success(
+            self.handler._map_userinfo_to_user(
+                userinfo, token, "user-agent", "10.10.10.10"
+            )
+        )
+        self.assertEqual(mxid, "@test_user_2:test")