mirror of
https://mau.dev/maunium/synapse.git
synced 2024-09-29 20:55:39 +00:00
Support for MSC4108 via delegation (#17086)
This adds support for MSC4108 via delegation, similar to what has been done for MSC3886 --------- Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
This commit is contained in:
parent
28f5ad07d3
commit
c8e0bed426
1
changelog.d/17086.feature
Normal file
1
changelog.d/17086.feature
Normal file
@ -0,0 +1 @@
|
|||||||
|
Support delegating the rendezvous mechanism described MSC4108 to an external implementation.
|
@ -411,3 +411,14 @@ class ExperimentalConfig(Config):
|
|||||||
self.msc4069_profile_inhibit_propagation = experimental.get(
|
self.msc4069_profile_inhibit_propagation = experimental.get(
|
||||||
"msc4069_profile_inhibit_propagation", False
|
"msc4069_profile_inhibit_propagation", False
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# MSC4108: Mechanism to allow OIDC sign in and E2EE set up via QR code
|
||||||
|
self.msc4108_delegation_endpoint: Optional[str] = experimental.get(
|
||||||
|
"msc4108_delegation_endpoint", None
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.msc4108_delegation_endpoint is not None and not self.msc3861.enabled:
|
||||||
|
raise ConfigError(
|
||||||
|
"MSC4108 requires MSC3861 to be enabled",
|
||||||
|
("experimental", "msc4108_delegation_endpoint"),
|
||||||
|
)
|
||||||
|
@ -909,7 +909,18 @@ def set_cors_headers(request: "SynapseRequest") -> None:
|
|||||||
request.setHeader(
|
request.setHeader(
|
||||||
b"Access-Control-Allow-Methods", b"GET, HEAD, POST, PUT, DELETE, OPTIONS"
|
b"Access-Control-Allow-Methods", b"GET, HEAD, POST, PUT, DELETE, OPTIONS"
|
||||||
)
|
)
|
||||||
if request.experimental_cors_msc3886:
|
if request.path is not None and request.path.startswith(
|
||||||
|
b"/_matrix/client/unstable/org.matrix.msc4108/rendezvous"
|
||||||
|
):
|
||||||
|
request.setHeader(
|
||||||
|
b"Access-Control-Allow-Headers",
|
||||||
|
b"Content-Type, If-Match, If-None-Match",
|
||||||
|
)
|
||||||
|
request.setHeader(
|
||||||
|
b"Access-Control-Expose-Headers",
|
||||||
|
b"Synapse-Trace-Id, Server, ETag",
|
||||||
|
)
|
||||||
|
elif request.experimental_cors_msc3886:
|
||||||
request.setHeader(
|
request.setHeader(
|
||||||
b"Access-Control-Allow-Headers",
|
b"Access-Control-Allow-Headers",
|
||||||
b"X-Requested-With, Content-Type, Authorization, Date, If-Match, If-None-Match",
|
b"X-Requested-With, Content-Type, Authorization, Date, If-Match, If-None-Match",
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# This file is licensed under the Affero General Public License (AGPL) version 3.
|
# This file is licensed under the Affero General Public License (AGPL) version 3.
|
||||||
#
|
#
|
||||||
# Copyright 2022 The Matrix.org Foundation C.I.C.
|
# Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||||
# Copyright (C) 2023 New Vector, Ltd
|
# Copyright (C) 2023-2024 New Vector, Ltd
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU Affero General Public License as
|
# it under the terms of the GNU Affero General Public License as
|
||||||
@ -34,7 +34,7 @@ if TYPE_CHECKING:
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class RendezvousServlet(RestServlet):
|
class MSC3886RendezvousServlet(RestServlet):
|
||||||
"""
|
"""
|
||||||
This is a placeholder implementation of [MSC3886](https://github.com/matrix-org/matrix-spec-proposals/pull/3886)
|
This is a placeholder implementation of [MSC3886](https://github.com/matrix-org/matrix-spec-proposals/pull/3886)
|
||||||
simple client rendezvous capability that is used by the "Sign in with QR" functionality.
|
simple client rendezvous capability that is used by the "Sign in with QR" functionality.
|
||||||
@ -76,6 +76,30 @@ class RendezvousServlet(RestServlet):
|
|||||||
# PUT, GET and DELETE are not implemented as they should be fulfilled by the redirect target.
|
# PUT, GET and DELETE are not implemented as they should be fulfilled by the redirect target.
|
||||||
|
|
||||||
|
|
||||||
|
class MSC4108DelegationRendezvousServlet(RestServlet):
|
||||||
|
PATTERNS = client_patterns(
|
||||||
|
"/org.matrix.msc4108/rendezvous$", releases=[], v1=False, unstable=True
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, hs: "HomeServer"):
|
||||||
|
super().__init__()
|
||||||
|
redirection_target: Optional[str] = (
|
||||||
|
hs.config.experimental.msc4108_delegation_endpoint
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
redirection_target is not None
|
||||||
|
), "Servlet is only registered if there is a delegation target"
|
||||||
|
self.endpoint = redirection_target.encode("utf-8")
|
||||||
|
|
||||||
|
async def on_POST(self, request: SynapseRequest) -> None:
|
||||||
|
respond_with_redirect(
|
||||||
|
request, self.endpoint, statusCode=TEMPORARY_REDIRECT, cors=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None:
|
def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None:
|
||||||
if hs.config.experimental.msc3886_endpoint is not None:
|
if hs.config.experimental.msc3886_endpoint is not None:
|
||||||
RendezvousServlet(hs).register(http_server)
|
MSC3886RendezvousServlet(hs).register(http_server)
|
||||||
|
|
||||||
|
if hs.config.experimental.msc4108_delegation_endpoint is not None:
|
||||||
|
MSC4108DelegationRendezvousServlet(hs).register(http_server)
|
||||||
|
@ -140,6 +140,9 @@ class VersionsRestServlet(RestServlet):
|
|||||||
"org.matrix.msc4069": self.config.experimental.msc4069_profile_inhibit_propagation,
|
"org.matrix.msc4069": self.config.experimental.msc4069_profile_inhibit_propagation,
|
||||||
# Allows clients to handle push for encrypted events.
|
# Allows clients to handle push for encrypted events.
|
||||||
"org.matrix.msc4028": self.config.experimental.msc4028_push_encrypted_events,
|
"org.matrix.msc4028": self.config.experimental.msc4028_push_encrypted_events,
|
||||||
|
# MSC4108: Mechanism to allow OIDC sign in and E2EE set up via QR code
|
||||||
|
"org.matrix.msc4108": self.config.experimental.msc4108_delegation_endpoint
|
||||||
|
is not None,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -27,8 +27,10 @@ from synapse.util import Clock
|
|||||||
|
|
||||||
from tests import unittest
|
from tests import unittest
|
||||||
from tests.unittest import override_config
|
from tests.unittest import override_config
|
||||||
|
from tests.utils import HAS_AUTHLIB
|
||||||
|
|
||||||
endpoint = "/_matrix/client/unstable/org.matrix.msc3886/rendezvous"
|
msc3886_endpoint = "/_matrix/client/unstable/org.matrix.msc3886/rendezvous"
|
||||||
|
msc4108_endpoint = "/_matrix/client/unstable/org.matrix.msc4108/rendezvous"
|
||||||
|
|
||||||
|
|
||||||
class RendezvousServletTestCase(unittest.HomeserverTestCase):
|
class RendezvousServletTestCase(unittest.HomeserverTestCase):
|
||||||
@ -41,11 +43,35 @@ class RendezvousServletTestCase(unittest.HomeserverTestCase):
|
|||||||
return self.hs
|
return self.hs
|
||||||
|
|
||||||
def test_disabled(self) -> None:
|
def test_disabled(self) -> None:
|
||||||
channel = self.make_request("POST", endpoint, {}, access_token=None)
|
channel = self.make_request("POST", msc3886_endpoint, {}, access_token=None)
|
||||||
|
self.assertEqual(channel.code, 404)
|
||||||
|
channel = self.make_request("POST", msc4108_endpoint, {}, access_token=None)
|
||||||
self.assertEqual(channel.code, 404)
|
self.assertEqual(channel.code, 404)
|
||||||
|
|
||||||
@override_config({"experimental_features": {"msc3886_endpoint": "/asd"}})
|
@override_config({"experimental_features": {"msc3886_endpoint": "/asd"}})
|
||||||
def test_redirect(self) -> None:
|
def test_msc3886_redirect(self) -> None:
|
||||||
channel = self.make_request("POST", endpoint, {}, access_token=None)
|
channel = self.make_request("POST", msc3886_endpoint, {}, access_token=None)
|
||||||
self.assertEqual(channel.code, 307)
|
self.assertEqual(channel.code, 307)
|
||||||
self.assertEqual(channel.headers.getRawHeaders("Location"), ["/asd"])
|
self.assertEqual(channel.headers.getRawHeaders("Location"), ["/asd"])
|
||||||
|
|
||||||
|
@unittest.skip_unless(HAS_AUTHLIB, "requires authlib")
|
||||||
|
@override_config(
|
||||||
|
{
|
||||||
|
"disable_registration": True,
|
||||||
|
"experimental_features": {
|
||||||
|
"msc4108_delegation_endpoint": "https://asd",
|
||||||
|
"msc3861": {
|
||||||
|
"enabled": True,
|
||||||
|
"issuer": "https://issuer",
|
||||||
|
"client_id": "client_id",
|
||||||
|
"client_auth_method": "client_secret_post",
|
||||||
|
"client_secret": "client_secret",
|
||||||
|
"admin_token": "admin_token_value",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
def test_msc4108_delegation(self) -> None:
|
||||||
|
channel = self.make_request("POST", msc4108_endpoint, {}, access_token=None)
|
||||||
|
self.assertEqual(channel.code, 307)
|
||||||
|
self.assertEqual(channel.headers.getRawHeaders("Location"), ["https://asd"])
|
||||||
|
Loading…
Reference in New Issue
Block a user