Fix MSC4143: advertise org.matrix.msc4143 in /versions unstable_features#19646
Conversation
There was a problem hiding this comment.
Pull request overview
Fixes regressions in Synapse’s MSC4143 (MatrixRTC) support by making the RTC transports endpoint usable as a public discovery API and ensuring MSC4143 capability is advertised via /versions.
Changes:
- Remove authentication requirement from
/_matrix/client/unstable/org.matrix.msc4143/rtc/transports. - Advertise
org.matrix.msc4143in/versionsunstable_featureswhenmsc4143_enabledis set. - Update/add tests and add a changelog fragment documenting the fixes.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
synapse/rest/client/matrixrtc.py |
Makes /rtc/transports a public (unauthenticated) discovery endpoint. |
synapse/rest/client/versions.py |
Adds org.matrix.msc4143 to /versions unstable_features. |
tests/rest/client/test_matrixrtc.py |
Updates tests to reflect unauthenticated access expectations. |
changelog.d/99999.bugfix |
Documents the two MSC4143 bugfixes. |
Comments suppressed due to low confidence (1)
synapse/rest/client/matrixrtc.py:46
- Now that this endpoint is intentionally public, returning
hs.config.matrix_rtc.transportsverbatim increases the risk of accidentally exposing sensitive or irrelevant config keys if an admin misconfiguresmatrix_rtc.transports(the config model currently accepts an untyped list). Consider sanitizing/validating the response to a strict schema (e.g. whitelist allowed keys per transport type) before returning it.
async def on_GET(self, request: SynapseRequest) -> tuple[int, JsonDict]:
# No authentication required: this is a public discovery endpoint.
# Clients such as Element X call it without a token to determine
# whether the server supports MatrixRTC before establishing a session.
if self._transports:
return 200, {"rtc_transports": self._transports}
return 200, {}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @override_config({"experimental_features": {"msc4143_enabled": True}}) | ||
| def test_matrixrtc_endpoint_requires_authentication(self) -> None: | ||
| def test_matrixrtc_endpoint_accessible_without_authentication(self) -> None: | ||
| """The /rtc/transports endpoint is a public discovery endpoint. | ||
| Clients use it to check MatrixRTC support before establishing a session, | ||
| so it must not require authentication. | ||
| """ | ||
| channel = self.make_request("GET", f"{PATH_PREFIX}/rtc/transports") | ||
| self.assertEqual(401, channel.code, channel.json_body) | ||
| self.assertEqual(200, channel.code, channel.json_body) |
There was a problem hiding this comment.
The new unauthenticated-access test only checks the no-transports case (default config). To prevent regressions, add a test that configures at least one matrix_rtc.transports entry and verifies an unauthenticated GET returns 200 and includes that transport (the existing transport-content test currently uses an access token).
| @@ -0,0 +1 @@ | |||
| Fix `/_matrix/client/unstable/org.matrix.msc4143/rtc/transports` returning 401 for unauthenticated requests. This endpoint is a public discovery endpoint used by clients (e.g. Element X) to check MatrixRTC support before establishing a session. Also advertise `org.matrix.msc4143` in `unstable_features` when `msc4143_enabled` is set. | |||
There was a problem hiding this comment.
The changelog fragment filename 99999.bugfix looks like a placeholder rather than the usual issue/PR-number-based naming used elsewhere in changelog.d/ (e.g. 19615.doc, 19633.misc). Rename this fragment to the correct number to avoid collisions and keep towncrier fragments traceable.
| ), | ||
| # MSC4140: Delayed events | ||
| "org.matrix.msc4140": bool(self.config.server.max_event_delay_ms), | ||
| # MSC4143: Matrix RTC transports (LiveKit backend) | ||
| "org.matrix.msc4143": self.config.experimental.msc4143_enabled, | ||
| # Simplified sliding sync |
There was a problem hiding this comment.
This adds a new /versions unstable_features flag for MSC4143, but there’s no accompanying test asserting it is false by default and true when experimental_features.msc4143_enabled is set (similar to the existing coverage for org.matrix.msc4140 in tests/rest/client/test_delayed_events.py). Adding a small /versions test would help prevent regressions.
reivilibre
left a comment
There was a problem hiding this comment.
Thanks, though not seeing this matching the MSC
| # MSC4140: Delayed events | ||
| "org.matrix.msc4140": bool(self.config.server.max_event_delay_ms), | ||
| # MSC4143: Matrix RTC transports (LiveKit backend) | ||
| "org.matrix.msc4143": self.config.experimental.msc4143_enabled, |
There was a problem hiding this comment.
org.matrix.msc4143 missing from unstable_features in /versions
Setting msc4143_enabled: true in experimental_features correctly registers the REST endpoint, but the corresponding org.matrix.msc4143 flag was never added to the unstable_features map returned by /_matrix/client/versions. Every other experimental MSC follows the pattern of advertising itself there; MSC4143 was simply missed.
This needs to be fixed in the MSC if desired.
The MSC does not currently prescribe this flag to be added to /versions
There was a problem hiding this comment.
yeah fair point, the msc’s unstable prefix section doesn't mention this. looks like it just got missed - every other msc does this and without it clients have no way to know if the unstable endpoint exists
i can open a pr on matrix-spec-proposals to add it. do you want me to keep this change here in the meantime or should i pull it out until the msc is updated?
There was a problem hiding this comment.
I've added a thread on the MSC matrix-org/matrix-spec-proposals#4143 (comment)
We can see if the author gets back to us
I think it probably makes sense to have one (though it's not an automatic thing for every MSC as it's not always the case)
|
|
||
| async def on_GET(self, request: SynapseRequest) -> tuple[int, JsonDict]: | ||
| # Require authentication for this endpoint. | ||
| await self._auth.get_user_by_req(request) |
There was a problem hiding this comment.
not seeing in the MSC where it says this should be public, please can you point it out?
There was a problem hiding this comment.
hey, so the msc doesn't explicitly say "no auth required", but I think the client behaviour makes it pretty clear that's the intent. there's a bunch of people in #19621 who captured their server logs and you can see element x straight up not sending an authorization header for this endpoint #19621 (comment). it's not a bug in the client - it's calling it as a pre-call capability check, before any session is started.
makes sense when you think about it - the section is literally called "Discovery of RTC Transports", and discovery endpoints in matrix are always public (/versions, .well-known, etc). the msc's security section mentions each transport having its own auth - that's about the livekit jwt stuff, not about who can hit the discovery endpoint.
if you'd rather have it spelled out in the msc i can open a pr there too, just lmk
There was a problem hiding this comment.
update: just tested this on a live server - upgraded to 1.151.0 (stock, no patches), tried making a call in Element X 26.04.2, and got this in the server logs immediately:
GET /_matrix/client/unstable/org.matrix.msc4143/rtc/transports
-> 401 Missing access token
User-Agent: Element X/26.04.2 (Google Pixel 7; Android 17)
call failed instantly. reverted to the patched version, call worked. so this is reproducible on the latest client version too, and .well-known/rtc_foci alone doesn't help - Element X hits this endpoint regardless
There was a problem hiding this comment.
also found matrix-org/matrix-js-sdk#5245 which kinda explains the whole thing - Element Call runs as a widget inside Element X, and RoomWidgetClient just... can't send auth tokens directly, it goes through the widget api instead. so yeah, the endpoint kinda needs to be public by design
There was a problem hiding this comment.
This thread on the MSC matrix-org/matrix-spec-proposals#4143 (comment) seems to cover the auth aspect, where there is at least one comment from someone believing it is meant to require authentication.
In my opinion this endpoint should require authentication because the server doesn't want to provide its RTC servers to unauthenticated people.
(This is also why the existing TURN server discovery endpoint requires authentication: https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3voipturnserver)
But I think I will need to ask the MSC author to be doubly sure.
There was a problem hiding this comment.
See matrix-org/matrix-spec-proposals#4143 (comment)
TL/DR the endpoint requires authentication:
- The design of MatrixRTC transports requires only local clients to access the transport list. Clients from other homeserver need to pickup the required information from the MatrixRTC membership event(s)
- For example, the Multi-SFU MatrixRTC Transport (MSC4195: MatrixRTC Transport using LiveKit Backend matrix-org/matrix-spec-proposals#4195)
- Hence, only "local" clients need to access MatrixRTC backend information
- Clients from other homeserver get the information via https://github.com/hughns/matrix-spec-proposals/blob/hughns/matrixrtc-livekit/proposals/4195-matrixrtc-livekit.md#transport-usage-client
There was a problem hiding this comment.
Here is the updated MSC paragraph
The /_matrix/client/unstable/org.matrix.msc4143/rtc/transports endpoint was incorrectly requiring authentication. Clients such as Element X (26.03.3+) call this endpoint without an access token to discover whether the server supports MatrixRTC before establishing a session. The 401 response caused these clients to show "call not supported". Additionally, the org.matrix.msc4143 flag was not being advertised in the unstable_features map of /_matrix/client/versions, even when msc4143_enabled was set in experimental_features. This inconsistency meant clients that check unstable_features (instead of or in addition to /rtc/transports) would also incorrectly conclude calls are unsupported. Closes element-hq#19621 Closes element-hq#19580
- Add unauthenticated test with transport data configured - Add /versions unstable_features test for org.matrix.msc4143 - Rename changelog fragment from 99999.bugfix to 19646.bugfix
9a5a471 to
0415504
Compare
|
For context, this is now fixed in EC: EC will only use this endpoint (and expects it to be authenticated) if it has an access token: /**
* Fetches the first rtc_foci from the backend.
* This will not throw errors, but instead just log them and return null if the expected config is not found or malformed.
* @private
*/
private async tryBackendTransports(): Promise<LivekitTransportConfig | null> {
const client = this.client;
// MSC4143: Attempt to fetch transports from backend.
// TODO: Workaround for an issue in the js-sdk RoomWidgetClient that
// is not yet implementing _unstable_getRTCTransports properly (via widget API new action).
// For now we just skip this call if we are in a widget.
// In widget mode the client is a `RoomWidgetClient` which has no access token (it is using the widget API).
// Could be removed once the js-sdk is fixed (https://github.com/matrix-org/matrix-js-sdk/issues/5245)
const isSPA = !!client.getAccessToken();
if (isSPA && "_unstable_getRTCTransports" in client) {
this.logger.info("First try to use getRTCTransports end point ...");
try {
const transportList = await doNetworkOperationWithRetry(async () =>
client._unstable_getRTCTransports(),
);
const first = transportList.filter(isLivekitTransportConfig)[0];
if (first) {
return first;
} else {
this.logger.info(
`No livekit transport found in getRTCTransports end point`,
transportList,
);
}
} catch (ex) {
this.logger.info(`Failed to use getRTCTransports end point: ${ex}`);
}
} else {
this.logger.debug(`getRTCTransports end point not available`);
}
return null;
} |
|
ok makes sense, dropping the auth change after fkwp's comment. didn't realize that was intentional by design |
revert matrixrtc.py to require authentication per MSC4143 design (fkwp confirmed this is intentional). widget mode issue tracked in matrix-org/matrix-js-sdk#5245. keep the org.matrix.msc4143 unstable_features advertisement in /versions.
What does this PR do?
org.matrix.msc4143was missing from theunstable_featuresmap returned by/_matrix/client/versionswhenmsc4143_enabled: trueis set. Every other experimental MSC follows this pattern; MSC4143 was simply missed.Without this flag, clients have no standard way to discover whether the server supports MSC4143 before calling the endpoint.
The fix adds the flag in line with the existing pattern, along with tests.
Closes #19580