diff --git a/api/client-server/definitions/client_device.yaml b/api/client-server/definitions/client_device.yaml new file mode 100644 index 00000000..6dc3abf3 --- /dev/null +++ b/api/client-server/definitions/client_device.yaml @@ -0,0 +1,44 @@ +# 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. + +type: object +description: A client device +title: Device +properties: + device_id: + type: string + description: Identifier of this device. + example: QBUAZIFURK + display_name: + type: string + description: |- + Display name set by the user for this device. Absent if no name has been + set. + example: android + last_seen_ip: + type: string + description: |- + The IP address where this device was last seen. (May be a few minutes out + of date, for efficiency reasons). + example: 1.2.3.4 + last_seen_ts: + type: integer + format: int64 + description: |- + The timestamp (in milliseconds since the unix epoch) when this devices + was last seen. (May be a few minutes out of date, for efficiency + reasons). + example: 1474491775024 +required: + - device_id diff --git a/api/client-server/device_management.yaml b/api/client-server/device_management.yaml new file mode 100644 index 00000000..ddfbad85 --- /dev/null +++ b/api/client-server/device_management.yaml @@ -0,0 +1,177 @@ +# 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 device management API" + version: "1.0.0" +host: localhost:8008 +schemes: + - https + - http +basePath: /_matrix/client/%CLIENT_MAJOR_VERSION% +consumes: + - application/json +produces: + - application/json +securityDefinitions: + $ref: definitions/security.yaml +paths: + "/devices": + get: + summary: List registered devices for the current user + description: |- + Gets information about all devices for the current user. + security: + - accessToken: [] + responses: + 200: + description: Device information + schema: + type: object + properties: + devices: + type: array + description: A list of all registered devices for this user. + items: + type: object + allOf: + - $ref: "definitions/client_device.yaml" + examples: + application/json: |- + { + "devices": [ + { + "device_id": "QBUAZIFURK", + "display_name": "android", + "last_seen_ip": "1.2.3.4", + "last_seen_ts": 1474491775024 + } + ] + } + tags: + - Device management + "/devices/{deviceId}": + get: + summary: Get a single device + description: |- + Gets information on a single device, by device id. + security: + - accessToken: [] + parameters: + - in: path + type: string + name: deviceId + description: The device to retrieve. + required: true + x-example: "QBUAZIFURK" + responses: + 200: + description: Device information + schema: + type: object + allOf: + - $ref: "definitions/client_device.yaml" + examples: + application/json: |- + { + "device_id": "QBUAZIFURK", + "display_name": "android", + "last_seen_ip": "1.2.3.4", + "last_seen_ts": 1474491775024 + } + 404: + description: The current user has no device with the given ID. + tags: + - Device management + put: + summary: Update a device + description: |- + Updates the metadata on the given device. + security: + - accessToken: [] + parameters: + - in: path + type: string + name: deviceId + description: The device to update. + required: true + x-example: "QBUAZIFURK" + - in: body + name: body + required: true + description: New information for the device. + schema: + type: object + properties: + display_name: + type: string + description: |- + The new display name for this device. If not given, the + display name is unchanged. + example: My other phone + responses: + 200: + description: The device was successfully updated. + examples: + application/json: |- + {} + schema: + type: object # empty json object + 404: + description: The current user has no device with the given ID. + tags: + - Device management + delete: + summary: Delete a device + description: |- + This API endpoint uses the `User-Interactive Authentication API`_. + + Deletes the given device, and invalidates any access token assoicated with it. + security: + - accessToken: [] + parameters: + - in: path + type: string + name: deviceId + description: The device to delete. + required: true + x-example: "QBUAZIFURK" + - in: body + name: body + schema: + type: object + properties: + auth: + description: |- + Additional authentication information for the + user-interactive authentication API. + "$ref": "definitions/auth_data.yaml" + responses: + 200: + description: |- + The device was successfully removed, or had been removed + previously. + schema: + type: object + examples: + application/json: |- + {} + 401: + description: |- + The homeserver requires additional authentication information. + schema: + "$ref": "definitions/auth_response.yaml" + tags: + - Device management diff --git a/api/client-server/login.yaml b/api/client-server/login.yaml index 7731f507..8c0282be 100644 --- a/api/client-server/login.yaml +++ b/api/client-server/login.yaml @@ -33,6 +33,14 @@ paths: description: |- Authenticates the user, and issues an access token they can use to authorize themself in subsequent requests. + + If the client does not supply a ``device_id``, the server must + auto-generate one. + + The returned access token must be associated with the ``device_id`` + supplied by the client or generated by the server. The server may + invalidate any access token previously associated with that device. See + `Relationship between access tokens and devices`_. parameters: - in: body name: body @@ -42,7 +50,8 @@ paths: { "type": "m.login.password", "user": "cheeky_monkey", - "password": "ilovebananas" + "password": "ilovebananas", + "initial_device_display_name": "Jungle Phone" } properties: type: @@ -67,6 +76,17 @@ paths: type: string description: |- Required when ``type`` is ``m.login.token``. The login token. + device_id: + type: string + description: |- + ID of the client device. If this does not correspond to a + known client device, a new device will be created. The server + will auto-generate a device_id if this is not specified. + initial_device_display_name: + type: string + description: |- + A display name to assign to the newly-created device. Ignored + if ``device_id`` corresponds to a known device. required: ["type"] responses: @@ -77,7 +97,8 @@ paths: { "user_id": "@cheeky_monkey:matrix.org", "access_token": "abc123", - "home_server": "matrix.org" + "home_server": "matrix.org", + "device_id": "GHTYAJCE" } schema: type: object @@ -93,6 +114,11 @@ paths: home_server: type: string description: The hostname of the homeserver on which the account has been registered. + device_id: + type: string + description: |- + ID of the logged-in device. Will be the same as the + corresponding parameter in the request, if one was specified. 400: description: |- Part of the request was invalid. For example, the login type may not be recognised. diff --git a/api/client-server/registration.yaml b/api/client-server/registration.yaml index 8145824e..756004c1 100644 --- a/api/client-server/registration.yaml +++ b/api/client-server/registration.yaml @@ -42,6 +42,13 @@ paths: If registration is successful, this endpoint will issue an access token the client can use to authorize itself in subsequent requests. + If the client does not supply a ``device_id``, the server must + auto-generate one. + + The returned access token must be associated with the ``device_id`` + supplied by the client or generated by the server. The server may + invalidate any access token previously associated with that device. See + `Relationship between access tokens and devices`_. parameters: - in: query name: kind @@ -84,7 +91,19 @@ paths: type: string description: The desired password for the account. example: ilovebananas - required: ["password"] + device_id: + type: string + description: |- + ID of the client device. If this does not correspond to a + known client device, a new device will be created. The server + will auto-generate a device_id if this is not specified. + example: GHTYAJCE + initial_device_display_name: + type: string + description: |- + A display name to assign to the newly-created device. Ignored + if ``device_id`` corresponds to a known device. + example: Jungle Phone responses: 200: description: The account has been registered. @@ -93,7 +112,8 @@ paths: { "user_id": "@cheeky_monkey:matrix.org", "access_token": "abc123", - "home_server": "matrix.org" + "home_server": "matrix.org", + "device_id": "GHTYAJCE" } schema: type: object @@ -109,6 +129,11 @@ paths: home_server: type: string description: The hostname of the homeserver on which the account has been registered. + device_id: + type: string + description: |- + ID of the registered device. Will be the same as the + corresponding parameter in the request, if one was specified. 400: description: |- Part of the request was invalid. This may include one of the following error codes: diff --git a/changelogs/client_server.rst b/changelogs/client_server.rst index a22f3b7f..875d5ce1 100644 --- a/changelogs/client_server.rst +++ b/changelogs/client_server.rst @@ -32,8 +32,10 @@ (`#390 `_). - Add ``filter`` optional query param to ``/messages`` (`#390 `_). - - Add "Send-to-Device messaging" module + - Add 'Send-to-Device messaging' module (`#386 `_). + - Add 'Device management' module + (`#402 `_). - Require that User-Interactive auth fallback pages call ``window.postMessage`` to notify apps of completion (`#398 `_). diff --git a/specification/client_server_api.rst b/specification/client_server_api.rst index a5194a1d..588f3fb0 100644 --- a/specification/client_server_api.rst +++ b/specification/client_server_api.rst @@ -185,6 +185,21 @@ return with a status of 401 and the error code, ``M_MISSING_TOKEN`` or to choose an appropriate format. Server implementors may like to investigate `macaroons `_. +Relationship between access tokens and devices +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Client `devices`_ are closely related to access tokens. Matrix servers should +record which device each access token is assigned to, so that subsequent +requests can be handled correctly. + +By default, the `Login`_ and `Registration`_ processes auto-generate a new +``device_id``. A client is also free to generate its own ``device_id`` or, +provided the user remains the same, reuse a device: in ether case the client +should pass the ``device_id`` in the request body. If the client sets the +``device_id``, the server will invalidate any access token previously assigned +to that device. There is therefore at most one active access token assigned to +each device at any one time. + User-Interactive Authentication API ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1366,6 +1381,7 @@ have to wait in milliseconds before they can try again. .. References .. _`macaroon`: http://research.google.com/pubs/pub41892.html +.. _`devices`: ../intro.html#devices .. Links through the external API docs are below .. ============================================= diff --git a/specification/intro.rst b/specification/intro.rst index 0ecfdec5..5d0587f2 100644 --- a/specification/intro.rst +++ b/specification/intro.rst @@ -160,6 +160,35 @@ allocated the account and has the form:: See the `Identifier Grammar`_ section for full details of the structure of user IDs. + +Devices +~~~~~~~ + +The Matrix specification has a particular meaning for the term "device". As a +user, I might have several devices: a desktop client, some web browsers, an +Android device, an iPhone, etc. They broadly relate to a real device in the +physical world, but you might have several browsers on a physical device, or +several Matrix client applications on a mobile device, each of which would be +its own device. + +Devices are used primarily to manage the keys used for end-to-end encryption +(each device gets its own copy of the decryption keys), but they also help +users manage their access - for instance, by revoking access to particular +devices. + +When a user first uses a client, it registers itself as a new device. The +longevity of devices might depend on the type of client. A web client will +probably drop all of its state on logout, and create a new device every time +you log in, to ensure that cryptography keys are not leaked to a new user. In +a mobile client, it might be acceptable to reuse the device if a login session +expires, provided the user is the same. + +Devices are identified by a ``device_id``, which is unique within the scope of +a given user. + +A user may assign a human-readable display name to a device, to help them +manage their devices. + Events ~~~~~~ diff --git a/specification/modules/device_management.rst b/specification/modules/device_management.rst new file mode 100644 index 00000000..3f9c8452 --- /dev/null +++ b/specification/modules/device_management.rst @@ -0,0 +1,41 @@ +.. 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. + +Device Management +================= + +.. _module:device-management: + +This module provides a means for a user to manage their `devices`_. + +Client behaviour +---------------- +Clients that implement this module should offer the user a list of registered +devices, as well as the means to update their display names. Clients should +also allow users to delete disused devices. + +{{device_management_cs_http_api}} + +Security considerations +----------------------- + +Deleting devices has security implications: it invalidates the access_token +assigned to the device, so an attacker could use it to log out the real user +(and do it repeatedly every time the real user tries to log in to block the +attacker). Servers should require additional authentication beyond the access +token when deleting devices (for example, requiring that the user resubmit +their password). + +The display names of devices are publicly visible. Clients should consider +advising the user of this. diff --git a/specification/targets.yaml b/specification/targets.yaml index b90201d1..7d415fb4 100644 --- a/specification/targets.yaml +++ b/specification/targets.yaml @@ -44,6 +44,7 @@ groups: # reusable blobs of files when prefixed with 'group:' - modules/presence.rst - modules/content_repo.rst - modules/send_to_device.rst + - modules/device_management.rst - modules/end_to_end_encryption.rst - modules/history_visibility.rst - modules/push.rst