Merge pull request #1478 from turt2live/travis/s2s/doc-cleanup
General clean up on the s2s spec
This commit is contained in:
commit
efb1787391
1 changed files with 133 additions and 143 deletions
|
@ -23,14 +23,13 @@ Federation API
|
||||||
|
|
||||||
Matrix homeservers use the Federation APIs (also known as server-server APIs)
|
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
|
to communicate with each other. Homeservers use these APIs to push messages to
|
||||||
each other in real-time, to
|
each other in real-time, to retrieve historic messages from each other, and to
|
||||||
historic messages from each other, and to
|
|
||||||
query profile and presence information about users on each other's servers.
|
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
|
The APIs are implemented using HTTPS requests between each of the servers.
|
||||||
servers. These HTTPS requests are strongly authenticated using public key
|
These HTTPS requests are strongly authenticated using public key signatures
|
||||||
signatures at the TLS transport layer and using public key signatures in
|
at the TLS transport layer and using public key signatures in HTTP
|
||||||
HTTP Authorization headers at the HTTP layer.
|
Authorization headers at the HTTP layer.
|
||||||
|
|
||||||
There are three main kinds of communication that occur between homeservers:
|
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}}
|
{{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
|
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
|
``event_ids`` for the same ``(state_type, state_key)``. The events thus
|
||||||
affected are said to be *conflicting* events.
|
affected are said to be *conflicting* events.
|
||||||
|
|
||||||
Protocol URLs
|
|
||||||
-------------
|
|
||||||
|
|
||||||
.. WARNING::
|
Backfilling and retrieving missing events
|
||||||
This section may be misleading or inaccurate.
|
-----------------------------------------
|
||||||
|
|
||||||
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
|
Joining Rooms
|
||||||
-------------
|
-------------
|
||||||
|
@ -580,45 +701,6 @@ participating in the room.
|
||||||
here. What purpose does it serve expanding them out in full, when surely
|
here. What purpose does it serve expanding them out in full, when surely
|
||||||
they'll appear in the state anyway?
|
they'll appear in the state anyway?
|
||||||
|
|
||||||
Backfilling and retrieving missing events
|
|
||||||
-----------------------------------------
|
|
||||||
|
|
||||||
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}}
|
|
||||||
|
|
||||||
Inviting to a room
|
Inviting to a room
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
@ -719,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
|
``m.room.member`` invite event comes from the user owning the invited third-party
|
||||||
identifier.
|
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
|
Public Room Directory
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue