Proposal for IS & IM TOS API
parent
ace94f02b7
commit
23af87e9fc
@ -0,0 +1,203 @@
|
||||
# MSCXXXX: Terms of Service API for Identity Servers and Integration Managers
|
||||
|
||||
MSC1692 introduces a method for homeservers to require that users read and
|
||||
agree to certain documents before being permitted to use the service. This
|
||||
proposal introduces a corresponding method that can be used with Identity
|
||||
Servers and Integration Managers.
|
||||
|
||||
The challenge here is that Identity Servers do not require any kind of user
|
||||
login to access the service and so are unable to track what users have agreed
|
||||
to what terms in the way that Homeservers do. We thereforce cannot re-use the
|
||||
same method for Identity Servers without fundamentally changing the Identity
|
||||
Service API.
|
||||
|
||||
Requirements for this proposal are:
|
||||
* ISs and IMs should be able to give multiple documents a user must agree to
|
||||
abide by
|
||||
* Each document shoud be versioned
|
||||
* ISs and IMs must be able to prevent users from using the service if they
|
||||
have not provided agreement.
|
||||
* A user should only have to agree to each version of each document once for
|
||||
their Matrix ID, ie. having agreed to a set of terms in one client, they
|
||||
should not have to agree to them again when using a different client.
|
||||
|
||||
## Proposal
|
||||
|
||||
Throuhgout this proposal, $prefix will be used to refer to the prefix of the
|
||||
API in question, ie. `/_matrix/identity/api/v1` for the IS API and
|
||||
`/_matrix/integrations/v1` for the IM API.
|
||||
|
||||
This proposal introduces:
|
||||
* The `$prefix/terms` endpoint
|
||||
* The `m.third_party_terms` section in account data
|
||||
* The `X-TERMS-TOKEN` HTTP header
|
||||
|
||||
### Terms API
|
||||
|
||||
New API endpoints will be introduced:
|
||||
|
||||
#### `GET $prefix/terms`:
|
||||
This returns a set of documents that the user must agree to abide by in order
|
||||
to use the service. Its response is similar to the structure used in the
|
||||
`m.terms` UI auth flow of the Client/Server API:
|
||||
|
||||
```json
|
||||
{
|
||||
"policies": {
|
||||
"terms_of_service": {
|
||||
"version": "2.0",
|
||||
"en": {
|
||||
"name": "Terms of Service",
|
||||
"url": "https://example.org/somewhere/terms-2.0-en.html"
|
||||
},
|
||||
"fr": {
|
||||
"name": "Conditions d'utilisation",
|
||||
"url": "https://example.org/somewhere/terms-2.0-fr.html"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Each document (ie. key/value pair in the 'policies' object) MUST be
|
||||
uniquely identified by its URL. It is therefore strongly recommended
|
||||
that the URL contains the version number of the document. The name
|
||||
and version keys, however, are used only to provide a human-readable
|
||||
description of the document to the user.
|
||||
|
||||
In the IM API, the client should provide authentication for this endpoint.
|
||||
|
||||
#### `POST $prefix/terms`:
|
||||
Requests to this endpoint have a single key, `user_accepts` whose value is
|
||||
a list of URLs (given by the `url` field in the GET response) of documents that
|
||||
the user has agreed to:
|
||||
|
||||
```json
|
||||
{
|
||||
"user_accepts": ["https://example.org/somewhere/terms-2.0-en.html"]
|
||||
}
|
||||
```
|
||||
|
||||
In the IM API, the client should provide authentication for this endpoint.
|
||||
|
||||
The clients MUST include the correct URL for the language of the document that
|
||||
was presented to the user and they agreed to. How servers store or serialise
|
||||
acceptance into the `acceptance_token` is not defined, eg. they may internally
|
||||
transform all URLs to the URL of the English-language version of each document
|
||||
if the server deems it appropriate to do so. Servers should accept agreement of
|
||||
any one language of each document as sufficient, regardless of what language a
|
||||
client is operating in: users should not have to re-consent to documents if
|
||||
they change their client to a different language.
|
||||
|
||||
The response MAY contain a `acceptance_token` which, if given, is an
|
||||
opaque string that the client must store for user in subsequent requests
|
||||
to any endpoint to the same server.
|
||||
|
||||
If the server has stored the fact that the user has agreed to these terms,
|
||||
(which implies the user is authenticated) it can supply no `acceptance_token`.
|
||||
The server may instead choose to supply an `acceptance_token`, for example if,
|
||||
as in the IS API, the user is unauthenticated and therefore the server is
|
||||
unable to store the fact a user has agreed to a set of terms.
|
||||
|
||||
The `acceptance_token` is opaque and it is up to the server how it computes it,
|
||||
but the server must be able to given an `acceptance_token`, compute whether it
|
||||
constitutes agreement to a given set of terms. For example, the simplest (but
|
||||
most verbose) implemenation would be to make the `acceptance_token` the JSON
|
||||
array of documents as provided in the request. A smarter implementation may be
|
||||
a simple hash, or even cryptograhic hash if desired.
|
||||
|
||||
### Third-Party Terms Account Data
|
||||
|
||||
This proposal also defines the `m.third_party_terms` section in User Account
|
||||
Data in the client/server API that clients SHOULD use to track what sets of
|
||||
terms the user has consented to. This has an array of URLs under the 'accepted'
|
||||
key to which the user has agreed to.
|
||||
|
||||
An `m.third_party_terms` section therefore resembles the following:
|
||||
|
||||
```json
|
||||
{
|
||||
"accepted": [
|
||||
"https://example.org/somewhere/terms-1.2-en.html",
|
||||
"https://example.org/somewhere/privacy-1.2-en.html"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Whenever a client submits a `POST $prefix/terms` request to an IS or IM, it
|
||||
SHOULD update this account data section adding any the URLs of any additional
|
||||
documents that the user agreed to to this list.
|
||||
|
||||
### Terms Acceptance in the API
|
||||
|
||||
Any request to any endpoint in the IS and IM APIs, with the exception of
|
||||
`/_matrix/identity/api/v1` may return a `M_TERMS_NOT_SIGNED` errcode. This
|
||||
indicates that the user must agree to (new) terms in order to use or continue
|
||||
to use the service.
|
||||
|
||||
The client uses the `GET $prefix/terms` endpoint to get the latest set of terms
|
||||
that must be agreed to. It then cross-references this set of documents against
|
||||
the `m.third_party_terms` account data and presents to the user any documents
|
||||
that they have not already agreed to, along with UI for them to indicate their
|
||||
agreement. Once the user has indicated their agreement, then, and only then,
|
||||
must the client use the `POST $prefix/terms` API to signal to the server the
|
||||
set of documents that the user has agreed to.
|
||||
|
||||
If the server returns an `acceptance_token`, the client should include this
|
||||
token in the `X-TERMS-TOKEN` HTTP header in all subsequent requests to an
|
||||
endpoint on the API with the exception of `/_matrix/identity/api/v1`.
|
||||
|
||||
Both making the `POST $prefix/terms` request and providing an `X-TERMS-TOKEN`
|
||||
header signal that the user consents to the terms contained within the
|
||||
corresponding documents. That is to say, if a client or user obtains an
|
||||
acceptance token via means other than a response to the `POST $perfix/terms`
|
||||
API, inclusion of the acceptance token in an `X-TERMS-TOKEN` header in a
|
||||
request still constitutes agreement to the terms in the corresponding
|
||||
documents.
|
||||
|
||||
## Tradeoffs
|
||||
|
||||
This introduces a different way of accepting terms from the client/server API
|
||||
which uses User-Interactive Authentication. In the client/server API, the use
|
||||
of UI auth allows terms acceptance to be integrated into the registration flow
|
||||
in a simple and backwards-compatible way. Indtroducing the UI Auth mechanism
|
||||
into these other APIs would add significant complexity, so this functionality
|
||||
has been provided with simpler, dedicated endpoints.
|
||||
|
||||
## Potential issues
|
||||
|
||||
If the server does not authentcate users, some mechanism is required to track
|
||||
users agreement to terms. The introduction of an extra HTTP header on all
|
||||
requests adds overhead to every request and complexity to the client to add a
|
||||
custom header.
|
||||
|
||||
|
||||
## Security considerations
|
||||
|
||||
The `acceptance_token` is, in effect, a cookie and could be used to identify
|
||||
users of the service. Users of the Integration manager must be authenticated
|
||||
anyway, so this is irrelevant for the IM API. It could allow an Identity Server
|
||||
to identify users where it may otherwise not be able to do so (if a client was
|
||||
careful to mask other identifying HTTP headers). Given most requests to the IS
|
||||
API, by their nature, include 3pids which, even if hashed, will make users
|
||||
easily identifiable, this probably does not add any significant concern.
|
||||
|
||||
It is assumed that once servers publish a given version of a document at a
|
||||
given URL, the contents of that URL will not change. This could be mitigated by
|
||||
identifying documents based on a hash of their contents rather than their URLs.
|
||||
Agreement to terms in the client/server API makes this assumption, so this
|
||||
proposal aims to be consistent.
|
||||
|
||||
|
||||
## Conclusion
|
||||
|
||||
This proposal adds an error response to all endpoints on the API and a custom
|
||||
HTTP header on all requests that is used to signal agreement to a set of terms
|
||||
and conditions. The use of the header is only necessary if the server has no
|
||||
other means of tracking acceptance of terms per-user. The IS API is not
|
||||
authenticated so ISes will have no choice but to use the header. The IM API is
|
||||
authenticated so IMs may either use the header or store acceptance per-user.
|
||||
|
||||
A separate endpoint is specified with a GET request for retrieving the set
|
||||
of terms required and a POST to indicate that the user consents to those
|
||||
terms.
|
Loading…
Reference in New Issue