Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Add an admin API endpoint to find a user based on its external ID in an auth provider. #13810

Merged
merged 3 commits into from
Sep 16, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/13810.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add an admin API endpoint to find a user based on its external ID in an auth provider.
24 changes: 24 additions & 0 deletions docs/admin_api/user_admin_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1155,3 +1155,27 @@ GET /_synapse/admin/v1/username_available?username=$localpart

The request and response format is the same as the
[/_matrix/client/r0/register/available](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-register-available) API.

### Find a user based on their ID in an auth provider

The API is:

```
GET /_synapse/admin/v1/auth_providers/$provider/users/$external_id
```

A response body like the following is returned:

```json
{
"user_id": "@hello:example.org"
}
```
sandhose marked this conversation as resolved.
Show resolved Hide resolved

**Parameters**

The following parameters should be set in the URL:

- `provider` - The ID of the authentication provider, as advertised by the [`GET /_matrix/client/v3/login`](https://spec.matrix.org/latest/client-server-api/#post_matrixclientv3login) API in the `m.login.sso` authentication method.
- `external_id` - The user ID from the authentication provider. Usually corresponds to the `sub` claim for OIDC providers, or to the `uid` attestation for SAML2 providers.
sandhose marked this conversation as resolved.
Show resolved Hide resolved

2 changes: 2 additions & 0 deletions synapse/rest/admin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
SearchUsersRestServlet,
ShadowBanRestServlet,
UserAdminServlet,
UserByExternalId,
UserMembershipRestServlet,
UserRegisterServlet,
UserRestServletV2,
Expand Down Expand Up @@ -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:
Expand Down
27 changes: 27 additions & 0 deletions synapse/rest/admin/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -1156,3 +1156,30 @@ async def on_GET(
"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}