diff --git a/.circleci/config.yml b/.circleci/config.yml index 659380b0..b37478bf 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -97,7 +97,7 @@ jobs: command: DOCS_URL="${CIRCLE_BUILD_URL}/artifacts/${CIRCLE_NODE_INDEX}/${CIRCLE_WORKING_DIRECTORY/#\~/$HOME}/api/client-server/index.html"; echo $DOCS_URL build-dev-scripts: docker: - - image: golang:1.8 + - image: golang:1.10 steps: - checkout - run: diff --git a/README.rst b/README.rst index b8847bfb..ace8ebdd 100644 --- a/README.rst +++ b/README.rst @@ -138,4 +138,4 @@ Issue tracking Issues with the Matrix specification are tracked in `GitHub `_. -See `meta/labels.rst `_ for notes on what the labels mean. +See `meta/github-labels.rst `_ for notes on what the labels mean. diff --git a/api/identity/associations.yaml b/api/identity/associations.yaml index 8ff4a9ed..82c70fb8 100644 --- a/api/identity/associations.yaml +++ b/api/identity/associations.yaml @@ -30,6 +30,7 @@ paths: description: |- Determines if a given 3pid has been validated by a user. operationId: getValidated3pid + deprecated: true parameters: - in: query type: string @@ -104,6 +105,7 @@ paths: ``application/x-form-www-urlencoded`` data. However, this usage is deprecated. operationId: bind + deprecated: true parameters: - in: body name: body @@ -221,6 +223,7 @@ paths: through to the client requesting an unbind through a homeserver, if the homeserver is acting on behalf of a client. operationId: unbind + deprecated: true parameters: - in: body name: body diff --git a/api/identity/definitions/security.yaml b/api/identity/definitions/security.yaml new file mode 100644 index 00000000..ef49ff5c --- /dev/null +++ b/api/identity/definitions/security.yaml @@ -0,0 +1,18 @@ +# Copyright 2019 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +accessToken: + type: apiKey + description: The access_token returned by a call to ``/register``. + name: access_token + in: query diff --git a/api/identity/email_associations.yaml b/api/identity/email_associations.yaml index 38186432..6ac28cd0 100644 --- a/api/identity/email_associations.yaml +++ b/api/identity/email_associations.yaml @@ -46,6 +46,7 @@ paths: ``application/x-form-www-urlencoded`` data. However, this usage is deprecated. operationId: emailRequestToken + deprecated: true parameters: - in: body name: body @@ -92,6 +93,7 @@ paths: ``application/x-form-www-urlencoded`` data. However, this usage is deprecated. operationId: emailSubmitTokenPost + deprecated: true parameters: - in: body name: body @@ -142,6 +144,7 @@ paths: Note that, in contrast with the POST version, this endpoint will be used by end-users, and so the response should be human-readable. operationId: emailSubmitTokenGet + deprecated: true parameters: - in: query type: string diff --git a/api/identity/invitation_signing.yaml b/api/identity/invitation_signing.yaml index 4e10e2b5..e2ac28b0 100644 --- a/api/identity/invitation_signing.yaml +++ b/api/identity/invitation_signing.yaml @@ -33,6 +33,7 @@ paths: The identity server will look up ``token`` which was stored in a call to ``store-invite``, and fetch the sender of the invite. operationId: blindlySignStuff + deprecated: true parameters: - in: body name: body diff --git a/api/identity/lookup.yaml b/api/identity/lookup.yaml index fd50f94b..166b0962 100644 --- a/api/identity/lookup.yaml +++ b/api/identity/lookup.yaml @@ -32,6 +32,7 @@ paths: summary: Look up the Matrix user ID for a 3pid. description: Look up the Matrix user ID for a 3pid. operationId: lookupUser + deprecated: true parameters: - in: query type: string @@ -101,6 +102,7 @@ paths: summary: Lookup Matrix user IDs for a list of 3pids. description: Lookup Matrix user IDs for a list of 3pids. operationId: lookupUsers + deprecated: true parameters: - in: body name: body diff --git a/api/identity/phone_associations.yaml b/api/identity/phone_associations.yaml index b9933f1a..28312a4d 100644 --- a/api/identity/phone_associations.yaml +++ b/api/identity/phone_associations.yaml @@ -46,6 +46,7 @@ paths: ``application/x-form-www-urlencoded`` data. However, this usage is deprecated. operationId: msisdnRequestToken + deprecated: true parameters: - in: body name: body @@ -94,6 +95,7 @@ paths: ``application/x-form-www-urlencoded`` data. However, this usage is deprecated. operationId: msisdnSubmitTokenPost + deprecated: true parameters: - in: body name: body @@ -144,6 +146,7 @@ paths: Note that, in contrast with the POST version, this endpoint will be used by end-users, and so the response should be human-readable. operationId: msisdnSubmitTokenGet + deprecated: true parameters: - in: query type: string diff --git a/api/identity/ping.yaml b/api/identity/ping.yaml index 05e12a87..d7249a77 100644 --- a/api/identity/ping.yaml +++ b/api/identity/ping.yaml @@ -36,6 +36,7 @@ paths: This is primarly used for auto-discovery and health check purposes by entities acting as a client for the identity server. operationId: ping + deprecated: true responses: 200: description: An identity server is ready to serve requests. diff --git a/api/identity/pubkey.yaml b/api/identity/pubkey.yaml index e657c61c..a585e7ec 100644 --- a/api/identity/pubkey.yaml +++ b/api/identity/pubkey.yaml @@ -30,6 +30,7 @@ paths: description: |- Get the public key for the passed key ID. operationId: getPubKey + deprecated: true parameters: - in: path type: string @@ -72,6 +73,7 @@ paths: Check whether a long-term public key is valid. The response should always be the same, provided the key exists. operationId: isPubKeyValid + deprecated: true parameters: - in: query type: string @@ -101,6 +103,7 @@ paths: description: |- Check whether a short-term public key is valid. operationId: isEphemeralPubKeyValid + deprecated: true parameters: - in: query type: string diff --git a/api/identity/store_invite.yaml b/api/identity/store_invite.yaml index bca78d7e..4a5d525d 100644 --- a/api/identity/store_invite.yaml +++ b/api/identity/store_invite.yaml @@ -55,6 +55,7 @@ paths: server's ability. Identity servers may use these variables when notifying the ``address`` of the pending invite for display purposes. operationId: storeInvite + deprecated: true parameters: - in: body name: body diff --git a/api/identity/v2_associations.yaml b/api/identity/v2_associations.yaml new file mode 100644 index 00000000..d1b29a8f --- /dev/null +++ b/api/identity/v2_associations.yaml @@ -0,0 +1,308 @@ +# Copyright 2018 New Vector Ltd +# Copyright 2019 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +swagger: '2.0' +info: + title: "Matrix Identity Service Establishing Associations API" + version: "2.0.0" +host: localhost:8090 +schemes: + - https +basePath: /_matrix/identity/v2 +consumes: + - application/json +produces: + - application/json +securityDefinitions: + $ref: definitions/security.yaml +paths: + "/3pid/getValidated3pid": + get: + summary: Check whether ownership of a 3pid was validated. + description: |- + Determines if a given 3pid has been validated by a user. + operationId: getValidated3pidV2 + security: + - accessToken: [] + parameters: + - in: query + type: string + name: sid + description: The Session ID generated by the ``requestToken`` call. + required: true + x-example: 1234 + - in: query + type: string + name: client_secret + description: The client secret passed to the ``requestToken`` call. + required: true + x-example: monkeys_are_GREAT + responses: + 200: + description: Validation information for the session. + examples: + application/json: { + "medium": "email", + "validated_at": 1457622739026, + "address": "louise@bobs.burgers" + } + schema: + type: object + properties: + medium: + type: string + description: The medium type of the 3pid. + address: + type: string + description: The address of the 3pid being looked up. + validated_at: + type: integer + description: |- + Timestamp, in milliseconds, indicating the time that the 3pid + was validated. + required: ['medium', 'address', 'validated_at'] + 400: + description: |- + The session has not been validated. + + If the session has not been validated, then ``errcode`` will be + ``M_SESSION_NOT_VALIDATED``. If the session has timed out, then + ``errcode`` will be ``M_SESSION_EXPIRED``. + examples: + application/json: { + "errcode": "M_SESSION_NOT_VALIDATED", + "error": "This validation session has not yet been completed" + } + schema: + $ref: "../client-server/definitions/errors/error.yaml" + 404: + description: The Session ID or client secret were not found. + examples: + application/json: { + "errcode": "M_NO_VALID_SESSION", + "error": "No valid session was found matching that sid and client secret" + } + schema: + $ref: "../client-server/definitions/errors/error.yaml" + "/3pid/bind": + post: + summary: Publish an association between a session and a Matrix user ID. + description: |- + Publish an association between a session and a Matrix user ID. + + Future calls to ``/lookup`` for any of the session\'s 3pids will return + this association. + + Note: for backwards compatibility with previous drafts of this + specification, the parameters may also be specified as + ``application/x-form-www-urlencoded`` data. However, this usage is + deprecated. + operationId: bindV2 + security: + - accessToken: [] + parameters: + - in: body + name: body + schema: + type: object + example: { + "sid": "1234", + "client_secret": "monkeys_are_GREAT", + "mxid": "@ears:matrix.org" + } + properties: + sid: + type: string + description: The Session ID generated by the ``requestToken`` call. + client_secret: + type: string + description: The client secret passed to the ``requestToken`` call. + mxid: + type: string + description: The Matrix user ID to associate with the 3pids. + required: ["sid", "client_secret", "mxid"] + responses: + 200: + description: The association was published. + examples: + application/json: { + "address": "louise@bobs.burgers", + "medium": "email", + "mxid": "@ears:matrix.org", + "not_before": 1428825849161, + "not_after": 4582425849161, + "ts": 1428825849161, + "signatures": { + "matrix.org": { + "ed25519:0": "ENiU2YORYUJgE6WBMitU0mppbQjidDLanAusj8XS2nVRHPu+0t42OKA/r6zV6i2MzUbNQ3c3MiLScJuSsOiVDQ" + } + } + } + schema: + type: object + properties: + address: + type: string + description: The 3pid address of the user being looked up. + medium: + type: string + description: The medium type of the 3pid. + mxid: + type: string + description: The Matrix user ID associated with the 3pid. + not_before: + type: integer + description: A unix timestamp before which the association is not known to be valid. + not_after: + type: integer + description: A unix timestamp after which the association is not known to be valid. + ts: + type: integer + description: The unix timestamp at which the association was verified. + signatures: + type: object + description: |- + The signatures of the verifying identity servers which show that the + association should be trusted, if you trust the verifying identity + services. + $ref: "../../schemas/server-signatures.yaml" + required: + - address + - medium + - mxid + - not_before + - not_after + - ts + - signatures + 400: + description: |- + The association was not published. + + If the session has not been validated, then ``errcode`` will be + ``M_SESSION_NOT_VALIDATED``. If the session has timed out, then + ``errcode`` will be ``M_SESSION_EXPIRED``. + examples: + application/json: { + "errcode": "M_SESSION_NOT_VALIDATED", + "error": "This validation session has not yet been completed" + } + schema: + $ref: "../client-server/definitions/errors/error.yaml" + 404: + description: The Session ID or client secret were not found + examples: + application/json: { + "errcode": "M_NO_VALID_SESSION", + "error": "No valid session was found matching that sid and client secret" + } + schema: + $ref: "../client-server/definitions/errors/error.yaml" + "/3pid/unbind": + post: + summary: Remove an association between a session and a Matrix user ID. + description: |- + Remove an association between a session and a Matrix user ID. + + Future calls to ``/lookup`` for any of the session's 3pids will not + return the removed association. + + The identity server should authenticate the request in one of two + ways: + + 1. The request is signed by the homeserver which controls the ``user_id``. + 2. The request includes the ``sid`` and ``client_secret`` parameters, + as per ``/3pid/bind``, which proves ownership of the 3PID. + + If this endpoint returns a JSON Matrix error, that error should be passed + through to the client requesting an unbind through a homeserver, if the + homeserver is acting on behalf of a client. + operationId: unbindV2 + security: + - accessToken: [] + parameters: + - in: body + name: body + schema: + type: object + example: { + "sid": "1234", + "client_secret": "monkeys_are_GREAT", + "mxid": "@ears:example.org", + "threepid": { + "medium": "email", + "address": "monkeys_have_ears@example.org" + } + } + properties: + sid: + type: string + description: The Session ID generated by the ``requestToken`` call. + client_secret: + type: string + description: The client secret passed to the ``requestToken`` call. + mxid: + type: string + description: The Matrix user ID to remove from the 3pids. + threepid: + type: object + title: 3PID + description: |- + The 3PID to remove. Must match the 3PID used to generate the session + if using ``sid`` and ``client_secret`` to authenticate this request. + properties: + medium: + type: string + description: |- + A medium from the `3PID Types`_ Appendix, matching the medium + of the identifier to unbind. + address: + type: string + description: The 3PID address to remove. + required: ['medium', 'address'] + required: ["threepid", "mxid"] + responses: + 200: + description: The association was successfully removed. + examples: + application/json: {} + schema: + type: object + 400: + description: |- + If the response body is not a JSON Matrix error, the identity server + does not support unbinds. If a JSON Matrix error is in the response + body, the requesting party should respect the error. + 404: + description: |- + If the response body is not a JSON Matrix error, the identity server + does not support unbinds. If a JSON Matrix error is in the response + body, the requesting party should respect the error. + 403: + description: |- + The credentials supplied to authenticate the request were invalid. + This may also be returned if the identity server does not support + the chosen authentication method (such as blocking homeservers from + unbinding identifiers). + examples: + application/json: { + "errcode": "M_FORBIDDEN", + "error": "Invalid homeserver signature" + } + schema: + $ref: "../client-server/definitions/errors/error.yaml" + 501: + description: |- + If the response body is not a JSON Matrix error, the identity server + does not support unbinds. If a JSON Matrix error is in the response + body, the requesting party should respect the error. diff --git a/api/identity/v2_email_associations.yaml b/api/identity/v2_email_associations.yaml new file mode 100644 index 00000000..eff18eaf --- /dev/null +++ b/api/identity/v2_email_associations.yaml @@ -0,0 +1,183 @@ +# Copyright 2018 New Vector Ltd +# Copyright 2019 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +swagger: '2.0' +info: + title: "Matrix Identity Service Email Associations API" + version: "2.0.0" +host: localhost:8090 +schemes: + - https +basePath: /_matrix/identity/v2 +consumes: + - application/json +produces: + - application/json +securityDefinitions: + $ref: definitions/security.yaml +paths: + "/validate/email/requestToken": + post: + summary: Request a token for validating an email address. + description: |- + Create a session for validating an email address. + + The identity server will send an email containing a token. If that + token is presented to the identity server in the future, it indicates + that that user was able to read the email for that email address, and + so we validate ownership of the email address. + + Note that homeservers offer APIs that proxy this API, adding + additional behaviour on top, for example, + ``/register/email/requestToken`` is designed specifically for use when + registering an account and therefore will inform the user if the email + address given is already registered on the server. + + Note: for backwards compatibility with previous drafts of this + specification, the parameters may also be specified as + ``application/x-form-www-urlencoded`` data. However, this usage is + deprecated. + operationId: emailRequestTokenV2 + security: + - accessToken: [] + parameters: + - in: body + name: body + schema: + $ref: "definitions/request_email_validation.yaml" + responses: + 200: + description: Session created. + schema: + $ref: "definitions/sid.yaml" + 400: + description: | + An error ocurred. Some possible errors are: + + - ``M_INVALID_EMAIL``: The email address provided was invalid. + - ``M_EMAIL_SEND_ERROR``: The validation email could not be sent. + examples: + application/json: { + "errcode": "M_INVALID_EMAIL", + "error": "The email address is not valid" + } + schema: + $ref: "../client-server/definitions/errors/error.yaml" + "/validate/email/submitToken": + post: + summary: Validate ownership of an email address. + description: |- + Validate ownership of an email address. + + If the three parameters are consistent with a set generated by a + ``requestToken`` call, ownership of the email address is considered to + have been validated. This does not publish any information publicly, or + associate the email address with any Matrix user ID. Specifically, + calls to ``/lookup`` will not show a binding. + + The identity server is free to match the token case-insensitively, or + carry out other mapping operations such as unicode + normalisation. Whether to do so is an implementation detail for the + identity server. Clients must always pass on the token without + modification. + + Note: for backwards compatibility with previous drafts of this + specification, the parameters may also be specified as + ``application/x-form-www-urlencoded`` data. However, this usage is + deprecated. + operationId: emailSubmitTokenPostV2 + security: + - accessToken: [] + parameters: + - in: body + name: body + schema: + type: object + example: { + "sid": "1234", + "client_secret": "monkeys_are_GREAT", + "token": "atoken" + } + properties: + sid: + type: string + description: The session ID, generated by the ``requestToken`` call. + client_secret: + type: string + description: The client secret that was supplied to the ``requestToken`` call. + token: + type: string + description: The token generated by the ``requestToken`` call and emailed to the user. + required: ["sid", "client_secret", "token"] + responses: + 200: + description: + The success of the validation. + examples: + application/json: { + "success": true + } + schema: + type: object + properties: + success: + type: boolean + description: Whether the validation was successful or not. + required: ['success'] + get: + summary: Validate ownership of an email address. + description: |- + Validate ownership of an email address. + + If the three parameters are consistent with a set generated by a + ``requestToken`` call, ownership of the email address is considered to + have been validated. This does not publish any information publicly, or + associate the email address with any Matrix user ID. Specifically, + calls to ``/lookup`` will not show a binding. + + Note that, in contrast with the POST version, this endpoint will be + used by end-users, and so the response should be human-readable. + operationId: emailSubmitTokenGetV2 + security: + - accessToken: [] + parameters: + - in: query + type: string + name: sid + required: true + description: The session ID, generated by the ``requestToken`` call. + x-example: 1234 + - in: query + type: string + name: client_secret + required: true + description: The client secret that was supplied to the ``requestToken`` call. + x-example: monkeys_are_GREAT + - in: query + type: string + name: token + required: true + description: The token generated by the ``requestToken`` call and emailed to the user. + x-example: atoken + responses: + "200": + description: Email address is validated. + "3xx": + description: |- + Email address is validated, and the ``next_link`` parameter was + provided to the ``requestToken`` call. The user must be redirected + to the URL provided by the ``next_link`` parameter. + "4xx": + description: + Validation failed. diff --git a/api/identity/v2_invitation_signing.yaml b/api/identity/v2_invitation_signing.yaml new file mode 100644 index 00000000..c1267bdc --- /dev/null +++ b/api/identity/v2_invitation_signing.yaml @@ -0,0 +1,101 @@ +# Copyright 2018 New Vector Ltd +# Copyright 2019 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +swagger: '2.0' +info: + title: "Matrix Identity Service Ephemeral Invitation Signing API" + version: "2.0.0" +host: localhost:8090 +schemes: + - https +basePath: /_matrix/identity/v2 +consumes: + - application/json +produces: + - application/json +securityDefinitions: + $ref: definitions/security.yaml +paths: + "/sign-ed25519": + post: + summary: Sign invitation details + description: |- + Sign invitation details. + + The identity server will look up ``token`` which was stored in a call + to ``store-invite``, and fetch the sender of the invite. + operationId: blindlySignStuffV2 + security: + - accessToken: [] + parameters: + - in: body + name: body + schema: + type: object + example: { + "mxid": "@foo:bar.com", + "token": "sometoken", + "private_key": "base64encodedkey" + } + properties: + mxid: + type: string + description: The Matrix user ID of the user accepting the invitation. + token: + type: string + description: The token from the call to ``store-invite``. + private_key: + type: string + description: The private key, encoded as `Unpadded base64`_. + required: ["mxid", "token", "private_key"] + responses: + 200: + description: The signed JSON of the mxid, sender, and token. + schema: + type: object + properties: + mxid: + type: string + description: The Matrix user ID of the user accepting the invitation. + sender: + type: string + description: The Matrix user ID of the user who sent the invitation. + signatures: + type: object + description: The signature of the mxid, sender, and token. + $ref: "../../schemas/server-signatures.yaml" + token: + type: string + description: The token for the invitation. + required: ['mxid', 'sender', 'signatures', 'token'] + examples: + application/json: { + "mxid": "@foo:bar.com", + "sender": "@baz:bar.com", + "signatures": { + "my.id.server": { + "ed25519:0": "def987" + } + }, + "token": "abc123" + } + 404: + description: The token was not found. + examples: + application/json: { + "errcode": "M_UNRECOGNIZED", + "error": "Didn't recognize token" + } + schema: + $ref: "../client-server/definitions/errors/error.yaml" diff --git a/api/identity/v2_phone_associations.yaml b/api/identity/v2_phone_associations.yaml new file mode 100644 index 00000000..cfaea410 --- /dev/null +++ b/api/identity/v2_phone_associations.yaml @@ -0,0 +1,185 @@ +# Copyright 2018 New Vector Ltd +# Copyright 2019 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +swagger: '2.0' +info: + title: "Matrix Identity Service Phone Number Associations API" + version: "2.0.0" +host: localhost:8090 +schemes: + - https +basePath: /_matrix/identity/v2 +consumes: + - application/json +produces: + - application/json +securityDefinitions: + $ref: definitions/security.yaml +paths: + "/validate/msisdn/requestToken": + post: + summary: Request a token for validating a phone number. + description: |- + Create a session for validating a phone number. + + The identity server will send an SMS message containing a token. If + that token is presented to the identity server in the future, it + indicates that that user was able to read the SMS for that phone + number, and so we validate ownership of the phone number. + + Note that homeservers offer APIs that proxy this API, adding + additional behaviour on top, for example, + ``/register/msisdn/requestToken`` is designed specifically for use when + registering an account and therefore will inform the user if the phone + number given is already registered on the server. + + Note: for backwards compatibility with previous drafts of this + specification, the parameters may also be specified as + ``application/x-form-www-urlencoded`` data. However, this usage is + deprecated. + operationId: msisdnRequestTokenV2 + security: + - accessToken: [] + parameters: + - in: body + name: body + schema: + $ref: "definitions/request_msisdn_validation.yaml" + responses: + 200: + description: Session created. + schema: + $ref: "definitions/sid.yaml" + 400: + description: | + An error ocurred. Some possible errors are: + + - ``M_INVALID_ADDRESS``: The phone number provided was invalid. + - ``M_SEND_ERROR``: The validation SMS could not be sent. + - ``M_DESTINATION_REJECTED``: The identity server cannot deliver an + SMS to the provided country or region. + examples: + application/json: { + "errcode": "M_INVALID_ADDRESS", + "error": "The phone number is not valid" + } + schema: + $ref: "../client-server/definitions/errors/error.yaml" + "/validate/msisdn/submitToken": + post: + summary: Validate ownership of a phone number. + description: |- + Validate ownership of a phone number. + + If the three parameters are consistent with a set generated by a + ``requestToken`` call, ownership of the phone number is considered to + have been validated. This does not publish any information publicly, or + associate the phone number address with any Matrix user + ID. Specifically, calls to ``/lookup`` will not show a binding. + + The identity server is free to match the token case-insensitively, or + carry out other mapping operations such as unicode + normalisation. Whether to do so is an implementation detail for the + identity server. Clients must always pass on the token without + modification. + + Note: for backwards compatibility with previous drafts of this + specification, the parameters may also be specified as + ``application/x-form-www-urlencoded`` data. However, this usage is + deprecated. + operationId: msisdnSubmitTokenPostV2 + security: + - accessToken: [] + parameters: + - in: body + name: body + schema: + type: object + example: { + "sid": "1234", + "client_secret": "monkeys_are_GREAT", + "token": "atoken" + } + properties: + sid: + type: string + description: The session ID, generated by the ``requestToken`` call. + client_secret: + type: string + description: The client secret that was supplied to the ``requestToken`` call. + token: + type: string + description: The token generated by the ``requestToken`` call and sent to the user. + required: ["sid", "client_secret", "token"] + responses: + 200: + description: + The success of the validation. + examples: + application/json: { + "success": true + } + schema: + type: object + properties: + success: + type: boolean + description: Whether the validation was successful or not. + required: ['success'] + get: + summary: Validate ownership of a phone number. + description: |- + Validate ownership of a phone number. + + If the three parameters are consistent with a set generated by a + ``requestToken`` call, ownership of the phone number address is + considered to have been validated. This does not publish any + information publicly, or associate the phone number with any Matrix + user ID. Specifically, calls to ``/lookup`` will not show a binding. + + Note that, in contrast with the POST version, this endpoint will be + used by end-users, and so the response should be human-readable. + operationId: msisdnSubmitTokenGetV2 + security: + - accessToken: [] + parameters: + - in: query + type: string + name: sid + required: true + description: The session ID, generated by the ``requestToken`` call. + x-example: 1234 + - in: query + type: string + name: client_secret + required: true + description: The client secret that was supplied to the ``requestToken`` call. + x-example: monkeys_are_GREAT + - in: query + type: string + name: token + required: true + description: The token generated by the ``requestToken`` call and sent to the user. + x-example: atoken + responses: + "200": + description: Phone number is validated. + "3xx": + description: |- + Phone number address is validated, and the ``next_link`` parameter + was provided to the ``requestToken`` call. The user must be + redirected to the URL provided by the ``next_link`` parameter. + "4xx": + description: + Validation failed. diff --git a/api/identity/v2_ping.yaml b/api/identity/v2_ping.yaml new file mode 100644 index 00000000..61f5d35b --- /dev/null +++ b/api/identity/v2_ping.yaml @@ -0,0 +1,46 @@ +# Copyright 2018 Kamax Sàrl +# Copyright 2018 New Vector Ltd +# Copyright 2019 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +swagger: "2.0" +info: + title: "Matrix Identity Service Ping API" + version: "2.0.0" +host: localhost:8090 +schemes: + - https +basePath: /_matrix/identity +produces: + - application/json +paths: + "/v2": + get: + summary: Checks that an identity server is available at this API endpoint. + description: |- + Checks that an identity server is available at this API endpoint. + + To discover that an identity server is available at a specific URL, + this endpoint can be queried and will return an empty object. + + This is primarly used for auto-discovery and health check purposes + by entities acting as a client for the identity server. + operationId: pingV2 + responses: + 200: + description: An identity server is ready to serve requests. + examples: + application/json: {} + schema: + type: object diff --git a/api/identity/v2_pubkey.yaml b/api/identity/v2_pubkey.yaml new file mode 100644 index 00000000..68facd68 --- /dev/null +++ b/api/identity/v2_pubkey.yaml @@ -0,0 +1,127 @@ +# Copyright 2016 OpenMarket Ltd +# Copyright 2019 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +swagger: '2.0' +info: + title: "Matrix Identity Service Public Key API" + version: "2.0.0" +host: localhost:8090 +schemes: + - https +basePath: /_matrix/identity/v2 +consumes: + - application/json +produces: + - application/json +paths: + "/pubkey/{keyId}": + get: + summary: Get a public key. + description: |- + Get the public key for the passed key ID. + operationId: getPubKeyV2 + parameters: + - in: path + type: string + name: keyId + required: true + description: |- + The ID of the key. This should take the form algorithm:identifier + where algorithm identifies the signing algorithm, and the identifier + is an opaque string. + x-example: "ed25519:0" + responses: + 200: + description: + The public key exists. + examples: + application/json: { + "public_key": "VXuGitF39UH5iRfvbIknlvlAVKgD1BsLDMvBf0pmp7c" + } + schema: + type: object + properties: + public_key: + type: string + description: Unpadded Base64 encoded public key. + required: ['public_key'] + 404: + description: + The public key was not found. + examples: + application/json: { + "errcode": "M_NOT_FOUND", + "error": "The public key was not found" + } + schema: + $ref: "../client-server/definitions/errors/error.yaml" + "/pubkey/isvalid": + get: + summary: Check whether a long-term public key is valid. + description: |- + Check whether a long-term public key is valid. The response should always + be the same, provided the key exists. + operationId: isPubKeyValidV2 + parameters: + - in: query + type: string + name: public_key + required: true + description: |- + The unpadded base64-encoded public key to check. + x-example: "VXuGitF39UH5iRfvbIknlvlAVKgD1BsLDMvBf0pmp7c" + responses: + 200: + description: + The validity of the public key. + examples: + application/json: { + "valid": true + } + schema: + type: object + properties: + valid: + type: boolean + description: Whether the public key is recognised and is currently valid. + required: ['valid'] + "/pubkey/ephemeral/isvalid": + get: + summary: Check whether a short-term public key is valid. + description: |- + Check whether a short-term public key is valid. + operationId: isEphemeralPubKeyValidV2 + parameters: + - in: query + type: string + name: public_key + required: true + description: |- + The unpadded base64-encoded public key to check. + x-example: "VXuGitF39UH5iRfvbIknlvlAVKgD1BsLDMvBf0pmp7c" + responses: + 200: + description: + The validity of the public key. + examples: + application/json: { + "valid": true + } + schema: + type: object + properties: + valid: + type: boolean + description: Whether the public key is recognised and is currently valid. + required: ['valid'] diff --git a/api/identity/v2_store_invite.yaml b/api/identity/v2_store_invite.yaml new file mode 100644 index 00000000..afc41a1c --- /dev/null +++ b/api/identity/v2_store_invite.yaml @@ -0,0 +1,165 @@ +# Copyright 2018 New Vector Ltd +# Copyright 2019 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +swagger: '2.0' +info: + title: "Matrix Identity Service Store Invitations API" + version: "2.0.0" +host: localhost:8090 +schemes: + - https +basePath: /_matrix/identity/v2 +consumes: + - application/json +produces: + - application/json +securityDefinitions: + $ref: definitions/security.yaml +paths: + "/store-invite": + post: + summary: Store pending invitations to a user's 3pid. + description: |- + Store pending invitations to a user's 3pid. + + In addition to the request parameters specified below, an arbitrary + number of other parameters may also be specified. These may be used in + the invite message generation described below. + + The service will generate a random token and an ephemeral key used for + accepting the invite. + + The service also generates a ``display_name`` for the inviter, which is + a redacted version of ``address`` which does not leak the full contents + of the ``address``. + + The service records persistently all of the above information. + + It also generates an email containing all of this data, sent to the + ``address`` parameter, notifying them of the invitation. + + Also, the generated ephemeral public key will be listed as valid on + requests to ``/_matrix/identity/v2/pubkey/ephemeral/isvalid``. + + Currently, invites may only be issued for 3pids of the ``email`` medium. + + Optional fields in the request should be populated to the best of the + server's ability. Identity servers may use these variables when notifying + the ``address`` of the pending invite for display purposes. + operationId: storeInviteV2 + security: + - accessToken: [] + parameters: + - in: body + name: body + schema: + type: object + properties: + medium: + type: string + description: The literal string ``email``. + example: "email" + address: + type: string + description: The email address of the invited user. + example: "foo@example.com" + room_id: + type: string + description: The Matrix room ID to which the user is invited + example: "!something:example.org" + sender: + type: string + description: The Matrix user ID of the inviting user + example: "@bob:example.com" + room_alias: + type: string + description: |- + The Matrix room alias for the room to which the user is + invited. This should be retrieved from the ``m.room.canonical_alias`` + state event. + example: "#somewhere:exmaple.org" + room_avatar_url: + type: string + description: |- + The Content URI for the room to which the user is invited. This should + be retrieved from the ``m.room.avatar`` state event. + example: "mxc://example.org/s0meM3dia" + room_join_rules: + type: string + description: |- + The ``join_rule`` for the room to which the user is invited. This should + be retrieved from the ``m.room.join_rules`` state event. + example: "public" + room_name: + type: string + description: |- + The name of the room to which the user is invited. This should be retrieved + from the ``m.room.name`` state event. + example: "Bob's Emporium of Messages" + sender_display_name: + type: string + description: The display name of the user ID initiating the invite. + example: "Bob Smith" + sender_avatar_url: + type: string + description: The Content URI for the avatar of the user ID initiating the invite. + example: "mxc://example.org/an0th3rM3dia" + required: ["medium", "address", "room_id", "sender"] + responses: + 200: + description: The invitation was stored. + schema: + type: object + properties: + token: + type: string + description: | + The generated token. Must be a string consisting of the + characters ``[0-9a-zA-Z.=_-]``. Its length must not exceed + 255 characters and it must not be empty. + public_keys: + type: array + description: | + A list of [server's long-term public key, generated ephemeral + public key]. + items: + type: string + display_name: + type: string + description: The generated (redacted) display_name. + required: ['token', 'public_keys', 'display_name'] + example: + application/json: { + "token": "sometoken", + "public_keys": [ + "serverpublickey", + "ephemeralpublickey" + ], + "display_name": "f...@b..." + } + 400: + description: | + An error has occured. + + If the 3pid is already bound to a Matrix user ID, the error code + will be ``M_THREEPID_IN_USE``. If the medium is unsupported, the + error code will be ``M_UNRECOGNIZED``. + examples: + application/json: { + "errcode": "M_THREEPID_IN_USE", + "error": "Binding already known", + "mxid": "@alice:example.com" + } + schema: + $ref: "../client-server/definitions/errors/error.yaml" diff --git a/changelogs/client_server/newsfragments/2247.clarification b/changelogs/client_server/newsfragments/2247.clarification new file mode 100644 index 00000000..43553399 --- /dev/null +++ b/changelogs/client_server/newsfragments/2247.clarification @@ -0,0 +1 @@ +Fix the ``m.room_key_request`` ``action`` value, setting it from ``cancel_request`` to ``request_cancellation``. diff --git a/event-schemas/examples/m.room_key_request$cancel_request b/event-schemas/examples/m.room_key_request$cancel_request index c6eb25de..afc1c350 100644 --- a/event-schemas/examples/m.room_key_request$cancel_request +++ b/event-schemas/examples/m.room_key_request$cancel_request @@ -1,6 +1,6 @@ { "content": { - "action": "cancel_request", + "action": "request_cancellation", "requesting_device_id": "RJYKSTBOIE", "request_id": "1495474790150.19" }, diff --git a/event-schemas/schema/m.room_key_request b/event-schemas/schema/m.room_key_request index 007d0086..c08ac0e3 100644 --- a/event-schemas/schema/m.room_key_request +++ b/event-schemas/schema/m.room_key_request @@ -38,7 +38,7 @@ properties: action: enum: - request - - cancel_request + - request_cancellation type: string requesting_device_id: description: ID of the device requesting the key. diff --git a/meta/github-labels.rst b/meta/github-labels.rst new file mode 100644 index 00000000..f674b81b --- /dev/null +++ b/meta/github-labels.rst @@ -0,0 +1,91 @@ +The following labels are used to help categorize issues: + +`spec-omission `_ +-------------------------------------------------------------------------------- + +Things which have been implemented but not currently specified. These may range +from entire API endpoints, to particular options or return parameters. + +Issues with this label will have been implemented in `Synapse +`_. Normally there will be a design +document in Google Docs or similar which describes the feature. + +Examples: + +* `Spec PUT /directory/list `_ +* `Unspec'd server_name request param for /join/{roomIdOrAlias} + `_ + +`clarification `_ +-------------------------------------------------------------------------------- + +An area where the spec could do with being more explicit. + +Examples: + +* `Spec the implicit limit on /syncs + `_ + +* `Clarify the meaning of the currently_active flags in presence events + `_ + +`spec-bug `_ +---------------------------------------------------------------------- + +Something which is in the spec, but is wrong. + +Note: this is *not* for things that are badly designed or don't work well +(for which see 'improvement' or 'feature') - it is for places where the +spec doesn't match reality. + +Examples: + +* `swagger is wrong for directory PUT + `_ + +* `receipts section still refers to initialSync + `_ + +`improvement `_ +---------------------------------------------------------------------------- + +A suggestion for a relatively simple improvement to the protocol. + +Examples: + +* `We need a 'remove 3PID' API so that users can remove mappings + `_ +* `We should mandate that /publicRooms requires an access_token + `_ + +`feature `_ +-------------------------------------------------------------------- + +A suggestion for a significant extension to the matrix protocol which +needs considerable consideration before implementation. + +Examples: + +* `Peer-to-peer Matrix `_ +* `Specify a means for clients to "edit" previous messages + `_ + + +`wart `_ +-------------------------------------------------------------- + +A point where the protocol is inconsistent or inelegant, but which isn't really +causing anybody any problems right now. Might be nice to consider fixing one +day. + + +`question `_ +---------------------------------------------------------------------- + +A thought or idea about the protocol which we aren't really sure whether to +pursue or not. + +Examples: + +* `Should we prepend anti-eval code to our json responses? + `_ diff --git a/proposals/1957-integrations-discovery.md b/proposals/1957-integrations-discovery.md new file mode 100644 index 00000000..85939726 --- /dev/null +++ b/proposals/1957-integrations-discovery.md @@ -0,0 +1,189 @@ +# MSC1957: Integration manager discovery + +**Note**: this proposal is part of a larger "Integrations API" which has not yet been defined. +See [MSC1956](https://github.com/matrix-org/matrix-doc/pull/1956) for details. + +**Note**: this proposal makes use of the existing Widget API proposed by +[MSC1236](https://github.com/matrix-org/matrix-doc/issues/1236). + +Users should have the freedom to choose which integration manager they want to use in their client, while +also accepting suggestions from their homeserver and client. Clients need to know where to find the different +integration managers and how to contact them. + + +## Proposal + +A single logged in user may be influenced by zero or more integration managers at any given time. Managers +are sourced from the client's own configuration, homeserver discovery information, and the user's personal +account data in the form of widgets. Clients should support users using more than one integration manager +at a given time, although the rules for how this can be handled are defined later in this proposal. + +#### Client-configured integration managers + +This is left as an implementation detail. In the case of Riot, this is likely to be part of the existing +`config.json` options, although likely modified to support multiple managers instead of one. + +#### Homeserver-configured integration managers + +The integration managers suggested by a homeserver are done through the existing +[.well-known](https://matrix.org/docs/spec/client_server/r0.4.0.html#get-well-known-matrix-client) discovery +mechanism. The added optional fields, which should not affect a client's ability to log a user in, are: +```json +{ + "m.integrations": { + "managers": [ + { + "api_url": "https://integrations.example.org", + "ui_url": "https://integrations.example.org/ui" + }, + { + "api_url": "https://bots.example.org" + } + ] + } +} +``` + +As shown, the homeserver is able to suggest multiple integration managers through this method. Each manager +must have an `api_url` which must be an `http` or `https` URL. The `ui_url` is optional and if not provided +is the same as the `api_url`. Like the `api_url`, the `ui_url` must be `http` or `https` if supplied. + +The `ui_url` is ultimately treated the same as a widget, except that the `data` object from the widget is not +present and must not be templated here. Variables like `$matrix_display_name` are able to function, however. +Integration managers should never use the `$matrix_user_id` as authoritative and instead seek other ways to +determine the user ID. This is covered by other proposals. + +The `api_url` is the URL clients will use when *not* embedding the integration manager, and instead showing +its own purpose-built interface. + +Clients should query the `.well-known` information for the homeserver periodically to update the integration +manager settings for that homeserver. The client is not expected to validate or use any other information +contained in the response. Current recommendations are to query the configuration when the client starts up +and every 8 hours after that. Clients can additionally refresh the configuration whenever they feel is +necessary (such as every time the user opens the integration manager). + +#### User-configured integration managers + +Users can specify integration managers in the form of account widgets. The `type` is to be `m.integration_manager` +and the content would look something similar to: +```json +{ + "url": "https://integrations.example.org/ui?displayName=$matrix_display_name", + "data": { + "api_url": "https://integrations.example.org" + } +} +``` + +The `api_url` in the `data` object is required and has the same meaning as the homeserver-defined `api_url`. +The `url` of the widget is analogous to the `ui_url` from the homeserver configuration above, however normal +widget rules apply here. + +The user is able to have multiple integration managers through use of multiple widgets. + +The query string shown in the example is to demonstrate that integration managers are widgets and can +make use of the template options provided to widgets. + +#### Display order of integration managers + +Clients which have support for integration managers should display at least 1 manager, but should +display multiple via something like tabs. Clients must prefer to display the user's configured +integration managers over any defaults, and if only displaying one manager must pick the first +manager after sorting the `state_key`s of the applicable widgets in lexicographical order. Clients +can additionally display default managers if they so wish, and should preserve the order defined in +the various defaults. If the user has no configured integration managers, the client must prefer +to display one or more of the managers suggested by the homeserver over the managers recommended +by the client. + +The client can optionally support a way to entirely disable integration manager support, even if the +user and homeserver have managers defined. + +The rationale for having the client prefer to use the user's integration managers first is so that +the user can tailor their experience within Matrix if desired. Similarly, a homeserver may wish to +subject all of their users to the same common integration manager as would be common in some organizations. +The client's own preference is a last ditch effort to have an integration manager available to the +user so they don't get left out. + +#### Displaying integration managers + +Clients simply open the `ui_url` (or equivalent) in an `iframe` or similar. In the current ecosystem, +integration managers would receive a `scalar_token` to identify the user - this is no longer the case +and instead integration managers must seek other avenues for determining the user ID. Other proposals +cover how to do this in the context of the integrations API. + +Integration managers shown in this way must be treated like widgets, regardless of source. In practice +this means exposing the Widget API to the manager and applying necessary scoping to keep the manager +as an account widget rather than a room widget. + +#### Discovering a manager by only the domain name + +Clients may wish to ask users for a single canonical domain name so they can find the manager to add +to the user's account transparently. This differs from the .well-known discovery which allows homeservers +to recommend their own integration manager: the homeserver is not recommending a default here. The +user has instead opted to pick an integration manager (identified only by domain name) and the client +is expected to resolve that to a set of URLs it can use for the manager. + +Similar to the .well-known discovery done by servers (and clients during login), clients which have an +integrations domain (eg: "example.org") make a regular HTTPS request to +`https://example.org/.well-known/matrix/integrations` which returns an object which looks like the +following: +```json +{ + "m.integrations_widget": { + "url": "https://integrations.example.org/ui?displayName=$matrix_display_name", + "data": { + "api_url": "https://integrations.example.org" + } + } +} +``` + +The response should be parsed as JSON. If the endpoint returns an error or is missing the `m.integrations_widget` +property, the client should assume there is no integrations manager running on that domain. The +`m.integrations_widget` is an object which has the exact same format as the account widget for +an integration manager, described above. The client should wrap the object verbatim into the appropriate +account data location. + +Because the .well-known file would be accessed by web browsers, among other platforms, the server +should be using appropriate CORS headers for the request. The recommended headers are the same as those +which are already recommended for homeserver discovery in the Client-Server API. + +*Note*: this could reuse the client-server mechanic for discovery and just omit the homeserver information +however that conflates many concerns together on the one endpoint. A new endpoint is instead proposed +to keep the concerns isolated. + +The query string shown in the example is to demonstrate that integration managers are widgets and can +make use of the template options provided to widgets. + +## Tradeoffs + +We could limit the user (and by extension, the homeserver and client) to exactly 1 integration manager +and not worry about tabs or other concepts, however this restricts a user's access to integrations. +In a scenario where the user wants to use widgets from Service A and bots from Service B, they'd +end up switching accounts or clients to gain access to either service, or potentially just give up +and walk away from the problem. Instead of having the user switch between clients, we might as well +support this use case, even if it is moderately rare. + +We could also define the integration managers in a custom account data event rather than defining them +as a widget. Doing so just adds clutter to the account data and risks duplicating code in clients as +using widgets gets us URL templating for free (see the section earlier on in this proposal about account +widgets for more information: "User-configured integration managers"). + + +## Future extensions + +Some things which may be desirable in the future are: +* Avatars for the different managers +* Human-readable names for the different managers +* Supporting `ui_url`s targeting specific clients for a more consistent design + + +## Security considerations + +When displaying integration managers, clients should not trust that the input is sanitary. Per the +proposal above, an integration manager is only permitted to be served from HTTP(S) URIs. A given +integration manager can still have malicious intent however, and clients should ensure any sandboxing +on the manager is appropriate such that it can communicate with the client, but cannot perform +unauthorized actions. Other URI schemes are just as dangerous and could potentially be allowed by +this proposal - use cases are less defined and desirable for schemes like `file://` and are excluded +by this proposal. They can be added in a future proposal if a use case arises. diff --git a/proposals/1961-integrations-auth.md b/proposals/1961-integrations-auth.md new file mode 100644 index 00000000..1f868e4c --- /dev/null +++ b/proposals/1961-integrations-auth.md @@ -0,0 +1,73 @@ +# MSC1961: Integration manager authentication + +A set of common APIs needs to be defined for clients to be able to interact with an integration +manager. This proposal covers the authentication portion of that API. + +**Note**: this proposal is part of a larger "Integrations API" which has not yet been defined. +See [MSC1956](https://github.com/matrix-org/matrix-doc/pull/1956) for details. + + +## Proposal + +All specified APIs (except `/register`) will take an `Authorization` header with a `Bearer` token returned +from a call to `/register`. This token is used to authorize the request and to identify who is making the +request. The token may also be specified as the `access_token` query string parameter, similar to the +Client-Server API. + +#### POST `/_matrix/integrations/v1/account/register` + +Exchanges an OpenID object for a token which can be used to authorize future requests to the manager. + +Request body is an OpenID object as returned by `/_matrix/client/r0/user/:userId/openid/request_token`. + +Response is: +```json +{ + "token": "OpaqueString" +} +``` + +The token should consist of URL-safe base64 characters. Integration managers should be careful to validate +the OpenID object by ensuring the `/_matrix/federation/v1/openid/userinfo` response has a `sub` which belongs +to the `matrix_server_name` provided in the original OpenID object. + +Applications which register for a token are responsible for tracking which integration manager they are for. +This can usually be done by tracking the hostname of the integration manager and matching a token with it. + +#### GET `/_matrix/integrations/v1/account` + +Gets information about the token's owner, such as the user ID for which it belongs. + +Besides a token, no other information is required for the request. + +Response is: +```json +{ + "user_id": "@alice:example.org" +} +``` + +The `user_id` is the user ID which was represented in the OpenID object provided to `/register`. Integration +managers may be interested in also supplying information about the user's credit balance for paid integrations +here. Preferably, custom information is stored under a namespaced key like so: +```json +{ + "user_id": "@alice:example.org", + "org.example.paid.integrations": { + "credit": 20000 + } +} +``` + +#### POST `/_matrix/integrations/v1/account/logout` + +Logs the token out, rendering it useless for future requests. + +Request body is an empty object. Response body is also an empty object if successful. + + +## Security considerations + +Clients should be sure to call `/logout` where possible when the user is logging out or no longer needs access +to a given manager. Clients should additionally be cautious about which managers they register for tokens with, +as some integration managers may be untrusted. diff --git a/proposals/2140-terms-of-service-2.md b/proposals/2140-terms-of-service-2.md new file mode 100644 index 00000000..9f96a00b --- /dev/null +++ b/proposals/2140-terms-of-service-2.md @@ -0,0 +1,335 @@ +# MSC2140: Terms of Service API for Identity Servers and Integration Managers + +[MSC1692](https://github.com/matrix-org/matrix-doc/issues/1692) 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. + +Requirements for this proposal are: + * ISes and IMs should be able to give multiple documents a user must agree to + abide by + * Each document shoud be versioned + * ISes and IMs must, for each request that they handle, know that the user + making the request has agreed to their data being used. This need not be + absolute proof (we will always have to trust that the client actually + showed the document to the user) but it must be reasonably demonstrable that + the user has given informed consent for the client to use that service. + * ISes 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. + * Documents should be de-duplicated between services. If two or more services + are hosted by the same organisation, the organisation should have the + option to give their users a single document that encompasses both services + (bearing in mind that the user must be able to opt-out of components of a + service whilst still being able to use the service without that component). + +Identity Servers do not currently 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. + +## Proposal + +Throuhgout this proposal, $prefix will be used to refer to the prefix of the +API in question, ie. `/_matrix/identity/v2` for the IS API and +`/_matrix/integrations/v1` for the IM API. + +Note the removal of the `/api` prefix and migration to v2 in the IS API +following convention from +[MSC2134](https://github.com/matrix-org/matrix-doc/issues/2134). + +This proposal introduces: + * A v2 API prefix, with authentication, for the Identity Service + * The `$prefix/terms` endpoint + * The `m.accepted_terms` section in account data + * `POST /_matrix/client/r0/account/3pid/unbind` endpoints on the client/server + API + +This proposal removes: + * The `bind_email` and `bind_msisdn` on the Homeserver `/register` endpoint + +This proposal relies on both Integration Managers and Identity Servers being +able to identify users by their MXID and store the fact that a given MXID has +indicated that they accept the terms given. Integration Managers already +identify users in this way by authenticating them using the OpenID endpoint on +the Homeserver. This proposal introduces the same mechanism to Identity Servers +and adds authentication across the Identity Service API. + +### IS API Authentication + +All current endpoints within `/_matrix/identity/api/v1/` will be duplicated +into `/_matrix/identity/v2`, noting that MSC2134 changes the behaviour of +lookups. Authentication is still expected on MSC2134's proposed endpoints. +Support for `application/x-form-www-urlencoded` parameters in requests will +be dropped from all endpoints. + +Any request to any endpoint within `/_matrix/identity/v2`, with the exception +of: + * `/_matrix/identity/v2` + * `/_matrix/identity/v2/pubkey/*` + * The new `$prefix/account/register` endpoint + * The new `GET /_matrix/identity/v2/terms` + * `$prefix/account/logout` + +...may return an error with `M_UNAUTHORIZED` errcode with HTTP status code 401. +This indicates that the user must authenticate with OpenID and supply a valid +`access_token`. + +Clients authenticate either via an `Authorization` header with a `Bearer` token +or an `access_token` query parameter. + +The existing endpoints under `/_matrix/identity/api/v1/` continue to be +unauthenticated but will be deprecated. ISes may support the old v1 API for as +long as they wish. Once ISes remove support for the old APIs, those endpoints +must return HTTP Status 404. Clients must update to use the v2 API as soon as +possible. + +OpenID authentication in the IS API will work the same as in the Integration Manager +API, as specified in [MSC1961](https://github.com/matrix-org/matrix-doc/issues/1961). + +When clients supply an identity server to the Homeserver in order for the +Homeserver to make calls to the IS on its behalf, it must also supply its +access token for the Identity Server alongside in the `id_access_token` key of +the same JSON object. That is, in the main request object for `requestToken` +and `/_matrix/client/r0/rooms/{roomId}/invite` requests and in the +`threepidCreds` object when supplying 3PID credentials (eg. in the +`m.email.identity` UI auth stage). The server must also relay +`M_TERMS_NOT_SIGNED` errors back to the client. Exceptions to this are any +requests where the only IS operation the Homeserver may perform is unbinding, +ie. `/_matrix/client/r0/account/deactivate` and +`/_matrix/client/r0/account/3pid/delete`, in which case the unbind will be +authenticated by a signed request from the Homeserver. + +### HS Register API + +The `bind_email` and `bind_msisdn` options to `/_matrix/client/r0/register` in +the client/server API will be removed. Due to the fact that +`/_matrix/identity/v2/3pid/bind` requires authentication, it will no longer be +possible for the Homeserver to bind 3PIDs as part of the registration process. + +### IS Register API + +The following new APIs will be introduced to support OpenID auth as per +[MSC1961](https://github.com/matrix-org/matrix-doc/issues/1961): + + * `/_matrix/identity/v2/account/register` + * `/_matrix/identity/v2/account` + * `/_matrix/identity/v2/account/logout` + +Note again the removal of the `/api` prefix and migration to v2 following +convention from +[MSC2134](https://github.com/matrix-org/matrix-doc/issues/2134). + +### 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" + } + }, + "privacy_policy": { + "version": "1.2", + "en": { + "name": "Privacy Policy", + "url": "https://example.org/somewhere/privacy-1.2-en.html" + }, + "fr": { + "name": "Politique de confidentialité", + "url": "https://example.org/somewhere/privacy-1.2-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. + +This endpoint does *not* require authentication. + +#### `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"] +} +``` + +This endpoint requires authentication. + +The clients MUST include the correct URL for the language of the document that +was presented to the user and they agreed to. 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 server responds with an empty JSON object. The server must not assume that +the client will agree to all documents in a single request. + +### Accepted Terms Account Data + +This proposal also defines the `m.accepted_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.accepted_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 or +completes an `m.terms` flow on the HS (or as soon as possible afterwards, ie. +after registration is complete), 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 + +Before any requests are made to an Identity Server or Integration Manager, +the client must use the `GET $prefix/terms` endpoint to fetch the set of +documents that the user must agree to in order to use the service. + +It then cross-references this set of documents against the `m.accepted_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. If there are no +such documents (ie. if the `policies` dict is empty or the user has already +agreed to all documents) the client proceeds to perform the OpenID +registration. If there are new terms documents, the client prompts the user for +agreement, then once the user has indicated their agreement, it adds these URLs +to `m.accepted_terms` account data and then proceeds with OpenID +authentication, getting a token from the Homeserver and submitting this to the +service using the `register` endpoint. + +Having done this, if the user agreed to any new documents, it performs a `POST +$prefix/terms` request to signal to the server the set of documents that the +user has agreed to. + +Any request to any endpoint in the IM API, and the `/_matrix/identity/v2/` +namespace of the IS API, with the exception of `/_matrix/identity/v2` itself, +may return: + + * `M_UNAUTHORIZED` errcode with HTTP status code 401. This indicates that + the user must authenticate with OpenID and supply a valid `access_token`. + * `M_TERMS_NOT_SIGNED` errcode with HTTP status code 403. This indicates + that the user must agree to (new) terms in order to use or continue to + use the service. + +The `/_matrix/identity/v2/3pid/unbind` endpoint must not return either of these +errors if the request has a valid signature from a Homeserver, and is being authenticated as such. + +In summary, the process for using a service that has not previously been used +in the current login session is: + + * `GET $prefix/terms` + * Compare result with `m.accepted_terms` account data, get set of documents + pending agreement. + * If non-empty, show this set of documents to the user and wait for the user + to indicate their agreement. + * Add the newly agreed documents to `m.accepted_terms`. + * On success, or if there were no documents pending agreement, get an OpenID + token from the Homeserver and submit this token to the `register` endpoint. + Store the resulting access token. + * If the set of documents pending agreement was non-empty, Perform a + `POST $prefix/terms` request to the service with these documents. + +### `POST /_matrix/client/r0/account/3pid/unbind` + +A client uses this client/server API endpoint to request that the Homeserver +removes the given 3PID from the given Identity Server, or all Identity Servers. +Takes the same parameters as +`POST /_matrix/client/r0/account/3pid/delete`, ie. `id_server`, `medium`, +`address` and the newly added `is_token`. + +Returns the same as `POST /_matrix/client/r0/account/3pid/delete`. + +Clients may add IS bindings for 3PIDs that already exist on the user's +Homeserver account by using the `POST /_matrix/client/r0/account/3pid` +to re-add the 3PID. + +## Tradeoffs + +The Identity Service API previously did not require authentication, and OpenID +is reasonably complex, adding a significant burden to both clients and servers. +A custom HTTP header was also considered that could be added to assert that the +client agrees to a particular set of terms. We decided against this in favour +of re-using existing primitives that already exist in the Matrix ecosystem. +Custom HTTP headers are not used anywhere else within Matrix. This also gives a +very simple and natural way for ISes to enforce that users may only bind 3PIDs +to their own MXIDs. + +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. Another option here would be to use +UI Auth on the register endpoint. This would also not allow users to register +before accepting the terms. However, this would then make the OpenID +registration process different and non-standard. + +The `m.accepted_terms` section contains only URLs of the documents that +have been agreed to. This loses information like the name and version of +the document, but: + * It would be up to the clients to copy this information correctly into + account data. + * Having just the URLs makes it much easier for clients to make a list + of URLs and find documents not already agreed to. + +## Potential issues + +This change deprecates all v1 endpoints and so will require clients to update +to continue working. + +## Security considerations + +Requiring authentication on the IS API means it will no longer be possible to +use it anonymously. + +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. diff --git a/proposals/2230-identity-server-account-data.md b/proposals/2230-identity-server-account-data.md new file mode 100644 index 00000000..19fb3062 --- /dev/null +++ b/proposals/2230-identity-server-account-data.md @@ -0,0 +1,71 @@ +# MSC2230: Store Identity Server in Account Data + +The URL of the Identity Server to use is currently specified at registration and +login time and then used for the lifetime of a login session. If users wish to +specify a custom one, they must do so each time they log in on every client. +Once they have chosen an Identity Server to advertise their 3PIDs on, it would +be normal that they would wish to continue using this Identity Server for all +Identity requests in their account accross all clients. This proposal aims to +make this easier. + +## Proposal + +The base URL of the Identity Server is to be stored in user account data. It +shall be stored in the same format as in a .well-known file under the event type +`m.identity_server` and shall comprise a single key, `base_url` which is the +base URL of the ID Server to use (that is, the part before `/_matrix`, including +`https://`). + +Upon registration or login, a client SHOULD refrain from performing any requests +to the Identity Server until the account data has been fetched from the server. +Once it has the account data, it SHOULD check for the presence of the +`m.identity_server` key. If present, the `base_url` in this key SHOULD be used +as the Identity Server base URL for the duration of the login session. If this +key is not present, the client SHOULD use whatever value it would have used prior +to this MSC. It should not update the account data in this situation. + +Client SHOULD listen for changes in the `m.identity_server` account data value +and update the URL that they use for ID Server requests accordingly. + +Clients can offer a way for users to change the ID server being used. If they +do, the client MUST update the value of `m.identity_server` accordingly. + +The `m.identity_server` may be present with a `base_url` of `null`. In this case, +clients MUST treat this as no ID Server URL being set and not perform ID +Server requests, disabling any functionality that requires such requests. + +Conversely, if a user wishes to disable ID Server functionality, the client +shall action this by setting the `base_url` of the `m.identity_server` +account data entry to `null`. + +### Transition Period + +Clients will continue to use whatever IS URLs they currently use until the +user sets one explicitly, at which point it will be written to account data +and all clients will start using this value. + +## Tradeoffs + +There are a number of ways to transition to this new scheme. Clients could +populate the account data with their current ID Server URL as soon as +possible, and immediately use any new value seen on account data. This +would a much faster migration but any users with clients using different +ID Servers would suddenly find all their clients using the ID Server of +whichever client they updated first. + +## Potential issues + +Users will no longer be able to have different clients configured with +different ID Servers. + +## Security considerations + +An attacker would be able to force all a user clients to use a given ID Server +if they gained control of any of a user's logins. + +## Conclusion + +This makes the ID server an account setting which means it persists between +logins. The intention would be to phase out clients ever asking for an ID +Server URL at registration or login: this will be much easier for users to +understand whilst still retaining the flexibilty for those who want it. diff --git a/scripts/templating/matrix_templates/templates/http-api.tmpl b/scripts/templating/matrix_templates/templates/http-api.tmpl index 74836045..d2ee3ff7 100644 --- a/scripts/templating/matrix_templates/templates/http-api.tmpl +++ b/scripts/templating/matrix_templates/templates/http-api.tmpl @@ -1,11 +1,15 @@ {% import 'tables.tmpl' as tables -%} -``{{endpoint.method}} {{endpoint.path}}`` -{{(5 + (endpoint.path | length) + (endpoint.method | length)) * title_kind}} {% if "deprecated" in endpoint and endpoint.deprecated -%} +Deprecated: ``{{endpoint.method}} {{endpoint.path}}`` +{{(17 + (endpoint.path | length) + (endpoint.method | length)) * title_kind}} + .. WARNING:: This API is deprecated and will be removed from a future release. +{% else %} +``{{endpoint.method}} {{endpoint.path}}`` +{{(5 + (endpoint.path | length) + (endpoint.method | length)) * title_kind}} {% endif -%} {{endpoint.desc}} diff --git a/specification/identity_service_api.rst b/specification/identity_service_api.rst index 89604644..f8211f70 100644 --- a/specification/identity_service_api.rst +++ b/specification/identity_service_api.rst @@ -57,6 +57,8 @@ The following other versions are also available, in reverse chronological order: General principles ------------------ +.. TODO: TravisR - Define auth for IS v2 API in a future PR + The purpose of an identity server is to validate, store, and answer questions about the identities of users. In particular, it stores associations of the form "identifier X represents the same user as identifier Y", where identities may @@ -176,6 +178,8 @@ Status check {{ping_is_http_api}} +{{v2_ping_is_http_api}} + Key management -------------- @@ -195,11 +199,15 @@ service's long-term keys. {{pubkey_is_http_api}} +{{v2_pubkey_is_http_api}} + Association lookup ------------------ {{lookup_is_http_api}} +.. TODO: TravisR - Add v2 lookup API in future PR + Establishing associations ------------------------- @@ -243,16 +251,22 @@ Email associations {{email_associations_is_http_api}} +{{v2_email_associations_is_http_api}} + Phone number associations ~~~~~~~~~~~~~~~~~~~~~~~~~ {{phone_associations_is_http_api}} +{{v2_phone_associations_is_http_api}} + General ~~~~~~~ {{associations_is_http_api}} +{{v2_associations_is_http_api}} + Invitation storage ------------------ @@ -267,6 +281,8 @@ long-term private key for the identity server. {{store_invite_is_http_api}} +{{v2_store_invite_is_http_api}} + Ephemeral invitation signing ---------------------------- @@ -277,6 +293,8 @@ this isn't possible. {{invitation_signing_is_http_api}} +{{v2_invitation_signing_is_http_api}} + .. _`Unpadded Base64`: ../appendices.html#unpadded-base64 .. _`3PID Types`: ../appendices.html#pid-types .. _`Signing JSON`: ../appendices.html#signing-json diff --git a/specification/modules/end_to_end_encryption.rst b/specification/modules/end_to_end_encryption.rst index 329c0170..7758e2c1 100644 --- a/specification/modules/end_to_end_encryption.rst +++ b/specification/modules/end_to_end_encryption.rst @@ -756,8 +756,8 @@ sending `m.room_key_request`_ to-device messages to other devices with device, it can forward the keys to the first device by sending an encrypted `m.forwarded_room_key`_ to-device message. The first device should then send an `m.room_key_request`_ to-device message with ``action`` set to -``cancel_request`` to the other devices that it had originally sent the key -request to; a device that receives a ``cancel_request`` should disregard any +``request_cancellation`` to the other devices that it had originally sent the key +request to; a device that receives a ``request_cancellation`` should disregard any previously-received ``request`` message with the same ``request_id`` and ``requesting_device_id``. diff --git a/specification/proposals_intro.rst b/specification/proposals_intro.rst index 20cfd48d..de65ba27 100644 --- a/specification/proposals_intro.rst +++ b/specification/proposals_intro.rst @@ -79,7 +79,7 @@ their proposed changes to the Matrix protocol: * Pragmatism rather than perfection * Proof rather than conjecture -Please see [MSC1779](https://github.com/matrix-org/matrix-doc/blob/matthew/msc1779/proposals/1779-open-governance.md) +Please see `MSC1779 `_ for full details of the project's Guiding Principles. Technical notes