-
Notifications
You must be signed in to change notification settings - Fork 382
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
MSC3720: Account status #3720
base: main
Are you sure you want to change the base?
MSC3720: Account status #3720
Changes from 8 commits
41efaef
55a4727
d6bcb04
2d3aec8
813b379
1c3417c
87853fd
92120dd
30732a4
d8292f0
bda4880
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
# MSC3720: Account status endpoint | ||
|
||
Matrix clients sometimes need a way to display additional information about a | ||
user. For example, when interacting with a Matrix user, it might be useful for | ||
clients to show whether this user's account has been deactivated, or even exists | ||
at all. | ||
|
||
Currently clients are forced to resort to hacks to try to derive this | ||
information. Some, for example, check whether a user has a profile (display | ||
name, avatar) set when trying to send an invite, which means that if a user | ||
doesn't have any profile information (which is valid under the Matrix | ||
specification), the inviter might be warned that the user might not exist. | ||
|
||
## Proposal | ||
Half-Shot marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Two new endpoints are added to the specification, one to the client-server API | ||
and one to the server-server API. | ||
Comment on lines
+16
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think an alternative to this proposal is to do one or both of the following:
Was this considered? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sort of, except that one of the requirements I'm working with (which I haven't mentioned in the MSC) is that the response needs to be easily extensible. As mentioned in this comment, this is a port of a feature used in the Tchap infrastructure. That infrastructure uses Synapse's account validity (which isn't part of the spec and imo doesn't really have a place in there), and uses this feature to also figure out whether a user is expired (a second step of the Synapse work will be adding a config flag to Synapse to optionally include account validity status to this endpoint's response). As far as I can tell, none of the alternatives you've mentioned offer this kind of extensibility. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, after giving it some more thought, it feels quite wrong to me to use the profile endpoint for information that's not profile-related. |
||
|
||
### `GET /_matrix/client/v1/account_status` | ||
|
||
This endpoint requires authentication via an access token. | ||
|
||
This endpoint takes a `user_id` query parameter indicating which user account(s) | ||
to look up the status of. This parameter may appear multiple times in the | ||
request if the client wishes to look up the statuses of multiple users at once. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks like it will allow bulk username enumeration, which is usually considered a security flaw. Maybe it being authenticated is "OK" and being able to query for users on a homeserver isn't considered private info right now, but something feels off with being able to do it in bulk. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah I agree that this can be concerning. Maybe a good compromise could be adding a limit (eg 15) to the number of users that can be looked up in a single request, and encourage homeservers to aggressively rate-limit the endpoint? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (I would like the ability to not limit appservices here, as they have more of a valid need to do bulk lookups) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Sounds like an implementation detail? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, this is just an avocation for keeping bulk fetching / not setting limits in the spec but allowing implementations the leeway of setting their own limits (so as not to write-out bulk lookups in the spec or anything). No limitations in the spec covers my use case :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah fair enough :) Yeah the idea is very much to allow bulk lookups. |
||
|
||
If no error arises, the endpoint responds with a body using the following | ||
format: | ||
|
||
```json | ||
{ | ||
"account_statuses": { | ||
"@user1:example.com": { | ||
"exists": true, | ||
"deactivated": false | ||
}, | ||
"@user2:example.com": { | ||
"exists": false | ||
}, | ||
}, | ||
"failures": [ | ||
"@user3:example.com", | ||
"@user4:otherexample.com" | ||
] | ||
} | ||
``` | ||
|
||
The `account_statuses` object in the response lists all statuses that could | ||
successfully be retrieved. Each key in this object maps to one of the `user_id` | ||
parameter(s) in the request. For each account: | ||
|
||
* `exists` is a boolean that indicates whether an account exists with this user | ||
ID. | ||
* `deactivated` is a boolean that indicates whether the account has been | ||
deactivated. Omitted if `exists` is `false`. | ||
|
||
The `failures` object in the response lists all user IDs for which no status | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FWIW, this is different from what There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is intentional - sorry for not pointing it out explicitly. I thought that it would be good to allow homeserver implementations to refuse to serve the status of specific accounts while still providing this bit of information for other accounts. I'm happy to change this if people think it would be better to just copy what |
||
could be retrieved for any reason (e.g. federation issues, missing federation | ||
endpoint, missing user in the remote server's response, etc). | ||
|
||
The combination of the lists of user IDs from `user_statuses` and `failures` | ||
must match the full list of user IDs provided in the request via `user_id` | ||
parameters. | ||
|
||
If one or more account(s) is not local to the homeserver this request is | ||
performed on, the homeserver must attempt to retrieve account status using the | ||
federation endpoint described below. | ||
|
||
Below is how this endpoint behaves in case of errors: | ||
|
||
* If no `user_id` parameter is provided, the endpoint responds with a 400 status | ||
code and a `M_MISSING_PARAM` error code. | ||
* If one or more of the `user_id` parameter(s) provided cannot be parsed as a | ||
valid Matrix user ID, the endpoint responds with a 400 status code and a | ||
`M_INVALID_PARAM` error code. | ||
|
||
### `GET /_matrix/federation/v1/query/account_status` | ||
|
||
This endpoint behaves in an identical way to the client-side endpoint described | ||
above, with the additional following error case: | ||
|
||
* If one or more of the `user_id` parameter(s) does not match an account that | ||
belong to the homeserver receiving the request, the endpoint responds with a | ||
400 status code and a `M_INVALID_PARAM` error code. | ||
|
||
### `m.account_status` capability | ||
|
||
Some server administrators might not want to disclose too much information about | ||
their users. To support this use case, homeservers must expose a | ||
`m.account_status` capability to tell clients whether they support retrieving | ||
account status via the client-side endpoint described above. | ||
|
||
## Security considerations | ||
|
||
Should a server administrator not want to disclose information about their users | ||
through the federation endpoint described above, they should use a reverse proxy | ||
or similar tool to prevent access to the endpoint. On top of this, homeserver | ||
implementations may implement measures to respond with a 403 status code and a | ||
`M_FORBIDDEN` error code in this case. | ||
|
||
## Unstable prefixes | ||
|
||
Until this proposal is stabilised in a new version of the Matrix specification, | ||
implementations should use the following paths for the endpoints described in | ||
this document: | ||
|
||
| Stable path | Unstable path | | ||
|-----------------------------------------------|------------------------------------------------------------------------| | ||
| `/_matrix/client/v1/account_status` | `/_matrix/client/unstable/org.matrix.msc3720/account_status` | | ||
| `/_matrix/federation/v1/query/account_status` | `/_matrix/federation/unstable/org.matrix.msc3720/query/account_status` | | ||
|
||
Additionally, implementations should use the unstable identifier | ||
`org.matrix.msc3720.account_status` instead of `m.account_status` for the | ||
client-side capability. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would a user interact with non-existent users? You can't make a room to them, I don't think. I'm failing to see when this would come up in a client!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A common use case would be trying to start a DM using an MXID: if the user is on a remote homeserver the only way to know if the MXID maps to an existing user is trying to retrieve extra data on them and see if it works, in a kinda hacky way. Currently (iirc) Element clients do this by trying to retrieve the user's profile and displaying a warning if no profile could be found, but that doesn't necessarily indicate the user doesn't exist.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically this is what I mean:
Peek.2022-02-16.17-45.mp4
Note that in this capture "User [...] does not exist" appears but it looks like Element added it given this is the actual response from Synapse on the profile request: