From ef5d3b9f302982f04f1decad72c0cdaefbc398e4 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 28 Aug 2019 15:12:24 -0600 Subject: [PATCH 1/8] Correct token reference in MSC2140 --- proposals/2140-terms-of-service-2.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/2140-terms-of-service-2.md b/proposals/2140-terms-of-service-2.md index 9f96a00b5..e5bcd0ac8 100644 --- a/proposals/2140-terms-of-service-2.md +++ b/proposals/2140-terms-of-service-2.md @@ -170,7 +170,7 @@ This endpoint does *not* require authentication. #### `POST $prefix/terms`: Requests to this endpoint have a single key, `user_accepts` whose value is -a list of URLs (given by the `url` field in the GET response) of documents that +a list of URLs (given by the `url` field in the GET response) of documents that the user has agreed to: ```json @@ -269,7 +269,7 @@ A client uses this client/server API endpoint to request that the Homeserver removes the given 3PID from the given Identity Server, or all Identity Servers. Takes the same parameters as `POST /_matrix/client/r0/account/3pid/delete`, ie. `id_server`, `medium`, -`address` and the newly added `is_token`. +`address` and the newly added `id_access_token`. Returns the same as `POST /_matrix/client/r0/account/3pid/delete`. From e40d9e296d098a5a476efaa5e0f845418c017333 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 28 Aug 2019 15:12:47 -0600 Subject: [PATCH 2/8] Split OpenID token info out verbatim --- .../definitions/openid_token.yaml | 36 +++++++++++++++++++ api/client-server/openid.yaml | 23 +----------- 2 files changed, 37 insertions(+), 22 deletions(-) create mode 100644 api/client-server/definitions/openid_token.yaml diff --git a/api/client-server/definitions/openid_token.yaml b/api/client-server/definitions/openid_token.yaml new file mode 100644 index 000000000..8c84c26fa --- /dev/null +++ b/api/client-server/definitions/openid_token.yaml @@ -0,0 +1,36 @@ +# Copyright 2018 New Vector Ltd +# Copyright 2019 The Matrix.org Foundation C.I.C. +# +# 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. +type: object +properties: + access_token: + type: string + description: |- + An access token the consumer may use to verify the identity of + the person who generated the token. This is given to the federation + API ``GET /openid/userinfo``. + token_type: + type: string + description: The string ``Bearer``. + matrix_server_name: + type: string + description: |- + The homeserver domain the consumer should use when attempting to + verify the user's identity. + expires_in: + type: integer + description: |- + The number of seconds before this token expires and a new one must + be generated. +required: ['access_token', 'token_type', 'matrix_server_name', 'expires_in'] diff --git a/api/client-server/openid.yaml b/api/client-server/openid.yaml index cb982fb32..01fdf68f8 100644 --- a/api/client-server/openid.yaml +++ b/api/client-server/openid.yaml @@ -73,28 +73,7 @@ paths: "expires_in": 3600, } schema: - type: object - properties: - access_token: - type: string - description: |- - An access token the consumer may use to verify the identity of - the person who generated the token. This is given to the federation - API ``GET /openid/userinfo``. - token_type: - type: string - description: The string ``Bearer``. - matrix_server_name: - type: string - description: |- - The homeserver domain the consumer should use when attempting to - verify the user's identity. - expires_in: - type: integer - description: |- - The number of seconds before this token expires and a new one must - be generated. - required: ['access_token', 'token_type', 'matrix_server_name', 'expires_in'] + $ref: "definitions/openid_token.yaml" 429: description: This request was rate-limited. schema: From 4d0ea641211e2ea0292a1bc12392b955c903f285 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 28 Aug 2019 15:39:49 -0600 Subject: [PATCH 3/8] Define authentication, ripping off the client-server API description --- .../definitions/openid_token.yaml | 2 +- api/identity/v2_auth.yaml | 109 ++++++++++++++++++ specification/identity_service_api.rst | 29 ++++- 3 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 api/identity/v2_auth.yaml diff --git a/api/client-server/definitions/openid_token.yaml b/api/client-server/definitions/openid_token.yaml index 8c84c26fa..b50fcd54c 100644 --- a/api/client-server/definitions/openid_token.yaml +++ b/api/client-server/definitions/openid_token.yaml @@ -19,7 +19,7 @@ properties: description: |- An access token the consumer may use to verify the identity of the person who generated the token. This is given to the federation - API ``GET /openid/userinfo``. + API ``GET /openid/userinfo`` to verify the user's identity. token_type: type: string description: The string ``Bearer``. diff --git a/api/identity/v2_auth.yaml b/api/identity/v2_auth.yaml new file mode 100644 index 000000000..16864b8e5 --- /dev/null +++ b/api/identity/v2_auth.yaml @@ -0,0 +1,109 @@ +# Copyright 2019 The Matrix.org Foundation C.I.C. +# +# 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 Identity Service Authentication API" + version: "2.0.0" +host: localhost:8090 +schemes: + - https +basePath: /_matrix/identity/v2 +consumes: + - application/json +produces: + - application/json +securityDefinitions: + $ref: definitions/security.yaml +paths: + "/account/register": + post: + summary: Exchanges an OpenID token for an access token. + description: |- + Exchanges an OpenID token from the homeserver for an access token to + access the identity server. The request body is the same as the values + returned by ``/openid/request_token`` in the Client-Server API. + operationId: registerAccount + parameters: + - in: body + name: body + schema: + $ref: "../client-server/definitions/openid_token.yaml" + responses: + 200: + description: |- + A token which can be used to authenticate future requests to the + identity server. + examples: + application/json: { + "token": "abc123_OpaqueString" + } + schema: + type: object + properties: + token: + type: string + description: |- + An opaque string representing the token to authenticate future + requests to the identity server with. + required: ['token'] + "/account": + get: + summary: Gets account holder information for a given token. + description: |- + Gets information about what user owns the access token used in the request. + operationId: getAccount + security: + - accessToken: [] + parameters: [] + responses: + 200: + description: The token holder's information. + examples: + application/json: { + "user_id": "@alice:example.org" + } + schema: + type: object + properties: + user_id: + type: string + description: The user ID which registered the token. + required: ['user_id'] + "/account/logout": + post: + summary: Logs out an access token, rendering it unusable. + description: |- + Logs out the access token, preventing it from being used to authenticate + future requests to the server. + operationId: logout + security: + - accessToken: [] + parameters: [] + responses: + 200: + description: The token was successfully logged out. + examples: + application/json: {} + schema: + type: object + 401: + description: |- + The token is not registered or is otherwise unknown to the server. + examples: + application/json: { + "errcode": "M_UNKNOWN_TOKEN", + "error": "Unrecognised access token" + } + schema: + $ref: "../client-server/definitions/errors/error.yaml" diff --git a/specification/identity_service_api.rst b/specification/identity_service_api.rst index f8211f70d..455e10b49 100644 --- a/specification/identity_service_api.rst +++ b/specification/identity_service_api.rst @@ -57,8 +57,6 @@ The following other versions are also available, in reverse chronological order: General principles ------------------ -.. TODO: TravisR - Define auth for IS v2 API in a future PR - The purpose of an identity server is to validate, store, and answer questions about the identities of users. In particular, it stores associations of the form "identifier X represents the same user as identifier Y", where identities may @@ -173,6 +171,33 @@ to be returned by servers on all requests are:: Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization +Authentication +-------------- + +Most ``v2`` endpoints in the Identity Service API require authentication in order +to ensure that the requesting user has accepted all relevant policies and is otherwise +permitted to make the request. The ``v1`` API (currently deprecated) does not require +this authentication, however using ``v1`` is strongly discouraged as it will be removed +in a future release. + +Identity Servers use a scheme similar to the Client-Server API's concept of access +tokens to authenticate users. The access tokens provided by an Identity Server cannot +be used to authenticate Client-Server API requests. + +An access token is provided to an endpoint in one of two ways: + +1. Via a query string parameter, ``access_token=TheTokenHere``. +2. Via a request header, ``Authorization: Bearer TheTokenHere``. + +Clients are encouraged to the use the ``Authorization`` header where possible to prevent +the access token being leaked in access/HTTP logs. The query string should only be used +in cases where the ``Authorization`` header is inaccessible for the client. + +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 ``M_UNKNOWN_TOKEN`` respectively. + +{{v2_auth_is_http_api}} + Status check ------------ From 0408373cf93bed99ab8422b84467da539b258b31 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 28 Aug 2019 15:43:47 -0600 Subject: [PATCH 4/8] Litter the client-server API with id_access_token --- api/client-server/administrative_contact.yaml | 11 ++++++++++- api/client-server/create_room.yaml | 5 ++++- .../definitions/request_email_validation.yaml | 5 ++++- .../definitions/request_msisdn_validation.yaml | 5 ++++- api/client-server/registration.yaml | 5 +++++ api/client-server/third_party_membership.yaml | 6 +++++- specification/client_server_api.rst | 6 ++++-- 7 files changed, 36 insertions(+), 7 deletions(-) diff --git a/api/client-server/administrative_contact.yaml b/api/client-server/administrative_contact.yaml index 0e93e4cd7..30153bb01 100644 --- a/api/client-server/administrative_contact.yaml +++ b/api/client-server/administrative_contact.yaml @@ -110,10 +110,13 @@ paths: id_server: type: string description: The identity server to use. + id_access_token: + type: string + description: An access token previously registered with the identity server. sid: type: string description: The session identifier given by the identity server. - required: ["client_secret", "id_server", "sid"] + required: ["client_secret", "id_server", "id_access_token", "sid"] bind: type: boolean description: |- @@ -125,6 +128,7 @@ paths: example: { "three_pid_creds": { "id_server": "matrix.org", + "id_access_token": "abc123_OpaqueString", "sid": "abc123987", "client_secret": "d0n'tT3ll" }, @@ -189,6 +193,11 @@ paths: homeserver does not know the original ``id_server``, it MUST return a ``id_server_unbind_result`` of ``no-support``. example: "example.org" + id_access_token: + type: string + description: |- + An access token previously registered with the identity server. Required + if an ``id_server`` is specified. medium: type: string description: The medium of the third party identifier being removed. diff --git a/api/client-server/create_room.yaml b/api/client-server/create_room.yaml index bce61aad3..d7a29d995 100644 --- a/api/client-server/create_room.yaml +++ b/api/client-server/create_room.yaml @@ -139,6 +139,9 @@ paths: id_server: type: string description: The hostname+port of the identity server which should be used for third party identifier lookups. + id_access_token: + type: string + description: An access token previously registered with the identity server. medium: type: string # TODO: Link to Identity Service spec when it eixsts @@ -146,7 +149,7 @@ paths: address: type: string description: The invitee's third party identifier. - required: ["id_server", "medium", "address"] + required: ["id_server", "id_access_token", "medium", "address"] room_version: type: string description: |- diff --git a/api/client-server/definitions/request_email_validation.yaml b/api/client-server/definitions/request_email_validation.yaml index 15bc5b3ae..63e3ee215 100644 --- a/api/client-server/definitions/request_email_validation.yaml +++ b/api/client-server/definitions/request_email_validation.yaml @@ -23,4 +23,7 @@ allOf: include a port. This parameter is ignored when the homeserver handles 3PID verification. example: "id.example.com" - required: ["id_server"] + id_access_token: + type: string + description: An access token previously registered with the identity server. + required: ["id_server", "id_access_token"] diff --git a/api/client-server/definitions/request_msisdn_validation.yaml b/api/client-server/definitions/request_msisdn_validation.yaml index 370a10cca..435136288 100644 --- a/api/client-server/definitions/request_msisdn_validation.yaml +++ b/api/client-server/definitions/request_msisdn_validation.yaml @@ -23,4 +23,7 @@ allOf: include a port. This parameter is ignored when the homeserver handles 3PID verification. example: "id.example.com" - required: ["id_server"] + id_access_token: + type: string + description: An access token previously registered with the identity server. + required: ["id_server", "id_access_token"] diff --git a/api/client-server/registration.yaml b/api/client-server/registration.yaml index 71177d0c6..a747e38b9 100644 --- a/api/client-server/registration.yaml +++ b/api/client-server/registration.yaml @@ -542,6 +542,11 @@ paths: it must return an ``id_server_unbind_result`` of ``no-support``. example: "example.org" + id_access_token: + type: string + description: |- + An access token previously registered with the identity server. Required if an + ``id_server`` is supplied. responses: 200: description: The account has been deactivated. diff --git a/api/client-server/third_party_membership.yaml b/api/client-server/third_party_membership.yaml index 077e1f6af..075cd34be 100644 --- a/api/client-server/third_party_membership.yaml +++ b/api/client-server/third_party_membership.yaml @@ -92,6 +92,7 @@ paths: type: object example: { "id_server": "matrix.org", + "id_access_token": "abc123_OpaqueString", "medium": "email", "address": "cheeky@monkey.com" } @@ -99,6 +100,9 @@ paths: id_server: type: string description: The hostname+port of the identity server which should be used for third party identifier lookups. + id_access_token: + type: string + description: An access token previously registered with the identity server. medium: type: string # TODO: Link to Identity Service spec when it eixsts @@ -106,7 +110,7 @@ paths: address: type: string description: The invitee's third party identifier. - required: ["id_server", "medium", "address"] + required: ["id_server", "id_access_token", "medium", "address"] responses: 200: description: The user has been invited to join the room. diff --git a/specification/client_server_api.rst b/specification/client_server_api.rst index 916604a37..5ff710d14 100644 --- a/specification/client_server_api.rst +++ b/specification/client_server_api.rst @@ -802,7 +802,8 @@ To use this authentication type, clients should submit an auth dict as follows: { "sid": "", "client_secret": "", - "id_server": "" + "id_server": "", + "id_access_token": "" } ], "session": "" @@ -830,7 +831,8 @@ To use this authentication type, clients should submit an auth dict as follows: { "sid": "", "client_secret": "", - "id_server": "" + "id_server": "", + "id_access_token": "" } ], "session": "" From aa98137514f121c55a1e4282bb50835fb85b8e82 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 28 Aug 2019 15:45:28 -0600 Subject: [PATCH 5/8] Add changelog --- changelogs/client_server/newsfragments/2255.breaking | 1 + changelogs/identity_service/newsfragments/2255.new | 1 + 2 files changed, 2 insertions(+) create mode 100644 changelogs/client_server/newsfragments/2255.breaking create mode 100644 changelogs/identity_service/newsfragments/2255.new diff --git a/changelogs/client_server/newsfragments/2255.breaking b/changelogs/client_server/newsfragments/2255.breaking new file mode 100644 index 000000000..f9c8c6e19 --- /dev/null +++ b/changelogs/client_server/newsfragments/2255.breaking @@ -0,0 +1 @@ +Add a required ``id_access_token`` to many places which require an ``id_server`` parameter. diff --git a/changelogs/identity_service/newsfragments/2255.new b/changelogs/identity_service/newsfragments/2255.new new file mode 100644 index 000000000..fcb6ba88e --- /dev/null +++ b/changelogs/identity_service/newsfragments/2255.new @@ -0,0 +1 @@ +Add ``/account``, ``/account/register``, and ``/account/logout`` to authenticate with the identity server. From fad99743836862d6651816de0a23d3437fd0987b Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 28 Aug 2019 15:40:02 -0600 Subject: [PATCH 6/8] Add missed changelog from prior PR --- changelogs/identity_service/newsfragments/2254.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/identity_service/newsfragments/2254.feature diff --git a/changelogs/identity_service/newsfragments/2254.feature b/changelogs/identity_service/newsfragments/2254.feature new file mode 100644 index 000000000..089d01fe8 --- /dev/null +++ b/changelogs/identity_service/newsfragments/2254.feature @@ -0,0 +1 @@ +Deprecate the v1 API in favour of an authenticated v2 API. From 91f862d9e8c34ec2b85be955975ae44b41351249 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 28 Aug 2019 20:57:07 -0600 Subject: [PATCH 7/8] Use the right error code for 401 errors --- specification/identity_service_api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/identity_service_api.rst b/specification/identity_service_api.rst index 455e10b49..4afac6ef6 100644 --- a/specification/identity_service_api.rst +++ b/specification/identity_service_api.rst @@ -194,7 +194,7 @@ the access token being leaked in access/HTTP logs. The query string should only in cases where the ``Authorization`` header is inaccessible for the client. 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 ``M_UNKNOWN_TOKEN`` respectively. +status of 401 and the error code ``M_UNAUTHORIZED``. {{v2_auth_is_http_api}} From 001c51a7401f646d765c07d92593913d90a2ba47 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 Sep 2019 15:09:59 -0600 Subject: [PATCH 8/8] /3pid/delete and /deactivate don't take an id_access_token --- api/client-server/administrative_contact.yaml | 9 ++++----- api/client-server/registration.yaml | 9 ++++----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/api/client-server/administrative_contact.yaml b/api/client-server/administrative_contact.yaml index 30153bb01..4b8e1d631 100644 --- a/api/client-server/administrative_contact.yaml +++ b/api/client-server/administrative_contact.yaml @@ -176,6 +176,10 @@ paths: description: |- Removes a third party identifier from the user's account. This might not cause an unbind of the identifier from the identity server. + + Unlike other endpoints, this endpoint does not take an ``id_access_token`` + parameter because the homeserver is expected to sign the request to the + identity server instead. operationId: delete3pidFromAccount security: - accessToken: [] @@ -193,11 +197,6 @@ paths: homeserver does not know the original ``id_server``, it MUST return a ``id_server_unbind_result`` of ``no-support``. example: "example.org" - id_access_token: - type: string - description: |- - An access token previously registered with the identity server. Required - if an ``id_server`` is specified. medium: type: string description: The medium of the third party identifier being removed. diff --git a/api/client-server/registration.yaml b/api/client-server/registration.yaml index a747e38b9..596dfe348 100644 --- a/api/client-server/registration.yaml +++ b/api/client-server/registration.yaml @@ -519,6 +519,10 @@ paths: The homeserver may change the flows available depending on whether a valid access token is provided. + + Unlike other endpoints, this endpoint does not take an ``id_access_token`` + parameter because the homeserver is expected to sign the request to the + identity server instead. security: - accessToken: [] operationId: deactivateAccount @@ -542,11 +546,6 @@ paths: it must return an ``id_server_unbind_result`` of ``no-support``. example: "example.org" - id_access_token: - type: string - description: |- - An access token previously registered with the identity server. Required if an - ``id_server`` is supplied. responses: 200: description: The account has been deactivated.