mirror of
https://github.com/vector-im/element-call.git
synced 2026-10-16 23:45:50 +00:00
src/livekit/auth now fronts two flows. For a transport with a LiveKit SFU `url`, tokens come from our own homeserver's MSC4195 get_token endpoint and delayed leaves are delegated through delegate_delayed_leave, both via the js-sdk's unstable client methods. Transports with only a livekit_service_url keep using the OpenID flow against the JWT service. A transport advertising both shapes lets a subscriber fall back to the OpenID flow when the homeserver answers get_token with a 404 (Synapse reports M_UNRECOGNIZED for unknown routes rather than M_NOT_FOUND), so a client can still join calls hosted on servers that have not deployed MSC4195 yet. Publishers never fall back: a homeserver that advertises a `url` but does not implement the endpoints is misconfigured and the admin should hear about it, so they get NoMatrix2AuthorizationService. Delegation uses the same flow as the token so that the participant identity the service computes matches. The local member only probes a transport's delegate_delayed_leave endpoint when it has a service URL. The developer settings tab validates a custom service URL through the same facade.
125 lines
3.0 KiB
TypeScript
125 lines
3.0 KiB
TypeScript
/*
|
|
Copyright 2026 Element Creations Ltd.
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
Please see LICENSE in the repository root for full details.
|
|
*/
|
|
|
|
import { type MatrixClient } from "matrix-js-sdk";
|
|
import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager";
|
|
|
|
import { extractFullConfigFromToken, type SFUConfig } from "./types.ts";
|
|
import { doNetworkOperationWithRetry } from "../../utils/matrix.ts";
|
|
|
|
export type ClientGetTokenParts = Pick<
|
|
MatrixClient,
|
|
"_unstable_getLivekitToken"
|
|
>;
|
|
|
|
export interface GetSFUConfigParams {
|
|
/**
|
|
* The Matrix client.
|
|
*/
|
|
client: ClientGetTokenParts;
|
|
/**
|
|
* Data identifying the local user's session membership.
|
|
*/
|
|
membership: CallMembershipIdentityParts;
|
|
/**
|
|
* The WebSocket URL of the SFU for which we wish to get an access token.
|
|
*/
|
|
url: string;
|
|
/**
|
|
* The name of the homeserver to which the SFU belongs.
|
|
*/
|
|
serverName: string;
|
|
/**
|
|
* The ID of the Matrix room in which the session takes place.
|
|
*/
|
|
roomId: string;
|
|
/**
|
|
* The ID of the MatrixRTC slot in which the session takes place.
|
|
*/
|
|
slotId: string;
|
|
}
|
|
|
|
/**
|
|
* Gets an {@link SFUConfig} appropriate for connecting to a given SFU, using
|
|
* the MSC4195 LiveKit client-server API endpoints.
|
|
*/
|
|
export async function getSFUConfig({
|
|
client,
|
|
membership,
|
|
url,
|
|
serverName,
|
|
roomId,
|
|
slotId,
|
|
}: GetSFUConfigParams): Promise<SFUConfig> {
|
|
const res = await doNetworkOperationWithRetry(async () =>
|
|
client._unstable_getLivekitToken({
|
|
url,
|
|
server_name: serverName,
|
|
room_id: roomId,
|
|
slot_id: slotId,
|
|
member_id: membership.memberId,
|
|
}),
|
|
);
|
|
return extractFullConfigFromToken({ url, jwt: res.jwt });
|
|
}
|
|
|
|
export type ClientDelegationParts = Pick<
|
|
MatrixClient,
|
|
"_unstable_delegateDelayedLeave" | "baseUrl"
|
|
>;
|
|
|
|
export interface DelegateDelayedLeaveParams {
|
|
/**
|
|
* The Matrix client.
|
|
*/
|
|
client: ClientDelegationParts;
|
|
/**
|
|
* Data identifying the local user's session membership.
|
|
*/
|
|
membership: CallMembershipIdentityParts;
|
|
/**
|
|
* The WebSocket URL of the SFU to which we are publishing and wish to
|
|
* delegate the delayed leave event.
|
|
*/
|
|
url: string;
|
|
/**
|
|
* The ID of the Matrix room in which the session takes place.
|
|
*/
|
|
roomId: string;
|
|
/**
|
|
* The ID of the MatrixRTC slot in which the session takes place.
|
|
*/
|
|
slotId: string;
|
|
/**
|
|
* The delay ID of the leave event to be delegated.
|
|
*/
|
|
delayId: string;
|
|
}
|
|
|
|
/**
|
|
* Delegates a delayed leave event to a given SFU, so that the event will
|
|
* be sent on our behalf whenever we disconnect from the SFU.
|
|
*/
|
|
export async function delegateDelayedLeave({
|
|
client,
|
|
membership,
|
|
url,
|
|
roomId,
|
|
slotId,
|
|
delayId,
|
|
}: DelegateDelayedLeaveParams): Promise<void> {
|
|
await doNetworkOperationWithRetry(async () =>
|
|
client._unstable_delegateDelayedLeave({
|
|
url,
|
|
room_id: roomId,
|
|
slot_id: slotId,
|
|
member_id: membership.memberId,
|
|
delay_id: delayId,
|
|
}),
|
|
);
|
|
}
|