mirror of
https://github.com/element-hq/synapse.git
synced 2026-03-29 06:39:55 +00:00
Updates for experimental MSC4388 support (sign-in with QR code) (#19573)
This commit is contained in:
1
changelog.d/19573.feature
Normal file
1
changelog.d/19573.feature
Normal file
@@ -0,0 +1 @@
|
||||
Updated experimental support for [MSC4388: Secure out-of-band channel for sign in with QR](https://github.com/matrix-org/matrix-spec-proposals/pull/4388).
|
||||
@@ -538,9 +538,9 @@ class ExperimentalConfig(Config):
|
||||
# See: https://github.com/element-hq/synapse/issues/19433
|
||||
msc4388_mode = experimental.get("msc4388_mode", "off")
|
||||
|
||||
if msc4388_mode not in ["off", "public", "authenticated"]:
|
||||
if msc4388_mode not in ["off", "open", "authenticated"]:
|
||||
raise ConfigError(
|
||||
"msc4388_mode must be one of 'off', 'public' or 'authenticated'",
|
||||
"msc4388_mode must be one of 'off', 'open' or 'authenticated'",
|
||||
("experimental", "msc4388_mode"),
|
||||
)
|
||||
self.msc4388_enabled: bool = msc4388_mode != "off"
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#
|
||||
|
||||
import logging
|
||||
from http import HTTPStatus
|
||||
from http.client import TEMPORARY_REDIRECT
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
@@ -81,6 +82,12 @@ class MSC4388CreateRendezvousServlet(RestServlet):
|
||||
hs.config.experimental.msc4388_requires_authentication
|
||||
)
|
||||
|
||||
async def on_GET(self, request: SynapseRequest) -> tuple[int, Any]:
|
||||
if self.require_authentication:
|
||||
# This will raise if the user is not authenticated
|
||||
await self.auth.get_user_by_req(request)
|
||||
return HTTPStatus.OK, {"create_available": True}
|
||||
|
||||
async def on_POST(self, request: SynapseRequest) -> tuple[int, Any]:
|
||||
if self.require_authentication:
|
||||
# This will raise if the user is not authenticated
|
||||
|
||||
@@ -189,8 +189,6 @@ class VersionsRestServlet(RestServlet):
|
||||
is not None
|
||||
)
|
||||
),
|
||||
# MSC4388: Secure out-of-band channel for sign in with QR
|
||||
"io.element.msc4388": (self.config.experimental.msc4388_enabled),
|
||||
# MSC4140: Delayed events
|
||||
"org.matrix.msc4140": bool(self.config.server.max_event_delay_ms),
|
||||
# Simplified sliding sync
|
||||
|
||||
@@ -131,6 +131,10 @@ class RendezvousServletTestCase(unittest.HomeserverTestCase):
|
||||
}
|
||||
)
|
||||
def test_off(self) -> None:
|
||||
# Discovery endpoint should return 404
|
||||
channel = self.make_request("GET", rz_endpoint, {}, access_token=None)
|
||||
self.assertEqual(channel.code, 404)
|
||||
# Create session should also fail
|
||||
channel = self.make_request("POST", rz_endpoint, {}, access_token=None)
|
||||
self.assertEqual(channel.code, 404)
|
||||
|
||||
@@ -143,7 +147,7 @@ class RendezvousServletTestCase(unittest.HomeserverTestCase):
|
||||
"endpoint": "https://issuer",
|
||||
},
|
||||
"experimental_features": {
|
||||
"msc4388_mode": "public",
|
||||
"msc4388_mode": "open",
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -156,6 +160,11 @@ class RendezvousServletTestCase(unittest.HomeserverTestCase):
|
||||
- Deleting the data
|
||||
- Sequence token handling
|
||||
"""
|
||||
# Discovery should return 200
|
||||
channel = self.make_request("GET", rz_endpoint, {}, access_token=None)
|
||||
self.assertEqual(channel.code, 200)
|
||||
self.assertTrue(channel.json_body.get("create_available"))
|
||||
|
||||
# We can post arbitrary data to the endpoint
|
||||
channel = self.make_request(
|
||||
"POST",
|
||||
@@ -268,7 +277,11 @@ class RendezvousServletTestCase(unittest.HomeserverTestCase):
|
||||
self.setup_mock_oauth()
|
||||
alice_token = self.register_oauth_user("alice", "device1")
|
||||
|
||||
# This should fail without authentication:
|
||||
# Discovery should fail due to lack of authentication
|
||||
channel = self.make_request("GET", rz_endpoint, {}, access_token=None)
|
||||
self.assertEqual(channel.code, 401)
|
||||
|
||||
# Creating a session should fail without authentication:
|
||||
channel = self.make_request(
|
||||
"POST",
|
||||
rz_endpoint,
|
||||
@@ -277,6 +290,11 @@ class RendezvousServletTestCase(unittest.HomeserverTestCase):
|
||||
)
|
||||
self.assertEqual(channel.code, 401)
|
||||
|
||||
# Discovery should succeed with authentication
|
||||
channel = self.make_request("GET", rz_endpoint, {}, access_token=alice_token)
|
||||
self.assertEqual(channel.code, 200)
|
||||
self.assertTrue(channel.json_body.get("create_available"))
|
||||
|
||||
# This should work as we are now authenticated
|
||||
channel = self.make_request(
|
||||
"POST",
|
||||
@@ -288,7 +306,7 @@ class RendezvousServletTestCase(unittest.HomeserverTestCase):
|
||||
rendezvous_id = channel.json_body["id"]
|
||||
sequence_token = channel.json_body["sequence_token"]
|
||||
expires_in_ms = channel.json_body["expires_in_ms"]
|
||||
self.assertGreater(expires_in_ms, 0)
|
||||
self.assertEqual(expires_in_ms, 120000)
|
||||
|
||||
session_endpoint = rz_endpoint + f"/{rendezvous_id}"
|
||||
|
||||
@@ -302,7 +320,7 @@ class RendezvousServletTestCase(unittest.HomeserverTestCase):
|
||||
self.assertEqual(channel.code, 200)
|
||||
self.assertEqual(channel.json_body["data"], "foo=bar")
|
||||
self.assertEqual(channel.json_body["sequence_token"], sequence_token)
|
||||
self.assertEqual(channel.json_body["expires_in_ms"], expires_in_ms)
|
||||
self.assertEqual(channel.json_body["expires_in_ms"], expires_in_ms - 100)
|
||||
|
||||
# We can update the data without authentication
|
||||
channel = self.make_request(
|
||||
@@ -325,7 +343,7 @@ class RendezvousServletTestCase(unittest.HomeserverTestCase):
|
||||
self.assertEqual(channel.code, 200)
|
||||
self.assertEqual(channel.json_body["data"], "foo=baz")
|
||||
self.assertEqual(channel.json_body["sequence_token"], new_sequence_token)
|
||||
self.assertEqual(channel.json_body["expires_in_ms"], expires_in_ms - 200)
|
||||
self.assertEqual(channel.json_body["expires_in_ms"], expires_in_ms - 300)
|
||||
|
||||
# We can delete the data without authentication
|
||||
channel = self.make_request(
|
||||
@@ -355,7 +373,7 @@ class RendezvousServletTestCase(unittest.HomeserverTestCase):
|
||||
"endpoint": "https://issuer",
|
||||
},
|
||||
"experimental_features": {
|
||||
"msc4388_mode": "public",
|
||||
"msc4388_mode": "open",
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -402,7 +420,7 @@ class RendezvousServletTestCase(unittest.HomeserverTestCase):
|
||||
"endpoint": "https://issuer",
|
||||
},
|
||||
"experimental_features": {
|
||||
"msc4388_mode": "public",
|
||||
"msc4388_mode": "open",
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -473,7 +491,7 @@ class RendezvousServletTestCase(unittest.HomeserverTestCase):
|
||||
"endpoint": "https://issuer",
|
||||
},
|
||||
"experimental_features": {
|
||||
"msc4388_mode": "public",
|
||||
"msc4388_mode": "open",
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -531,7 +549,7 @@ class RendezvousServletTestCase(unittest.HomeserverTestCase):
|
||||
"endpoint": "https://issuer",
|
||||
},
|
||||
"experimental_features": {
|
||||
"msc4388_mode": "public",
|
||||
"msc4388_mode": "open",
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -585,7 +603,7 @@ class RendezvousServletTestCase(unittest.HomeserverTestCase):
|
||||
"endpoint": "https://issuer",
|
||||
},
|
||||
"experimental_features": {
|
||||
"msc4388_mode": "public",
|
||||
"msc4388_mode": "open",
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -648,7 +666,7 @@ class RendezvousServletTestCase(unittest.HomeserverTestCase):
|
||||
"endpoint": "https://issuer",
|
||||
},
|
||||
"experimental_features": {
|
||||
"msc4388_mode": "public",
|
||||
"msc4388_mode": "open",
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -698,7 +716,7 @@ class RendezvousServletTestCase(unittest.HomeserverTestCase):
|
||||
"endpoint": "https://issuer",
|
||||
},
|
||||
"experimental_features": {
|
||||
"msc4388_mode": "public",
|
||||
"msc4388_mode": "open",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user