Newer
Older
localpart entry of usernames (e.g. "user" rather than "@user:matrix.org"), as the
client may not be able to determine its ``user_id`` in this case.
If a login has multiple requests, the home server may wish to create a session. If
a home server responds with a 'session' key to a request, clients MUST submit it in
subsequent requests until the login is completed::
This specification defines the following login types:
Kegan Dougal
committed
- ``m.login.password``
- ``m.login.oauth2``
- ``m.login.email.code``
- ``m.login.email.url``
Kegan Dougal
committed
:Type:
m.login.password
:Description:
Login is supported via a username and password.
To respond to this type, reply with::
"type": "m.login.password",
"user": "<user_id or user localpart>",
"password": "<password>"
The home server MUST respond with either new credentials, the next stage of the login
process, or a standard error response.
OAuth2-based
------------
Kegan Dougal
committed
:Type:
m.login.oauth2
:Description:
Login is supported via OAuth2 URLs. This login consists of multiple requests.
{
"type": "m.login.oauth2",
"uri": <Authorization Request URI OR service selection URI>
The home server acts as a 'confidential' client for the purposes of OAuth2.
If the uri is a ``sevice selection URI``, it MUST point to a webpage which prompts the
user to choose which service to authorize with. On selection of a service, this
MUST link through to an ``Authorization Request URI``. If there is only 1 service which the
home server accepts when logging in, this indirection can be skipped and the
"uri" key can be the ``Authorization Request URI``.
The client then visits the ``Authorization Request URI``, which then shows the OAuth2
Allow/Deny prompt. Hitting 'Allow' returns the ``redirect URI`` with the auth code.
Home servers can choose any path for the ``redirect URI``. The client should visit
the ``redirect URI``, which will then finish the OAuth2 login process, granting the
home server an access token for the chosen service. When the home server gets
this access token, it verifies that the cilent has authorised with the 3rd party, and
can now complete the login. The OAuth2 ``redirect URI`` (with auth code) MUST respond
with either new credentials, the next stage of the login process, or a standard error
response.
For example, if a home server accepts OAuth2 from Google, it would return the
Authorization Request URI for Google::
{
"uri": "https://accounts.google.com/o/oauth2/auth?response_type=code&
client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=photos"
}
The client then visits this URI and authorizes the home server. The client then
visits the REDIRECT_URI with the auth code= query parameter which returns::
{
"access_token": "0123456789abcdef"
}
Email-based (code)
------------------
Kegan Dougal
committed
:Type:
m.login.email.code
:Description:
Login is supported by typing in a code which is sent in an email. This login
consists of multiple requests.
{
"type": "m.login.email.code",
"user": "<user_id or user localpart>",
"email": "<email address>"
After validating the email address, the home server MUST send an email containing
an authentication code and return::
"type": "m.login.email.code",
"session": "<session id>"
The second request in this login stage involves sending this authentication code::
{
"type": "m.login.email.code",
"session": "<session id>",
"code": "<code in email sent>"
The home server MUST respond to this with either new credentials, the next stage of
the login process, or a standard error response.
Email-based (url)
-----------------
Kegan Dougal
committed
:Type:
m.login.email.url
:Description:
Login is supported by clicking on a URL in an email. This login consists of
multiple requests.
{
"type": "m.login.email.url",
"user": "<user_id or user localpart>",
"email": "<email address>"
After validating the email address, the home server MUST send an email containing
an authentication URL and return::
"type": "m.login.email.url",
"session": "<session id>"
}
The email contains a URL which must be clicked. After it has been clicked, the
{
"type": "m.login.email.url",
The home server MUST respond to this with either new credentials, the next stage of
the login process, or a standard error response.
A common client implementation will be to periodically poll until the link is clicked.
If the link has not been visited yet, a standard error response with an errcode of
``M_LOGIN_EMAIL_URL_NOT_YET`` should be returned.
N-Factor Authentication
-----------------------
Multiple login stages can be combined to create N-factor authentication during login.
Kegan Dougal
committed
This can be achieved by responding with the ``next`` login type on completion of a
If a home server implements N-factor authentication, it MUST respond with all
Kegan Dougal
committed
``stages`` when initially queried for their login requirements::
"type": "<1st login type>",
"stages": [ <1st login type>, <2nd login type>, ... , <Nth login type> ]
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
This can be represented conceptually as::
_______________________
| Login Stage 1 |
| type: "<login type1>" |
| ___________________ |
| |_Request_1_________| | <-- Returns "session" key which is used throughout.
| ___________________ |
| |_Request_2_________| | <-- Returns a "next" value of "login type2"
|_______________________|
|
|
_________V_____________
| Login Stage 2 |
| type: "<login type2>" |
| ___________________ |
| |_Request_1_________| |
| ___________________ |
| |_Request_2_________| |
| ___________________ |
| |_Request_3_________| | <-- Returns a "next" value of "login type3"
|_______________________|
|
|
_________V_____________
| Login Stage 3 |
| type: "<login type3>" |
| ___________________ |
| |_Request_1_________| | <-- Returns user credentials
|_______________________|
Fallback
--------
Clients cannot be expected to be able to know how to process every single
login type. If a client determines it does not know how to handle a given
login type, it should request a login fallback page::
This MUST return an HTML page which can perform the entire login process.
Identity
========
.. NOTE::
This section is a work in progress.
.. TODO Dave
- 3PIDs and identity server, functions
Federation
==========
Federation is the term used to describe how to communicate between Matrix home
servers. Federation is a mechanism by which two home servers can exchange
Matrix event messages, both as a real-time push of current events, and as a
historic fetching mechanism to synchronise past history for clients to view. It
uses HTTP connections between each pair of servers involved as the underlying
transport. Messages are exchanged between servers in real-time by active pushing
from each server's HTTP client into the server of the other. Queries to fetch
historic data for the purpose of back-filling scrollback buffers and the like
can also be performed.
There are three main kinds of communication that occur between home servers:
Kegan Dougal
committed
:Queries:
These are single request/response interactions between a given pair of
Kegan Dougal
committed
servers, initiated by one side sending an HTTP GET request to obtain some
information, and responded by the other. They are not persisted and contain
no long-term significant history. They simply request a snapshot state at the
instant the query is made.
Kegan Dougal
committed
:Ephemeral Data Units (EDUs):
These are notifications of events that are pushed from one home server to
another. They are not persisted and contain no long-term significant history,
nor does the receiving home server have to reply to them.
Kegan Dougal
committed
:Persisted Data Units (PDUs):
These are notifications of events that are broadcast from one home server to
any others that are interested in the same "context" (namely, a Room ID).
They are persisted to long-term storage and form the record of history for
that context.
Kegan Dougal
committed
EDUs and PDUs are further wrapped in an envelope called a Transaction, which is
transferred from the origin to the destination home server using an HTTP PUT request.
Kegan Dougal
committed
Transactions
------------
.. WARNING::
This section may be misleading or inaccurate.
The transfer of EDUs and PDUs between home servers is performed by an exchange
Kegan Dougal
committed
of Transaction messages, which are encoded as JSON objects, passed over an
HTTP PUT request. A Transaction is meaningful only to the pair of home servers that
exchanged it; they are not globally-meaningful.
Kegan Dougal
committed
Each transaction has:
- An opaque transaction ID.
- A timestamp (UNIX epoch time in milliseconds) generated by its origin server.
- An origin and destination server name.
- A list of "previous IDs".
- A list of PDUs and EDUs - the actual message payload that the Transaction carries.
Kegan Dougal
committed
::
Kegan Dougal
committed
{
"transaction_id":"916d630ea616342b42e98a3be0b74113",
"ts":1404835423000,
"origin":"red",
"destination":"blue",
"prev_ids":["e1da392e61898be4d2009b9fecce5325"],
"pdus":[...],
Kegan Dougal
committed
"edus":[...]
}
Kegan Dougal
committed
The ``prev_ids`` field contains a list of previous transaction IDs that
the ``origin`` server has sent to this ``destination``. Its purpose is to act as a
sequence checking mechanism - the destination server can check whether it has
successfully received that Transaction, or ask for a retransmission if not.
Kegan Dougal
committed
The ``pdus`` field of a transaction is a list, containing zero or more PDUs.[*]
Each PDU is itself a JSON object containing a number of keys, the exact details of
which will vary depending on the type of PDU. Similarly, the ``edus`` field is
another list containing the EDUs. This key may be entirely absent if there are
no EDUs to transfer.
(* Normally the PDU list will be non-empty, but the server should cope with
receiving an "empty" transaction, as this is useful for informing peers of other
transaction IDs they should be aware of. This effectively acts as a push
mechanism to encourage peers to continue to replicate content.)
Kegan Dougal
committed
PDUs and EDUs
-------------
.. WARNING::
This section may be misleading or inaccurate.
Kegan Dougal
committed
All PDUs have:
- An ID
- A context
- A declaration of their type
- A list of other PDU IDs that have been seen recently on that context (regardless of which origin
sent them)
[[TODO(paul): Update this structure so that 'pdu_id' is a two-element
[origin,ref] pair like the prev_pdus are]]
Kegan Dougal
committed
::
Kegan Dougal
committed
{
"pdu_id":"a4ecee13e2accdadf56c1025af232176",
"context":"#example.green",
"origin":"green",
"ts":1404838188000,
"pdu_type":"m.text",
"prev_pdus":[["blue","99d16afbc857975916f1d73e49e52b65"]],
"content":...
Kegan Dougal
committed
"is_state":false
}
Kegan Dougal
committed
In contrast to Transactions, it is important to note that the ``prev_pdus``
field of a PDU refers to PDUs that any origin server has sent, rather than
Kegan Dougal
committed
previous IDs that this ``origin`` has sent. This list may refer to other PDUs sent
by the same origin as the current one, or other origins.
Because of the distributed nature of participants in a Matrix conversation, it
is impossible to establish a globally-consistent total ordering on the events.
However, by annotating each outbound PDU at its origin with IDs of other PDUs it
has received, a partial ordering can be constructed allowing causallity
relationships to be preserved. A client can then display these messages to the
end-user in some order consistent with their content and ensure that no message
that is semantically in reply of an earlier one is ever displayed before it.
PDUs fall into two main categories: those that deliver Events, and those that
synchronise State. For PDUs that relate to State synchronisation, additional
keys exist to support this:
Kegan Dougal
committed
::
{...,
"is_state":true,
"state_key":TODO
"power_level":TODO
"prev_state_id":TODO
"prev_state_origin":TODO}
[[TODO(paul): At this point we should probably have a long description of how
State management works, with descriptions of clobbering rules, power levels, etc
etc... But some of that detail is rather up-in-the-air, on the whiteboard, and
so on. This part needs refining. And writing in its own document as the details
relate to the server/system as a whole, not specifically to server-server
federation.]]
EDUs, by comparison to PDUs, do not have an ID, a context, or a list of
"previous" IDs. The only mandatory fields for these are the type, origin and
destination home server names, and the actual nested content.
Kegan Dougal
committed
::
{"edu_type":"m.presence",
"origin":"blue",
"destination":"orange",
"content":...}
Backfilling
-----------
.. NOTE::
This section is a work in progress.
.. TODO
- What it is, when is it used, how is it done
SRV Records
-----------
.. NOTE::
This section is a work in progress.
.. TODO
- Why it is needed
Security
========
- rate limiting
.. NOTE::
This section is a work in progress.
.. TODO
- crypto (s-s auth)
- E2E
- Lawful intercept + Key Escrow
TODO Mark
Policy Servers
==============
.. NOTE::
This section is a work in progress.
Content repository
==================
.. NOTE::
This section is a work in progress.
.. TODO
- path to upload
- format for thumbnail paths, mention what it is protecting against.
- content size limit and associated M_ERROR.
Address book repository
=======================
.. NOTE::
This section is a work in progress.
.. TODO
- format: POST(?) wodges of json, some possible processing, then return wodges of json on GET.
- processing may remove dupes, merge contacts, pepper with extra info (e.g. matrix-ability of
contacts), etc.
- Standard json format for contacts? Piggy back off vcards?
Glossary
========
.. NOTE::
This section is a work in progress.
.. TODO
- domain specific words/acronyms with definitions
User ID:
An opaque ID which identifies an end-user, which consists of some opaque
localpart combined with the domain name of their home server.
Kegan Dougal
committed
.. |createRoom| replace:: ``/createRoom``
.. _createRoom: /-rooms/create_room
.. |initialSync| replace:: ``/initialSync``
.. _initialSync: /-events/initial_sync
.. |roomInitialSync| replace:: ``/rooms/<room id>/initialSync``
.. _roomInitialSync: /-rooms/get_room_sync_data
.. |login| replace:: ``/login``
.. _login: /-login
.. _`Event Stream`: /-events/get_event_stream
.. _`Initial Sync`: /-events/initial_sync