-
Notifications
You must be signed in to change notification settings - Fork 435
MSC4464: verifiable links in profile #4464
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
Open
dozro
wants to merge
12
commits into
matrix-org:main
Choose a base branch
from
dozro:proposal/verifiable-links-in-profile
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+352
−0
Open
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
38e7ca2
initial commit of draft followup MSC
dozro 6a12c94
Clarify 'scope' field in verification results
dozro c7d4174
updated naming in line with updates to MSC4462
dozro ebb3145
line wraps to 80
dozro 5785a26
added unstable prefix for dns record
dozro 8be2295
clarification regarding errors and matrix backlink
dozro bceaa6e
expanding on possible alternatives
dozro 52c18da
various changes
dozro 55f917f
updated MSC to include the actual MSC number
dozro 1712887
fix: uri -> link html element
dozro ac5ae4c
adjusted the request to the endpoint to be a GET request
dozro 01c904c
Fix expires field format in verification object
dozro File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,352 @@ | ||
| # MSC4464: Verifiable Links in Profile | ||
|
|
||
| A lot of other chat platforms (like Discord) and social media platforms (like | ||
| Mastodon, Sharkey, ...) allow you to put a list of links in your profile which | ||
| then get verified. | ||
|
|
||
| In the fediverse (e.g. Mastodon) it is simply done by crawling the linked site | ||
| and searching for links with the `rel="me"` attribute. | ||
|
|
||
| This proposal introduces a way for Matrix homeservers to do a relationship based | ||
| (`rel="me"`), as known from the fediverse, but beyond that also a dns and matrix | ||
| backlink (useful for example for alt accounts) verification. This would go a | ||
| long way in establishing more feature parity to other popular platforms. | ||
|
|
||
| It would also go a long way in reducing the risk of impersonation and phishing | ||
| for a set of MSC4462 connections in profile. | ||
|
|
||
| ## Proposal | ||
|
|
||
| ### The role of the homeserver | ||
|
|
||
| A homeserver SHOULD provide a client-server API endpoint to verify link | ||
| relationship against under `/_matrix/client/v1/verify_profile_connection`. The | ||
| result of the link verification SHOULD be cached for some amount of time | ||
| (*implementation detail*). The homeserver SHOULD add a `expires` field to the | ||
| response, to indicate after what point in time a verification should be | ||
| considered outdated, after that time a client SHOULD reverify. | ||
|
|
||
| A homeserver MAY choose to disable the | ||
| `/_matrix/client/v1/verify_profile_connection` endpoint by its respective | ||
| configuration. Since there can be a lot of verification requests on a big | ||
| homeserver, a ratelimit may be applied (in which case a HTTP 429 should be | ||
| returned). | ||
|
|
||
| To prevent potentially infinite redirect loops, a restriction on the amount of | ||
| redirects SHOULD be applied. A homeserver MAY use a blocklist/allowlist if it | ||
| wants to filter what links they try to verify. However a homeserver MUST prevent | ||
| verification requests pointing to restricted addresses | ||
| ([RFC1918](https://www.rfc-editor.org/info/rfc1918), localhost, ...). | ||
|
|
||
| To verify a relationship it MUST match the full MXID (after normalization). | ||
|
|
||
| As a client may wish to display additional information regarding a link | ||
| (especially if the link is a web address) a homeserver MAY include url preview | ||
| information with the response. | ||
|
|
||
| A homeserver SHOULD allow verification request towards subpages (e.g. | ||
| `https://example.org/about`), but MUST NOT mark the whole domain as verified for | ||
| the mxid, it SHOULD as well allow multiple matrix-account-links per page. | ||
|
|
||
| #### Verification Methods | ||
|
|
||
| ##### Relationship | ||
|
|
||
| A homeserver | ||
|
|
||
| - MAY derive the cache time from the `cache-control` http response header. | ||
| - SHOULD upon request, with a payload defined below, fetch that link, parse, and | ||
| check if the relationship is given | ||
| - MAY restrict from which hosts websites can be fetched from for verification, | ||
| similar to link previews | ||
| - SHOULD enforce content-type (e.g. HTML only) | ||
| - MUST parse static HTML (no JS execution) | ||
| - MAY discard the verification and mark it as failed if the http response | ||
| exceeds 1MB in size | ||
| - SHOULD NOT regard links in `<iframe>`, even if they would pass the | ||
| verification | ||
| - MUST treat `rel` as ASCII case-insensitive | ||
|
|
||
| A homeserver checks the verification by checking for elements of type `a` or | ||
| `link` with the relationship me | ||
| ([`rel="ME"`](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/rel/me)). | ||
| A simple link (without the relationship) MUST NOT result in verifying a link | ||
| relationship. As a reference developers could see Mastodon's approach (see | ||
| [mastodon docs](https://docs.joinmastodon.org/user/profile/#verification)). | ||
|
|
||
| The homeserver SHOULD consider both the | ||
| [`matrix.to` address](https://spec.matrix.org/v1.18/appendices/#matrixto-navigation) | ||
| (e.g. `https://matrix.to/#/@alice:example.org`) and the | ||
| [`matrix` URI](https://spec.matrix.org/v1.18/appendices/#matrix-uri-scheme) | ||
| (e.g. `matrix:u/alice:example.org`) scheme for the backlink. | ||
|
|
||
| A homeserver SHOULD consider when evaluating a `matrix.to` address, that it | ||
| could also be encoded (e.g. `https://matrix.to/#/%40example%3Aexample.org`). | ||
|
|
||
| ##### DNS | ||
|
|
||
| A homeserver SHOULD also offer DNS based link verification, by checking the | ||
| domain for a `_matrix-verification.DOMAIN` txt record containing a comma | ||
| separated list of mxids. If a domain has been verified by DNS record all | ||
| subpages of the domain MUST also be marked as verified. However, if a subdomain | ||
| has been DNS verified, the root domain MUST NOT be marked as verified. A | ||
| homeserver SHOULD respect the DNS records TTL for it's caching. | ||
|
|
||
| Example txt record for `_matrix-verification.example.org`: | ||
|
|
||
| ``` | ||
| "@alice:example.org,@bob:example.org" | ||
| ``` | ||
|
|
||
| This example should result in the homeserver verifying the whole domain for both | ||
| `@alice:example.org` and `@bob:example.org`. | ||
|
|
||
| For the format of a MXID, the | ||
| [grammar of a user identifier in the spec](https://spec.matrix.org/v1.18/appendices/#user-identifiers) | ||
| finds application. | ||
|
|
||
| ##### Matrix | ||
|
|
||
| A relationship between matrix users SHOULD be marked as verified if they have a | ||
| bidirectional link towards each other. In other words if `@alice:example.org` | ||
| links to `@alice:example.com` the link MUST only be verified if | ||
| `@alice:example.com` also links back to `@alice:example.org`. | ||
|
|
||
| A homeserver would check this by requesting the profiles of both | ||
| `@alice:example.org` and `@alice:example.com`, and checks if they link to each | ||
| other. If they don't link to each other it SHOULD be treated as a failed | ||
| verification. If an error during lookup occurs it SHOULD be treated as an | ||
| erroring verification (see verification with `error` as result below). | ||
|
|
||
| #### Request to the endpoint | ||
|
|
||
| A client SHOULD, when wanting to check a link-user-relationship, send a `GET` | ||
| Request to the `/_matrix/client/v1/verify_profile_connection` endpoint. | ||
|
|
||
| The request should set the following query parameters: | ||
|
|
||
| - `uri` the uri a client wants to verify (example: `https://example.org`) | ||
| - `mxid` the mxid to check against, not the mxid of the user initiating the | ||
| request (example: `@alice:example.org`) | ||
| - `method` the verification method to use (accepted values: `m.method.dns`, | ||
| `m.method.relation`, or `m.method.matrix`) | ||
|
|
||
| #### Response format | ||
|
|
||
| For **successful verifications**, homeservers SHOULD respond to the client with | ||
| the following: | ||
|
|
||
| ```json | ||
| { | ||
| "verification": { | ||
| "result": "success", | ||
| "method": "m.method.dns" | "m.method.relation" | "m.method.matrix", | ||
| // expiry should be defined as the unix epoch after which to try again | ||
| "expires": 1778107123, | ||
| "scope": "m.scope.site" | "m.scope.domain" | "m.scope.account" | ||
| }, | ||
| // optional additional url preview stuff | ||
| "preview_url": { | ||
| // same format as defined for url preview responses | ||
| // see https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv1mediapreview_url | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| The scope field describes the extent of the verified relationship: | ||
|
|
||
| - `m.scope.site` indicates verification of a specific URL (related to | ||
| `m.method.relation`) | ||
| - `m.scope.domain` indicates verification of an entire domain and its subpages | ||
| (related to `m.method.dns`) | ||
| - `m.scope.account` indicates verification of an account-level identifier (e.g. | ||
| a Matrix user ID, related to `m.method.matrix`) | ||
|
|
||
| While the `scope` and `method` fields may appear redundant, the `scope` field | ||
| makes the extent, not the strength, of a verification result explicit. This | ||
| allows clients to interpret verification results without relying on | ||
| method-specific behavior (e.g. determining whether a verification applies to a | ||
| single URL or an entire domain). | ||
|
|
||
| Additionally, including `scope` allows for future extensibility, where new | ||
| verification methods may be introduced without requiring clients to infer the | ||
| scope from the method. | ||
|
|
||
| For **failed/erroring verifications**, homeservers SHOULD respond to the client | ||
| with the following: | ||
|
|
||
| ```json | ||
| { | ||
| "verification": { | ||
| "result": "not_found" | "error" | "verification_failed", | ||
| "method": "m.method.dns" | "m.method.relation" | "m.method.matrix", | ||
| "expires": "1778107123" | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| The `result` should use the following logic: | ||
|
|
||
| - `not_found` if a http request returns `404`, or a DNS lookup returns | ||
| `NXDOMAIN` | ||
| - `error` for other errors | ||
| - `verification_failed` if the request was successful the verification however | ||
| wasn't (i.e. the website loaded as expected but no matching `rel="me"` found) | ||
|
|
||
| For **rate-limited** request, homeservers SHOULD respond with a 429 response | ||
| like the following | ||
|
|
||
| ```json | ||
| { | ||
| "errcode": "M_LIMIT_EXCEEDED", | ||
| "error": "Too many requests", | ||
| "retry_after_ms": 2000 | ||
| } | ||
| ``` | ||
|
|
||
| Note that this is the same response a client would get for a rate-limited url | ||
| preview request. | ||
|
|
||
| ### The role of the client | ||
|
|
||
| #### Storage in the user profile | ||
|
|
||
| This proposal builds on | ||
| [MSC4462: Links in Profile](https://github.com/matrix-org/matrix-spec-proposals/pull/4462) | ||
| and extends its `m.connections` field in the user profile, with | ||
| `verification_method` as an attribute describing how the link can be verified. | ||
|
|
||
| Example of the extended `m.connections` field: | ||
|
|
||
| ```json | ||
| { | ||
| "m.connections": [ | ||
| { | ||
| "description": "homepage", | ||
| "uri": "https://example.org", | ||
| "verification_method": "m.method.dns" | ||
| }, | ||
| { | ||
| "description": "mastodon", | ||
| "uri": "https://mastodon.social/@example", | ||
| "verification_method": "m.method.relation" | ||
| }, | ||
| { | ||
| "description": "alt-account", | ||
| "uri": "matrix:u/alice:example.org", | ||
| "verification_method": "m.method.matrix" | ||
| } | ||
| ] | ||
| } | ||
| ``` | ||
|
|
||
| The value of `verification_method` may either be `m.method.dns`, | ||
| `m.method.relation`, or `m.method.matrix`. If it is unset clients MAY use the | ||
| same behaviour as for `m.method.relation` or mark the link as unverified. | ||
|
|
||
| #### Verifying a link | ||
|
|
||
| Clients | ||
|
|
||
| - MUST NOT mark a link as verified unless the homeserver marks the link as | ||
| verified | ||
| - SHOULD use the format specified in "Payload for the endpoint" to request | ||
| verification from homeserver | ||
| - MAY cache the result until the `expires` date if the verification has been | ||
| successful | ||
| - SHOULD consider the verification as outdated after `expires` has passed and | ||
| reverify | ||
| - SHOULD treat outdated verification as a link being unverified | ||
| - MAY cache failures to not overwhelm the homeserver with requests | ||
| - MAY hide unverified links from the user | ||
|
|
||
| ### Summary | ||
|
|
||
| A link MUST only be marked as verified if a verifiable relationship exists | ||
| between the MXID and the `uri`, established via one of the supported methods. | ||
|
|
||
| Depending on the method: | ||
|
|
||
| - Relationship- and Matrix-based verification REQUIRE bidirectional linking | ||
| - DNS-based verification establishes domain-level authority and does not require | ||
| a backlink from the target resource | ||
|
|
||
| Small but notable difference between the verification methods: DNS-based | ||
| verification verifies domain-level authority, whereas matrix- and relationship | ||
| based verification verify link-level reciprocity. | ||
|
|
||
| ## Potential issues | ||
|
|
||
| ### Single Page Sites using JavaScript | ||
|
|
||
| Nowadays a lot of sites are heavily reliant on the execution of JavaScript for | ||
| their content. There is a case in allowing parsing after JavaScript execution to | ||
| allow more sites. | ||
|
|
||
| However, that would open an attack vector and require a JavaScript runtime on | ||
| the homeserver, therefore the link must be present in static HTML, or using the | ||
| DNS method. | ||
|
|
||
| ## Alternatives | ||
|
|
||
| ### Verifying a link client side | ||
|
|
||
| A verification of links in the way this proposal proposes it for homeservers to | ||
| act, could also be done by clients. | ||
|
|
||
| However, this would have considerable security implications: | ||
|
|
||
| - fetching a arbitrary website (in that exposing the client ip to potentially | ||
| malicious actors) | ||
| - rendering a arbitrary website (could end up as an attack vector for cross side | ||
| scripting) | ||
| - a lot of requests to a website, if a lot of users look at one's profile (a | ||
| homeserver could cache the verification result) | ||
|
|
||
| ### Third Party Verification | ||
|
|
||
| Another possible alternative would be to rely on a set of supported third-party | ||
| verification services. However, this would require a shared trust model and | ||
| service discovery mechanism across the federation, which would complicate | ||
| deployment and interoperability. | ||
|
|
||
| If a clear use case emerges, this could be added later through a new | ||
| `verification_method` value. For example, a Discord integration could use | ||
| `"verification_method": "m.method.discord"`. This proposal therefore leaves | ||
| `verification_method` open for future methods. However this proposal doesn't in | ||
| itself propose third party verification methods. | ||
|
|
||
| ### Cryptographic Proofs | ||
|
|
||
| This is a plausible alternative. However, it would introduce additional protocol | ||
| complexity and key-management requirements, while providing little benefit over | ||
| the existing relationship-based approach already used by established platforms | ||
| such as Mastodon. | ||
|
|
||
| ## Security considerations | ||
|
|
||
| - A website could trigger cyclic redirects, therefore a server MUST enforce a | ||
| limit on redirects, see above | ||
| - DNS-based verification proves that the operator of a domain asserts an | ||
| association with a given MXID. It does not prove that the MXID owner controls | ||
| the domain. | ||
| - When a homeserver performs a verification (especially for relationship based | ||
| verification) it initiates a connection to an arbitrary website, which could | ||
| lead to leak some meta data to the website operator (similar to homeserver | ||
| based url previews) | ||
|
|
||
| ## Unstable prefix | ||
|
|
||
| implementations should use | ||
|
|
||
| - `fyi.cisnt.connections` instead of `m.connections` | ||
| - `fyi.cisnt.method.*` instead of `m.method.*` | ||
| - `fyi.cisnt.scope.*` instead of `m.scope.*` | ||
| - `_msc4464-verification` instead of `_matrix-verification` for the DNS TXT | ||
| record | ||
| - `/_matrix/client/unstable/fyi.cisnt.connections/verify_profile_connection` | ||
| instead of `/_matrix/client/v1/verify_profile_connection` | ||
|
|
||
| ## Dependencies | ||
|
|
||
| [MSC4462 (Links in Profile)](https://github.com/matrix-org/matrix-spec-proposals/pull/4462) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Implementation requirements: