diff --git a/src/appservice/Appservice.ts b/src/appservice/Appservice.ts index 6f2d0ea2..8be8c53c 100644 --- a/src/appservice/Appservice.ts +++ b/src/appservice/Appservice.ts @@ -135,6 +135,14 @@ export interface IAppserviceRegistration { */ "de.sorunome.msc2409.push_ephemeral"?: boolean; + /** + * ** Experimental ** + * + * Should the AS use the new device management APIs. Optional. + * @see https://github.com/matrix-org/matrix-spec-proposals/pull/4190 + */ + "io.element.msc4190"?: boolean; + // not interested in other options } diff --git a/src/appservice/Intent.ts b/src/appservice/Intent.ts index 9d1e719d..d9aeb2d9 100644 --- a/src/appservice/Intent.ts +++ b/src/appservice/Intent.ts @@ -1,3 +1,5 @@ +import { randomUUID } from "crypto"; + import { DeviceKeyAlgorithm, extractRequestError, @@ -162,9 +164,17 @@ export class Intent { } if (!prepared) { - // XXX: We work around servers that don't support device_id impersonation - const accessToken = await Promise.resolve(storage?.readValue("accessToken")); - if (!accessToken) { + let accessToken; + if (this.options.registration["io.element.msc4190"]) { + // Generate a random device ID and create it + deviceId = randomUUID(); + // Make sure the device is registered + await this.client.doRequest("PUT", `/_matrix/client/v3/devices/${deviceId}`, null, {}); + this.makeClient(true); + this.client.impersonateUserId(this.userId, deviceId); + prepared = true; + } else if (!(accessToken = await Promise.resolve(storage?.readValue("accessToken")))) { + // XXX: We work around servers that don't support device_id impersonation const loginBody = { type: "m.login.application_service", identifier: {