diff --git a/changelogs/client_server.rst b/changelogs/client_server.rst index 465565e18..fc539dc0b 100644 --- a/changelogs/client_server.rst +++ b/changelogs/client_server.rst @@ -34,6 +34,9 @@ (`#390 `_). - Add "Send-to-Device messaging" module (`#386 `_). + - Require that User-Interactive auth fallback pages call + ``window.postMessage`` to notify apps of completion + (`#398 `_). - Spec clarifications: diff --git a/specification/client_server_api.rst b/specification/client_server_api.rst index e12f6f40b..21e2d03e0 100644 --- a/specification/client_server_api.rst +++ b/specification/client_server_api.rst @@ -428,7 +428,8 @@ To use this authentication type, clients should submit an auth dict as follows: { "type": "m.login.password", "user": "", - "password": "" + "password": "", + "session": "" } Alternatively reply using a 3pid bound to the user's account on the homeserver @@ -441,7 +442,8 @@ follows: "type": "m.login.password", "medium": "", "address": "", - "password": "" + "password": "", + "session": "" } In the case that the homeserver does not know about the supplied 3pid, the @@ -460,7 +462,8 @@ To use this authentication type, clients should submit an auth dict as follows: { "type": "m.login.recaptcha", - "response": "" + "response": "", + "session": "" } Token-based @@ -477,7 +480,8 @@ To use this authentication type, clients should submit an auth dict as follows: { "type": "m.login.token", "token": "", - "txn_id": "" + "txn_id": "", + "session": "" } The ``nonce`` should be a random string generated by the client for the @@ -544,7 +548,8 @@ To use this authentication type, clients should submit an auth dict as follows: "client_secret": "", "id_server": "" } - ] + ], + "session": "" } Dummy Auth @@ -562,12 +567,13 @@ the type and session, if provided: .. code:: json { - "type": "m.login.dummy" + "type": "m.login.dummy", + "session": "" } Fallback -<<<<<<<< +++++++++ 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 the user to a web browser with the URL of a fallback page which will allow the @@ -577,11 +583,92 @@ should open is:: /_matrix/client/%CLIENT_MAJOR_VERSION%/auth//fallback/web?session= 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 -page must attempt to call the JavaScript function ``window.onAuthDone`` when -the authentication has been completed. +page must use the following JavaScript when the authentication has been +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 `_ 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": "" + } + + +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) { + if (ev.data !== "authDone" ) { + 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 ~~~~~