diff --git a/synapse/rest/admin/__init__.py b/synapse/rest/admin/__init__.py
index bac754e1b1..885669f9c7 100644
--- a/synapse/rest/admin/__init__.py
+++ b/synapse/rest/admin/__init__.py
@@ -80,6 +80,7 @@ from synapse.rest.admin.users import (
SearchUsersRestServlet,
ShadowBanRestServlet,
UserAdminServlet,
+ UserByExternalId,
UserMembershipRestServlet,
UserRegisterServlet,
UserRestServletV2,
@@ -275,6 +276,7 @@ def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None:
ListDestinationsRestServlet(hs).register(http_server)
RoomMessagesRestServlet(hs).register(http_server)
RoomTimestampToEventRestServlet(hs).register(http_server)
+ UserByExternalId(hs).register(http_server)
# Some servlets only get registered for the main process.
if hs.config.worker.worker_app is None:
diff --git a/synapse/rest/admin/users.py b/synapse/rest/admin/users.py
index 78ee9b6532..2ca6b2d08a 100644
--- a/synapse/rest/admin/users.py
+++ b/synapse/rest/admin/users.py
@@ -1156,3 +1156,30 @@ class AccountDataRestServlet(RestServlet):
"rooms": by_room_data,
},
}
+
+
+class UserByExternalId(RestServlet):
+ """Find a user based on an external ID from an auth provider"""
+
+ PATTERNS = admin_patterns(
+ "/auth_providers/(?P<provider>[^/]*)/users/(?P<external_id>[^/]*)"
+ )
+
+ def __init__(self, hs: "HomeServer"):
+ self._auth = hs.get_auth()
+ self._store = hs.get_datastores().main
+
+ async def on_GET(
+ self,
+ request: SynapseRequest,
+ provider: str,
+ external_id: str,
+ ) -> Tuple[int, JsonDict]:
+ await assert_requester_is_admin(self._auth, request)
+
+ user_id = await self._store.get_user_by_external_id(provider, external_id)
+
+ if user_id is None:
+ raise NotFoundError("User not found")
+
+ return HTTPStatus.OK, {"user_id": user_id}
|