From 41368dc5a7a9002b62a4baf4ce522e2f98862e87 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Mon, 8 Aug 2016 17:33:48 +0100 Subject: [PATCH 1/6] document CAS login Following the spirit of "document how it is, not how we wish it was", document the CAS login bits. --- api/client-server/cas_login_redirect.yaml | 53 ++++++++++++++++++ api/client-server/cas_login_ticket.yaml | 65 +++++++++++++++++++++++ api/client-server/login.yaml | 14 +++-- specification/client_server_api.rst | 9 ++++ specification/modules/cas_login.rst | 65 +++++++++++++++++++++++ specification/targets.yaml | 1 + 6 files changed, 204 insertions(+), 3 deletions(-) create mode 100644 api/client-server/cas_login_redirect.yaml create mode 100644 api/client-server/cas_login_ticket.yaml create mode 100644 specification/modules/cas_login.rst diff --git a/api/client-server/cas_login_redirect.yaml b/api/client-server/cas_login_redirect.yaml new file mode 100644 index 00000000..7a4cec5d --- /dev/null +++ b/api/client-server/cas_login_redirect.yaml @@ -0,0 +1,53 @@ +# Copyright 2016 OpenMarket 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 CAS Login API" + version: "1.0.0" +host: localhost:8008 +schemes: + - https + - http +basePath: /_matrix/client/%CLIENT_MAJOR_VERSION% +paths: + "/login/cas/redirect": + get: + summary: Redirect the user's browser to the CAS interface. + description: |- + A web-based Matrix client should instruct the user's browser to + navigate to this endpoint in order to log in via CAS. + + The server MUST respond with an HTTP redirect to the CAS interface. The + URI MUST include a ``service`` parameter giving the path of the + |/login/cas/ticket|_ endpoint (including the ``redirectUrl`` query + parameter). + + For example, if the endpoint is called with + ``redirectUrl=https://client.example.com/?q=p``, it might redirect to + ``https://cas.example.com/?service=https%3A%2F%2Fserver.example.com%2F_matrix%2Fclient%2F%CLIENT_MAJOR_VERSION%%2Flogin%2Fcas%2Fticket%3FredirectUrl%3Dhttps%253A%252F%252Fclient.example.com%252F%253Fq%253Dp``. + + parameters: + - in: query + type: string + name: redirectUrl + description: |- + URI to which the user will be redirected after the homeserver has + authenticated the user with CAS. + required: true + responses: + 302: + description: A redirect to the CAS interface. + headers: + Location: + type: "string" diff --git a/api/client-server/cas_login_ticket.yaml b/api/client-server/cas_login_ticket.yaml new file mode 100644 index 00000000..e1f2f7b0 --- /dev/null +++ b/api/client-server/cas_login_ticket.yaml @@ -0,0 +1,65 @@ +# Copyright 2016 OpenMarket 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 CAS Login API" + version: "1.0.0" +host: localhost:8008 +schemes: + - https + - http +basePath: /_matrix/client/%CLIENT_MAJOR_VERSION% +paths: + "/login/cas/ticket": + get: + summary: Receive and validate a CAS login ticket. + description: |- + Once the CAS server has authenticated the user, it will redirect the + browser to this endpoint (assuming |/login/cas/redirect|_ gave it the + correct ``service`` parameter). + + The server MUST call ``/proxyValidate`` on the CAS server, to validate + the ticket supplied by the browser. + + If validation is successful, the server must generate a Matrix login + token. It must then respond with an HTTP redirect to the URI given in + the ``redirectUrl`` parameter, adding a ``loginToken`` query parameter + giving the generated token. + + If validation is unsuccessful, the server should respond with a ``401 + Unauthorized`` error, the body of which will be displayed to the user. + parameters: + - in: query + type: string + name: redirectUrl + description: |- + The ``redirectUrl`` originally provided by the client to + |/login/cas/redirect|_. + required: true + - in: query + type: string + name: ticket + description: |- + CAS authentication ticket. + required: true + responses: + 302: + description: A redirect to the Matrix client. + headers: + Location: + type: "string" + x-example: |- + redirectUrl=https://client.example.com/?hs=https%3A%2F%2Fserver.example.com&loginToken=secrettoken + 401: + description: The server was unable to validate the CAS ticket. diff --git a/api/client-server/login.yaml b/api/client-server/login.yaml index 34b33cf3..04dd67c5 100644 --- a/api/client-server/login.yaml +++ b/api/client-server/login.yaml @@ -47,7 +47,9 @@ paths: properties: type: type: string - description: The login type being used. Currently only "m.login.password" is supported. + description: |- + The login type being used. One of ``m.login.password`` or + ``m.login.token``. user: type: string description: The fully qualified user ID or just local part of the user ID, to log in. @@ -59,8 +61,14 @@ paths: description: Third party identifier for the user. password: type: string - description: The user's password. - required: ["type", "password"] + description: |- + Required when ``type`` is ``m.login.password``. The user's + password. + token: + type: string + description: |- + Required when ``type`` is ``m.login.token``. The login token. + required: ["type"] responses: 200: diff --git a/specification/client_server_api.rst b/specification/client_server_api.rst index 9a342413..71eadb6b 100644 --- a/specification/client_server_api.rst +++ b/specification/client_server_api.rst @@ -554,6 +554,15 @@ explicitly, as follows: In the case that the homeserver does not know about the supplied 3pid, the homeserver must respond with 403 Forbidden. +To log in using a login token, a client should submit an auth dict as follows: + +.. code:: json + + { + "type": "m.login.token", + "token": "" + } + {{login_cs_http_api}} {{logout_cs_http_api}} diff --git a/specification/modules/cas_login.rst b/specification/modules/cas_login.rst new file mode 100644 index 00000000..51866bca --- /dev/null +++ b/specification/modules/cas_login.rst @@ -0,0 +1,65 @@ +.. Copyright 2016 OpenMarket 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. + +CAS-based client login +====================== + +.. _module:cas_login: + +Central Authentication Service (CAS) is a web-based single sign-on protocol. + +Client behaviour +---------------- + +An overview of the process, as used in Matrix, is as follows: + +1. The Matrix client instructs the user's browser to navigate to the + |/login/cas/redirect|_ endpoint on the user's homeserver. + +2. The homeserver responds with an HTTP redirect to the CAS user interface, + which the browser follows. + +3. The CAS system authenticates the user. + +4. The CAS server responds to the user's browser with a redirect back to the + |/login/cas/ticket|_ endpoint on the homeserver, which the browser + follows. A 'ticket' identifier is passed as a query-parameter in the + redirect. + +5. The homeserver receives the ticket ID from the user's browser, and makes a + request to the CAS server to validate the ticket. + +6. Having validated the ticket, the homeserver responds to the browser with a + third HTTP redirect, back to the Matrix client application. A login token + is passed as a query-parameter in the redirect. + +7. The Matrix client receives the login token and passes it to the |/login|_ + API. + +If successful, the user is redirected back to the client via the redirectUrl given to the +homeserver on the initial redirect request. In the url will be a loginToken query parameter +which contains a Matrix login token which the client should then use to complete the login +via the Token-based process described above. + + +{{cas_login_redirect_cs_http_api}} +{{cas_login_ticket_cs_http_api}} + + +.. |/login| replace:: ``/login`` +.. _/login: #post-matrix-client-%CLIENT_MAJOR_VERSION%-login +.. |/login/cas/redirect| replace:: ``/login/cas/redirect`` +.. _/login/cas/redirect: #get-matrix-client-%CLIENT_MAJOR_VERSION%-login-cas-redirect +.. |/login/cas/ticket| replace:: ``/login/cas/ticket`` +.. _/login/cas/ticket: #get-matrix-client-%CLIENT_MAJOR_VERSION%-login-cas-ticket diff --git a/specification/targets.yaml b/specification/targets.yaml index d759a7e8..6cbfa917 100644 --- a/specification/targets.yaml +++ b/specification/targets.yaml @@ -52,6 +52,7 @@ groups: # reusable blobs of files when prefixed with 'group:' - modules/account_data.rst - modules/admin.rst - modules/event_context.rst + - modules/cas_login.rst title_styles: ["=", "-", "~", "+", "^", "`", "@", ":"] From 4b0e546eeb069bf42f30e661b1e16e97cae7f67e Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 9 Aug 2016 12:02:38 +0100 Subject: [PATCH 2/6] PR feedback Fix some typos, and clarify several aspects of server behaviour. --- api/client-server/cas_login_ticket.yaml | 2 +- api/client-server/login.yaml | 5 +-- specification/modules/cas_login.rst | 53 +++++++++++++++++++++---- 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/api/client-server/cas_login_ticket.yaml b/api/client-server/cas_login_ticket.yaml index e1f2f7b0..02469489 100644 --- a/api/client-server/cas_login_ticket.yaml +++ b/api/client-server/cas_login_ticket.yaml @@ -60,6 +60,6 @@ paths: Location: type: "string" x-example: |- - redirectUrl=https://client.example.com/?hs=https%3A%2F%2Fserver.example.com&loginToken=secrettoken + https://client.example.com/?q=p&loginToken=secrettoken 401: description: The server was unable to validate the CAS ticket. diff --git a/api/client-server/login.yaml b/api/client-server/login.yaml index 04dd67c5..3ca397ea 100644 --- a/api/client-server/login.yaml +++ b/api/client-server/login.yaml @@ -47,9 +47,8 @@ paths: properties: type: type: string - description: |- - The login type being used. One of ``m.login.password`` or - ``m.login.token``. + enum: ["m.login.password", "m.login.token"] + description: The login type being used. user: type: string description: The fully qualified user ID or just local part of the user ID, to log in. diff --git a/specification/modules/cas_login.rst b/specification/modules/cas_login.rst index 51866bca..1c745198 100644 --- a/specification/modules/cas_login.rst +++ b/specification/modules/cas_login.rst @@ -17,10 +17,9 @@ CAS-based client login .. _module:cas_login: -Central Authentication Service (CAS) is a web-based single sign-on protocol. - -Client behaviour ----------------- +`Central Authentication Service +`_ +(CAS) is a web-based single sign-on protocol. An overview of the process, as used in Matrix, is as follows: @@ -47,15 +46,53 @@ An overview of the process, as used in Matrix, is as follows: 7. The Matrix client receives the login token and passes it to the |/login|_ API. -If successful, the user is redirected back to the client via the redirectUrl given to the -homeserver on the initial redirect request. In the url will be a loginToken query parameter -which contains a Matrix login token which the client should then use to complete the login -via the Token-based process described above. +Client behaviour +---------------- +The client starts the process by instructing the browser to navigate to +|/login/cas/redirect|_ with an appropriate ``redirectUrl``. Once authentication +is successful, the browser will be redirected to that ``redirectUrl``. {{cas_login_redirect_cs_http_api}} {{cas_login_ticket_cs_http_api}} +Server behaviour +---------------- + +The URI for the CAS system to be used should be configured on the server by the +server administrator. + +Handling the redirect endpoint +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When responding to the ``/login/cas/redirect`` endpoint, the server must +generate a URI for the CAS login page. The server should take the base CAS URI +described above, and add a ``service`` query-parameter. This parameter MUST be +the URI of the ``/login/cas/ticket`` endpoint, including the ``redirectUrl`` +query-parameter. Because the homeserver may not know its base URI, this may +also require manual configuration. + +Handling the authentication endpoint +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When responding to the ``/login/cas/ticket`` endpoint, the server MUST make a +request to the CAS server to validate the provided ticket. The server MAY also +check for certain user attributes in the response. Any required attributes +should be configured by the server administrator. + +Once the ticket has been validated, the server MUST map the CAS ``user_id`` +to a valid `Matrix user idenitifier <../intro.html#user-identifiers>`_. The +guidance in `Mapping from other character sets +<../intro.html#mapping-from-other-character-sets>`_ may be useful. + +If the generated user identifier represents a new user, it should be registered +as a new user. + +Finally, the server should generate a short-term login token. The generated +token should be a macaroon, suitable for use with the ``m.login.token`` type of +the |/login|_ API, and `token-based interactive login <#token-based>`_. The +lifetime of this token SHOULD be limited to around five seconds. + .. |/login| replace:: ``/login`` .. _/login: #post-matrix-client-%CLIENT_MAJOR_VERSION%-login From ec81b4c9fe4e23f482eed1bb08af81f9a7d71843 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 9 Aug 2016 12:16:20 +0100 Subject: [PATCH 3/6] More PR feedback Add a couple of TODO sections --- specification/modules/cas_login.rst | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/specification/modules/cas_login.rst b/specification/modules/cas_login.rst index 1c745198..a0c8acca 100644 --- a/specification/modules/cas_login.rst +++ b/specification/modules/cas_login.rst @@ -53,6 +53,16 @@ The client starts the process by instructing the browser to navigate to |/login/cas/redirect|_ with an appropriate ``redirectUrl``. Once authentication is successful, the browser will be redirected to that ``redirectUrl``. +.. TODO-spec + + Should we recommend some sort of CSRF protection here (specifically, we + should guard against people accidentally logging in by sending them a link + to ``/login/cas/redirect``. + + Maybe we should recommend that the ``redirectUrl`` should contain a CSRF + token which the client should then check before sending the login token to + ``/login``? + {{cas_login_redirect_cs_http_api}} {{cas_login_ticket_cs_http_api}} @@ -72,6 +82,12 @@ the URI of the ``/login/cas/ticket`` endpoint, including the ``redirectUrl`` query-parameter. Because the homeserver may not know its base URI, this may also require manual configuration. +.. TODO-spec: + + It might be nice if the server did some validation of the ``redirectUrl`` + parameter, so that we could give more meaningful errors in the case of + faulty/poorly-configured clients. + Handling the authentication endpoint ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 1f1dfdd91c095c5de7eb09f45a342f28bfe8dcb8 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 9 Aug 2016 15:51:12 +0100 Subject: [PATCH 4/6] More clarifications --- specification/client_server_api.rst | 9 ++++++--- specification/modules/cas_login.rst | 13 +++++++------ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/specification/client_server_api.rst b/specification/client_server_api.rst index 71eadb6b..d47bb093 100644 --- a/specification/client_server_api.rst +++ b/specification/client_server_api.rst @@ -407,7 +407,7 @@ Token-based :Type: ``m.login.token`` :Description: - The client submits a username and token. + The client submits a login token. To respond to this type, reply with an auth dict as follows: @@ -415,7 +415,6 @@ To respond to this type, reply with an auth dict as follows: { "type": "m.login.token", - "user": "", "token": "", "txn_id": "" } @@ -433,7 +432,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 newly provisioned access_token). -The ``token`` must be a macaroon. +The ``token`` must be a macaroon, with a caveat encoding the user id. There is +therefore no need for the client to submit a separate username. OAuth2-based <<<<<<<<<<<< @@ -563,6 +563,9 @@ To log in using a login token, a client should submit an auth dict as follows: "token": "" } +As with `token-based`_ interactive login, the ``token`` must be a macroon with +a caveat which includes the user id. + {{login_cs_http_api}} {{logout_cs_http_api}} diff --git a/specification/modules/cas_login.rst b/specification/modules/cas_login.rst index a0c8acca..4c3b826a 100644 --- a/specification/modules/cas_login.rst +++ b/specification/modules/cas_login.rst @@ -33,7 +33,7 @@ An overview of the process, as used in Matrix, is as follows: 4. The CAS server responds to the user's browser with a redirect back to the |/login/cas/ticket|_ endpoint on the homeserver, which the browser - follows. A 'ticket' identifier is passed as a query-parameter in the + follows. A 'ticket' identifier is passed as a query parameter in the redirect. 5. The homeserver receives the ticket ID from the user's browser, and makes a @@ -41,7 +41,7 @@ An overview of the process, as used in Matrix, is as follows: 6. Having validated the ticket, the homeserver responds to the browser with a third HTTP redirect, back to the Matrix client application. A login token - is passed as a query-parameter in the redirect. + is passed as a query parameter in the redirect. 7. The Matrix client receives the login token and passes it to the |/login|_ API. @@ -77,15 +77,16 @@ Handling the redirect endpoint When responding to the ``/login/cas/redirect`` endpoint, the server must generate a URI for the CAS login page. The server should take the base CAS URI -described above, and add a ``service`` query-parameter. This parameter MUST be +described above, and add a ``service`` query parameter. This parameter MUST be the URI of the ``/login/cas/ticket`` endpoint, including the ``redirectUrl`` -query-parameter. Because the homeserver may not know its base URI, this may +query parameter. Because the homeserver may not know its base URI, this may also require manual configuration. .. TODO-spec: It might be nice if the server did some validation of the ``redirectUrl`` - parameter, so that we could give more meaningful errors in the case of + parameter, so that we could check that aren't going to redirect to a non-TLS + endpoint, and to give more meaningful errors in the case of faulty/poorly-configured clients. Handling the authentication endpoint @@ -97,7 +98,7 @@ check for certain user attributes in the response. Any required attributes should be configured by the server administrator. Once the ticket has been validated, the server MUST map the CAS ``user_id`` -to a valid `Matrix user idenitifier <../intro.html#user-identifiers>`_. The +to a valid `Matrix user identifier <../intro.html#user-identifiers>`_. The guidance in `Mapping from other character sets <../intro.html#mapping-from-other-character-sets>`_ may be useful. From 0248afe6accdee6ea36035c59538f30c36b3375b Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 9 Aug 2016 16:28:29 +0100 Subject: [PATCH 5/6] login with invalid token gives a 403 --- specification/client_server_api.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/specification/client_server_api.rst b/specification/client_server_api.rst index d47bb093..fb140c22 100644 --- a/specification/client_server_api.rst +++ b/specification/client_server_api.rst @@ -552,7 +552,7 @@ explicitly, as follows: } 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``. To log in using a login token, a client should submit an auth dict as follows: @@ -564,7 +564,8 @@ To log in using a login token, a client should submit an auth dict as follows: } As with `token-based`_ interactive login, the ``token`` must be a macroon with -a caveat which includes the user id. +a caveat which includes the user id. In the case that the token is not valid, the +homeserver must respond with ``403 Forbidden`` and an error code of ``M_FORBIDDEN``. {{login_cs_http_api}} From 07fa64d73d2fe83ac9571d842e7fa0d10a307d74 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 9 Aug 2016 16:46:49 +0100 Subject: [PATCH 6/6] Update changelog --- changelogs/client_server.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/changelogs/client_server.rst b/changelogs/client_server.rst index 8d903cd0..40d5d764 100644 --- a/changelogs/client_server.rst +++ b/changelogs/client_server.rst @@ -14,6 +14,8 @@ - Add ``filename`` parameter to ``POST /_matrix/media/r0/upload`` (`#364 `_). + - Document CAS-based client login and the use of ``m.login.token`` in + ``/login`` (`#367 `_). r0.2.0