Skip to content

Instantly share code, notes, and snippets.

@jryans
Last active November 27, 2020 11:30
Show Gist options
  • Save jryans/839a09bf0c5a70e2f36ed990d50ed928 to your computer and use it in GitHub Desktop.
Save jryans/839a09bf0c5a70e2f36ed990d50ed928 to your computer and use it in GitHub Desktop.
3PID API Flows

3PID API Flows

This attempts to describe how the author (@jryans) believes 3PID API flows are working today to support review and criticism. Much of this came from reading the Synapse implementation, so it's possible this follows Synapse more closely than the spec.

This currently uses IS API v1 for simplicity, but the services in play here should be converting to IS API v2.

The flows we are analysing include:

  1. Adding a 3PID to HS account during registration
  2. Adding a 3PID to HS account after registration
  3. Changing the bind status of a 3PID
  4. Reset password via email

1. Adding a 3PID to HS account during registration

Involves APIs:

  • POST /_matrix/client/r0/register/<medium>/requestToken
  • POST /_matrix/identity/api/v1/validate/<medium>/requestToken
  • GET /_matrix/identity/api/v1/validate/<medium>/submitToken
  • POST /_matrix/client/r0/register
  • GET /_matrix/identity/api/v1/3pid/getValidated3pid

diagram-1-add-during-reg

2. Adding a 3PID to HS account after registration

2a. Adding a 3PID to HS account after registration (pre-MSC2290)

Involves APIs:

  • POST /_matrix/client/r0/account/3pid/<medium>/requestToken
  • POST /_matrix/identity/api/v1/validate/<medium>/requestToken
  • GET /_matrix/identity/api/v1/validate/<medium>/submitToken
  • POST /_matrix/client/r0/account/3pid
  • GET /_matrix/identity/api/v1/3pid/getValidated3pid

This is a subset of flow 3a below. It's nearly the same, but there's no need to delete the 3PID first.

diagram-2a-add-after-reg

2b. Adding a 3PID to HS account after registration (post-MSC2290)

Involves APIs:

  • POST /_matrix/client/r0/account/3pid/<medium>/requestToken
  • POST /_matrix/identity/api/v1/validate/<medium>/requestToken
  • GET /_matrix/identity/api/v1/validate/<medium>/submitToken
  • POST /_matrix/client/r0/account/3pid/add
  • GET /_matrix/identity/api/v1/3pid/getValidated3pid

diagram-2b-add-after-reg

3. Changing the bind status of a 3PID

3a. Changing the bind status of a 3PID (pre-MSC2290)

Involves APIs:

  • POST /_matrix/client/r0/account/3pid/delete
  • POST /_matrix/client/r0/account/3pid/<medium>/requestToken
  • POST /_matrix/identity/api/v1/validate/<medium>/requestToken
  • GET /_matrix/identity/api/v1/validate/<medium>/submitToken
  • POST /_matrix/client/r0/account/3pid
  • GET /_matrix/identity/api/v1/3pid/getValidated3pid
  • POST /_matrix/identity/api/v1/3pid/bind
  • POST /_matrix/federation/v1/3pid/onbind

diagram-3a-change-bind-status

3b. Changing the bind status of a 3PID (post-MSC2290)

Involves APIs:

  • POST /_matrix/identity/api/v1/validate/<medium>/requestToken
  • GET /_matrix/identity/api/v1/validate/<medium>/submitToken
  • POST /_matrix/client/r0/account/3pid/bind
  • GET /_matrix/identity/api/v1/3pid/getValidated3pid
  • POST /_matrix/identity/api/v1/3pid/bind
  • POST /_matrix/federation/v1/3pid/onbind

diagram-3b-change-bind-status

4. Reset password via email

Involves APIs:

  • POST /_matrix/client/r0/account/password/email/requestToken
  • POST /_matrix/identity/api/v1/validate/<medium>/requestToken
  • GET /_matrix/identity/api/v1/validate/<medium>/submitToken
  • POST /_matrix/client/r0/account/password
  • GET /_matrix/identity/api/v1/3pid/getValidated3pid

diagram-4-password-reset

title Adding a 3PID to HS account during registration
participant User
participant Client
participant HS
participant Validation Delegate
Client->HS:POST /_matrix/client/r0/register/email/requestToken
activate HS
rbox over HS:📖 No auth on HS\n🛑 Reject if 3PID already known to HS\n⚠️ Email sent by trusted delegate or HS itself
HS->Validation Delegate:POST /_matrix/identity/api/v1/validate/email/requestToken
activate Validation Delegate
HS<--Validation Delegate:result
deactivate Validation Delegate
Client<--HS:result
deactivate HS
User<-Validation Delegate:Sends email
User->Validation Delegate:GET submit_url or /_matrix/identity/api/v1/validate/email/submitToken
Client->HS:POST /_matrix/client/r0/register
activate HS
rbox over HS:📖 No auth on HS\n⚠️ Validate 3PID session with trusted delegate or HS itself
HS->Validation Delegate:GET /_matrix/identity/api/v1/3pid/getValidated3pid
activate Validation Delegate
HS<--Validation Delegate:result
deactivate Validation Delegate
rbox over HS:Add 3PID to account
Client<--HS:result
deactivate HS
title Adding a 3PID to HS account after registration (pre-MSC2290)
participant User
participant Client
participant HS
participant IS
Client->HS:POST /_matrix/client/r0/account/3pid/email/requestToken
activate HS
rbox over HS:📖 No auth on HS\n🛑 Reject if 3PID already known to HS
HS->IS:POST /_matrix/identity/api/v1/validate/email/requestToken
activate IS
HS<--IS:result
deactivate IS
Client<--HS:result
deactivate HS
User<-IS:Sends email
User->IS:GET /_matrix/identity/api/v1/validate/email/submitToken
Client->HS:POST /_matrix/client/r0/account/3pid\n{ bind: false }
activate HS
rbox over HS:🛂 User must be authed\n⚠️ Any IS can be used\nValidate 3PID session with IS
HS->IS:GET /_matrix/identity/api/v1/3pid/getValidated3pid
activate IS
HS<--IS:result
deactivate IS
rbox over HS:Add 3PID to account
Client<--HS:result
deactivate HS
title Adding a 3PID to HS account after registration (post-MSC2290)
participant User
participant Client
participant HS
participant Validation Delegate
Client->HS:POST /_matrix/client/r0/account/3pid/email/requestToken
activate HS
rbox over HS:📖 No auth on HS\n🛑 Reject if 3PID already known to HS\n⚠️ Email sent by trusted delegate or HS itself
HS->Validation Delegate:POST /_matrix/identity/api/v1/validate/email/requestToken
activate Validation Delegate
HS<--Validation Delegate:result
deactivate Validation Delegate
Client<--HS:result
deactivate HS
User<-Validation Delegate:Sends email
User->Validation Delegate:GET submit_url or /_matrix/identity/api/v1/validate/email/submitToken
Client->HS:POST /_matrix/client/r0/account/3pid/add
activate HS
rbox over HS:🛂 User must be authed\n⚠️ Validate 3PID session with trusted delegate or HS itself
HS->Validation Delegate:GET /_matrix/identity/api/v1/3pid/getValidated3pid
activate Validation Delegate
HS<--Validation Delegate:result
deactivate Validation Delegate
rbox over HS:Add 3PID to account
Client<--HS:result
deactivate HS
title Changing the bind status of a 3PID (pre-MSC2290)
participant User
participant Client
participant HS
participant IS
==Remove existing unbound 3PID==
Client->HS:POST /_matrix/client/r0/account/3pid/delete
activate HS
rbox over HS:🛂 User must be authed\nRemove 3PID from account\nNo associated IS
Client<--HS:result
deactivate HS
==Add same 3PID with binding==
Client->HS:POST /_matrix/client/r0/account/3pid/email/requestToken
activate HS
rbox over HS:📖 No auth on HS\n🛑 Reject if 3PID already known to HS
HS->IS:POST /_matrix/identity/api/v1/validate/email/requestToken
activate IS
HS<--IS:result
deactivate IS
Client<--HS:result
deactivate HS
User<-IS:Sends email
User->IS:GET /_matrix/identity/api/v1/validate/email/submitToken
Client->HS:POST /_matrix/client/r0/account/3pid\n{ bind: true }
activate HS
rbox over HS:🛂 User must be authed\n⚠️ Any IS can be used\nValidate 3PID session with IS
HS->IS:GET /_matrix/identity/api/v1/3pid/getValidated3pid
activate IS
HS<--IS:result
deactivate IS
rbox over HS:Add 3PID to account
HS->IS:POST /_matrix/identity/api/v1/3pid/bind
activate IS
rbox over IS:Store 3PID binding
HS<-IS:POST /_matrix/federation/v1/3pid/onbind
HS<--IS:result
deactivate IS
rbox over HS:Record 3PID as bound on IS
Client<--HS:result
deactivate HS
title Changing the bind status of a 3PID (post-MSC2290)
participant User
participant Client
participant HS
participant IS
Client->IS:POST /_matrix/identity/api/v1/validate/email/requestToken
activate IS
Client<--IS:result
deactivate IS
User<-IS:Sends email
User->IS:GET /_matrix/identity/api/v1/validate/email/submitToken
Client->HS:POST /_matrix/client/r0/account/3pid/bind
activate HS
rbox over HS:🛂 User must be authed\n⚠️ Any IS can be used\nValidate 3PID session with IS
HS->IS:GET /_matrix/identity/api/v1/3pid/getValidated3pid
activate IS
HS<--IS:result
deactivate IS
HS->IS:POST /_matrix/identity/api/v1/3pid/bind
activate IS
rbox over IS:Store 3PID binding
HS<-IS:POST /_matrix/federation/v1/3pid/onbind
HS<--IS:result
deactivate IS
rbox over HS:Record 3PID as bound on IS
Client<--HS:result
deactivate HS
title Reset password via email
participant User
participant Client
participant HS
participant Validation Delegate
Client->HS:POST /_matrix/client/r0/account/password/email/requestToken
activate HS
rbox over HS:📖 No auth on HS\n🛂 HS account lookup by email\n⚠️ Email revalidated by trusted delegate or HS itself
HS->Validation Delegate:POST /_matrix/identity/api/v1/validate/email/requestToken
activate Validation Delegate
HS<--Validation Delegate:result
deactivate Validation Delegate
Client<--HS:result
deactivate HS
User<-Validation Delegate:Sends email
User->Validation Delegate:GET submit_url or /_matrix/identity/api/v1/validate/email/submitToken
Client->HS:POST /_matrix/client/r0/account/password
activate HS
rbox over HS:🛂 Auth on the HS via email\n⚠️ Validate 3PID session with trusted delegate or HS itself
HS->Validation Delegate:GET /_matrix/identity/api/v1/3pid/getValidated3pid
activate Validation Delegate
HS<--Validation Delegate:result
deactivate Validation Delegate
rbox over HS:Set new password\nRevoke access tokens
Client<--HS:result
deactivate HS
@richvdh
Copy link

richvdh commented Sep 23, 2019

  1. What exactly does "No auth on HS" mean?
  2. Am I right in understanding that the only flow that adds a 3pid to the IS (so that it can be used for discovery) is flow 3 in a post-MSC2290 world?
    2.1. Which flows did so in a pre-MSC2290 world?
  3. Flows 1, 2 and 4 could do with noting (somehow) that the client may have to submit the token via the submit_url if that is returned.
  4. In flow 2a: /account/3pid is called with {bind: false} and yet the HS calls /identity/3pid/bind
    4.1. Would it be worth having a sequence diagram for the post-MSC2290 equivalent of the /account/3pid with {bind:true} flow? even if that is identical to flow 2b followed by 3b, it might be worth making explicit?
  5. How does the client know that it is time to perform the request which requires a validated session (/register / /account/3pid/* / /account/password) ? Does it just poll until it gets a success or an unexpected error code? Could this be represented in the sequence diagrams?

@jryans
Copy link
Author

jryans commented Sep 23, 2019

  1. What exactly does "No auth on HS" mean?

This means the API does not require you to authorise as a user on that homeserver. For Synapse, it should be equivalent to "the API does not call get_user_by_req".

  1. Am I right in understanding that the only flow that adds a 3pid to the IS (so that it can be used for discovery) is flow 3 in a post-MSC2290 world?

Yes, that's correct: only flow 3b of changing bind status to true adds to the IS now.

2.1. Which flows did so in a pre-MSC2290 world?

Before MSC2290, the "entangled" POST account/3pid with bind param from flow 2a would have also done so, but we now ignore that bind param. Even earlier on, we used to support binding to the IS at registration time (flow 1) as well. Riot no longer sends bind: true at registration, though some other client could do so.

  1. Flows 1, 2 and 4 could do with noting (somehow) that the client may have to submit the token via the submit_url if that is returned.

Right, will add in the next version... I believe that's only relevant for MSISDN at the moment?

  1. In flow 2a: /account/3pid is called with {bind: false} and yet the HS calls /identity/3pid/bind

Ah hmm, yes, that looks like an error in the diagram. Will update, thanks!

4.1. Would it be worth having a sequence diagram for the post-MSC2290 equivalent of the /account/3pid with {bind:true} flow? even if that is identical to flow 2b followed by 3b, it might be worth making explicit?

Hmm, we could add it, though it's a bit of broken flow post-MSC2290, since the bind param is now ignored, making it equivalent to having passed bind: false instead.

  1. How does the client know that it is time to perform the request which requires a validated session (/register / /account/3pid/* / /account/password) ? Does it just poll until it gets a success or an unexpected error code? Could this be represented in the sequence diagrams?

It varies depending on the client, the particular UX flow, etc. Sometimes the user is prompted for a validation code (MSISDN) so that just sits with a prompt, others use a continue button you need to click manually, and still others are a bit smarter and poll until success. Yes, I'll try to add something that represents that generically.

@richvdh
Copy link

richvdh commented Sep 23, 2019

  1. What exactly does "No auth on HS" mean?

This means the API does not require you to authorise as a user on that homeserver. For Synapse, it should be equivalent to "the API does not call get_user_by_req".

ah right. makes sense.

  1. Am I right in understanding that the only flow that adds a 3pid to the IS (so that it can be used for discovery) is flow 3 in a post-MSC2290 world?

Yes, that's correct: only flow 3b of changing bind status to true adds to the IS now.

2.1. Which flows did so in a pre-MSC2290 world?

Before MSC2290, the "entangled" POST account/3pid with bind param from flow 2a would have also done so, but we now ignore that bind param. Even earlier on, we used to support binding to the IS at registration time (flow 1) as well. Riot no longer sends bind: true at registration, though some other client could do so.

makes sense...

  1. Flows 1, 2 and 4 could do with noting (somehow) that the client may have to submit the token via the submit_url if that is returned.

Right, will add in the next version... I believe that's only relevant for MSISDN at the moment?

Yeees, although as per https://github.com/matrix-org/matrix-doc/issues/2302, I think that's the wrong way to think about it. In theory an implementation would be within its rights to send you an email saying "your token is 9999, go type it in" - in which case it should return a submit_url and the client should give you a window which lets you type in the token and will then send it to the submit_url.

4.1. Would it be worth having a sequence diagram for the post-MSC2290 equivalent of the /account/3pid with {bind:true} flow? even if that is identical to flow 2b followed by 3b, it might be worth making explicit?

Hmm, we could add it, though it's a bit of broken flow post-MSC2290, since the bind param is now ignored, making it equivalent to having passed bind: false instead.

I guess what I'm saying is: given there must exist some clients which want to do the thing that you got with {bind:true}, perhaps we should show how a client would implement a flow that achieves the same results post-MSC2290?

@jryans
Copy link
Author

jryans commented Oct 10, 2019

Recent changes:

  • Updated flow 2a to fix errant requests about binding
  • Renamed IS to Validation Delegate when used as trusted delegate by the HS
  • Added mention of submit_url where applicable

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment