-
-
Notifications
You must be signed in to change notification settings - Fork 116
Description
Transaction IDs are currently scoped by access token. They are used to make some request idempotent, and to help client map sent event when they get back in /sync
.
Problem is, since MSC2918 (aka. refresh tokens), a client may refresh its access token, which may lead to scenarios like this:
- the client starts a
/sync
with an access token T1 - since T1 is about to expire, it refreshes it and gets an access token T2
- it sends an event via
/rooms/{room}/send/{type}/{txnId}
with the access token T2 /sync
gets back with the newly created event, but without thetransaction_id
field, since that/sync
was done with another access token
which directly contradicts the spec, where says on the transaction_id
field:
The client-supplied transaction ID, for example, provided via
PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}
, if the client being given the event is the same one which sent it.
There are other places in the spec where we mention those transaction IDs:
The client-server API typically uses
HTTP PUT
to submit requests with a client-generated transaction identifier. This means that these requests are idempotent. The scope of a transaction identifier is a particular access token. It only serves to identify new requests from retransmits. After the request has finished, the {txnId} value should be changed (how is not specified; a monotonically increasing integer is recommended).
And on the txnId
on /send
:
The transaction ID for this event. Clients should generate an ID unique across requests with the same access token; it will be used by the server to ensure idempotency of requests.
What I suggest is to use the device_id
(+ user_id
) instead of the access token to scope those transaction IDs.
Related Synapse issue: matrix-org/synapse#13064 and PR: matrix-org/synapse#13083