mirror of
https://github.com/vector-im/element-call.git
synced 2026-10-16 23:45:50 +00:00
Make the auth choice mode independent again
This commit is contained in:
@@ -21,7 +21,6 @@ import { delegateDelayedLeave, getSFUConfig } from ".";
|
||||
import { mocked } from "storybook/test";
|
||||
import { ConnectionError, MatrixError } from "matrix-js-sdk";
|
||||
import { NoMatrix2AuthorizationService } from "../../utils/errors";
|
||||
import { MatrixRTCMode } from "../../config/ConfigOptions";
|
||||
import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager";
|
||||
|
||||
vi.mock("./openID", () => ({ getSFUConfig: vi.fn() }));
|
||||
@@ -84,7 +83,6 @@ describe("getSFUConfig", () => {
|
||||
membership,
|
||||
serverName: "example.org",
|
||||
role: "subscriber" as const,
|
||||
matrixRTCMode: MatrixRTCMode.Matrix_2_0,
|
||||
roomId,
|
||||
slotId,
|
||||
logger,
|
||||
@@ -186,12 +184,24 @@ describe("getSFUConfig", () => {
|
||||
expect(openID.getSFUConfig).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("uses CS API when publishing with url transport", async () => {
|
||||
expect(
|
||||
await getSFUConfig({
|
||||
...defaultParams,
|
||||
transport: urlTransport,
|
||||
role: "publisher",
|
||||
}),
|
||||
).toEqual(expect.objectContaining({ jwt: csApiJWTToken }));
|
||||
expect(client._unstable_getLivekitToken).toHaveBeenCalled();
|
||||
expect(openID.getSFUConfig).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not fall back to OpenID when publishing", async () => {
|
||||
client._unstable_getLivekitToken.mockRejectedValueOnce(unsupportedError);
|
||||
await expect(
|
||||
getSFUConfig({
|
||||
...defaultParams,
|
||||
transport: urlAndServiceUrlTransport,
|
||||
transport: urlTransport,
|
||||
role: "publisher",
|
||||
}),
|
||||
).rejects.toThrow(expect.any(NoMatrix2AuthorizationService));
|
||||
@@ -199,7 +209,7 @@ describe("getSFUConfig", () => {
|
||||
expect(openID.getSFUConfig).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("uses OpenID when publishing in compatibility mode with url + livekit_service_url transport", async () => {
|
||||
it("uses OpenID when publishing with url + livekit_service_url transport", async () => {
|
||||
// Subscribers predating MSC4195 expect a legacy participant identity from
|
||||
// anyone advertising a state event, which only the JWT service assigns
|
||||
expect(
|
||||
@@ -207,7 +217,6 @@ describe("getSFUConfig", () => {
|
||||
...defaultParams,
|
||||
transport: urlAndServiceUrlTransport,
|
||||
role: "publisher",
|
||||
matrixRTCMode: MatrixRTCMode.Compatibility,
|
||||
}),
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
@@ -221,31 +230,6 @@ describe("getSFUConfig", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("uses CS API when publishing in compatibility mode with url transport", async () => {
|
||||
expect(
|
||||
await getSFUConfig({
|
||||
...defaultParams,
|
||||
transport: urlTransport,
|
||||
role: "publisher",
|
||||
matrixRTCMode: MatrixRTCMode.Compatibility,
|
||||
}),
|
||||
).toEqual(expect.objectContaining({ jwt: csApiJWTToken }));
|
||||
expect(client._unstable_getLivekitToken).toHaveBeenCalled();
|
||||
expect(openID.getSFUConfig).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("uses CS API when subscribing in compatibility mode with url + livekit_service_url transport", async () => {
|
||||
expect(
|
||||
await getSFUConfig({
|
||||
...defaultParams,
|
||||
transport: urlAndServiceUrlTransport,
|
||||
matrixRTCMode: MatrixRTCMode.Compatibility,
|
||||
}),
|
||||
).toEqual(expect.objectContaining({ jwt: csApiJWTToken }));
|
||||
expect(client._unstable_getLivekitToken).toHaveBeenCalled();
|
||||
expect(openID.getSFUConfig).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not fall back to OpenID on connection error", async () => {
|
||||
const client_ = {
|
||||
...client,
|
||||
@@ -275,7 +259,6 @@ describe("delegateDelayedLeave", () => {
|
||||
roomId,
|
||||
slotId,
|
||||
delayId: "delay123",
|
||||
matrixRTCMode: MatrixRTCMode.Matrix_2_0,
|
||||
logger,
|
||||
};
|
||||
|
||||
@@ -305,21 +288,11 @@ describe("delegateDelayedLeave", () => {
|
||||
expect(openID.getSFUConfig).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("uses CS API with url + livekit_service_url transport", async () => {
|
||||
await delegateDelayedLeave({
|
||||
...defaultParams,
|
||||
transport: urlAndServiceUrlTransport,
|
||||
});
|
||||
expect(client._unstable_delegateDelayedLeave).toHaveBeenCalled();
|
||||
expect(openID.getSFUConfig).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("uses OpenID in compatibility mode with url + livekit_service_url transport", async () => {
|
||||
it("uses OpenID with url + livekit_service_url transport", async () => {
|
||||
// Must match the flow that got the token, so the identities line up
|
||||
await delegateDelayedLeave({
|
||||
...defaultParams,
|
||||
transport: urlAndServiceUrlTransport,
|
||||
matrixRTCMode: MatrixRTCMode.Compatibility,
|
||||
});
|
||||
expect(client._unstable_delegateDelayedLeave).not.toHaveBeenCalled();
|
||||
expect(openID.getSFUConfig).toHaveBeenCalledWith(
|
||||
@@ -330,18 +303,4 @@ describe("delegateDelayedLeave", () => {
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("does not fall back to OpenID with url + livekit_service_url transport", async () => {
|
||||
client._unstable_delegateDelayedLeave.mockRejectedValueOnce(
|
||||
unsupportedError,
|
||||
);
|
||||
await expect(
|
||||
delegateDelayedLeave({
|
||||
...defaultParams,
|
||||
transport: urlAndServiceUrlTransport,
|
||||
}),
|
||||
).rejects.toThrow();
|
||||
expect(client._unstable_delegateDelayedLeave).toHaveBeenCalled();
|
||||
expect(openID.getSFUConfig).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,7 +14,6 @@ import * as openID from "./openID";
|
||||
import * as csApi from "./csApi";
|
||||
import { type SFUConfig } from "./types";
|
||||
import { NoMatrix2AuthorizationService } from "../../utils/errors";
|
||||
import { MatrixRTCMode } from "../../config/ConfigOptions";
|
||||
|
||||
export type { ClientOpenIDParts } from "./openID";
|
||||
export type { ClientGetTokenParts, ClientDelegationParts } from "./csApi";
|
||||
@@ -80,11 +79,6 @@ export interface GetSFUConfigParams {
|
||||
* Whether we want to publish or only subscribe on the {@link transport}.
|
||||
*/
|
||||
role: "publisher" | "subscriber";
|
||||
/**
|
||||
* The MatrixRTC mode, which decides the format of our membership event and
|
||||
* so the participant identity a publisher must have.
|
||||
*/
|
||||
matrixRTCMode: MatrixRTCMode;
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@@ -99,7 +93,6 @@ export async function getSFUConfig({
|
||||
roomId,
|
||||
slotId,
|
||||
role,
|
||||
matrixRTCMode,
|
||||
logger,
|
||||
}: GetSFUConfigParams): Promise<SFUConfig> {
|
||||
const viaOpenID = async (serviceUrl: string): Promise<SFUConfig> =>
|
||||
@@ -113,7 +106,7 @@ export async function getSFUConfig({
|
||||
logger,
|
||||
});
|
||||
|
||||
const flow = chooseAuthFlow(transport, role, matrixRTCMode);
|
||||
const flow = chooseAuthFlow(transport, role);
|
||||
if (flow.kind === "openID") return await viaOpenID(flow.serviceUrl);
|
||||
|
||||
try {
|
||||
@@ -174,10 +167,6 @@ export interface DelegateDelayedLeaveParams {
|
||||
* The delay ID of the leave event to be delegated.
|
||||
*/
|
||||
delayId: string;
|
||||
/**
|
||||
* The MatrixRTC mode, which decides the format of our membership event.
|
||||
*/
|
||||
matrixRTCMode: MatrixRTCMode;
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
@@ -192,13 +181,12 @@ export async function delegateDelayedLeave({
|
||||
roomId,
|
||||
slotId,
|
||||
delayId,
|
||||
matrixRTCMode,
|
||||
logger,
|
||||
}: DelegateDelayedLeaveParams): Promise<void> {
|
||||
// It's important that we use the same flow (CS API or OpenID) as whatever we
|
||||
// would've used to get a JWT token for this transport, since the participant
|
||||
// identity computed by the service needs to match.
|
||||
const flow = chooseAuthFlow(transport, "publisher", matrixRTCMode);
|
||||
const flow = chooseAuthFlow(transport, "publisher");
|
||||
if (flow.kind === "csApi") {
|
||||
try {
|
||||
await csApi.delegateDelayedLeave({
|
||||
@@ -246,25 +234,19 @@ export type AuthFlow =
|
||||
*
|
||||
* Only the JWT service's `/sfu/get` endpoint assigns the legacy participant
|
||||
* identity that clients predating MSC4195 expect from anyone advertising a
|
||||
* membership state event, which is what compatibility mode sends. So a
|
||||
* publisher in compatibility mode keeps using the JWT service wherever the
|
||||
* transport still offers one, even if it also has a `url`. Subscribers may use
|
||||
* the CS API regardless, as nobody matches their identity.
|
||||
* membership state event. So a publisher keeps using the JWT service wherever
|
||||
* the transport still offers one, even if it also has a `url`. Subscribers may
|
||||
* use the CS API regardless, as nobody matches their identity.
|
||||
* @param transport The transport to authenticate against.
|
||||
* @param role Whether we want to publish or only subscribe on the transport.
|
||||
* @param matrixRTCMode The MatrixRTC mode, which decides the format of our
|
||||
* membership event.
|
||||
*/
|
||||
export function chooseAuthFlow(
|
||||
transport: UnstableLivekitTransport,
|
||||
role: "publisher" | "subscriber",
|
||||
matrixRTCMode: MatrixRTCMode,
|
||||
): AuthFlow {
|
||||
if ("url" in transport) {
|
||||
const useCsApi =
|
||||
!("livekit_service_url" in transport) ||
|
||||
role === "subscriber" ||
|
||||
matrixRTCMode === MatrixRTCMode.Matrix_2_0;
|
||||
!("livekit_service_url" in transport) || role === "subscriber";
|
||||
if (useCsApi) return { kind: "csApi", url: transport.url };
|
||||
}
|
||||
return { kind: "openID", serviceUrl: transport.livekit_service_url };
|
||||
|
||||
Reference in New Issue
Block a user