Merge remote-tracking branch 'remotes/origin/master' into kitsune-map-to-enum-support

pull/977/head
Kitsune Ral 5 years ago
commit 6b37bb1dd9

@ -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 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: build-dev-scripts:
docker: docker:
- image: golang:1.8 - image: golang:1.10
steps: steps:
- checkout - checkout
- run: - run:
@ -121,4 +121,4 @@ workflows:
notify: notify:
webhooks: webhooks:
- url: https://giles.cadair.com/circleci - url: https://giles.cadair.dev/circleci

@ -138,4 +138,4 @@ Issue tracking
Issues with the Matrix specification are tracked in `GitHub Issues with the Matrix specification are tracked in `GitHub
<https://github.com/matrix-org/matrix-doc/issues>`_. <https://github.com/matrix-org/matrix-doc/issues>`_.
See `meta/labels.rst <meta/labels.rst>`_ for notes on what the labels mean. See `meta/github-labels.rst <meta/github-labels.rst>`_ for notes on what the labels mean.

@ -110,10 +110,16 @@ paths:
id_server: id_server:
type: string type: string
description: The identity server to use. description: The identity server to use.
id_access_token:
type: string
description: |-
An access token previously registered with the identity server. Servers
can treat this as optional to distinguish between r0.5-compatible clients
and this specification version.
sid: sid:
type: string type: string
description: The session identifier given by the identity server. description: The session identifier given by the identity server.
required: ["client_secret", "id_server", "sid"] required: ["client_secret", "id_server", "id_access_token", "sid"]
bind: bind:
type: boolean type: boolean
description: |- description: |-
@ -125,6 +131,7 @@ paths:
example: { example: {
"three_pid_creds": { "three_pid_creds": {
"id_server": "matrix.org", "id_server": "matrix.org",
"id_access_token": "abc123_OpaqueString",
"sid": "abc123987", "sid": "abc123987",
"client_secret": "d0n'tT3ll" "client_secret": "d0n'tT3ll"
}, },
@ -172,6 +179,10 @@ paths:
description: |- description: |-
Removes a third party identifier from the user's account. This might not Removes a third party identifier from the user's account. This might not
cause an unbind of the identifier from the identity server. cause an unbind of the identifier from the identity server.
Unlike other endpoints, this endpoint does not take an ``id_access_token``
parameter because the homeserver is expected to sign the request to the
identity server instead.
operationId: delete3pidFromAccount operationId: delete3pidFromAccount
security: security:
- accessToken: [] - accessToken: []
@ -226,6 +237,69 @@ paths:
- id_server_unbind_result - id_server_unbind_result
tags: tags:
- User data - User data
"/account/3pid/unbind":
post:
summary: Removes a user's third party identifier from an identity server.
description: |-
Removes a user's third party identifier from the provided identity server
without removing it from the homeserver.
Unlike other endpoints, this endpoint does not take an ``id_access_token``
parameter because the homeserver is expected to sign the request to the
identity server instead.
operationId: unbind3pidFromAccount
security:
- accessToken: []
parameters:
- in: body
name: body
schema:
type: object
properties:
id_server:
type: string
description: |-
The identity server to unbind from. If not provided, the homeserver
MUST use the ``id_server`` the identifier was added through. If the
homeserver does not know the original ``id_server``, it MUST return
a ``id_server_unbind_result`` of ``no-support``.
example: "example.org"
medium:
type: string
description: The medium of the third party identifier being removed.
enum: ["email", "msisdn"]
example: "email"
address:
type: string
description: The third party address being removed.
example: "example@example.org"
required: ['medium', 'address']
responses:
200:
description: |-
The identity server has disassociated the third party identifier from the
user.
schema:
type: object
properties:
id_server_unbind_result:
type: string
enum:
# XXX: I don't know why, but the order matters here so that "no-support"
# doesn't become "no- support" by the renderer.
- "no-support"
- "success"
description: |-
An indicator as to whether or not the identity server was able to unbind
the 3PID. ``success`` indicates that the identity server has unbound the
identifier whereas ``no-support`` indicates that the identity server
refuses to support the request or the homeserver was not able to determine
an identity server to unbind from.
example: "success"
required:
- id_server_unbind_result
tags:
- User data
"/account/3pid/email/requestToken": "/account/3pid/email/requestToken":
post: post:
summary: Begins the validation process for an email address for association with the user's account. summary: Begins the validation process for an email address for association with the user's account.

@ -139,6 +139,12 @@ paths:
id_server: id_server:
type: string type: string
description: The hostname+port of the identity server which should be used for third party identifier lookups. description: The hostname+port of the identity server which should be used for third party identifier lookups.
id_access_token:
type: string
description: |-
An access token previously registered with the identity server. Servers
can treat this as optional to distinguish between r0.5-compatible clients
and this specification version.
medium: medium:
type: string type: string
# TODO: Link to Identity Service spec when it eixsts # TODO: Link to Identity Service spec when it eixsts
@ -146,7 +152,7 @@ paths:
address: address:
type: string type: string
description: The invitee's third party identifier. description: The invitee's third party identifier.
required: ["id_server", "medium", "address"] required: ["id_server", "id_access_token", "medium", "address"]
room_version: room_version:
type: string type: string
description: |- description: |-

@ -0,0 +1,36 @@
# 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.
type: object
properties:
access_token:
type: string
description: |-
An access token the consumer may use to verify the identity of
the person who generated the token. This is given to the federation
API ``GET /openid/userinfo`` to verify the user's identity.
token_type:
type: string
description: The string ``Bearer``.
matrix_server_name:
type: string
description: |-
The homeserver domain the consumer should use when attempting to
verify the user's identity.
expires_in:
type: integer
description: |-
The number of seconds before this token expires and a new one must
be generated.
required: ['access_token', 'token_type', 'matrix_server_name', 'expires_in']

@ -23,4 +23,10 @@ allOf:
include a port. This parameter is ignored when the homeserver handles include a port. This parameter is ignored when the homeserver handles
3PID verification. 3PID verification.
example: "id.example.com" example: "id.example.com"
required: ["id_server"] id_access_token:
type: string
description: |-
An access token previously registered with the identity server. Servers
can treat this as optional to distinguish between r0.5-compatible clients
and this specification version.
required: ["id_server", "id_access_token"]

@ -23,4 +23,10 @@ allOf:
include a port. This parameter is ignored when the homeserver handles include a port. This parameter is ignored when the homeserver handles
3PID verification. 3PID verification.
example: "id.example.com" example: "id.example.com"
required: ["id_server"] id_access_token:
type: string
description: |-
An access token previously registered with the identity server. Servers
can treat this as optional to distinguish between r0.5-compatible clients
and this specification version.
required: ["id_server", "id_access_token"]

@ -73,28 +73,7 @@ paths:
"expires_in": 3600, "expires_in": 3600,
} }
schema: schema:
type: object $ref: "definitions/openid_token.yaml"
properties:
access_token:
type: string
description: |-
An access token the consumer may use to verify the identity of
the person who generated the token. This is given to the federation
API ``GET /openid/userinfo``.
token_type:
type: string
description: The string ``Bearer``.
matrix_server_name:
type: string
description: |-
The homeserver domain the consumer should use when attempting to
verify the user's identity.
expires_in:
type: integer
description: |-
The number of seconds before this token expires and a new one must
be generated.
required: ['access_token', 'token_type', 'matrix_server_name', 'expires_in']
429: 429:
description: This request was rate-limited. description: This request was rate-limited.
schema: schema:

@ -95,18 +95,6 @@ paths:
should be authenticated, but is instead used to should be authenticated, but is instead used to
authenticate the ``register`` call itself. authenticate the ``register`` call itself.
"$ref": "definitions/auth_data.yaml" "$ref": "definitions/auth_data.yaml"
bind_email:
type: boolean
description: |-
If true, the server binds the email used for authentication to
the Matrix ID with the identity server.
example: false
bind_msisdn:
type: boolean
description: |-
If true, the server binds the phone number used for authentication
to the Matrix ID with the identity server.
example: false
username: username:
type: string type: string
description: |- description: |-
@ -519,6 +507,10 @@ paths:
The homeserver may change the flows available depending on whether a The homeserver may change the flows available depending on whether a
valid access token is provided. valid access token is provided.
Unlike other endpoints, this endpoint does not take an ``id_access_token``
parameter because the homeserver is expected to sign the request to the
identity server instead.
security: security:
- accessToken: [] - accessToken: []
operationId: deactivateAccount operationId: deactivateAccount

@ -92,6 +92,7 @@ paths:
type: object type: object
example: { example: {
"id_server": "matrix.org", "id_server": "matrix.org",
"id_access_token": "abc123_OpaqueString",
"medium": "email", "medium": "email",
"address": "cheeky@monkey.com" "address": "cheeky@monkey.com"
} }
@ -99,6 +100,12 @@ paths:
id_server: id_server:
type: string type: string
description: The hostname+port of the identity server which should be used for third party identifier lookups. description: The hostname+port of the identity server which should be used for third party identifier lookups.
id_access_token:
type: string
description: |-
An access token previously registered with the identity server. Servers
can treat this as optional to distinguish between r0.5-compatible clients
and this specification version.
medium: medium:
type: string type: string
# TODO: Link to Identity Service spec when it eixsts # TODO: Link to Identity Service spec when it eixsts
@ -106,7 +113,7 @@ paths:
address: address:
type: string type: string
description: The invitee's third party identifier. description: The invitee's third party identifier.
required: ["id_server", "medium", "address"] required: ["id_server", "id_access_token", "medium", "address"]
responses: responses:
200: 200:
description: The user has been invited to join the room. description: The user has been invited to join the room.

@ -30,6 +30,7 @@ paths:
description: |- description: |-
Determines if a given 3pid has been validated by a user. Determines if a given 3pid has been validated by a user.
operationId: getValidated3pid operationId: getValidated3pid
deprecated: true
parameters: parameters:
- in: query - in: query
type: string type: string
@ -104,6 +105,7 @@ paths:
``application/x-form-www-urlencoded`` data. However, this usage is ``application/x-form-www-urlencoded`` data. However, this usage is
deprecated. deprecated.
operationId: bind operationId: bind
deprecated: true
parameters: parameters:
- in: body - in: body
name: body name: body
@ -221,6 +223,7 @@ paths:
through to the client requesting an unbind through a homeserver, if the through to the client requesting an unbind through a homeserver, if the
homeserver is acting on behalf of a client. homeserver is acting on behalf of a client.
operationId: unbind operationId: unbind
deprecated: true
parameters: parameters:
- in: body - in: body
name: body name: body

@ -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

@ -46,6 +46,7 @@ paths:
``application/x-form-www-urlencoded`` data. However, this usage is ``application/x-form-www-urlencoded`` data. However, this usage is
deprecated. deprecated.
operationId: emailRequestToken operationId: emailRequestToken
deprecated: true
parameters: parameters:
- in: body - in: body
name: body name: body
@ -92,6 +93,7 @@ paths:
``application/x-form-www-urlencoded`` data. However, this usage is ``application/x-form-www-urlencoded`` data. However, this usage is
deprecated. deprecated.
operationId: emailSubmitTokenPost operationId: emailSubmitTokenPost
deprecated: true
parameters: parameters:
- in: body - in: body
name: body name: body
@ -142,6 +144,7 @@ paths:
Note that, in contrast with the POST version, this endpoint will be Note that, in contrast with the POST version, this endpoint will be
used by end-users, and so the response should be human-readable. used by end-users, and so the response should be human-readable.
operationId: emailSubmitTokenGet operationId: emailSubmitTokenGet
deprecated: true
parameters: parameters:
- in: query - in: query
type: string type: string
@ -162,7 +165,7 @@ paths:
description: The token generated by the ``requestToken`` call and emailed to the user. description: The token generated by the ``requestToken`` call and emailed to the user.
x-example: atoken x-example: atoken
responses: responses:
"200": 200:
description: Email address is validated. description: Email address is validated.
"3xx": "3xx":
description: |- description: |-

@ -33,6 +33,7 @@ paths:
The identity server will look up ``token`` which was stored in a call The identity server will look up ``token`` which was stored in a call
to ``store-invite``, and fetch the sender of the invite. to ``store-invite``, and fetch the sender of the invite.
operationId: blindlySignStuff operationId: blindlySignStuff
deprecated: true
parameters: parameters:
- in: body - in: body
name: body name: body

@ -16,7 +16,7 @@
# limitations under the License. # limitations under the License.
swagger: '2.0' swagger: '2.0'
info: info:
title: "Matrix Identity Service Lookup API" title: "Matrix Identity Service Lookup API"
version: "1.0.0" version: "1.0.0"
host: localhost:8090 host: localhost:8090
schemes: schemes:
@ -32,6 +32,7 @@ paths:
summary: Look up the Matrix user ID for a 3pid. summary: Look up the Matrix user ID for a 3pid.
description: Look up the Matrix user ID for a 3pid. description: Look up the Matrix user ID for a 3pid.
operationId: lookupUser operationId: lookupUser
deprecated: true
parameters: parameters:
- in: query - in: query
type: string type: string
@ -101,6 +102,7 @@ paths:
summary: Lookup Matrix user IDs for a list of 3pids. summary: Lookup Matrix user IDs for a list of 3pids.
description: Lookup Matrix user IDs for a list of 3pids. description: Lookup Matrix user IDs for a list of 3pids.
operationId: lookupUsers operationId: lookupUsers
deprecated: true
parameters: parameters:
- in: body - in: body
name: body name: body

@ -46,6 +46,7 @@ paths:
``application/x-form-www-urlencoded`` data. However, this usage is ``application/x-form-www-urlencoded`` data. However, this usage is
deprecated. deprecated.
operationId: msisdnRequestToken operationId: msisdnRequestToken
deprecated: true
parameters: parameters:
- in: body - in: body
name: body name: body
@ -94,6 +95,7 @@ paths:
``application/x-form-www-urlencoded`` data. However, this usage is ``application/x-form-www-urlencoded`` data. However, this usage is
deprecated. deprecated.
operationId: msisdnSubmitTokenPost operationId: msisdnSubmitTokenPost
deprecated: true
parameters: parameters:
- in: body - in: body
name: body name: body
@ -144,6 +146,7 @@ paths:
Note that, in contrast with the POST version, this endpoint will be Note that, in contrast with the POST version, this endpoint will be
used by end-users, and so the response should be human-readable. used by end-users, and so the response should be human-readable.
operationId: msisdnSubmitTokenGet operationId: msisdnSubmitTokenGet
deprecated: true
parameters: parameters:
- in: query - in: query
type: string type: string
@ -164,7 +167,7 @@ paths:
description: The token generated by the ``requestToken`` call and sent to the user. description: The token generated by the ``requestToken`` call and sent to the user.
x-example: atoken x-example: atoken
responses: responses:
"200": 200:
description: Phone number is validated. description: Phone number is validated.
"3xx": "3xx":
description: |- description: |-

@ -36,6 +36,7 @@ paths:
This is primarly used for auto-discovery and health check purposes This is primarly used for auto-discovery and health check purposes
by entities acting as a client for the identity server. by entities acting as a client for the identity server.
operationId: ping operationId: ping
deprecated: true
responses: responses:
200: 200:
description: An identity server is ready to serve requests. description: An identity server is ready to serve requests.

@ -30,6 +30,7 @@ paths:
description: |- description: |-
Get the public key for the passed key ID. Get the public key for the passed key ID.
operationId: getPubKey operationId: getPubKey
deprecated: true
parameters: parameters:
- in: path - in: path
type: string type: string
@ -72,6 +73,7 @@ paths:
Check whether a long-term public key is valid. The response should always Check whether a long-term public key is valid. The response should always
be the same, provided the key exists. be the same, provided the key exists.
operationId: isPubKeyValid operationId: isPubKeyValid
deprecated: true
parameters: parameters:
- in: query - in: query
type: string type: string
@ -101,6 +103,7 @@ paths:
description: |- description: |-
Check whether a short-term public key is valid. Check whether a short-term public key is valid.
operationId: isEphemeralPubKeyValid operationId: isEphemeralPubKeyValid
deprecated: true
parameters: parameters:
- in: query - in: query
type: string type: string

@ -55,6 +55,7 @@ paths:
server's ability. Identity servers may use these variables when notifying server's ability. Identity servers may use these variables when notifying
the ``address`` of the pending invite for display purposes. the ``address`` of the pending invite for display purposes.
operationId: storeInvite operationId: storeInvite
deprecated: true
parameters: parameters:
- in: body - in: body
name: body name: body

@ -0,0 +1,333 @@
# 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"
403:
description: |
The user must do something in order to use this endpoint. One example
is an ``M_TERMS_NOT_SIGNED`` error where the user must `agree to more terms`_.
examples:
application/json: {
"errcode": "M_TERMS_NOT_SIGNED",
"error": "Please accept our updated terms of service before continuing"
}
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"
403:
description: |
The user must do something in order to use this endpoint. One example
is an ``M_TERMS_NOT_SIGNED`` error where the user must `agree to more terms`_.
examples:
application/json: {
"errcode": "M_TERMS_NOT_SIGNED",
"error": "Please accept our updated terms of service before continuing"
}
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).
Another common error code is ``M_TERMS_NOT_SIGNED`` where the user
needs to `agree to more terms`_ in order to continue.
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.

@ -0,0 +1,131 @@
# 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 Authentication 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:
"/account/register":
post:
summary: Exchanges an OpenID token for an access token.
description: |-
Exchanges an OpenID token from the homeserver for an access token to
access the identity server. The request body is the same as the values
returned by ``/openid/request_token`` in the Client-Server API.
operationId: registerAccount
parameters:
- in: body
name: body
schema:
$ref: "../client-server/definitions/openid_token.yaml"
responses:
200:
description: |-
A token which can be used to authenticate future requests to the
identity server.
examples:
application/json: {
"token": "abc123_OpaqueString"
}
schema:
type: object
properties:
token:
type: string
description: |-
An opaque string representing the token to authenticate future
requests to the identity server with.
required: ['token']
"/account":
get:
summary: Gets account holder information for a given token.
description: |-
Gets information about what user owns the access token used in the request.
operationId: getAccount
security:
- accessToken: []
parameters: []
responses:
200:
description: The token holder's information.
examples:
application/json: {
"user_id": "@alice:example.org"
}
schema:
type: object
properties:
user_id:
type: string
description: The user ID which registered the token.
required: ['user_id']
403:
description: |
The user must do something in order to use this endpoint. One example
is an ``M_TERMS_NOT_SIGNED`` error where the user must `agree to more terms`_.
examples:
application/json: {
"errcode": "M_TERMS_NOT_SIGNED",
"error": "Please accept our updated terms of service before continuing"
}
schema:
$ref: "../client-server/definitions/errors/error.yaml"
"/account/logout":
post:
summary: Logs out an access token, rendering it unusable.
description: |-
Logs out the access token, preventing it from being used to authenticate
future requests to the server.
operationId: logout
security:
- accessToken: []
parameters: []
responses:
200:
description: The token was successfully logged out.
examples:
application/json: {}
schema:
type: object
401:
description: |-
The token is not registered or is otherwise unknown to the server.
examples:
application/json: {
"errcode": "M_UNKNOWN_TOKEN",
"error": "Unrecognised access token"
}
schema:
$ref: "../client-server/definitions/errors/error.yaml"
403:
description: |
The user must do something in order to use this endpoint. One example
is an ``M_TERMS_NOT_SIGNED`` error where the user must `agree to more terms`_.
examples:
application/json: {
"errcode": "M_TERMS_NOT_SIGNED",
"error": "Please accept our updated terms of service before continuing"
}
schema:
$ref: "../client-server/definitions/errors/error.yaml"

@ -0,0 +1,216 @@
# 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"
403:
description: |
The user must do something in order to use this endpoint. One example
is an ``M_TERMS_NOT_SIGNED`` error where the user must `agree to more terms`_.
examples:
application/json: {
"errcode": "M_TERMS_NOT_SIGNED",
"error": "Please accept our updated terms of service before continuing"
}
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']
403:
description: |
The user must do something in order to use this endpoint. One example
is an ``M_TERMS_NOT_SIGNED`` error where the user must `agree to more terms`_.
examples:
application/json: {
"errcode": "M_TERMS_NOT_SIGNED",
"error": "Please accept our updated terms of service before continuing"
}
schema:
$ref: "../client-server/definitions/errors/error.yaml"
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.
403:
description: |
The user must do something in order to use this endpoint. One example
is an ``M_TERMS_NOT_SIGNED`` error where the user must `agree to more terms`_.
examples:
application/json: {
"errcode": "M_TERMS_NOT_SIGNED",
"error": "Please accept our updated terms of service before continuing"
}
schema:
$ref: "../client-server/definitions/errors/error.yaml"

@ -0,0 +1,112 @@
# 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"
403:
description: |
The user must do something in order to use this endpoint. One example
is an ``M_TERMS_NOT_SIGNED`` error where the user must `agree to more terms`_.
examples:
application/json: {
"errcode": "M_TERMS_NOT_SIGNED",
"error": "Please accept our updated terms of service before continuing"
}
schema:
$ref: "../client-server/definitions/errors/error.yaml"

@ -0,0 +1,148 @@
# Copyright 2016 OpenMarket Ltd
# Copyright 2017 Kamax.io
# Copyright 2017 New Vector Ltd
# 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 Lookup 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:
"/hash_details":
get:
summary: Gets hash function information from the server.
description: |-
Gets parameters for hashing identifiers from the server. This can include
any of the algorithms defined in this specification.
operationId: getHashDetails
security:
- accessToken: []
parameters: []
responses:
200:
description: The hash function information.
examples:
application/json: {
"lookup_pepper": "matrixrocks",
"algorithms": ["none", "sha256"]
}
schema:
type: object
properties:
lookup_pepper:
type: string
description: |-
The pepper the client MUST use in hashing identifiers, and MUST
supply to the ``/lookup`` endpoint when performing lookups.
Servers SHOULD rotate this string often.
algorithms:
type: array
items:
type: string
description: |-
The algorithms the server supports. Must contain at least ``sha256``.
required: ['lookup_pepper', 'algorithms']
"/lookup":
post:
summary: Look up Matrix User IDs for a set of 3PIDs.
description: |-
Looks up the set of Matrix User IDs which have bound the 3PIDs given, if
bindings are available. Note that the format of the addresses is defined
later in this specification.
operationId: lookupUsersV2
security:
- accessToken: []
parameters:
- in: body
name: body
schema:
type: object
properties:
algorithm:
type: string
description: |-
The algorithm the client is using to encode the ``addresses``. This
should be one of the available options from ``/hash_details``.
example: "sha256"
pepper:
type: string
description: |-
The pepper from ``/hash_details``. This is required even when the
``algorithm`` does not make use of it.
example: "matrixrocks"
addresses:
type: array
items:
type: string
description: |-
The addresses to look up. The format of the entries here depend on
the ``algorithm`` used. Note that queries which have been incorrectly
hashed or formatted will lead to no matches.
example: [
"4kenr7N9drpCJ4AfalmlGQVsOn3o2RHjkADUpXJWZUc",
"nlo35_T5fzSGZzJApqu8lgIudJvmOQtDaHtr-I4rU7I"
]
required: ['algorithm', 'pepper', 'addresses']
responses:
200:
description:
The associations for any matched ``addresses``.
examples:
application/json: {
"mappings": {
"4kenr7N9drpCJ4AfalmlGQVsOn3o2RHjkADUpXJWZUc": "@alice:example.org"
}
}
schema:
type: object
properties:
mappings:
type: object
description: |-
Any applicable mappings of ``addresses`` to Matrix User IDs. Addresses
which do not have associations will not be included, which can make
this property be an empty object.
title: AssociatedMappings
additionalProperties:
type: string
required: ['mappings']
400:
description:
The client's request was invalid in some way. One possible problem could
be the ``pepper`` being invalid after the server has rotated it - this is
presented with the ``M_INVALID_PEPPER`` error code. Clients SHOULD make
a call to ``/hash_details`` to get a new pepper in this scenario, being
careful to avoid retry loops.
``M_INVALID_PARAM`` can also be returned to indicate the client supplied
an ``algorithm`` that is unknown to the server.
examples:
application/json: {
"errcode": "M_INVALID_PEPPER",
"error": "Unknown or invalid pepper - has it been rotated?"
}
schema:
$ref: "../client-server/definitions/errors/error.yaml"

@ -0,0 +1,218 @@
# 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"
403:
description: |
The user must do something in order to use this endpoint. One example
is an ``M_TERMS_NOT_SIGNED`` error where the user must `agree to more terms`_.
examples:
application/json: {
"errcode": "M_TERMS_NOT_SIGNED",
"error": "Please accept our updated terms of service before continuing"
}
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']
403:
description: |
The user must do something in order to use this endpoint. One example
is an ``M_TERMS_NOT_SIGNED`` error where the user must `agree to more terms`_.
examples:
application/json: {
"errcode": "M_TERMS_NOT_SIGNED",
"error": "Please accept our updated terms of service before continuing"
}
schema:
$ref: "../client-server/definitions/errors/error.yaml"
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.
403:
description: |
The user must do something in order to use this endpoint. One example
is an ``M_TERMS_NOT_SIGNED`` error where the user must `agree to more terms`_.
examples:
application/json: {
"errcode": "M_TERMS_NOT_SIGNED",
"error": "Please accept our updated terms of service before continuing"
}
schema:
$ref: "../client-server/definitions/errors/error.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

@ -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']

@ -0,0 +1,176 @@
# 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"
403:
description: |
The user must do something in order to use this endpoint. One example
is an ``M_TERMS_NOT_SIGNED`` error where the user must `agree to more terms`_.
examples:
application/json: {
"errcode": "M_TERMS_NOT_SIGNED",
"error": "Please accept our updated terms of service before continuing"
}
schema:
$ref: "../client-server/definitions/errors/error.yaml"

@ -0,0 +1,149 @@
# 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 Terms of Service 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:
"/terms":
get:
summary: Gets the terms of service offered by the server.
description: |-
Gets all the terms of service offered by the server. The client is expected
to filter through the terms to determine which terms need acceptance from the
user. Note that this endpoint does not require authentication.
operationId: getTerms
parameters: []
responses:
200:
description: |-
The terms of service offered by the server.
examples:
application/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"
}
}
}
}
schema:
type: object
properties:
policies:
type: object
title: Policy Map
description: |-
The policies the server offers. Mapped from arbitrary ID (unused in
this version of the specification) to a Policy Object.
additionalProperties:
type: object
title: Policy Object
description: |-
The policy. Includes a map of language (ISO 639-2) to language-specific
policy information.
properties:
version:
type: string
description: |-
The version for the policy. There are no requirements on what this
might be and could be "alpha", semantically versioned, or arbitrary.
required: ['version']
# TODO: TravisR - Make this render
additionalProperties:
type: object
title: Internationalised Policy
description: |-
The policy information for the specified language.
properties:
name:
type: string
description: The translated name of the policy.
url:
type: string
description: |-
The URL, which should include the policy ID, version, and language
in it, to be presented to the user as the policy. URLs should have
all three criteria to avoid conflicts when the policy is updated
in the future: for example, if this was "https://example.org/terms.html"
then the server would be unable to update it because the client would
have already added that URL to the ``m.accepted_terms`` collection.
required: ['name', 'url']
required: ['policies']
post:
summary: Indicates acceptance of terms to the server.
description: |-
Called by a client to indicate that the user has accepted/agreed to the included
set of URLs. Servers MUST NOT assume that the client will be sending all previously
accepted URLs and should therefore append the provided URLs to what the server
already knows has been accepted.
Clients MUST provide the URL of the policy in the language that was presented
to the user. Servers SHOULD consider acceptance of any one language's URL as
acceptance for all other languages of that policy.
The server should avoid returning ``M_TERMS_NOT_SIGNED`` because the client
may not be accepting all terms at once.
operationId: agreeToTerms
security:
- accessToken: []
parameters:
- in: body
name: body
schema:
type: object
properties:
user_accepts:
type: array
items:
type: string
description: The URLs the user is accepting in this request.
example: "https://example.org/somewhere/terms-2.0-en.html"
required: ['user_accepts']
responses:
200:
description: |-
The server has considered the user as having accepted the provided URLs.
examples:
application/json: {}
schema:
type: object

@ -68,3 +68,163 @@ paths:
description: The public room list for the homeserver. description: The public room list for the homeserver.
schema: schema:
$ref: "../client-server/definitions/public_rooms_response.yaml" $ref: "../client-server/definitions/public_rooms_response.yaml"
post:
summary: Gets the public rooms on the server with optional filter.
description: |-
Lists the public rooms on the server, with optional filter.
This API returns paginated responses. The rooms are ordered by the number
of joined members, with the largest rooms first.
Note that this endpoint receives and returns the same format that is seen
in the Client-Server API's ``POST /publicRooms`` endpoint.
operationId: queryPublicRooms
security:
- signedRequest: []
parameters:
- in: body
name: body
required: true
description: |-
Options for which rooms to return.
schema:
type: object
properties:
limit:
type: integer
description: |-
Limit the number of results returned.
since:
type: string
description: |-
A pagination token from a previous request, allowing servers
to get the next (or previous) batch of rooms. The direction
of pagination is specified solely by which token is supplied,
rather than via an explicit flag.
filter:
type: object
title: "Filter"
description: |-
Filter to apply to the results.
properties:
generic_search_term:
type: string
description: |-
A string to search for in the room metadata, e.g. name,
topic, canonical alias etc. (Optional).
include_all_networks:
type: boolean
description: |-
Whether or not to include all known networks/protocols from
application services on the homeserver. Defaults to false.
example: false
third_party_instance_id:
type: string
description: |-
The specific third party network/protocol to request from the
homeserver. Can only be used if ``include_all_networks`` is false.
example: "irc"
example: {
"limit": 10,
"filter": {
"generic_search_term": "foo"
},
"include_all_networks": false,
"third_party_instance_id": "irc"
}
responses:
200:
description: A list of the rooms on the server.
schema:
type: object
description: A list of the rooms on the server.
required: ["chunk"]
properties:
chunk:
title: "PublicRoomsChunks"
type: array
description: |-
A paginated chunk of public rooms.
items:
type: object
title: "PublicRoomsChunk"
required:
- room_id
- num_joined_members
- world_readable
- guest_can_join
properties:
aliases:
type: array
description: |-
Aliases of the room. May be empty.
items:
type: string
canonical_alias:
type: string
description: |-
The canonical alias of the room, if any.
name:
type: string
description: |-
The name of the room, if any.
num_joined_members:
type: integer
description: |-
The number of members joined to the room.
room_id:
type: string
description: |-
The ID of the room.
topic:
type: string
description: |-
The topic of the room, if any.
world_readable:
type: boolean
description: |-
Whether the room may be viewed by guest users without joining.
guest_can_join:
type: boolean
description: |-
Whether guest users may join the room and participate in it.
If they can, they will be subject to ordinary power level
rules like any other user.
avatar_url:
type: string
description: The URL for the room's avatar, if one is set.
next_batch:
type: string
description: |-
A pagination token for the response. The absence of this token
means there are no more results to fetch and the client should
stop paginating.
prev_batch:
type: string
description: |-
A pagination token that allows fetching previous results. The
absence of this token means there are no results before this
batch, i.e. this is the first batch.
total_room_count_estimate:
type: integer
description: |-
An estimate on the total number of public rooms, if the
server has an estimate.
examples:
application/json: {
"chunk": [
{
"aliases": ["#murrays:cheese.bar"],
"avatar_url": "mxc://bleeker.street/CHEDDARandBRIE",
"guest_can_join": false,
"name": "CHEESE",
"num_joined_members": 37,
"room_id": "!ol19s:bleecker.street",
"topic": "Tasty tasty cheese",
"world_readable": true
}
],
"next_batch": "p190q",
"prev_batch": "p1902",
"total_room_count_estimate": 115
}

@ -0,0 +1 @@
Fix the ``m.room_key_request`` ``action`` value, setting it from ``cancel_request`` to ``request_cancellation``.

@ -0,0 +1 @@
Add a required ``id_access_token`` to many places which require an ``id_server`` parameter.

@ -0,0 +1 @@
Remove ``bind_msisdn`` and ``bind_email`` from ``/register`` now that the identity server's bind endpoint requires authentication.

@ -0,0 +1 @@
Add ``m.identity_server`` account data for tracking the user's preferred identity server.

@ -0,0 +1 @@
Add ``POST /account/3pid/unbind`` for removing a 3PID from an identity server.

@ -0,0 +1 @@
Deprecate the v1 API in favour of an authenticated v2 API.

@ -0,0 +1 @@
Add ``/account``, ``/account/register``, and ``/account/logout`` to authenticate with the identity server.

@ -0,0 +1 @@
Add endpoints for accepting and handling terms of service.

@ -0,0 +1 @@
Add ``/hash_details`` and a new ``/lookup`` endpoint for performing hashed association lookups.

@ -0,0 +1 @@
Add new ``POST /publicRooms`` endpoint for filtering the room directory.

@ -0,0 +1,10 @@
{
"$ref": "core/event.json",
"type": "m.accepted_terms",
"content": {
"accepted": [
"https://example.org/somewhere/terms-1.2-en.html",
"https://example.org/somewhere/privacy-1.2-en.html"
]
}
}

@ -0,0 +1,7 @@
{
"$ref": "core/event.json",
"type": "m.identity_server",
"content": {
"base_url": "https://example.org"
}
}

@ -1,6 +1,6 @@
{ {
"content": { "content": {
"action": "cancel_request", "action": "request_cancellation",
"requesting_device_id": "RJYKSTBOIE", "requesting_device_id": "RJYKSTBOIE",
"request_id": "1495474790150.19" "request_id": "1495474790150.19"
}, },

@ -0,0 +1,23 @@
---
allOf:
- $ref: core-event-schema/event.yaml
description: |-
A list of terms URLs the user has previously accepted. Clients SHOULD use this
to avoid presenting the user with terms they have already agreed to.
properties:
content:
type: object
properties:
accepted:
type: array
items:
type: string
description: |-
The list of URLs the user has previously accepted. Should be appended to
when the user agrees to new terms.
type:
enum:
- m.accepted_terms
type: string
title: Accepted Terms of Service URLs
type: object

@ -0,0 +1,23 @@
---
allOf:
- $ref: core-event-schema/event.yaml
description: |-
Persists the user's preferred identity server, or preference to not use
an identity server at all, in the user's account data.
properties:
content:
type: object
properties:
base_url:
type: string
description: |-
The URL of the identity server the user prefers to use, or ``null``
if the user does not want to use an identity server. This value is
similar in structure to the ``base_url`` for identity servers in the
``.well-known/matrix/client`` schema.
type:
enum:
- m.identity_server
type: string
title: Identity Server Preference
type: object

@ -38,7 +38,7 @@ properties:
action: action:
enum: enum:
- request - request
- cancel_request - request_cancellation
type: string type: string
requesting_device_id: requesting_device_id:
description: ID of the device requesting the key. description: ID of the device requesting the key.

@ -0,0 +1,91 @@
The following labels are used to help categorize issues:
`spec-omission <https://github.com/matrix-org/matrix-doc/labels/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
<https://github.com/matrix-org/synapse>`_. Normally there will be a design
document in Google Docs or similar which describes the feature.
Examples:
* `Spec PUT /directory/list <https://github.com/matrix-org/matrix-doc/issues/417>`_
* `Unspec'd server_name request param for /join/{roomIdOrAlias}
<https://github.com/matrix-org/matrix-doc/issues/904>`_
`clarification <https://github.com/matrix-org/matrix-doc/labels/clarification>`_
--------------------------------------------------------------------------------
An area where the spec could do with being more explicit.
Examples:
* `Spec the implicit limit on /syncs
<https://github.com/matrix-org/matrix-doc/issues/708>`_
* `Clarify the meaning of the currently_active flags in presence events
<https://github.com/matrix-org/matrix-doc/issues/686>`_
`spec-bug <https://github.com/matrix-org/matrix-doc/labels/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
<https://github.com/matrix-org/matrix-doc/issues/933>`_
* `receipts section still refers to initialSync
<https://github.com/matrix-org/matrix-doc/issues/695>`_
`improvement <https://github.com/matrix-org/matrix-doc/labels/improvement>`_
----------------------------------------------------------------------------
A suggestion for a relatively simple improvement to the protocol.
Examples:
* `We need a 'remove 3PID' API so that users can remove mappings
<https://github.com/matrix-org/matrix-doc/issues/620>`_
* `We should mandate that /publicRooms requires an access_token
<https://github.com/matrix-org/matrix-doc/issues/612>`_
`feature <https://github.com/matrix-org/matrix-doc/labels/feature>`_
--------------------------------------------------------------------
A suggestion for a significant extension to the matrix protocol which
needs considerable consideration before implementation.
Examples:
* `Peer-to-peer Matrix <https://github.com/matrix-org/matrix-doc/issues/710>`_
* `Specify a means for clients to "edit" previous messages
<https://github.com/matrix-org/matrix-doc/issues/682>`_
`wart <https://github.com/matrix-org/matrix-doc/labels/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 <https://github.com/matrix-org/matrix-doc/labels/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?
<https://github.com/matrix-org/matrix-doc/issues/908>`_

@ -41,34 +41,17 @@ The template should have the following sections:
* **Introduction** - This should cover the primary problem and broad description of the solution. * **Introduction** - This should cover the primary problem and broad description of the solution.
* **Proposal** - The gory details of the proposal. * **Proposal** - The gory details of the proposal.
* **Tradeoffs** - Any items of the proposal that are less desirable should be listed here. Alternative
solutions to the same problem could also be listed here.
* **Potential issues** - This is where problems with the proposal would be listed, such as changes * **Potential issues** - This is where problems with the proposal would be listed, such as changes
that are not backwards compatible. that are not backwards compatible.
* **Alternatives** - This section lists alternative solutions to the same
problem which have been considered and dismsissed.
* **Security considerations** - Discussion of what steps were taken to avoid security issues in the * **Security considerations** - Discussion of what steps were taken to avoid security issues in the
future and any potential risks in the proposal. future and any potential risks in the proposal.
* **Conclusion** - A repeat of the problem and solution.
Furthermore, the template should not be required to be followed. However it is strongly recommended to Furthermore, the template should not be required to be followed. However it is strongly recommended to
maintain some sense of consistency between proposals. maintain some sense of consistency between proposals.
## Tradeoffs
*This is where alternative solutions could be listed. There's almost always another way to do things
and this section gives you the opportunity to highlight why those ways are not as desirable. The
argument made in this example is that all of the text provided by the template could be integrated
into the proposals introduction, although with some risk of losing clarity.*
Instead of adding a template to the repository, the assistance it provides could be integrated into
the proposal process itself. There is an argument to be had that the proposal process should be as
descriptive as possible, although having even more detail in the proposals introduction could lead to
some confusion or lack of understanding. Not to mention if the document is too large then potential
authors could be scared off as the process suddenly looks a lot more complicated than it is. For those
reasons, this proposal does not consider integrating the template in the proposals introduction a good
idea.
## Potential issues ## Potential issues
*Not all proposals are perfect. Sometimes there's a known disadvantage to implementing the proposal, *Not all proposals are perfect. Sometimes there's a known disadvantage to implementing the proposal,
@ -84,6 +67,22 @@ is beneficial and not considered a significant problem because it will lead to a
can follow. can follow.
## Alternatives
*This is where alternative solutions could be listed. There's almost always another way to do things
and this section gives you the opportunity to highlight why those ways are not as desirable. The
argument made in this example is that all of the text provided by the template could be integrated
into the proposals introduction, although with some risk of losing clarity.*
Instead of adding a template to the repository, the assistance it provides could be integrated into
the proposal process itself. There is an argument to be had that the proposal process should be as
descriptive as possible, although having even more detail in the proposals introduction could lead to
some confusion or lack of understanding. Not to mention if the document is too large then potential
authors could be scared off as the process suddenly looks a lot more complicated than it is. For those
reasons, this proposal does not consider integrating the template in the proposals introduction a good
idea.
## Security considerations ## Security considerations
*Some proposals may have some security aspect to them that was addressed in the proposed solution. This *Some proposals may have some security aspect to them that was addressed in the proposed solution. This
@ -94,20 +93,3 @@ of concerns where possible.*
By having a template available, people would know what the desired detail for a proposal is. This is not By having a template available, people would know what the desired detail for a proposal is. This is not
considered a risk because it is important that people understand the proposal process from start to end. considered a risk because it is important that people understand the proposal process from start to end.
## Conclusion
*Repeating the problem and solution in different words helps reviewers understand the problem a bit more.
This section should wrap up any loose ends left in the document, as well as cover a brief overview of the
content in each section. Note that the example here doesn't touch on the specific implementation details
described in the "Proposal" section - just the high-level points made there.*
Not having a template for people to follow when making their proposals could lead to large differences
between each MSC. This would make it difficult for reviewers, and there's a potential that some information
could be left out by accident. A template written in the same format the proposal process requires would
give authors the ability to understand how to better explain their own proposal.
A descriptive template would help potential authors comprehend what the proposal process requires by
demonstrating what is expected of a proposal. Although this is more effort up front, it would lead to more
time saved in the future due to questions about the process.

@ -0,0 +1,50 @@
# Remove the '200' value from some federation responses
Some responses formats in the federation API specifications use the form `[200,
res]` in which `res` is the JSON object containing the actual response for the
affected endpoints. This was due to a mishap while building synapse's federation
features, and has been left as is because fixing it would induce backward
incompatibility.
This proposal proposes a backward compatible alternative
## Proposal
Add a new version of the following endpoints under the prefix
`/_matrix/federation/v2`:
* `PUT /_matrix/federation/v2/send_join/{roomId}/{eventId}`
* `PUT /_matrix/federation/v2/send_leave/{roomId}/{eventId}`
Which are the exact same endpoints as their equivalents under the `v1` prefix,
except for the response format, which changes from:
```
[
200,
res
]
```
To:
```
res
```
Where `res` is the JSON object containing the response to a request directed at
one of the affected endpoints.
This proposal doesn't address the `PUT
/_matrix/federation/v1/invite/{roomId}/{eventId}` endpoint since
[MSC1794](https://github.com/matrix-org/matrix-doc/pull/1794) already takes care
of it.
If a call to any of the `v2` endpoints described in this proposal results in an
unrecognised request exception (i.e. in a response with a 400 or a 404 status
code), then the sending server should retry the request with the `v1` API.
## Alternative solutions
An alternative solution would be to make the change in the `v1` federation API,
but would break backward compatibility, thus would be harder to manage.

@ -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.

@ -0,0 +1,348 @@
# MSC2140: Terms of Service API for Identity Servers and Integration Managers
*Note*: This MSC was added to in [MSC2264](https://github.com/matrix-org/matrix-doc/pull/2264)
[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`. Similar to the other unbind endpoints, this endpoint does not
require an `id_access_token` because the homeserver can only unbind.
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.
### Unstable feature flag for transition
In order to allow client implementations to determine if the homeserver they are developed
against supports `id_access_token`, an unstable feature flag of `m.id_access_token`
is to be added to `/versions`. When the flag is `false` or not present, clients must assume
that the homeserver does not support being given `id_access_token` and may receive an error
for doing so. Clients are expected to use the supported specification versions the homeserver
advertises instead of the feature flag's presence once this proposal is included in a release
of the specification.
## 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.

@ -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.

@ -0,0 +1,56 @@
# MSC2263: Give homeservers the ability to handle their own 3PID registrations/password resets
In order to better protect the privacy of a user, Matrix is wanting to shift to
a model where identity servers have less control over the affairs of the homeserver.
Identity servers are currently used to reset the passwords of users on a given homeserver
as an identity verification technique, however there is no reason why the homeserver
itself can't handle the verification. This proposal allows for a homeserver to verify
the identity of users itself, without the use of an identity server.
## Proposal
The `id_server` parameter is to become optional on the following endpoints:
* `/_matrix/client/:version/account/3pid/:medium/requestToken`
* `/_matrix/client/:version/register/:medium/requestToken`
* `/_matrix/client/:version/account/password/:medium/requestToken`
The `id_server` parameter is additionally deprecated with intention of being removed
in a future specification release on the `/register/:medium` and `/account/password/:medium`
endpoints. Once appropriate adoption has been achieved, the specification can safely
remove the parameter as supported. The reason for this deprecation is to completely
remove the identity server's ability to be involved in password resets/registration.
Users wishing to bind their 3rd party identifiers can do so after registration, and
clients can automate this if they so desire.
Note that `bind_email` and `bind_msisdn` on `/register` have already been removed
by [MSC2140](https://github.com/matrix-org/matrix-doc/pull/2140).
As per [MSC2140](https://github.com/matrix-org/matrix-doc/pull/2140), an `id_access_token`
is required only if an `id_server` is supplied.
Although not specified as required in the specification currently, the `id_server`
as part of User-Interactive Authentication is also optional if this proposal is accepted.
When the client requests a token without an `id_server`, it should not specify an
`id_server` in UIA.
Homeservers can reuse HTTP 400 `M_SERVER_NOT_TRUSTED` as an error code on the `/requestToken`
endpoints listed above if they do not trust the identity server the user is supplying.
In order to allow client implementations to determine if the homeserver they are developed
against supports `id_server` being optional, an unstable feature flag of `m.require_identity_server`
is to be added to `/versions`. When the flag is `true` or not present, clients must assume
that the homeserver requires an `id_server` (ie: it has not yet considered it optional).
If this proposal is accepted, clients are expected to use the supported specification versions
the homeserver advertises instead of the feature flag's presence.
## Tradeoffs
Homeservers may have to set up MSISDN/email support to their implementations. This is believed
to be of minimal risk compared to allowing the identity server to continue being involved
with password reset/registration.
## Security considerations
The identity server was previously involved with affairs only the homeserver cares about.
This is no longer the case.

@ -1,9 +1,9 @@
[ tool.giles ] [ tool.gilesbot ]
[ tool.giles.circleci_artifacts.docs ] [ tool.gilesbot.circleci_artifacts.docs ]
url = "gen/index.html" url = "gen/index.html"
message = "Click details to preview the HTML documentation." message = "Click details to preview the HTML documentation."
[ tool.giles.circleci_artifacts.swagger ] [ tool.gilesbot.circleci_artifacts.swagger ]
url = "client-server/index.html" url = "client-server/index.html"
message = "Click to preview the swagger build." message = "Click to preview the swagger build."

@ -1,11 +1,15 @@
{% import 'tables.tmpl' as tables -%} {% 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 -%} {% if "deprecated" in endpoint and endpoint.deprecated -%}
Deprecated: ``{{endpoint.method}} {{endpoint.path}}``
{{(17 + (endpoint.path | length) + (endpoint.method | length)) * title_kind}}
.. WARNING:: .. WARNING::
This API is deprecated and will be removed from a future release. 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 -%} {% endif -%}
{{endpoint.desc}} {{endpoint.desc}}

@ -594,7 +594,21 @@ class MatrixUnits(Units):
raise Exception("Error handling parameter %s" % param_name, e) raise Exception("Error handling parameter %s" % param_name, e)
# endfor[param] # endfor[param]
good_response = None good_response = None
for code in sorted(endpoint_swagger.get("responses", {}).keys()): endpoint_status_codes = endpoint_swagger.get("responses", {}).keys()
# Check to see if any of the status codes are strings ("4xx") and if
# so convert everything to a string to avoid comparing ints and strings.
has_string_status = False
for code in endpoint_status_codes:
if isinstance(code, str):
has_string_status = True
break
if has_string_status:
endpoint_status_codes = [str(i) for i in endpoint_status_codes]
for code in sorted(endpoint_status_codes):
# Convert numeric responses to ints, assuming they got converted
# above.
if isinstance(code, str) and code.isdigit():
code = int(code)
res = endpoint_swagger["responses"][code] res = endpoint_swagger["responses"][code]
if not good_response and code == 200: if not good_response and code == 200:
good_response = res good_response = res

@ -802,7 +802,8 @@ To use this authentication type, clients should submit an auth dict as follows:
{ {
"sid": "<identity server session id>", "sid": "<identity server session id>",
"client_secret": "<identity server client secret>", "client_secret": "<identity server client secret>",
"id_server": "<url of identity server authed with, e.g. 'matrix.org:8090'>" "id_server": "<url of identity server authed with, e.g. 'matrix.org:8090'>",
"id_access_token": "<access token previously registered with the identity server>"
} }
], ],
"session": "<session ID>" "session": "<session ID>"
@ -830,7 +831,8 @@ To use this authentication type, clients should submit an auth dict as follows:
{ {
"sid": "<identity server session id>", "sid": "<identity server session id>",
"client_secret": "<identity server client secret>", "client_secret": "<identity server client secret>",
"id_server": "<url of identity server authed with, e.g. 'matrix.org:8090'>" "id_server": "<url of identity server authed with, e.g. 'matrix.org:8090'>",
"id_access_token": "<access token previously registered with the identity server>"
} }
], ],
"session": "<session ID>" "session": "<session ID>"
@ -1139,6 +1141,41 @@ Current account information
{{whoami_cs_http_api}} {{whoami_cs_http_api}}
Notes on identity servers
+++++++++++++++++++++++++
Identity servers in Matrix store bindings (relationships) between a user's third
party identifier, typically email or phone number, and their user ID. Once a user
has chosen an identity server, that identity server should be used by all clients.
Clients can see which identity server the user has chosen through the ``m.identity_server``
account data event, as described below. Clients SHOULD refrain from making requests
to any identity server until the presence of ``m.identity_server`` is confirmed as
(not) present. If present, the client SHOULD check for the presence of the ``base_url``
property in the event's content. If the ``base_url`` is present, the client SHOULD
use the identity server in that property as the identity server for the user. If the
``base_url`` is missing, or the account data event is not present, the client SHOULD
use whichever default value it normally would for an identity server, if applicable.
Clients SHOULD NOT update the account data with the default identity server when the
user is missing an identity server in their account data.
Clients SHOULD listen for changes to the ``m.identity_server`` account data event
and update the identity server they are contacting as a result.
If the client offers a way to set the identity server to use, it MUST update the
value of ``m.identity_server`` accordingly. A ``base_url`` of ``null`` MUST be
treated as though the user does not want to use an identity server, disabling all
related functionality as a result.
Clients SHOULD refrain from populating the account data as a migration step for users
who are lacking the account data, unless the user sets the identity server within
the client to a value. For example, a user which has no ``m.identity_server`` account
data event should not end up with the client's default identity server in their
account data, unless the user first visits their account settings to set the identity
server.
{{m_identity_server_event}}
Capabilities negotiation Capabilities negotiation
------------------------ ------------------------

@ -155,6 +155,23 @@ should allow a 3PID to be mapped to a Matrix user identity, but not in the other
direction (i.e. one should not be able to get all 3PIDs associated with a Matrix direction (i.e. one should not be able to get all 3PIDs associated with a Matrix
user ID, or get all 3PIDs associated with a 3PID). user ID, or get all 3PIDs associated with a 3PID).
Version 1 API deprecation
-------------------------
.. TODO: Remove this section when the v1 API is removed.
As described on each of the version 1 endpoints, the v1 API is deprecated in
favour of the v2 API described here. The major difference, with the exception
of a few isolated cases, is that the v2 API requires authentication to ensure
the user has given permission for the identity server to operate on their data.
The v1 API is planned to be removed from the specification in a future version.
Clients SHOULD attempt the v2 endpoints first, and if they receive a ``404``,
``400``, or similar error they should try the v1 endpoint or fail the operation.
Clients are strongly encouraged to warn the user of the risks in using the v1 API,
if they are planning on using it.
Web browser clients Web browser clients
------------------- -------------------
@ -171,11 +188,67 @@ to be returned by servers on all requests are::
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization
Authentication
--------------
Most ``v2`` endpoints in the Identity Service API require authentication in order
to ensure that the requesting user has accepted all relevant policies and is otherwise
permitted to make the request. The ``v1`` API (currently deprecated) does not require
this authentication, however using ``v1`` is strongly discouraged as it will be removed
in a future release.
Identity Servers use a scheme similar to the Client-Server API's concept of access
tokens to authenticate users. The access tokens provided by an Identity Server cannot
be used to authenticate Client-Server API requests.
An access token is provided to an endpoint in one of two ways:
1. Via a query string parameter, ``access_token=TheTokenHere``.
2. Via a request header, ``Authorization: Bearer TheTokenHere``.
Clients are encouraged to the use the ``Authorization`` header where possible to prevent
the access token being leaked in access/HTTP logs. The query string should only be used
in cases where the ``Authorization`` header is inaccessible for the client.
When credentials are required but missing or invalid, the HTTP call will return with a
status of 401 and the error code ``M_UNAUTHORIZED``.
{{v2_auth_is_http_api}}
.. _`agree to more terms`:
Terms of service
----------------
Identity Servers are encouraged to have terms of service (or similar policies) to
ensure that users have agreed to their data being processed by the server. To facilitate
this, an identity server can respond to almost any authenticated API endpoint with a
HTTP 403 and the error code ``M_TERMS_NOT_SIGNED``. The error code is used to indicate
that the user must accept new terms of service before being able to continue.
All endpoints which support authentication can return the ``M_TERMS_NOT_SIGNED`` error.
When clients receive the error, they are expected to make a call to ``GET /terms`` to
find out what terms the server offers. The client compares this to the ``m.accepted_terms``
account data for the user (described later) and presents the user with option to accept
the still-missing terms of service. After the user has made their selection, if applicable,
the client sends a request to ``POST /terms`` to indicate the user's acceptance. The
server cannot expect that the client will send acceptance for all pending terms, and the
client should not expect that the server will not respond with another ``M_TERMS_NOT_SIGNED``
on their next request. The terms the user has just accepted are appended to ``m.accepted_terms``.
{{m_accepted_terms_event}}
{{v2_terms_is_http_api}}
Status check Status check
------------ ------------
{{ping_is_http_api}} {{ping_is_http_api}}
{{v2_ping_is_http_api}}
Key management Key management
-------------- --------------
@ -195,11 +268,142 @@ service's long-term keys.
{{pubkey_is_http_api}} {{pubkey_is_http_api}}
{{v2_pubkey_is_http_api}}
Association lookup Association lookup
------------------ ------------------
{{lookup_is_http_api}} {{lookup_is_http_api}}
{{v2_lookup_is_http_api}}
Client behaviour
~~~~~~~~~~~~~~~~
.. TODO: Remove this note when v1 is removed completely
.. Note::
This section only covers the v2 lookup endpoint. The v1 endpoint is described
in isolation above.
Prior to performing a lookup clients SHOULD make a request to the ``/hash_details``
endpoint to determine what algorithms the server supports (described in more detail
below). The client then uses this information to form a ``/lookup`` request and
receive known bindings from the server.
Clients MUST support at least the ``sha256`` algorithm.
Server behaviour
~~~~~~~~~~~~~~~~
.. TODO: Remove this note when v1 is removed completely
.. Note::
This section only covers the v2 lookup endpoint. The v1 endpoint is described
in isolation above.
Servers, upon receipt of a ``/lookup`` request, will compare the query against
known bindings it has, hashing the identifiers it knows about as needed to
verify exact matches to the request.
Servers MUST support at least the ``sha256`` algorithm.
Algorithms
~~~~~~~~~~
Some algorithms are defined as part of the specification, however other formats
can be negotiated between the client and server using ``/hash_details``.
``sha256``
++++++++++
This algorithm MUST be supported by clients and servers at a minimum. It is
additionally the preferred algorithm for lookups.
When using this algorithm, the client converts the query first into strings
separated by spaces in the format ``<address> <medium> <pepper>``. The ``<pepper>``
is retrieved from ``/hash_details``, the ``<medium>`` is typically ``email`` or
``msisdn`` (both lowercase), and the ``<address>`` is the 3PID to search for.
For example, if the client wanted to know about ``alice@example.org``'s bindings,
it would first format the query as ``alice@example.org email ThePepperGoesHere``.
.. admonition:: Rationale
Mediums and peppers are appended to the address to prevent a common prefix
for each 3PID, helping prevent attackers from pre-computing the internal state
of the hash function.
After formatting each query, the string is run through SHA-256 as defined by
`RFC 4634 <https://tools.ietf.org/html/rfc4634>`_. The resulting bytes are then
encoded using URL-Safe `Unpadded Base64`_ (similar to `room version 4's
event ID format <../../rooms/v4.html#event-ids>`_).
An example set of queries when using the pepper ``matrixrocks`` would be::
"alice@example.com email matrixrocks" -> "4kenr7N9drpCJ4AfalmlGQVsOn3o2RHjkADUpXJWZUc"
"bob@example.com email matrixrocks" -> "LJwSazmv46n0hlMlsb_iYxI0_HXEqy_yj6Jm636cdT8"
"18005552067 msisdn matrixrocks" -> "nlo35_T5fzSGZzJApqu8lgIudJvmOQtDaHtr-I4rU7I"
The set of hashes is then given as the ``addresses`` array in ``/lookup``. Note
that the pepper used MUST be supplied as ``pepper`` in the ``/lookup`` request.
``none``
++++++++
This algorithm performs plaintext lookups on the identity server. Typically this
algorithm should not be used due to the security concerns of unhashed identifiers,
however some scenarios (such as LDAP-backed identity servers) prevent the use of
hashed identifiers. Identity servers (and optionally clients) can use this algorithm
to perform those kinds of lookups.
Similar to the ``sha256`` algorithm, the client converts the queries into strings
separated by spaces in the format ``<address> <medium>`` - note the lack of ``<pepper>``.
For example, if the client wanted to know about ``alice@example.org``'s bindings,
it would format the query as ``alice@example.org email``.
The formatted strings are then given as the ``addresses`` in ``/lookup``. Note that
the ``pepper`` is still required, and must be provided to ensure the client has made
an appropriate request to ``/hash_details`` first.
Security considerations
~~~~~~~~~~~~~~~~~~~~~~~
.. Note::
`MSC2134 <https://github.com/matrix-org/matrix-doc/pull/2134>`_ has much more
information about the security considerations made for this section of the
specification. This section covers the high-level details for why the specification
is the way it is.
Typically the lookup endpoint is used when a client has an unknown 3PID it wants to
find a Matrix User ID for. Clients normally do this kind of lookup when inviting new
users to a room or searching a user's address book to find any Matrix users they may
not have discovered yet. Rogue or malicious identity servers could harvest this
unknown information and do nefarious things with it if it were sent in plain text.
In order to protect the privacy of users who might not have a Matrix identifier bound
to their 3PID addresses, the specification attempts to make it difficult to harvest
3PIDs.
.. admonition:: Rationale
Hashing identifiers, while not perfect, helps make the effort required to harvest
identifiers significantly higher. Phone numbers in particular are still difficult
to protect with hashing, however hashing is objectively better than not.
An alternative to hashing would be using bcrypt or similar with many rounds, however
by nature of needing to serve mobile clients and clients on limited hardware the
solution needs be kept relatively lightweight.
Clients should be cautious of servers not rotating their pepper very often, and
potentially of servers which use a weak pepper - these servers may be attempting to
brute force the identifiers or use rainbow tables to mine the addresses. Similarly,
clients which support the ``none`` algorithm should consider at least warning the user
of the risks in sending identifiers in plain text to the identity server.
Addresses are still potentially reversable using a calculated rainbow table given
some identifiers, such as phone numbers, common email address domains, and leaked
addresses are easily calculated. For example, phone numbers can have roughly 12
digits to them, making them an easier target for attack than email addresses.
Establishing associations Establishing associations
------------------------- -------------------------
@ -243,16 +447,22 @@ Email associations
{{email_associations_is_http_api}} {{email_associations_is_http_api}}
{{v2_email_associations_is_http_api}}
Phone number associations Phone number associations
~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~
{{phone_associations_is_http_api}} {{phone_associations_is_http_api}}
{{v2_phone_associations_is_http_api}}
General General
~~~~~~~ ~~~~~~~
{{associations_is_http_api}} {{associations_is_http_api}}
{{v2_associations_is_http_api}}
Invitation storage Invitation storage
------------------ ------------------
@ -267,6 +477,8 @@ long-term private key for the identity server.
{{store_invite_is_http_api}} {{store_invite_is_http_api}}
{{v2_store_invite_is_http_api}}
Ephemeral invitation signing Ephemeral invitation signing
---------------------------- ----------------------------
@ -277,6 +489,8 @@ this isn't possible.
{{invitation_signing_is_http_api}} {{invitation_signing_is_http_api}}
{{v2_invitation_signing_is_http_api}}
.. _`Unpadded Base64`: ../appendices.html#unpadded-base64 .. _`Unpadded Base64`: ../appendices.html#unpadded-base64
.. _`3PID Types`: ../appendices.html#pid-types .. _`3PID Types`: ../appendices.html#pid-types
.. _`Signing JSON`: ../appendices.html#signing-json .. _`Signing JSON`: ../appendices.html#signing-json

@ -106,7 +106,7 @@ The principles that Matrix attempts to follow are:
- Empowering the end-user - Empowering the end-user
+ The user should be able to choose the server and clients they use + The user should be able to choose the server and clients they use
+ The user should be control how private their communication is + The user should be able to control how private their communication is
+ The user should know precisely where their data is stored + The user should know precisely where their data is stored
- Fully decentralised - no single points of control over conversations or the - Fully decentralised - no single points of control over conversations or the

@ -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 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.forwarded_room_key`_ to-device message. The first device should then send an
`m.room_key_request`_ to-device message with ``action`` set to `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_cancellation`` to the other devices that it had originally sent the key
request to; a device that receives a ``cancel_request`` should disregard any request to; a device that receives a ``request_cancellation`` should disregard any
previously-received ``request`` message with the same ``request_id`` and previously-received ``request`` message with the same ``request_id`` and
``requesting_device_id``. ``requesting_device_id``.

@ -255,4 +255,4 @@ these is left to the implementer's discretion.
.. _`identity server /isvalid`: ../identity_service/%IDENTITY_RELEASE_LABEL%.html#get-matrix-identity-api-v1-pubkey-isvalid .. _`identity server /isvalid`: ../identity_service/%IDENTITY_RELEASE_LABEL%.html#get-matrix-identity-v2-pubkey-isvalid

@ -79,7 +79,7 @@ their proposed changes to the Matrix protocol:
* Pragmatism rather than perfection * Pragmatism rather than perfection
* Proof rather than conjecture * 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 <https://github.com/matrix-org/matrix-doc/blob/master/proposals/1779-open-governance.md>`_
for full details of the project's Guiding Principles. for full details of the project's Guiding Principles.
Technical notes Technical notes

Loading…
Cancel
Save