Create a personal session on MAS
In order to get an access token for a user, one needs to create a personal session on MAS. We now do so, and extract the access token and device ID from the response. TODO: We're handing back the MAS user ID as the device ID. Is that correct?
This commit is contained in:
+23
-3
@@ -74,13 +74,20 @@ class GuestRegistrationServlet(DirectServeJsonResource):
|
||||
continue
|
||||
|
||||
if self._mas_admin_client is None:
|
||||
logger.info("Registering local Synapse guest user with localpart '%s'", localpart)
|
||||
logger.info(
|
||||
"Registering local Synapse guest user with localpart '%s'",
|
||||
localpart,
|
||||
)
|
||||
user_id = await self._api.register_user(
|
||||
localpart, displayname + self._config.display_name_suffix
|
||||
)
|
||||
|
||||
device_id, access_token, _, _ = await self._api.register_device(
|
||||
user_id
|
||||
)
|
||||
else:
|
||||
logger.info("Registering MAS guest user with username '%s'", localpart)
|
||||
await self._mas_admin_client.create_user(localpart)
|
||||
mas_user_id = await self._mas_admin_client.create_user(localpart)
|
||||
|
||||
user_id = self._api.get_qualified_user_id(localpart)
|
||||
|
||||
@@ -89,7 +96,20 @@ class GuestRegistrationServlet(DirectServeJsonResource):
|
||||
displayname + self._config.display_name_suffix,
|
||||
)
|
||||
|
||||
device_id, access_token, _, _ = await self._api.register_device(user_id)
|
||||
# Determine how long to keep the access token valid for.
|
||||
#
|
||||
# If a user reaper is enabled, just have the token expire after
|
||||
# the configured period.
|
||||
expires_in = (
|
||||
self._config.user_expiration_seconds
|
||||
if self._config.enable_user_reaper
|
||||
else 0
|
||||
)
|
||||
device_id, access_token = (
|
||||
await self._mas_admin_client.create_personal_session(
|
||||
mas_user_id, expires_in
|
||||
)
|
||||
)
|
||||
|
||||
logger.debug("Registered user '%s'", user_id)
|
||||
|
||||
|
||||
@@ -22,15 +22,61 @@ class MasAdminClient:
|
||||
self._admin_api_base_url = config.admin_api_base_url.rstrip("/")
|
||||
self._oauth_base_url = config.oauth_base_url.rstrip("/")
|
||||
|
||||
async def create_user(self, username: str) -> None:
|
||||
async def create_user(self, username: str) -> str:
|
||||
"""Creates a new user in MAS with the given username.
|
||||
|
||||
Args:
|
||||
username: The username (localpart) of the user to create.
|
||||
|
||||
Returns:
|
||||
The MAS ID of the created user.
|
||||
"""
|
||||
token = await self.request_admin_token()
|
||||
url = self._build_admin_url("/api/admin/v1/users")
|
||||
|
||||
await self._api.http_client.post_json_get_json(
|
||||
response = await self._api.http_client.post_json_get_json(
|
||||
uri=url,
|
||||
post_json={"username": username},
|
||||
headers={"Authorization": [f"Bearer {token}"]},
|
||||
)
|
||||
|
||||
mas_user_id = response.get("data", {}).get("id")
|
||||
if mas_user_id is None or not isinstance(mas_user_id, str):
|
||||
raise ValueError("MAS user creation response missing `data.id` field")
|
||||
|
||||
return mas_user_id
|
||||
|
||||
async def create_personal_session(
|
||||
self, mas_user_id: str, expires_in: int
|
||||
) -> tuple[str, str]:
|
||||
token = await self.request_admin_token()
|
||||
url = self._build_admin_url("/api/admin/v1/personal-sessions")
|
||||
|
||||
request_body = {
|
||||
"actor_user_id": mas_user_id,
|
||||
"expires_in": expires_in,
|
||||
"scope": "openid urn:matrix:client:api:*",
|
||||
"human_name": "guest user",
|
||||
}
|
||||
|
||||
response = await self._api.http_client.post_json_get_json(
|
||||
uri=url,
|
||||
post_json=request_body,
|
||||
headers={"Authorization": [f"Bearer {token}"]},
|
||||
)
|
||||
|
||||
data = response.get("data", {})
|
||||
attributes = data.get("attributes", {}) if isinstance(data, dict) else {}
|
||||
access_token = attributes.get("access_token")
|
||||
# TODO: Is this the correct device ID?
|
||||
device_id = data.get("id") if isinstance(data, dict) else None
|
||||
|
||||
if not isinstance(access_token, str) or len(access_token) == 0:
|
||||
raise ValueError("MAS session response missing `access_token` field")
|
||||
if not isinstance(device_id, str) or len(device_id) == 0:
|
||||
raise ValueError("MAS session response missing device id")
|
||||
|
||||
return device_id, access_token
|
||||
|
||||
async def request_admin_token(self) -> str:
|
||||
url = self._build_oauth_url("/oauth2/token")
|
||||
|
||||
Reference in New Issue
Block a user