Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for .ready verification event (MSC2366) & other things #1140

Merged
merged 44 commits into from
Jan 20, 2020

Conversation

bwindels
Copy link
Contributor

@bwindels bwindels commented Jan 3, 2020

MSC: https://github.com/uhoreg/matrix-doc/blob/key_verification_accept/proposals/2366-key-verification-accept.md
Part of element-hq/element-web#11224
Required by matrix-org/matrix-react-sdk#3796

So #1109 formalized the request object that was already used in Crypto/index. This PR further puts all of the responsibilities of KeyVerificationStateObserver (react-sdk) into VerificationRequest (js-sdk) so the react-sdk can use the latter directly to drive the UI in matrix-org/matrix-react-sdk#3796. This makes it easier to keep all the parts that need to response to the state of a request in sync (toast, event tiles and right panel).

Most of the work in this PR went into displaying historical request (e.g. loaded from cache, or when back-paginating) correctly.

In order to make this work, I had to rewrite the state machine logic in VerificationRequest, and ended up storing all events by sender and type to not rely on order, because when loading events from cache the events are be emitted in reverse chronological order (e.g. receiving the .done event first and .request event last). To prevent the verifier or the verification request sending out any events (like .cancel) while replaying the events of a historical request, an observeOnly flag was added. This flag is turned off when receiving a non-live event (changes had to be made to determine this more reliably, e.g. when loading from cache), or when an event is too old, or when we detect the request is between two other parties (e.g. the user in the DM and another one of my own devices).

In-room requests are now also stored per roomId, not userId, as determining the other party of the request can be hard when the .request is not the first event received (when loading from cache). We need to take determine the other part for that event and ignore any other senders after that. For this reason the request lookup was abstracted into InRoomRequests and ToDeviceRequests.

The state machine now also relies on remote echos being passed to handleEvent (which are faked for to_device messages) as this handles replaying historical events, sending, and handling live events in one code path. Not relying on local echo for verification actions anymore also mean I could delete RequestCallbackChannel, which was used to inform the VerificationRequest that the verifier was sending something and to do local echo of that event.

As said, this PR also adds support for the .ready event as specified in MSC2366. This turns accepting a request into a separate step than choosing a verification method. To support this, VerificationRequest gained an accept method and waitForVerifier had to be changed as getting a verifier (when receiving a .start) now requires calling accept() first and not just waiting.

VerificationRequest now also handles cancelling with a timeout before the request is accepted (verifier has its own timeout after accepting a request).

Breaking change

2da7253 changes the return type of client.acceptVerification and client.acceptVerificationDM to return a promise of VerificationRequest object instead of a promise of the verifier. Also client.acceptVerificationDM was deleted, requests should now be accepted through VerificationRequest.accept. See commit message why this was needed. This being a breaking change, it might warrant bumping the major version number.

Cleanups still to do:

  • fix lint
  • fix test failure
  • remove debug logging

The commit log is a bit of a mess because of having to rewrite the state machine and at the same time adding .ready support. I had planned to restructure the commits but ran out of time, apologies to the reviewer for this.

as MSC2366 adds an extra interactive step to the verification process,
we can't wait for the verifier after sending the request.

This is a breaking change in the js-sdk as it changes the return type
of an existing method.
so we don't need to import the PHASE_ constants where we need to check
as it's harder to determine the other side of a request, given
the in-room code also processes remote echos for own events.
also put logic to block non-participating senders in VerificationRequest
so it is shared between both channels.

Remote echo's should not be passed to the verifier though.
as once in done, the request is removed from the request map
and the second .done event that comes in will not find the request
anymore, so the request wouldn't be attached to the event anymore,
breaking rendering it in the timeline.
next up is inspecting the .request event to
determine it reliably in InRoomChannel
also fail validation with any event not sent by or directed to us
as it doesn't need to happen for ToDeviceChannel
but doesn't work yet? data where liveEvent is fished out is undefined
this makes the verifier want to interact with the other party
when just reloading the session.
rather than the sender and from_device (which is not always set)

as this was one of the things breaking to_device verification
of ones own devices.
this was one of the things breaking to_device verification
@bwindels
Copy link
Contributor Author

bwindels commented Jan 3, 2020

Meant this to be a draft PR, still need to improve comments.

@bwindels bwindels requested a review from a team January 4, 2020 12:01
@turt2live turt2live requested review from turt2live and removed request for a team January 16, 2020 19:42
Copy link
Member

@turt2live turt2live left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is fine so far. It's hard to follow the state machine (both old and new), but with enough testing maybe it'll make sense. Similar to how our login system is impossible to follow.

@@ -894,8 +894,8 @@ MatrixClient.prototype.acceptVerificationDM = function(event, method) {
* @param {Array} devices array of device IDs to send requests to. Defaults to
* all devices owned by the user
*
* @returns {Promise<module:crypto/verification/Base>} resolves to a verifier
* when the request is accepted by the other user
* @returns {Promise<module:crypto/verification/request/VerificationRequest>} resolves to a VerificationRequest
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually we don't change the contract of our public functions, though in this case we're about to do a major version bump for the new build system anyways so this seems fine and convenient.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, see the breaking change comment in the description.

src/crypto/index.js Outdated Show resolved Hide resolved
@turt2live
Copy link
Member

I've merged in develop after I completely refactored the entire build system.

@turt2live turt2live mentioned this pull request Jan 18, 2020
@bwindels bwindels merged commit 22e6cfa into develop Jan 20, 2020
@t3chguy t3chguy deleted the bwindels/verification-right-panel branch May 10, 2022 14:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants