@ -158,14 +158,23 @@ recommended.
Client Authentication
Client Authentication
---------------------
---------------------
Most API endpoints require the user to identify themselves by presenting
Most API endpoints require the user to identify themselves by presenting
previously obtained credentials in the form of an `` access_token `` query
previously obtained credentials in the form of an `` access_token `` query
parameter.
parameter. An access token is typically obtained via the `Login`_ or
`Registration`_ processes.
When credentials are required but missing or invalid, the HTTP call will
When credentials are required but missing or invalid, the HTTP call will
return with a status of 401 and the error code, `` M_MISSING_TOKEN `` or
return with a status of 401 and the error code, `` M_MISSING_TOKEN `` or
`` M_UNKNOWN_TOKEN `` respectively.
`` M_UNKNOWN_TOKEN `` respectively.
.. NOTE ::
This specification does not mandate a particular format for the access
token. Clients should treat it as an opaque byte sequence. Servers are free
to choose an appropriate format. Server implementors may like to investigate
`macaroons <macaroon_> `_ .
User-Interactive Authentication API
User-Interactive Authentication API
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -289,8 +298,42 @@ successfully:
"session": "xxxxxx"
"session": "xxxxxx"
}
}
If the homeserver decides the attempt was unsuccessful, it returns an error
Individual stages may require more than one request to complete, in which case
message in the standard format:
the response will be as if the request was unauthenticated with the addition of
any other keys as defined by the auth type.
If the homeserver decides that an attempt on a stage was unsuccessful, but the
client may make a second attempt, it returns the same HTTP status 401 response
as above, with the addition of the standard `` errcode `` and `` error `` fields
describing the error. For example:
.. code ::
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"errcode": "M_FORBIDDEN",
"error": "Invalid password",
"completed": [ "example.type.foo" ],
"flows": [
{
"stages": [ "example.type.foo", "example.type.bar" ]
},
{
"stages": [ "example.type.foo", "example.type.baz" ]
}
],
"params": {
"example.type.baz": {
"example_key": "foobar"
}
},
"session": "xxxxxx"
}
If the request fails for a reason other than authentication, the server returns an error
message in the standard format. For example:
.. code ::
.. code ::
@ -302,10 +345,6 @@ message in the standard format:
"error": "Something was wrong"
"error": "Something was wrong"
}
}
Individual stages may require more than one request to complete, in which case
the response will be as if the request was unauthenticated with the addition of
any other keys as defined by the auth type.
If the client has completed all stages of a flow, the homeserver performs the
If the client has completed all stages of a flow, the homeserver performs the
API call and returns the result as normal.
API call and returns the result as normal.
@ -389,7 +428,8 @@ To use this authentication type, clients should submit an auth dict as follows:
{
{
"type": "m.login.password",
"type": "m.login.password",
"user": "<user_id or user localpart>",
"user": "<user_id or user localpart>",
"password": "<password>"
"password": "<password>",
"session": "<session ID>"
}
}
Alternatively reply using a 3pid bound to the user's account on the homeserver
Alternatively reply using a 3pid bound to the user's account on the homeserver
@ -402,18 +442,13 @@ follows:
"type": "m.login.password",
"type": "m.login.password",
"medium": "<The medium of the third party identifier. Must be 'email'>",
"medium": "<The medium of the third party identifier. Must be 'email'>",
"address": "<The third party address of the user>",
"address": "<The third party address of the user>",
"password": "<password>"
"password": "<password>",
"session": "<session ID>"
}
}
In the case that the homeserver does not know about the supplied 3pid, the
In the case that the homeserver does not know about the supplied 3pid, the
homeserver must respond with 403 Forbidden.
homeserver must respond with 403 Forbidden.
.. WARNING ::
Clients SHOULD enforce that the password provided is suitably complex. The
password SHOULD include a lower-case letter, an upper-case letter, a number
and a symbol and be at a minimum 8 characters in length. Servers MAY reject
weak passwords with an error code `` M_WEAK_PASSWORD `` .
Google ReCaptcha
Google ReCaptcha
<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<
:Type:
:Type:
@ -427,7 +462,8 @@ To use this authentication type, clients should submit an auth dict as follows:
{
{
"type": "m.login.recaptcha",
"type": "m.login.recaptcha",
"response": "<captcha response>"
"response": "<captcha response>",
"session": "<session ID>"
}
}
Token-based
Token-based
@ -444,7 +480,8 @@ To use this authentication type, clients should submit an auth dict as follows:
{
{
"type": "m.login.token",
"type": "m.login.token",
"token": "<token>",
"token": "<token>",
"txn_id": "<client generated nonce>"
"txn_id": "<client generated nonce>",
"session": "<session ID>"
}
}
The `` nonce `` should be a random string generated by the client for the
The `` nonce `` should be a random string generated by the client for the
@ -460,8 +497,8 @@ server side, as well as potentially invalidating the token completely once the
device has successfully logged in (e.g. when we receive a request from the
device has successfully logged in (e.g. when we receive a request from the
newly provisioned access_token).
newly provisioned access_token).
The `` token `` must be a macaroon, with a caveat encoding the user id. There is
The server must encode the user id in the `` token `` . There is therefore no need
therefore no need for the client to submit a separate username.
for the client to submit a separate username.
OAuth2-based
OAuth2-based
<<<<<<<<<<<<
<<<<<<<<<<<<
@ -511,7 +548,8 @@ To use this authentication type, clients should submit an auth dict as follows:
"client_secret": "<identity server client secret>",
"client_secret": "<identity server client secret>",
"id_server": "<url of identity server authed with, e.g. 'matrix.org:8090'>"
"id_server": "<url of identity server authed with, e.g. 'matrix.org:8090'>"
}
}
]
],
"session": "<session ID>"
}
}
Dummy Auth
Dummy Auth
@ -529,12 +567,13 @@ the type and session, if provided:
.. code :: json
.. code :: json
{
{
"type": "m.login.dummy"
"type": "m.login.dummy",
"session": "<session ID>"
}
}
Fallback
Fallback
<<<<<<<<
++++++++
Clients cannot be expected to be able to know how to process every single login
Clients cannot be expected to be able to know how to process every single login
type. If a client does not know how to handle a given login type, it can direct
type. If a client does not know how to handle a given login type, it can direct
the user to a web browser with the URL of a fallback page which will allow the
the user to a web browser with the URL of a fallback page which will allow the
@ -544,11 +583,93 @@ should open is::
/_matrix/client/%CLIENT_MAJOR_VERSION%/auth/<auth type>/fallback/web?session=<session ID>
/_matrix/client/%CLIENT_MAJOR_VERSION%/auth/<auth type>/fallback/web?session=<session ID>
Where `` auth type `` is the type name of the stage it is attempting and
Where `` auth type `` is the type name of the stage it is attempting and
`` session id `` is the ID of the session given by the homeserver.
`` session ID `` is the ID of the session given by the homeserver.
This MUST return an HTML page which can perform this authentication stage. This
This MUST return an HTML page which can perform this authentication stage. This
page must attempt to call the JavaScript function `` window.onAuthDone `` when
page must use the following JavaScript when the authentication has been
the authentication has been completed.
completed:
.. code :: javascript
if (window.onAuthDone) {
window.onAuthDone();
} else if (window.opener && window.opener.postMessage) {
window.opener.postMessage("authDone", "*");
}
This allows the client to either arrange for the global function `` onAuthDone ``
to be defined in an embedded browser, or to use the HTML5 `cross-document
messaging <https://www.w3.org/TR/webmessaging/#web-messaging>`_ API, to receive
a notification that the authentication stage has been completed.
Once a client receives the notificaton that the authentication stage has been
completed, it should resubmit the request with an auth dict with just the
session ID:
.. code :: json
{
"session": "<session ID>"
}
Example
<<<<<<<
A client webapp might use the following javascript to open a popup window which will
handle unknown login types:
.. code :: javascript
/**
* Arguments:
* homeserverUrl: the base url of the homeserver (eg "https://matrix.org")
*
* apiEndpoint: the API endpoint being used (eg
* "/_matrix/client/%CLIENT_MAJOR_VERSION%/account/password")
*
* loginType: the loginType being attempted (eg "m.login.recaptcha")
*
* sessionID: the session ID given by the homeserver in earlier requests
*
* onComplete: a callback which will be called with the results of the request
*/
function unknownLoginType(homeserverUrl, apiEndpoint, loginType, sessionID, onComplete) {
var popupWindow;
var eventListener = function(ev) {
// check it's the right message from the right place.
if (ev.data !== "authDone" || ev.origin !== homeserverUrl) {
return;
}
// close the popup
popupWindow.close();
window.removeEventListener("message", eventListener);
// repeat the request
var requestBody = {
auth: {
session: sessionID,
},
};
request({
method:'POST', url:apiEndpint, json:requestBody,
}, onComplete);
};
window.addEventListener("message", eventListener);
var url = homeserverUrl +
"/_matrix/client/%CLIENT_MAJOR_VERSION%/auth/" +
encodeURIComponent(loginType) +
"/fallback/web?session=" +
encodeURIComponent(sessionID);
popupWindow = window.open(url);
}
Login
Login
~~~~~
~~~~~
@ -595,9 +716,9 @@ follows:
"token": "<login token>"
"token": "<login token>"
}
}
As with `token-based`_ interactive login, the `` token `` must be a macroon with
As with `token-based`_ interactive login, the `` token `` must encode the
a caveat which includes the user id. In the case that the token is not valid, the
user id. In the case that the token is not valid, the homeserver must respond
homeserver must respond with `` 403 Forbidden `` and an error code of `` M_FORBIDDEN `` .
with `` 403 Forbidden `` and an error code of `` M_FORBIDDEN `` .
{{login_cs_http_api}}
{{login_cs_http_api}}
@ -615,6 +736,8 @@ This returns an HTML and JavaScript page which can perform the entire login
process. The page will attempt to call the JavaScript function
process. The page will attempt to call the JavaScript function
`` window.onLogin `` when login has been successfully completed.
`` window.onLogin `` when login has been successfully completed.
.. _Registration:
Account registration and management
Account registration and management
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -1230,6 +1353,9 @@ have to wait in milliseconds before they can try again.
homeserver come up with their own idea, causing totally unpredictable performance over
homeserver come up with their own idea, causing totally unpredictable performance over
federated rooms?
federated rooms?
.. References
.. _`macaroon`: http://research.google.com/pubs/pub41892.html
.. Links through the external API docs are below
.. Links through the external API docs are below
.. =============================================
.. =============================================
@ -1237,15 +1363,15 @@ have to wait in milliseconds before they can try again.
.. |/initialSync| replace :: `` /initialSync ``
.. |/initialSync| replace :: `` /initialSync ``
.. _/initialSync: #get-matrix-client-%CLIENT_MAJOR_VERSION%-initialsync
.. _/initialSync: #get-matrix-client-%CLIENT_MAJOR_VERSION%-initialsync
.. |/tokenrefresh| replace :: `` /tokenrefresh ``
.. _/tokenrefresh: #post-matrix-client-%CLIENT_MAJOR_VERSION%-tokenrefresh
.. |/sync| replace :: `` /sync ``
.. |/sync| replace :: `` /sync ``
.. _/sync: #get-matrix-client-%CLIENT_MAJOR_VERSION%-sync
.. _/sync: #get-matrix-client-%CLIENT_MAJOR_VERSION%-sync
.. |/events| replace :: `` /events ``
.. |/events| replace :: `` /events ``
.. _/events: #get-matrix-client-%CLIENT_MAJOR_VERSION%-events
.. _/events: #get-matrix-client-%CLIENT_MAJOR_VERSION%-events
.. |/createRoom| replace :: `` /createRoom ``
.. _/createRoom: #post-matrix-client-%CLIENT_MAJOR_VERSION%-createroom
.. |/rooms/<room_id>/initialSync| replace :: `` /rooms/<room_id>/initialSync ``
.. |/rooms/<room_id>/initialSync| replace :: `` /rooms/<room_id>/initialSync ``
.. _/rooms/<room_id>/initialSync: #get-matrix-client-%CLIENT_MAJOR_VERSION%-rooms-roomid-initialsync
.. _/rooms/<room_id>/initialSync: #get-matrix-client-%CLIENT_MAJOR_VERSION%-rooms-roomid-initialsync
@ -1258,6 +1384,9 @@ have to wait in milliseconds before they can try again.
.. |/rooms/<room_id>/state| replace :: `` /rooms/<room_id>/state ``
.. |/rooms/<room_id>/state| replace :: `` /rooms/<room_id>/state ``
.. _/rooms/<room_id>/state: #get-matrix-client-%CLIENT_MAJOR_VERSION%-rooms-roomid-state
.. _/rooms/<room_id>/state: #get-matrix-client-%CLIENT_MAJOR_VERSION%-rooms-roomid-state
.. |/rooms/<room_id>/send| replace :: `` /rooms/<room_id>/send ``
.. _/rooms/<room_id>/send: #put-matrix-client-%CLIENT_MAJOR_VERSION%-rooms-roomid-send-eventtype-txnid
.. |/rooms/<room_id>/invite| replace :: `` /rooms/<room_id>/invite ``
.. |/rooms/<room_id>/invite| replace :: `` /rooms/<room_id>/invite ``
.. _/rooms/<room_id>/invite: #post-matrix-client-%CLIENT_MAJOR_VERSION%-rooms-roomid-invite
.. _/rooms/<room_id>/invite: #post-matrix-client-%CLIENT_MAJOR_VERSION%-rooms-roomid-invite
@ -1278,3 +1407,6 @@ have to wait in milliseconds before they can try again.
.. |/account/3pid| replace :: `` /account/3pid ``
.. |/account/3pid| replace :: `` /account/3pid ``
.. _/account/3pid: #post-matrix-client-%CLIENT_MAJOR_VERSION%-account-3pid
.. _/account/3pid: #post-matrix-client-%CLIENT_MAJOR_VERSION%-account-3pid
.. |/user/<user_id>/account_data/<type>| replace :: `` /user/<user_id>/account_data/<type> ``
.. _/user/<user_id>/account_data/<type>: #put-matrix-client-%CLIENT_MAJOR_VERSION%-user-userid-account-data-type