Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 308ce68

Browse files
committed
Implement MSC3882 revision 1
1 parent 6d10337 commit 308ce68

File tree

7 files changed

+81
-13
lines changed

7 files changed

+81
-13
lines changed

synapse/rest/client/capabilities.py

+5
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ async def on_GET(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
8282
"enabled": self.config.experimental.msc3664_enabled,
8383
}
8484

85+
if self.config.experimental.msc3882_enabled:
86+
response["capabilities"]["org.matrix.msc3882.get_login_token"] = {
87+
"enabled": True,
88+
}
89+
8590
return HTTPStatus.OK, response
8691

8792

synapse/rest/client/login.py

+14-2
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ def __init__(self, hs: "HomeServer"):
107107
and hs.config.experimental.msc3866.require_approval_for_new_accounts
108108
)
109109

110+
# Whether MSC3882 get login token is enabled.
111+
self._get_login_token_enabled = hs.config.experimental.msc3882_enabled
112+
110113
self.auth = hs.get_auth()
111114

112115
self.clock = hs.get_clock()
@@ -145,7 +148,12 @@ def on_GET(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
145148
# to SSO.
146149
flows.append({"type": LoginRestServlet.CAS_TYPE})
147150

148-
if self.cas_enabled or self.saml2_enabled or self.oidc_enabled:
151+
if (
152+
self.cas_enabled
153+
or self.saml2_enabled
154+
or self.oidc_enabled
155+
or self._get_login_token_enabled
156+
):
149157
flows.append(
150158
{
151159
"type": LoginRestServlet.SSO_TYPE,
@@ -163,7 +171,11 @@ def on_GET(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
163171
# don't know how to implement, since they (currently) will always
164172
# fall back to the fallback API if they don't understand one of the
165173
# login flow types returned.
166-
flows.append({"type": LoginRestServlet.TOKEN_TYPE})
174+
tokenTypeFlow: Dict[str, Any] = {"type": LoginRestServlet.TOKEN_TYPE}
175+
# If MSC3882 is enabled we advertise the get_login_token flag.
176+
if self._get_login_token_enabled:
177+
tokenTypeFlow["org.matrix.msc3882.get_login_token"] = True
178+
flows.append(tokenTypeFlow)
167179

168180
flows.extend({"type": t} for t in self.auth_handler.get_supported_login_types())
169181

synapse/rest/client/login_token_request.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class LoginTokenRequestServlet(RestServlet):
3333
3434
Request:
3535
36-
POST /login/token HTTP/1.1
36+
POST /login/get_token HTTP/1.1
3737
Content-Type: application/json
3838
3939
{}
@@ -43,12 +43,12 @@ class LoginTokenRequestServlet(RestServlet):
4343
HTTP/1.1 200 OK
4444
{
4545
"login_token": "ABDEFGH",
46-
"expires_in": 3600,
46+
"expires_in_ms": 3600000,
4747
}
4848
"""
4949

5050
PATTERNS = client_patterns(
51-
"/org.matrix.msc3882/login/token$", releases=[], v1=False, unstable=True
51+
"/org.matrix.msc3882/login/get_token$", releases=[], v1=False, unstable=True
5252
)
5353

5454
def __init__(self, hs: "HomeServer"):
@@ -77,15 +77,15 @@ async def on_POST(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
7777

7878
login_token = await self.auth_handler.create_login_token_for_user_id(
7979
user_id=requester.user.to_string(),
80-
auth_provider_id="org.matrix.msc3882.login_token_request",
80+
auth_provider_id="org.matrix.msc3882.get_login_token",
8181
duration_ms=self.token_timeout,
8282
)
8383

8484
return (
8585
200,
8686
{
8787
"login_token": login_token,
88-
"expires_in": self.token_timeout // 1000,
88+
"expires_in_ms": self.token_timeout,
8989
},
9090
)
9191

synapse/rest/client/versions.py

-2
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,6 @@ def on_GET(self, request: Request) -> Tuple[int, JsonDict]:
112112
"fi.mau.msc2815": self.config.experimental.msc2815_enabled,
113113
# Adds a ping endpoint for appservices to check HS->AS connection
114114
"fi.mau.msc2659": self.config.experimental.msc2659_enabled,
115-
# Adds support for login token requests as per MSC3882
116-
"org.matrix.msc3882": self.config.experimental.msc3882_enabled,
117115
# Adds support for remotely enabling/disabling pushers, as per MSC3881
118116
"org.matrix.msc3881": self.config.experimental.msc3881_enabled,
119117
# Adds support for filtering /messages by event relation.

tests/rest/client/test_capabilities.py

+30
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,33 @@ def test_get_does_include_msc3244_fields_when_enabled(self) -> None:
186186
self.assertGreater(len(details["support"]), 0)
187187
for room_version in details["support"]:
188188
self.assertTrue(room_version in KNOWN_ROOM_VERSIONS, str(room_version))
189+
190+
def test_get_does_not_include_msc3882_fields_when_disabled(self) -> None:
191+
access_token = self.get_success(
192+
self.auth_handler.create_access_token_for_user_id(
193+
self.user, device_id=None, valid_until_ms=None
194+
)
195+
)
196+
197+
channel = self.make_request("GET", self.url, access_token=access_token)
198+
capabilities = channel.json_body["capabilities"]
199+
200+
self.assertEqual(channel.code, HTTPStatus.OK)
201+
self.assertTrue(
202+
"org.matrix.msc3882.get_login_token" not in capabilities
203+
or not capabilities["org.matrix.msc3882.get_login_token"]["enabled"]
204+
)
205+
206+
@override_config({"experimental_features": {"msc3882_enabled": True}})
207+
def test_get_does_include_msc3882_fields_when_enabled(self) -> None:
208+
access_token = self.get_success(
209+
self.auth_handler.create_access_token_for_user_id(
210+
self.user, device_id=None, valid_until_ms=None
211+
)
212+
)
213+
214+
channel = self.make_request("GET", self.url, access_token=access_token)
215+
capabilities = channel.json_body["capabilities"]
216+
217+
self.assertEqual(channel.code, HTTPStatus.OK)
218+
self.assertTrue(capabilities["org.matrix.msc3882.get_login_token"]["enabled"])

tests/rest/client/test_login.py

+23
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,29 @@ def test_require_approval(self) -> None:
446446
ApprovalNoticeMedium.NONE, channel.json_body["approval_notice_medium"]
447447
)
448448

449+
def test_get_login_flows_with_msc3882_disabled(self) -> None:
450+
"""GET /login should return m.login.token without get_login_token true"""
451+
channel = self.make_request("GET", "/_matrix/client/r0/login")
452+
self.assertEqual(channel.code, 200, channel.result)
453+
454+
flows = {flow["type"]: flow for flow in channel.json_body["flows"]}
455+
self.assertTrue(
456+
"m.login.token" not in flows
457+
or "org.matrix.msc3882.get_login_token" not in flows["m.login.token"]
458+
or not flows["m.login.token"]["org.matrix.msc3882.get_login_token"]
459+
)
460+
461+
@override_config({"experimental_features": {"msc3882_enabled": True}})
462+
def test_get_login_flows_with_msc3882_enabled(self) -> None:
463+
"""GET /login should return m.login.token without get_login_token true"""
464+
channel = self.make_request("GET", "/_matrix/client/r0/login")
465+
self.assertEqual(channel.code, 200, channel.result)
466+
467+
print(channel.json_body)
468+
469+
flows = {flow["type"]: flow for flow in channel.json_body["flows"]}
470+
self.assertTrue(flows["m.login.token"]["org.matrix.msc3882.get_login_token"])
471+
449472

450473
@skip_unless(has_saml2 and HAS_OIDC, "Requires SAML2 and OIDC")
451474
class MultiSSOTestCase(unittest.HomeserverTestCase):

tests/rest/client/test_login_token_request.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from tests import unittest
2323
from tests.unittest import override_config
2424

25-
endpoint = "/_matrix/client/unstable/org.matrix.msc3882/login/token"
25+
endpoint = "/_matrix/client/unstable/org.matrix.msc3882/login/get_token"
2626

2727

2828
class LoginTokenRequestServletTestCase(unittest.HomeserverTestCase):
@@ -82,7 +82,7 @@ def test_uia_on(self) -> None:
8282

8383
channel = self.make_request("POST", endpoint, uia, access_token=token)
8484
self.assertEqual(channel.code, 200)
85-
self.assertEqual(channel.json_body["expires_in"], 300)
85+
self.assertEqual(channel.json_body["expires_in_ms"], 300000)
8686

8787
login_token = channel.json_body["login_token"]
8888

@@ -103,7 +103,7 @@ def test_uia_off(self) -> None:
103103

104104
channel = self.make_request("POST", endpoint, {}, access_token=token)
105105
self.assertEqual(channel.code, 200)
106-
self.assertEqual(channel.json_body["expires_in"], 300)
106+
self.assertEqual(channel.json_body["expires_in_ms"], 300000)
107107

108108
login_token = channel.json_body["login_token"]
109109

@@ -130,4 +130,4 @@ def test_expires_in(self) -> None:
130130

131131
channel = self.make_request("POST", endpoint, {}, access_token=token)
132132
self.assertEqual(channel.code, 200)
133-
self.assertEqual(channel.json_body["expires_in"], 15)
133+
self.assertEqual(channel.json_body["expires_in_ms"], 15000)

0 commit comments

Comments
 (0)