@@ -76,6 +76,82 @@ local function test_access_token_from_query()
7676 )
7777end
7878
79+ local function test_username_decoded_from_synapse_token_without_whoami ()
80+ local request_handle = new_request_handle ({
81+ [" :path" ] = " /_matrix/client/v3/sync" ,
82+ -- syt_<unpadded-base64("alice")>_<random>_<crc>
83+ [" authorization" ] = " Bearer syt_YWxpY2U_abcdefghij1234567890_crc123"
84+ }, function ()
85+ error (" decodable token should not call whoami" )
86+ end )
87+
88+ assert_equal (
89+ synapse .get_user_identifier_from_request (request_handle , {}),
90+ " alice" ,
91+ " localpart should be decoded directly from a syt_ token"
92+ )
93+ end
94+
95+ local function test_username_decoded_consistent_across_devices ()
96+ local handle_a = new_request_handle ({
97+ [" :path" ] = " /_matrix/client/v3/sync" ,
98+ [" authorization" ] = " Bearer syt_Y2Fyb2wtdGVzdF85OQ_deviceAtokenAAAAAAA_crc111"
99+ }, function ()
100+ error (" decodable token should not call whoami" )
101+ end )
102+ local handle_b = new_request_handle ({
103+ [" :path" ] = " /_matrix/client/v3/sync" ,
104+ [" authorization" ] = " Bearer syt_Y2Fyb2wtdGVzdF85OQ_deviceBtokenBBBBBBB_crc222"
105+ }, function ()
106+ error (" decodable token should not call whoami" )
107+ end )
108+
109+ local key_a = synapse .get_user_identifier_from_request (handle_a , {})
110+ local key_b = synapse .get_user_identifier_from_request (handle_b , {})
111+
112+ assert_equal (key_a , " carol-test_99" , " device A should decode to the localpart" )
113+ assert_equal (key_b , " carol-test_99" , " device B should decode to the same localpart" )
114+ assert_equal (key_a , key_b , " the same user on different devices must hash to the same key" )
115+ end
116+
117+ local function test_non_synapse_token_falls_back_to_whoami ()
118+ local calls = 0
119+ local request_handle = new_request_handle ({
120+ [" :path" ] = " /_matrix/client/v3/sync" ,
121+ -- application-service / delegated-auth tokens don't follow the syt_ format
122+ [" authorization" ] = " Bearer as_some_opaque_appservice_token"
123+ }, function (_ , cluster , headers , body , timeout_ms )
124+ calls = calls + 1
125+ return { [" :status" ] = " 200" }, ' {"user_id":"@bridgebot:example.org"}'
126+ end )
127+
128+ assert_equal (
129+ synapse .get_user_identifier_from_request (request_handle , {}),
130+ " bridgebot" ,
131+ " non-syt tokens should resolve via whoami"
132+ )
133+ assert_equal (calls , 1 , " whoami should be used for tokens that aren't locally decodable" )
134+ end
135+
136+ local function test_malformed_synapse_token_falls_back_to_whoami ()
137+ local calls = 0
138+ local request_handle = new_request_handle ({
139+ [" :path" ] = " /_matrix/client/v3/sync" ,
140+ -- looks like a syt_ token, but the middle segment isn't valid base64
141+ [" authorization" ] = " Bearer syt_!!!not-base64!!!_randomstring12345_crc999"
142+ }, function (_ , cluster , headers , body , timeout_ms )
143+ calls = calls + 1
144+ return { [" :status" ] = " 200" }, ' {"user_id":"@erin:example.org"}'
145+ end )
146+
147+ assert_equal (
148+ synapse .get_user_identifier_from_request (request_handle , {}),
149+ " erin" ,
150+ " malformed syt_ tokens should fall back to whoami rather than crash"
151+ )
152+ assert_equal (calls , 1 , " whoami should be used when local decoding fails" )
153+ end
154+
79155local function test_whoami_lookup_returns_localpart ()
80156 local calls = 0
81157 local request_handle = new_request_handle ({
@@ -214,6 +290,10 @@ local tests = {
214290 test_room_id_from_encoded_path ,
215291 test_access_token_from_authorization_header ,
216292 test_access_token_from_query ,
293+ test_username_decoded_from_synapse_token_without_whoami ,
294+ test_username_decoded_consistent_across_devices ,
295+ test_non_synapse_token_falls_back_to_whoami ,
296+ test_malformed_synapse_token_falls_back_to_whoami ,
217297 test_whoami_lookup_returns_localpart ,
218298 test_whoami_lookup_forwards_xff ,
219299 test_whoami_lookup_without_xff ,
0 commit comments