Merge remote-tracking branch 'matrix-org/master' into travis/s2s/presence

pull/977/head
Travis Ralston 6 years ago
commit a53fa9300d

@ -0,0 +1,24 @@
# Copyright 2018 New Vector Ltd
#
# 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.
title: User identifier
description: |-
Identification information for a user
type: object
properties:
type:
type: string
description: The type of identification. See `Identifier types`_ for supported values and additional property descriptions.
required:
- type
additionalProperties: true

@ -1,4 +1,5 @@
# Copyright 2016 OpenMarket Ltd
# Copyright 2018 New Vector Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -85,7 +86,10 @@ paths:
type: object
example: {
"type": "m.login.password",
"user": "cheeky_monkey",
"identifier": {
"type": "m.id.user",
"user": "cheeky_monkey"
},
"password": "ilovebananas",
"initial_device_display_name": "Jungle Phone"
}
@ -94,15 +98,18 @@ paths:
type: string
enum: ["m.login.password", "m.login.token"]
description: The login type being used.
identifier:
description: Identification information for the user.
"$ref": "definitions/user_identifier.yaml"
user:
type: string
description: The fully qualified user ID or just local part of the user ID, to log in.
description: The fully qualified user ID or just local part of the user ID, to log in. Deprecated in favour of ``identifier``.
medium:
type: string
description: When logging in using a third party identifier, the medium of the identifier. Must be 'email'.
description: When logging in using a third party identifier, the medium of the identifier. Must be 'email'. Deprecated in favour of ``identifier``.
address:
type: string
description: Third party identifier for the user.
description: Third party identifier for the user. Deprecated in favour of ``identifier``.
password:
type: string
description: |-

@ -0,0 +1,103 @@
# Copyright 2018 New Vector Ltd
#
# 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 Client-Server OpenID API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
- application/json
securityDefinitions:
$ref: definitions/security.yaml
paths:
"/user/{userId}/openid/request_token":
post:
summary: Get an OpenID token object to verify the requester's identity.
description: |-
Gets an OpenID token object that the requester may supply to another
service to verify their identity in Matrix. The generated token is only
valid for exchanging for user information from the federation API for
OpenID.
The access token generated is only valid for the OpenID API. It cannot
be used to request another OpenID access token or call ``/sync``, for
example.
operationId: requestOpenIdToken
security:
- accessToken: []
parameters:
- in: path
type: string
name: userId
description: |-
The user to request and OpenID token for. Should be the user who
is authenticated for the request.
required: true
x-example: "@alice:example.com"
- in: body
name: body
description: An empty object. Reserved for future expansion.
required: true
schema:
type: object
example: {}
responses:
200:
description: |-
OpenID token information. This response is nearly compatible with the
response documented in the `OpenID 1.0 Specification <http://openid.net/specs/openid-connect-core-1_0.html#TokenResponse>`_
with the only difference being the lack of an ``id_token``. Instead,
the Matrix homeserver's name is provided.
examples:
application/json: {
"access_token": "SomeT0kenHere",
"token_type": "Bearer",
"matrix_server_name": "example.com",
"expires_in": 3600,
}
schema:
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``.
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: int
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:
description: This request was rate-limited.
schema:
"$ref": "definitions/errors/rate_limited.yaml"
tags:
- OpenID

@ -1,4 +1,5 @@
# Copyright 2016 OpenMarket Ltd
# Copyright 2018 New Vector Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -31,30 +32,30 @@ paths:
get:
summary: Gets the current pushers for the authenticated user
description: |-
Gets all currently active pushers for the authenticated user
Gets all currently active pushers for the authenticated user.
operationId: getPushers
security:
- accessToken: []
responses:
200:
description: The pushers for this user
description: The pushers for this user.
examples:
application/json: {
"pushers": [
{
"pushkey": "Xp/MzCt8/9DcSNE9cuiaoT5Ac55job3TdLSSmtmYl4A=",
"kind": "http",
"app_id": "face.mcapp.appy.prod",
"app_display_name": "Appy McAppface",
"device_display_name": "Alice's Phone",
"profile_tag": "xyz",
"lang": "en-US",
"data": {
"url": "https://example.com/_matrix/push/v1/notify"
}
"pushers": [
{
"pushkey": "Xp/MzCt8/9DcSNE9cuiaoT5Ac55job3TdLSSmtmYl4A=",
"kind": "http",
"app_id": "face.mcapp.appy.prod",
"app_display_name": "Appy McAppface",
"device_display_name": "Alice's Phone",
"profile_tag": "xyz",
"lang": "en-US",
"data": {
"url": "https://example.com/_matrix/push/v1/notify"
}
]
}
}
]
}
schema:
type: object
properties:
@ -70,7 +71,7 @@ paths:
pushkey:
type: string
description: |-
This is a unique identifier for this pusher. See `/set` for
This is a unique identifier for this pusher. See ``/set`` for
more detail.
Max length, 512 bytes.
kind:
@ -115,6 +116,19 @@ paths:
description: |-
Required if ``kind`` is ``http``. The URL to use to send
notifications to.
format:
type: string
description: |-
The format to use when sending notifications to the Push
Gateway.
required:
- pushkey
- app_id
- kind
- app_display_name
- device_display_name
- lang
- data
tags:
- Push notifications
"/pushers/set":
@ -130,23 +144,24 @@ paths:
parameters:
- in: body
name: pusher
description: The pusher information
description: The pusher information.
required: true
schema:
type: object
example: {
"lang": "en",
"kind": "http",
"app_display_name": "Mat Rix",
"device_display_name": "iPhone 9",
"profile_tag": "xxyyzz",
"app_id": "com.example.app.ios",
"pushkey": "APA91bHPRgkF3JUikC4ENAHEeMrd41Zxv3hVZjC9KtT8OvPVGJ-hQMRKRrZuJAEcl7B338qju59zJMjw2DELjzEvxwYv7hH5Ynpc1ODQ0aT4U4OFEeco8ohsN5PjL1iC2dNtk2BAokeMCg2ZXKqpc8FXKmhX94kIxQ",
"data": {
"url": "https://push-gateway.location.here"
},
"append": false
}
"lang": "en",
"kind": "http",
"app_display_name": "Mat Rix",
"device_display_name": "iPhone 9",
"profile_tag": "xxyyzz",
"app_id": "com.example.app.ios",
"pushkey": "APA91bHPRgkF3JUikC4ENAHEeMrd41Zxv3hVZjC9KtT8OvPVGJ-hQMRKRrZuJAEcl7B338qju59zJMjw2DELjzEvxwYv7hH5Ynpc1ODQ0aT4U4OFEeco8ohsN5PjL1iC2dNtk2BAokeMCg2ZXKqpc8FXKmhX94kIxQ",
"data": {
"url": "https://push-gateway.location.here/_matrix/push/v1/notify",
"format": "event_id_only"
},
"append": false
}
properties:
pushkey:
type: string
@ -157,11 +172,15 @@ paths:
for APNS or the Registration ID for GCM. If your notification
client has no such concept, use any unique identifier.
Max length, 512 bytes.
If the ``kind`` is ``"email"``, this is the email address to
send notifications to.
kind:
type: string
description: |-
The kind of pusher to configure. ``"http"`` makes a pusher that
sends HTTP pokes. ``null`` deletes the pusher.
sends HTTP pokes. ``"email"`` makes a pusher that emails the
user with unread notifications. ``null`` deletes the pusher.
app_id:
type: string
description: |-
@ -169,6 +188,8 @@ paths:
It is recommended that this end with the platform, such that
different platform versions get different app identifiers.
Max length, 64 chars.
If the ``kind`` is ``"email"``, this is ``"m.email"``.
app_display_name:
type: string
description: |-
@ -188,7 +209,7 @@ paths:
type: string
description: |-
The preferred language for receiving notifications (e.g. 'en'
or 'en-US')
or 'en-US').
data:
type: object
description: |-
@ -202,6 +223,14 @@ paths:
description: |-
Required if ``kind`` is ``http``. The URL to use to send
notifications to.
format:
type: string
description: |-
The format to send notifications in to Push Gateways if the
``kind`` is ``http``. The details about what fields the
homeserver should send to the push gateway are defined in the
`Push Gateway Specification`_. Currently the only format
available is 'event_id_only'.
append:
type: boolean
description: |-
@ -216,17 +245,17 @@ paths:
200:
description: The pusher was set.
examples:
application/json: {
}
application/json: {}
schema:
type: object # empty json object
type: object
description: An empty object.
400:
description: One or more of the pusher values were invalid.
examples:
application/json: {
"error": "Missing parameters: lang, data",
"errcode": "M_MISSING_PARAM"
}
"error": "Missing parameters: lang, data",
"errcode": "M_MISSING_PARAM"
}
schema:
"$ref": "definitions/errors/error.yaml"
429:

@ -0,0 +1,179 @@
# Copyright 2018 New Vector Ltd
#
# 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: "1.0.0"
host: localhost:8090
schemes:
- https
- http
basePath: /_matrix/identity/api/v1
produces:
- application/json
paths:
"/3pid/getValidated3pid":
get:
summary: Check whether ownership of a 3pid was validated.
description: A client can check whether ownership of a 3pid was validated
operationId: getValidated3pid
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 indicating the time that the 3pid was validated.
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"
}
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"
}
"/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 older versions of this
specification, the parameters may also be specified as
``application/x-form-www-urlencoded`` data. However, this usage is
deprecated.
operationId: bind
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 services which show that the association should be trusted, if you trust the verifying identity services.
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"
}
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"
}

@ -0,0 +1,197 @@
# Copyright 2018 New Vector Ltd
#
# 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: "1.0.0"
host: localhost:8090
schemes:
- https
- http
basePath: /_matrix/identity/api/v1
produces:
- application/json
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 service will send an email containing a token. If that
token is presented to the identity service 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 Home Servers 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 older versions of this
specification, the parameters may also be specified as
``application/x-form-www-urlencoded`` data. However, this usage is
deprecated.
operationId: emailRequestToken
parameters:
- in: body
name: body
schema:
type: object
example: {
"client_secret": "monkeys_are_GREAT",
"email": "foo@example.com",
"send_attempt": 1
}
properties:
client_secret:
type: string
description: A unique string used to identify the validation attempt
email:
type: string
description: The email address to validate.
send_attempt:
type: integer
description: |-
Optional. If specified, the server will only send an email if
the ``send_attempt`` is a number greater than the most recent
one which it has seen (or if it has never seen one), scoped
to that ``email`` + ``client_secret`` pair. This is to avoid
repeatedly sending the same email in the case of request
retries between the POSTing user and the identity
service. The client should increment this value if they
desire a new email (e.g. a reminder) to be sent.
next_link:
type: string
description: |-
Optional. When the validation is completed, the identity
service will redirect the user to this URL.
required: ["client_secret", "email"]
responses:
200:
description:
Session created.
examples:
application/json: {
"sid": "1234"
}
schema:
type: object
properties:
sid:
type: string
description: The session ID.
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.
"/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.
Note: for backwards compatibility with older versions of this
specification, the parameters may also be specified as
``application/x-form-www-urlencoded`` data. However, this usage is
deprecated.
operationId: emailSubmitTokenPost
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.
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: emailSubmitTokenGet
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.

@ -0,0 +1,90 @@
# Copyright 2018 New Vector Ltd
#
# 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: "1.0.0"
host: localhost:8090
schemes:
- https
- http
basePath: /_matrix/identity/api/v1
produces:
- application/json
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: blindlySignStuff
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: 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 signedjson 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.
token:
type: string
description: The token for the invitation.
examples:
application/json: {
"mxid": "@foo:bar.com",
"sender": "@baz:bar.com",
"signatures": {
"my.id.server": {
"ed25519:0": "def987"
}
},
"token": "abc123"
}
404:
description: Token was not found.
example: {
"errcode": "M_UNRECOGNIZED",
"error": "Didn't recognize token"
}

@ -0,0 +1,114 @@
# Copyright 2018 New Vector Ltd
#
# 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: "1.0.0"
host: localhost:8090
schemes:
- https
- http
basePath: /_matrix/identity/api/v1
produces:
- application/json
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/api/v1/pubkey/ephemeral/isvalid``.
operationId: storeInvite
parameters:
- in: body
name: body
schema:
type: object
example: {
"medium": "email",
"address": "foo@bar.baz",
"room_id": "!something:example.tld",
"sender": "@bob:example.com"
}
properties:
medium:
type: string
description: The literal string ``email``.
address:
type: string
description: The email address of the invited user.
room_id:
type: string
description: The Matrix room ID to which the user is invited
sender:
type: string
description: The Matrix user ID of the inviting user
required: ["medium", "address", "room_id", "sender"]
responses:
200:
description: The invitation was stored.
schema:
type: object
properties:
token:
type: string
description: The generated token.
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.
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": mxid
}

@ -21,3 +21,25 @@ Example:
name: fields...
type: string
```
## Using oneOf to provide type alternatives
<!-- TODO: Remove this section after upgrading to OpenAPI v3 -->
`oneOf` (available in JSON Schema and Swagger/OpenAPI v3 but not in v2)
is used in cases when a simpler type specification as a list of types
doesn't work, as in the following example:
```
properties:
old: # compliant with old Swagger
type:
- string
- object # Cannot specify a schema here
new: # uses oneOf extension
oneOf:
- type: string
- type: object
title: CustomSchemaForTheWin
properties:
...
```

@ -1,4 +1,5 @@
# Copyright 2016 OpenMarket Ltd
# Copyright 2018 New Vector Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -19,7 +20,7 @@ host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/push/%CLIENT_MAJOR_VERSION%
basePath: /_matrix/push/v1
consumes:
- application/json
produces:
@ -38,14 +39,14 @@ paths:
Notifications about a particular event will normally cause the user to be
alerted in some way. It is therefore necessary to perform duplicate
suppression for such notifications using the `event_id` field to avoid
suppression for such notifications using the ``event_id`` field to avoid
retries of this HTTP API causing duplicate alerts. The operation of
updating counts of unread notifications should be idempotent and
therefore do not require duplicate suppression.
Notifications are sent to the URL configured when the pusher is
created. This means that the HTTP path may be different depending on the
push gateway.
Notifications are sent to the URL configured when the pusher is created.
This means that the HTTP path may be different depending on the push
gateway.
operationId: notify
parameters:
- in: body
@ -55,36 +56,36 @@ paths:
schema:
type: object
example: {
"notification": {
"id": "$3957tyerfgewrf384",
"room_id": "!slw48wfj34rtnrf:example.com",
"type": "m.room.message",
"sender": "@exampleuser:matrix.org",
"sender_display_name": "Major Tom",
"room_name": "Mission Control",
"room_alias": "#exampleroom:matrix.org",
"prio": "high",
"content": {
"msgtype": "m.text",
"body": "I'm floating in a most peculiar way."
},
"counts": {
"unread" : 2,
"missed_calls": 1
},
"devices": [
{
"app_id": "org.matrix.matrixConsole.ios",
"pushkey": "V2h5IG9uIGVhcnRoIGRpZCB5b3UgZGVjb2RlIHRoaXM/",
"pushkey_ts": 12345678,
"data" : {},
"tweaks": {
"sound": "bing"
}
"notification": {
"id": "$3957tyerfgewrf384",
"room_id": "!slw48wfj34rtnrf:example.com",
"type": "m.room.message",
"sender": "@exampleuser:matrix.org",
"sender_display_name": "Major Tom",
"room_name": "Mission Control",
"room_alias": "#exampleroom:matrix.org",
"prio": "high",
"content": {
"msgtype": "m.text",
"body": "I'm floating in a most peculiar way."
},
"counts": {
"unread" : 2,
"missed_calls": 1
},
"devices": [
{
"app_id": "org.matrix.matrixConsole.ios",
"pushkey": "V2h5IG9uIGVhcnRoIGRpZCB5b3UgZGVjb2RlIHRoaXM/",
"pushkey_ts": 12345678,
"data" : {},
"tweaks": {
"sound": "bing"
}
]
}
}
]
}
}
required: ["notification"]
properties:
notification:
@ -111,14 +112,10 @@ paths:
type: string
description: |-
The type of the event as in the event's ``type`` field.
Required if the notification relates to a specific
Matrix event.
sender:
type: string
description: |-
The sender of the event as in the corresponding event field.
Required if the notification relates to a specific
Matrix event.
sender_display_name:
type: string
description: |-
@ -148,15 +145,16 @@ paths:
type: object
title: EventContent
description: |-
The ``content`` field from the event, if present. If the
event had no content field, this field is omitted.
The ``content`` field from the event, if present. The pusher
may omit this if the event had no content or for any other
reason.
counts:
type: object
title: Counts
description: |-
This is a dictionary of the current number of unacknowledged
communications for the recipient user. Counts whose value is
zero are omitted.
zero should be omitted.
properties:
unread:
type: integer
@ -180,10 +178,10 @@ paths:
app_id:
type: string
description: |-
The app_id given when the pusher was created.
The ``app_id`` given when the pusher was created.
pushkey:
type: string
description: The pushkey given when the pusher was created.
description: The ``pushkey`` given when the pusher was created.
pushkey_ts:
type: integer
description: |-
@ -202,13 +200,14 @@ paths:
description: |-
A dictionary of customisations made to the way this
notification is to be presented. These are added by push rules.
required: ['app_id', 'pushkey']
responses:
200:
description: A list of rejected push keys.
examples:
application/json: {
"rejected": [ "V2h5IG9uIGVhcnRoIGRpZCB5b3UgZGVjb2RlIHRoaXM/" ]
}
"rejected": [ "V2h5IG9uIGVhcnRoIGRpZCB5b3UgZGVjb2RlIHRoaXM/" ]
}
schema:
type: object # empty json object
properties:
@ -222,7 +221,8 @@ paths:
pushkeys and remove the associated pushers. It may not
necessarily be the notification in the request that failed:
it could be that a previous notification to the same pushkey
failed.
failed. May be empty.
items:
type: string
description: A pushkey
description: A pushkey that has been rejected.
required: ['rejected']

@ -0,0 +1,148 @@
# Copyright 2018 New Vector Ltd
#
# 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 Federation Events API"
version: "1.0.0"
host: localhost:8448
schemes:
- https
basePath: /_matrix/federation/v1
consumes:
- application/json
produces:
- application/json
securityDefinitions:
$ref: definitions/security.yaml
paths:
"/backfill/{roomId}":
get:
summary: Retrieves the events which precede the given event
description: |-
Retrieves a sliding-window history of previous PDUs that occurred in the given room.
Starting from the PDU ID(s) given in the ``v`` argument, the PDUs that preceded it
are retrieved, up to the total number given by the ``limit``.
operationId: backfillRoom
security:
- signedRequest: []
parameters:
- in: path
name: roomId
type: string
description: The room ID to backfill.
required: true
x-example: "!SomeRoom:matrix.org"
- in: query
name: v
type: array
items:
type: string
description: The event IDs to backfill from.
required: true
x-example: ["$abc123:matrix.org"]
- in: query
name: limit
type: integer
description: The maximum number of PDUs to retrieve, including the given events.
required: true
x-example: 2
responses:
200:
description: |-
A transaction containing the PDUs that preceded the given event(s), including the given
event(s), up to the given limit.
schema:
$ref: "definitions/transaction.yaml"
# Override the example to show the response of the request a bit better
examples:
application/json: {
"$ref": "examples/transaction.json",
"pdus": [
{
"$ref": "pdu.json",
"room_id": "!SomeRoom:matrix.org",
"event_id": "$abc123:matrix.org"
},
{
"$ref": "pdu.json",
"room_id": "!SomeRoom:matrix.org"
},
]
}
"/get_missing_events/{roomId}":
post:
summary: Retrieves events that the sender is missing
description: |-
Retrieves previous events that the sender is missing. This is done by doing a breadth-first
walk of the ``prev_events`` for the ``latest_events``, ignoring any events in ``earliest_events``
and stopping at the ``limit``.
operationId: getMissingPreviousEvents
security:
- signedRequest: []
parameters:
- in: path
name: roomId
type: string
description: The room ID to search in.
required: true
x-example: "!SomeRoom:matrix.org"
- in: body
name: body
schema:
type: object
properties:
limit:
type: integer
description: The maximum number of events to retrieve. Defaults to 10.
example: 10
min_depth:
type: integer
description: The minimum depth of events to retrieve. Defaults to 0.
example: 0
earliest_events:
type: array
description: |-
The latest events that the sender already has. These are skipped when retrieving
the previous events of ``latest_events``.
items:
type: string
example: ["$missing_event:domain.com"]
latest_events:
type: array
description: The events to retrieve the previous events for.
items:
type: string
example: ["$event_that_has_the_missing_event_as_a_previous_event:domain.com"]
required: ['earliest_events', 'latest_events']
responses:
200:
description: |-
The previous events for ``latest_events``, excluding any ``earliest_events``, up to the
provided ``limit``.
schema:
type: object
properties:
events:
type: array
description: The missing events.
items:
$ref: definitions/pdu.yaml
required: ['events']
examples:
application/json: {
"events": [
{"$ref": "examples/pdu.json"}
]
}

@ -0,0 +1,45 @@
# Copyright 2018 New Vector Ltd
#
# 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
title: Typing Notification EDU
description: A typing notification EDU for a user in a room.
allOf:
- $ref: ../edu.yaml
- type: object
properties:
edu_type:
type: string
description: The string ``m.typing``
example: "m.typing"
content:
type: object
description: The typing notification.
title: Typing Notification
properties:
room_id:
type: string
description: |-
The room where the user's typing status has been updated.
example: "!somewhere:matrix.org"
user_id:
type: string
description: |-
The user ID that has had their typing status changed.
example: "@john:matrix.org"
typing:
type: boolean
description: Whether the user is typing in the room or not.
example: true
required: ['room_id', 'user_id', 'typing']

@ -0,0 +1,19 @@
# Copyright 2018 New Vector Ltd
#
# 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.
signedRequest:
type: apiKey
description: |-
The ``Authorization`` header defined in the `Authentication`_ section.
name: Authorization
in: header

@ -24,6 +24,8 @@ consumes:
- application/json
produces:
- application/json
securityDefinitions:
$ref: definitions/security.yaml
paths:
"/event_auth/{roomId}/{eventId}":
get:
@ -31,6 +33,8 @@ paths:
description: |-
Retrieves the complete auth chain for a given event.
operationId: getEventAuth
security:
- signedRequest: []
parameters:
- in: path
name: roomId
@ -72,6 +76,8 @@ paths:
bottom-up after sorting each chain by depth then by event ID. The differences
are then discovered and returned as the response to this API call.
operationId: compareEventAuth
security:
- signedRequest: []
parameters:
- in: path
name: roomId

@ -22,6 +22,8 @@ schemes:
basePath: /_matrix/federation/v1
produces:
- application/json
securityDefinitions:
$ref: definitions/security.yaml
paths:
"/state/{roomId}":
get:
@ -29,6 +31,8 @@ paths:
description: |-
Retrieves a snapshot of a room's state at a given event.
operationId: getRoomState
security:
- signedRequest: []
parameters:
- in: path
name: roomId
@ -74,6 +78,8 @@ paths:
event IDs. This performs the same function as calling ``/state/{roomId}``,
however this returns just the event IDs rather than the full events.
operationId: getRoomStateIds
security:
- signedRequest: []
parameters:
- in: path
name: roomId
@ -117,6 +123,8 @@ paths:
description: |-
Retrieves a single event.
operationId: getEvent
security:
- signedRequest: []
parameters:
- in: path
name: eventId
@ -129,35 +137,3 @@ paths:
description: A transaction containing a single PDU which is the event requested.
schema:
$ref: "definitions/transaction.yaml"
"/backfill/{roomId}":
get:
summary: Retrieves the events which precede the given event
description: |-
Retreives a sliding-window history of previous PDUs that occurred in the given room.
Starting from the PDU ID(s) given in the ``v`` argument, the PDUs that preceded it
are retrieved, up to the total number given by the ``limit``.
operationId: backfillRoom
parameters:
- in: path
name: roomId
type: string
description: The room ID to backfill.
required: true
x-example: "!abc123:matrix.org"
- in: query
name: v
type: string # TODO: The description says this is plural - figure out how to specify multiple, and spec it
description: The event ID to backfill from.
required: true
x-example: "$abc123:matrix.org"
- in: query
name: limit
type: integer
description: The maximum number of events to retrieve.
required: true
x-example: 10
responses:
200:
description: A transaction containing the PDUs that preceded the given event(s).
schema:
$ref: "definitions/transaction.yaml"

@ -24,6 +24,8 @@ consumes:
- application/json
produces:
- application/json
securityDefinitions:
$ref: definitions/security.yaml
paths:
"/invite/{roomId}/{eventId}":
put:
@ -33,6 +35,8 @@ paths:
homeserver and the invited homeserver, it can be sent to all of the servers in the
room by the inviting homeserver.
operationId: sendInvite
security:
- signedRequest: []
parameters:
- in: path
name: roomId

@ -24,6 +24,8 @@ consumes:
- application/json
produces:
- application/json
securityDefinitions:
$ref: definitions/security.yaml
paths:
"/make_join/{roomId}/{userId}":
get:
@ -32,6 +34,8 @@ paths:
Asks the receiving server to return information that the sending
server will need to prepare a join event to get into the room.
operationId: makeJoin
security:
- signedRequest: []
parameters:
- in: path
name: roomId
@ -145,6 +149,8 @@ paths:
Submits a signed join event to the resident server for it
to accept it into the room's graph.
operationId: sendJoin
security:
- signedRequest: []
parameters:
- in: path
name: roomId

@ -24,6 +24,8 @@ consumes:
- application/json
produces:
- application/json
securityDefinitions:
$ref: definitions/security.yaml
paths:
"/make_leave/{roomId}/{userId}":
get:
@ -32,6 +34,8 @@ paths:
Asks the receiving server to return information that the sending
server will need to prepare a leave event to get out of the room.
operationId: makeLeave
security:
- signedRequest: []
parameters:
- in: path
name: roomId
@ -151,6 +155,8 @@ paths:
Submits a signed leave event to the resident server for it
to accept it into the room's graph.
operationId: sendLeave
security:
- signedRequest: []
parameters:
- in: path
name: roomId

@ -0,0 +1,63 @@
# Copyright 2017 Kamax.io
# Copyright 2018 New Vector Ltd
#
# 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 Federation OpenID API"
version: "1.0.0"
host: localhost:8448
schemes:
- https
basePath: /_matrix/federation/v1
produces:
- application/json
paths:
"/openid/userinfo":
get:
summary: Exchange an OpenID token for user information
description: |-
Exchanges an OpenID access token for information about the user
who generated the token. Currently this only exposes the Matrix
User ID of the owner.
operationId: exchangeOpenIdToken
parameters:
- in: path
name: access_token
type: string
description: |-
The OpenID access token to get information about the owner for.
required: true
x-example: SomeT0kenHere
responses:
200:
description: |-
Information about the user who generated the OpenID access token.
schema:
type: object
properties:
sub:
type: string
description: The Matrix User ID who generated the token.
example: "@alice:example.com"
required: ['sub']
401:
description: The token was not recognized or has expired.
schema:
$ref: "../client-server/definitions/errors/error.yaml"
examples:
application/json: {
"errcode": "M_UNKNOWN_TOKEN",
"error": "Access token unknown or expired"
}

@ -22,6 +22,8 @@ schemes:
basePath: /_matrix/federation/v1
produces:
- application/json
securityDefinitions:
$ref: definitions/security.yaml
paths:
"/publicRooms":
get:
@ -31,6 +33,8 @@ paths:
rooms that are listed on another homeserver's directory, just those
listed on the receiving homeserver's directory.
operationId: getPublicRooms
security:
- signedRequest: []
parameters:
- in: query
name: limit

@ -23,6 +23,8 @@ schemes:
basePath: /_matrix/federation/v1
produces:
- application/json
securityDefinitions:
$ref: definitions/security.yaml
paths:
"/query/{queryType}":
get:
@ -32,6 +34,8 @@ paths:
arguments are dependent on which type of query is being made. Known query types
are specified as their own endpoints as an extension to this definition.
operationId: queryInfo
security:
- signedRequest: []
parameters:
- in: path
name: queryType
@ -54,6 +58,8 @@ paths:
Servers may wish to cache the response to this query to avoid requesting the
information too often.
operationId: queryRoomDirectory
security:
- signedRequest: []
parameters:
- in: query
name: room_alias
@ -110,6 +116,9 @@ paths:
Servers may wish to cache the response to this query to avoid requesting the
information too often.
operationId: queryProfile
security:
- signedRequest: []
parameters:
- in: query
name: user_id

@ -24,6 +24,8 @@ consumes:
- application/json
produces:
- application/json
securityDefinitions:
$ref: definitions/security.yaml
paths:
"/exchange_third_party_invite/{roomId}":
put:
@ -34,6 +36,8 @@ paths:
an invite as per the `Inviting to a room`_ section before returning a
response to this request.
operationId: exchangeThirdPartyInvite
security:
- signedRequest: []
parameters:
- in: path
name: roomId

@ -24,6 +24,8 @@ consumes:
- application/json
produces:
- application/json
securityDefinitions:
$ref: definitions/security.yaml
paths:
"/send/{txnId}":
put:
@ -36,6 +38,8 @@ paths:
The sending server must wait and retry for a 200 OK response before sending a
transaction with a different ``txnId`` to the receiving server.
operationId: sendTransaction
security:
- signedRequest: []
parameters:
- in: path
name: txnId

@ -0,0 +1 @@
Add new user identifier object for logging in

@ -0,0 +1 @@
Document and improve client interaction with pushers.

@ -287,7 +287,9 @@ def get_json_schema_object_fields(obj, enforce_title=False):
def process_data_type(prop, required=False, enforce_title=True):
prop = inherit_parents(prop)
prop_type = prop['type']
prop_type = prop.get('oneOf', prop.get('type', []))
assert prop_type
tables = []
enum_desc = None
is_object = False
@ -318,6 +320,19 @@ def process_data_type(prop, required=False, enforce_title=True):
tables = nested["tables"]
enum_desc = nested["enum_desc"]
elif isinstance(prop_type, list):
prop_title = []
for t in prop_type:
if isinstance(t, dict):
nested = process_data_type(t)
tables.extend(nested['tables'])
prop_title.append(nested['title'])
# Assuming there's at most one enum among type options
enum_desc = nested['enum_desc']
if enum_desc:
enum_desc = "%s if the type is enum" % enum_desc
else:
prop_title.append(t)
else:
prop_title = prop_type

@ -461,7 +461,7 @@ Password-based
:Type:
``m.login.password``
:Description:
The client submits a username and secret password, both sent in plain-text.
The client submits an identifier and secret password, both sent in plain-text.
To use this authentication type, clients should submit an auth dict as follows:
@ -469,7 +469,26 @@ To use this authentication type, clients should submit an auth dict as follows:
{
"type": "m.login.password",
"user": "<user_id or user localpart>",
"identifier": {
...
},
"password": "<password>",
"session": "<session ID>"
}
where the ``identifier`` property is a user identifier object, as described in
`Identifier types`_.
For example, to authenticate using the user's Matrix ID, clients whould submit:
.. code:: json
{
"type": "m.login.password",
"identifier": {
"type": "m.id.user",
"user": "<user_id or user localpart>"
},
"password": "<password>",
"session": "<session ID>"
}
@ -482,8 +501,11 @@ follows:
{
"type": "m.login.password",
"medium": "<The medium of the third party identifier. Must be 'email'>",
"address": "<The third party address of the user>",
"identifier": {
"type": "m.id.thirdparty",
"medium": "<The medium of the third party identifier.>",
"address": "<The third party address of the user>"
},
"password": "<password>",
"session": "<session ID>"
}
@ -714,6 +736,78 @@ handle unknown login types:
}
Identifier types
++++++++++++++++
Some authentication mechanisms use a user identifier object to identify a
user. The user identifier object has a ``type`` field to indicate the type of
identifier being used, and depending on the type, has other fields giving the
information required to identify the user as described below.
This specification defines the following identifier types:
- ``m.id.user``
- ``m.id.thirdparty``
- ``m.id.phone``
Matrix User ID
<<<<<<<<<<<<<<
:Type:
``m.id.user``
:Description:
The user is identified by their Matrix ID.
A client can identify a user using their Matrix ID. This can either be the
fully qualified Matrix user ID, or just the localpart of the user ID.
.. code:: json
"identifier": {
"type": "m.id.user",
"user": "<user_id or user localpart>"
}
Third-party ID
<<<<<<<<<<<<<<
:Type:
``m.id.thirdparty``
:Description:
The user is identified by a third-party identifer in canonicalised form.
A client can identify a user using a 3pid associated with the user's account on
the homeserver, where the 3pid was previously associated using the
|/account/3pid|_ API. See the `3PID Types`_ Appendix for a list of Third-party
ID media.
.. code:: json
"identifier": {
"type": "m.id.thirdparty",
"medium": "<The medium of the third party identifier>",
"address": "<The canonicalised third party address of the user>"
}
Phone number
<<<<<<<<<<<<
:Type:
``m.id.phone``
:Description:
The user is identified by a phone number.
A client can identify a user using a phone number associated with the user's
account, where the phone number was previously associated using the
|/account/3pid|_ API. The phone number can be passed in as entered by the
user; the homeserver will be responsible for canonicalising it. If the client
wishes to canonicalise the phone number, then it can use the
``m.id.thirdparty`` identifier type with a ``medium`` of ``msisdn`` instead.
.. code:: json
"identifier": {
"type": "m.id.phone",
"country": "<The country that the phone number is from>",
"phone": "<The phone number>"
}
Login
~~~~~
@ -729,7 +823,10 @@ request as follows:
{
"type": "m.login.password",
"user": "<user_id or user localpart>",
"identifier": {
"type": "m.id.user",
"user": "<user_id or user localpart>"
},
"password": "<password>"
}
@ -741,8 +838,10 @@ explicitly, as follows:
{
"type": "m.login.password",
"medium": "<The medium of the third party identifier. Must be 'email'>",
"address": "<The third party address of the user>",
"identifier": {
"medium": "<The medium of the third party identifier>",
"address": "<The canonicalised third party address of the user>"
},
"password": "<password>"
}
@ -1477,3 +1576,4 @@ have to wait in milliseconds before they can try again.
.. _/user/<user_id>/account_data/<type>: #put-matrix-client-%CLIENT_MAJOR_VERSION%-user-userid-account-data-type
.. _`Unpadded Base64`: ../appendices.html#unpadded-base64
.. _`3PID Types`: ../appendices.html#pid-types

@ -114,100 +114,15 @@ session, within a 24 hour period since its most recent modification. Any
attempts to perform these actions after the expiry will be rejected, and a new
session should be created and used instead.
Creating a session
Email associations
~~~~~~~~~~~~~~~~~~
A client makes a call to::
{{email_associations_is_http_api}}
POST https://my.id.server:8090/_matrix/identity/api/v1/validate/email/requestToken
General
~~~~~~~
client_secret=monkeys_are_GREAT&
email=foo@bar.com&
send_attempt=1
It may also optionally specify next_link. If next_link is specified, when the
validation is completed, the identity service will redirect the user to that
URL.
This will create a new "session" on the identity service, identified by an
``sid``.
The identity service will send an email containing a token. If that token is
presented to the identity service 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.
We return the ``sid`` generated for this session to the caller, in a JSON object
containing the ``sid`` key.
If a send_attempt is specified, the server will only send an email if the
send_attempt is a number greater than the most recent one which it has seen (or
if it has never seen one), scoped to that email address + client_secret pair.
This is to avoid repeatedly sending the same email in the case of request
retries between the POSTing user and the identity service. The client should
increment this value if they desire a new email (e.g. a reminder) to be sent.
Note that Home Servers 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.
Validating ownership of an email
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A user may make either a ``GET`` or a ``POST`` request to
``/_matrix/identity/api/v1/validate/email/submitToken`` with the following
parameters (either as query parameters or URL-encoded POST parameters):
- ``sid`` the sid for the session, generated by the ``requestToken`` call.
- ``client_secret`` the client secret which was supplied to the ``requestToken`` call.
- ``token`` the token generated by the ``requestToken`` call, and emailed to the user.
If these three values 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.
Otherwise, an error will be returned.
Checking non-published 3pid ownership
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A client can check whether ownership of a 3pid was validated by making an
HTTP GET request to ``/_matrix/identity/api/v1/3pid/getValidated3pid``, passing
the ``sid`` and ``client_secret`` as query parameters from the ``requestToken``
call.
It will return something of either the form::
{"medium": "email", "validated_at": 1457622739026, "address": "foo@bar.com"}
or::
{"errcode": "M_SESSION_NOT_VALIDATED", "error": "This validation session has not yet been completed"}
If the ``sid`` and ``client_secret`` were not recognised, or were not correct,
an error will be returned.
Publishing a validated association
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
An association between a session and a Matrix user ID can be published by making
a URL-encoded HTTP POST request to ``/_matrix/identity/api/v1/3pid/bind`` with
the following parameters::
sid=sid&
client_secret=monkeys_are_GREAT&
mxid=@foo:bar.com
If the session is still valid, this will publish an association between the
3pids validated on that session and the passed Matrix user ID. Future calls
to ``/lookup`` for any of the session's 3pids will return this association.
If the 3pid has not yet been validated, the HTTP request will be rejected, and
the association will not be established.
If the ``sid`` and ``client_secret`` were not recognised, or were not correct,
an error will be returned.
{{associations_is_http_api}}
Invitation Storage
------------------
@ -216,32 +131,6 @@ An identity service can store pending invitations to a user's 3pid, which will
be retrieved and can be either notified on or look up when the 3pid is
associated with a Matrix user ID.
If one makes a ``POST`` request to ``/_matrix/identity/api/v1/store-invite`` with the following URL-encoded POST parameters:
- ``medium`` (string, required): The literal string ``email``.
- ``address`` (string, required): The email address of the invited user.
- ``room_id`` (string, required): The Matrix room ID to which the user is invited.
- ``sender`` (string, required): The matrix user ID of the inviting user.
An arbitrary number of other parameters may also be specified. These may be used in the email generation described below.
The service will look up whether the 3pid is bound to a Matrix user ID. If it is, the request will be rejected with a 400 status code.
If the medium is something other than the literal string ``email``, the request will be rejected with a 400 status code.
Otherwise, the service will then generate a random string called ``token``, and an ephemeral public key.
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.
The response body is then populated as the JSON-encoded dictionary containing the following fields:
- ``token`` (string): The generated token.
- ``public_keys`` ([string]): A list of [server's long-term public key, generated ephemeral public key].
- ``display_name`` (string): The generated (redacted) display_name.
At a later point, if the owner of that particular 3pid binds it with a Matrix user ID, the identity server will attempt to make an HTTP POST to the Matrix user's homeserver which looks roughly as below::
POST https://bar.com:8448/_matrix/federation/v1/3pid/onbind
@ -273,7 +162,7 @@ At a later point, if the owner of that particular 3pid binds it with a Matrix us
Where the signature is produced using a long-term private key.
Also, the generated ephemeral public key will be listed as valid on requests to ``/_matrix/identity/api/v1/pubkey/ephemeral/isvalid``.
{{store_invite_is_http_api}}
Ephemeral invitation signing
----------------------------
@ -281,23 +170,7 @@ Ephemeral invitation signing
To aid clients who may not be able to perform crypto themselves, the identity service offers some crypto functionality to help in accepting invitations.
This is less secure than the client doing it itself, but may be useful where this isn't possible.
The identity service will happily sign invitation details with a request-specified ed25519 private key for you, if you want it to. It takes URL-encoded POST parameters:
- mxid (string, required)
- token (string, required)
- private_key (string, required): The private key, encoded as `Unpadded base64`_.
It will look up ``token`` which was stored in a call to ``store-invite``, and fetch the sender of the invite. It will then respond with JSON which looks something like::
{
"mxid": "@foo:bar.com",
"sender": "@baz:bar.com",
"signatures" {
"my.id.server": {
"ed25519:0": "def987"
}
},
"token": "abc123"
}
{{invitation_signing_is_http_api}}
.. _`Unpadded Base64`: ../appendices.html#unpadded-base64
.. _`3PID Types`: ../appendices.html#pid-types

@ -0,0 +1,24 @@
.. Copyright 2018 New Vector Ltd.
..
.. 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.
OpenID
======
.. _module:openid:
This module allows users to verify their identity with a third party service. The
third party service does need to be matrix-aware in that it will need to know to
resolve matrix homeservers to exchange the user's token for identity information.
{{openid_cs_http_api}}

@ -622,3 +622,5 @@ shouldn't be sent in the push itself where possible. Instead, Push Gateways
should send a "sync" command to instruct the client to get new events from the
homeserver directly.
.. _`Push Gateway Specification`: ../push_gateway/unstable.html

@ -67,4 +67,9 @@ This describes the format used by "HTTP" pushers to send notifications of
events to Push Gateways. If the endpoint returns an HTTP error code, the
homeserver SHOULD retry for a reasonable amount of time using exponential backoff.
When pushing notifications for events, the hoemserver is expected to include all of
the event-related fields in the ``/notify`` request. When the homeserver is performing
a push where the ``format`` is ``"event_id_only"``, only the ``event_id``, ``room_id``,
``counts``, and ``devices`` are required to be populated.
{{push_notifier_push_http_api}}

@ -23,14 +23,13 @@ Federation API
Matrix homeservers use the Federation APIs (also known as server-server APIs)
to communicate with each other. Homeservers use these APIs to push messages to
each other in real-time, to
historic messages from each other, and to
each other in real-time, to retrieve historic messages from each other, and to
query profile and presence information about users on each other's servers.
The APIs are implemented using HTTPS GETs and PUTs between each of the
servers. These HTTPS requests are strongly authenticated using public key
signatures at the TLS transport layer and using public key signatures in
HTTP Authorization headers at the HTTP layer.
The APIs are implemented using HTTPS requests between each of the servers.
These HTTPS requests are strongly authenticated using public key signatures
at the TLS transport layer and using public key signatures in HTTP
Authorization headers at the HTTP layer.
There are three main kinds of communication that occur between homeservers:
@ -163,6 +162,97 @@ multiple servers to mitigate against DNS spoofing.
{{keys_query_ss_http_api}}
Authentication
--------------
Request Authentication
~~~~~~~~~~~~~~~~~~~~~~
Every HTTP request made by a homeserver is authenticated using public key
digital signatures. The request method, target and body are signed by wrapping
them in a JSON object and signing it using the JSON signing algorithm. The
resulting signatures are added as an Authorization header with an auth scheme
of ``X-Matrix``. Note that the target field should include the full path
starting with ``/_matrix/...``, including the ``?`` and any query parameters if
present, but should not include the leading ``https:``, nor the destination
server's hostname.
Step 1 sign JSON:
.. code::
{
"method": "GET",
"uri": "/target",
"origin": "origin.hs.example.com",
"destination": "destination.hs.example.com",
"content": <request body>,
"signatures": {
"origin.hs.example.com": {
"ed25519:key1": "ABCDEF..."
}
}
}
Step 2 add Authorization header:
.. code::
GET /target HTTP/1.1
Authorization: X-Matrix origin=origin.example.com,key="ed25519:key1",sig="ABCDEF..."
Content-Type: application/json
<JSON-encoded request body>
Example python code:
.. code:: python
def authorization_headers(origin_name, origin_signing_key,
destination_name, request_method, request_target,
content=None):
request_json = {
"method": request_method,
"uri": request_target,
"origin": origin_name,
"destination": destination_name,
}
if content_json is not None:
request["content"] = content
signed_json = sign_json(request_json, origin_name, origin_signing_key)
authorization_headers = []
for key, sig in signed_json["signatures"][origin_name].items():
authorization_headers.append(bytes(
"X-Matrix origin=%s,key=\"%s\",sig=\"%s\"" % (
origin_name, key, sig,
)
))
return ("Authorization", authorization_headers)
Response Authentication
~~~~~~~~~~~~~~~~~~~~~~~
Responses are authenticated by the TLS server certificate. A homeserver should
not send a request until it has authenticated the connected server to avoid
leaking messages to eavesdroppers.
Client TLS Certificates
~~~~~~~~~~~~~~~~~~~~~~~
Requests are authenticated at the HTTP layer rather than at the TLS layer
because HTTP services like Matrix are often deployed behind load balancers that
handle the TLS and these load balancers make it difficult to check TLS client
certificates.
A homeserver may provide a TLS client certificate and the receiving homeserver
may check that the client certificate matches the certificate of the origin
homeserver.
Transactions
------------
@ -485,15 +575,46 @@ A *conflict* occurs between states where those states have different
``event_ids`` for the same ``(state_type, state_key)``. The events thus
affected are said to be *conflicting* events.
Protocol URLs
-------------
.. WARNING::
This section may be misleading or inaccurate.
Backfilling and retrieving missing events
-----------------------------------------
All these URLs are name-spaced within a prefix of::
Once a homeserver has joined a room, it receives all the events emitted by
other homeservers in that room, and is thus aware of the entire history of the
room from that moment onwards. Since users in that room are able to request the
history by the ``/messages`` client API endpoint, it's possible that they might
step backwards far enough into history before the homeserver itself was a
member of that room.
To cover this case, the federation API provides a server-to-server analog of
the ``/messages`` client API, allowing one homeserver to fetch history from
another. This is the ``/backfill`` API.
To request more history, the requesting homeserver picks another homeserver
that it thinks may have more (most likely this should be a homeserver for
some of the existing users in the room at the earliest point in history it
has currently), and makes a ``/backfill`` request.
Similar to backfilling a room's history, a server may not have all the events
in the graph. That server may use the ``/get_missing_events`` API to acquire
the events it is missing.
.. TODO-spec
Specify (or remark that it is unspecified) how the server handles divergent
history. DFS? BFS? Anything weirder?
{{backfill_ss_http_api}}
Retrieving events
-----------------
In some circumstances, a homeserver may be missing a particular event or information
about the room which cannot be easily determined from backfilling. These APIs provide
homeservers with the option of getting events and the state of the room at a given
point in the timeline.
{{events_ss_http_api}}
/_matrix/federation/v1/...
Joining Rooms
-------------
@ -580,56 +701,6 @@ participating in the room.
here. What purpose does it serve expanding them out in full, when surely
they'll appear in the state anyway?
Backfilling
-----------
Once a homeserver has joined a room, it receives all the events emitted by
other homeservers in that room, and is thus aware of the entire history of the
room from that moment onwards. Since users in that room are able to request the
history by the ``/messages`` client API endpoint, it's possible that they might
step backwards far enough into history before the homeserver itself was a
member of that room.
To cover this case, the federation API provides a server-to-server analog of
the ``/messages`` client API, allowing one homeserver to fetch history from
another. This is the ``/backfill`` API.
To request more history, the requesting homeserver picks another homeserver
that it thinks may have more (most likely this should be a homeserver for some
of the existing users in the room at the earliest point in history it has
currently), and makes a ``/backfill`` request. The parameters of this request
give an event ID that the requesting homeserver wishes to obtain, and a number
specifying how many more events of history before that one to return at most.
The response to this request is an object with the following keys:
======================== ============ =========================================
Key Type Description
======================== ============ =========================================
``pdus`` List A list of events.
``origin`` String The name of the resident homeserver.
``origin_server_ts`` Integer A timestamp added by the resident
homeserver.
======================== ============ =========================================
The list of events given in ``pdus`` is returned in reverse chronological
order; having the most recent event first (i.e. the event whose event ID is
that requested by the requester in the ``v`` parameter).
.. TODO-spec
Specify (or remark that it is unspecified) how the server handles divergent
history. DFS? BFS? Anything weirder?
Retrieving events
----------------
In some circumstances, a homeserver may be missing a particular event or information
about the room which cannot be easily determined from backfilling. These APIs provide
homeservers with the option of getting events and the state of the room at a given
point in the timeline.
{{events_ss_http_api}}
Inviting to a room
------------------
@ -730,98 +801,6 @@ delivered when the invite was stored, this verification will prove that the
``m.room.member`` invite event comes from the user owning the invited third-party
identifier.
Authentication
--------------
Request Authentication
~~~~~~~~~~~~~~~~~~~~~~
Every HTTP request made by a homeserver is authenticated using public key
digital signatures. The request method, target and body are signed by wrapping
them in a JSON object and signing it using the JSON signing algorithm. The
resulting signatures are added as an Authorization header with an auth scheme
of ``X-Matrix``. Note that the target field should include the full path
starting with ``/_matrix/...``, including the ``?`` and any query parameters if
present, but should not include the leading ``https:``, nor the destination
server's hostname.
Step 1 sign JSON:
.. code::
{
"method": "GET",
"uri": "/target",
"origin": "origin.hs.example.com",
"destination": "destination.hs.example.com",
"content": <request body>,
"signatures": {
"origin.hs.example.com": {
"ed25519:key1": "ABCDEF..."
}
}
}
Step 2 add Authorization header:
.. code::
GET /target HTTP/1.1
Authorization: X-Matrix origin=origin.example.com,key="ed25519:key1",sig="ABCDEF..."
Content-Type: application/json
<JSON-encoded request body>
Example python code:
.. code:: python
def authorization_headers(origin_name, origin_signing_key,
destination_name, request_method, request_target,
content=None):
request_json = {
"method": request_method,
"uri": request_target,
"origin": origin_name,
"destination": destination_name,
}
if content_json is not None:
request["content"] = content
signed_json = sign_json(request_json, origin_name, origin_signing_key)
authorization_headers = []
for key, sig in signed_json["signatures"][origin_name].items():
authorization_headers.append(bytes(
"X-Matrix origin=%s,key=\"%s\",sig=\"%s\"" % (
origin_name, key, sig,
)
))
return ("Authorization", authorization_headers)
Response Authentication
~~~~~~~~~~~~~~~~~~~~~~~
Responses are authenticated by the TLS server certificate. A homeserver should
not send a request until it has authenticated the connected server to avoid
leaking messages to eavesdroppers.
Client TLS Certificates
~~~~~~~~~~~~~~~~~~~~~~~
Requests are authenticated at the HTTP layer rather than at the TLS layer
because HTTP services like Matrix are often deployed behind load balancers that
handle the TLS and these load balancers make it difficult to check TLS client
certificates.
A homeserver may provide a TLS client certificate and the receiving homeserver
may check that the client certificate matches the certificate of the origin
homeserver.
Public Room Directory
---------------------
@ -833,6 +812,16 @@ should be retrieved for.
{{public_rooms_ss_http_api}}
Typing Notifications
--------------------
When a server's users send typing notifications, those notifications need to
be sent to other servers in the room so their users are aware of the same
state. Receiving servers should verify that the user is in the room, and is
a user belonging to the sending server.
{{definition_ss_event_schemas_m_typing}}
Presence
--------
The server API for presence is based entirely on exchange of the following
@ -876,6 +865,18 @@ that can be made.
{{query_ss_http_api}}
OpenID
------
Third party services can exchange an access token previously generated by the
`Client-Server API` for information about a user. This can help verify that a
user is who they say they are without granting full access to the user's account.
Access tokens generated by the OpenID API are only good for the OpenID API and
nothing else.
{{openid_ss_http_api}}
Send-to-device messaging
------------------------
@ -901,6 +902,20 @@ the following EDU::
for the user
Content Repository
------------------
Attachments to events (images, files, etc) are uploaded to a homeserver via the
Content Repository described in the `Client-Server API`_. When a server wishes
to serve content originating from a remote server, it needs to ask the remote
server for the media.
Servers should use the server described in the Matrix Content URI, which has the
format ``mxc://{ServerName}/{MediaID}``. Servers should use the download endpoint
described in the `Client-Server API`_, being sure to use the ``allow_remote``
parameter (set to ``false``).
Signing Events
--------------
@ -1049,7 +1064,7 @@ that are too long.
.. _`Invitation storage`: ../identity_service/unstable.html#invitation-storage
.. _`Identity Service API`: ../identity_service/unstable.html
.. _`Client-Server API`: ../client_server/unstable.html#m-room-member
.. _`Client-Server API`: ../client_server/unstable.html
.. _`Inviting to a room`: #inviting-to-a-room
.. _`Canonical JSON`: ../appendices.html#canonical-json
.. _`Unpadded Base64`: ../appendices.html#unpadded-base64

@ -66,6 +66,7 @@ groups: # reusable blobs of files when prefixed with 'group:'
- modules/stickers.rst
- modules/report_content.rst
- modules/third_party_networks.rst
- modules/openid.rst
title_styles: ["=", "-", "~", "+", "^", "`", "@", ":"]

Loading…
Cancel
Save