From 98d85cf421f23233bbfde4232d78634836281cae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Wed, 8 May 2024 02:50:36 +0200 Subject: [PATCH 1/3] Add support for rendering string formats (#1814) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kévin Commaille --- .../internal/newsfragments/1814.clarification | 1 + data/custom-formats.yaml | 5 +++ .../partials/openapi/render-object-table.html | 32 +++++++++++++++++-- 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 changelogs/internal/newsfragments/1814.clarification diff --git a/changelogs/internal/newsfragments/1814.clarification b/changelogs/internal/newsfragments/1814.clarification new file mode 100644 index 000000000..a540ea7e0 --- /dev/null +++ b/changelogs/internal/newsfragments/1814.clarification @@ -0,0 +1 @@ +Add support for rendering string formats. diff --git a/data/custom-formats.yaml b/data/custom-formats.yaml index f0001c80d..5da7e6abb 100644 --- a/data/custom-formats.yaml +++ b/data/custom-formats.yaml @@ -31,3 +31,8 @@ mx-event-id: title: Event ID url: /appendices#event-ids # regex: "^\\$" + +uri: + title: URI + url: http://tools.ietf.org/html/rfc3986 + # no regex diff --git a/layouts/partials/openapi/render-object-table.html b/layouts/partials/openapi/render-object-table.html index 72ea5a8ae..d2b09acb6 100644 --- a/layouts/partials/openapi/render-object-table.html +++ b/layouts/partials/openapi/render-object-table.html @@ -128,6 +128,8 @@ * `anchor`: optional HTML element id for the target type, which will be used to link to it. + * `format`: optional string for the format of the type, used for strings. + */}} {{ define "partials/property-type" }} {{ $type := "" }} @@ -143,6 +145,15 @@ {{ $items := .items }} {{ $inner_type := partial "property-type" $items }} {{ $type = delimit (slice "[" $inner_type "]") "" }} + {{ else if eq .type "string" }} + {{ $type = "string" }} + + {{/* If the string uses a known format, use it. */}} + {{ with .format }} + {{ with partial "custom-format" . }} + {{ $type = . }} + {{ end }} + {{ end }} {{ else if or (reflect.IsSlice .type) .oneOf }} {{/* It's legal to specify an array of types. @@ -167,7 +178,7 @@ {{ $type = delimit $types "|" }} {{ else }} - {{/* A simple type like string or boolean */}} + {{/* A simple type like integer or boolean */}} {{ $type = (htmlEscape .type) }} {{ end }} @@ -241,8 +252,8 @@ {{ range $formatId, $formatType := $formatMap.Values }} {{ $formatKey := "string" }} {{ if ne $formatId "string" }} - {{ with index site.Data "custom-formats" $formatId }} - {{ $formatKey = printf "%s" (htmlEscape .url) (htmlEscape .title) }} + {{ with partial "custom-format" $formatId }} + {{ $formatKey = . }} {{ else }} {{ errorf "Unsupported value for `x-pattern-format`: %s" $formatId }} {{ end }} @@ -290,3 +301,18 @@ {{ if (index .property "x-addedInMatrixVersion") }}{{ partial "added-in" (dict "v" (index .property "x-addedInMatrixVersion")) }}{{ end -}} {{ if (index .property "x-changedInMatrixVersion") }}{{ partial "changed-in" (dict "changes_dict" (index .property "x-changedInMatrixVersion")) }}{{ end -}} {{ end }} + + +{{/* + Computes the type to display for a string format, given the identifier of + the format as a string. +*/}} +{{ define "partials/custom-format" }} + {{ $customFormat := "" }} + + {{ with index site.Data "custom-formats" . }} + {{ $customFormat = printf "%s" (htmlEscape .url) (htmlEscape .title) }} + {{ end }} + + {{ return $customFormat }} +{{ end }} From f4b34ba962b28a9372090759a74ca587b4774a9b Mon Sep 17 00:00:00 2001 From: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com> Date: Wed, 8 May 2024 13:22:26 +0100 Subject: [PATCH 2/3] Note that whitespace around `Authorization` param commas is allowed (#1818) --- .../server_server/newsfragments/1818.clarification | 1 + content/server-server-api.md | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) create mode 100644 changelogs/server_server/newsfragments/1818.clarification diff --git a/changelogs/server_server/newsfragments/1818.clarification b/changelogs/server_server/newsfragments/1818.clarification new file mode 100644 index 000000000..8c50b6ace --- /dev/null +++ b/changelogs/server_server/newsfragments/1818.clarification @@ -0,0 +1 @@ +Clarify that whitespace around commas is allowed in the `X-Matrix` `Authorization` header value params list. \ No newline at end of file diff --git a/content/server-server-api.md b/content/server-server-api.md index fb1b06f4e..e92d871c5 100644 --- a/content/server-server-api.md +++ b/content/server-server-api.md @@ -350,9 +350,10 @@ def authorization_headers(origin_name, origin_signing_key, The format of the Authorization header is given in [RFC 7235](https://datatracker.ietf.org/doc/html/rfc7235#section-2.1). In -summary, the header begins with authorization scheme `X-Matrix`, followed by -one or more spaces, followed by a comma-separated list of parameters written as -name=value pairs. The names are case insensitive and order does not matter. The +summary, the header begins with authorization scheme `X-Matrix`, followed by one +or more spaces, followed by a comma-separated list of parameters written as +name=value pairs. Zero or more spaces and tabs around each comma are allowed. +The names are case insensitive and order does not matter. The values must be enclosed in quotes if they contain characters that are not allowed in `token`s, as defined in [RFC 7230](https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.6); if a @@ -363,8 +364,9 @@ replaced by the character that follows the backslash. For compatibility with older servers, the sender should - only include one space after `X-Matrix`, -- only use lower-case names, and -- avoid using backslashes in parameter values. +- only use lower-case names, +- avoid using backslashes in parameter values, and +- avoid including whitespace around the commas between name=value pairs. For compatibility with older servers, the recipient should allow colons to be included in values without requiring the value to be enclosed in quotes. From df1e799c517a9bbdcc96e3f381fd6116d4136040 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Wed, 8 May 2024 14:51:18 +0100 Subject: [PATCH 3/3] Spec terms of service at registration (MSC1692) (#1812) Spec for matrix-org/matrix-spec-proposals#1692 Co-authored-by: Hubert Chathi --- .../client_server/newsfragments/1812.feature | 1 + content/client-server-api/_index.md | 153 ++++++++++++++++-- .../definitions/m.login.terms_params.yaml | 82 ++++++++++ 3 files changed, 226 insertions(+), 10 deletions(-) create mode 100644 changelogs/client_server/newsfragments/1812.feature create mode 100644 data/api/client-server/definitions/m.login.terms_params.yaml diff --git a/changelogs/client_server/newsfragments/1812.feature b/changelogs/client_server/newsfragments/1812.feature new file mode 100644 index 000000000..baa9aa7d6 --- /dev/null +++ b/changelogs/client_server/newsfragments/1812.feature @@ -0,0 +1 @@ +Specify terms of services at registration, as per [MSC1692](https://github.com/matrix-org/matrix-spec-proposals/pull/1692). diff --git a/content/client-server-api/_index.md b/content/client-server-api/_index.md index ba5272755..b0ce72896 100644 --- a/content/client-server-api/_index.md +++ b/content/client-server-api/_index.md @@ -546,8 +546,10 @@ request parameter. A client should first make a request with no `auth` parameter. The homeserver returns an HTTP 401 response, with a JSON body, as follows: - HTTP/1.1 401 Unauthorized - Content-Type: application/json +``` +HTTP/1.1 401 Unauthorized +Content-Type: application/json +``` ```json { @@ -590,8 +592,10 @@ given. It also contains other keys dependent on the auth type being attempted. For example, if the client is attempting to complete auth type `example.type.foo`, it might submit something like this: - POST /_matrix/client/v3/endpoint HTTP/1.1 - Content-Type: application/json +``` +POST /_matrix/client/v3/endpoint HTTP/1.1 +Content-Type: application/json +``` ```json { @@ -611,8 +615,10 @@ along with the same object as when no authentication was attempted, with the addition of the `completed` key which is an array of auth types the client has completed successfully: - HTTP/1.1 401 Unauthorized - Content-Type: application/json +``` +HTTP/1.1 401 Unauthorized +Content-Type: application/json +``` ```json { @@ -643,8 +649,10 @@ 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: - HTTP/1.1 401 Unauthorized - Content-Type: application/json +``` +HTTP/1.1 401 Unauthorized +Content-Type: application/json +``` ```json { @@ -671,8 +679,10 @@ status 401 response as above, with the addition of the standard If the request fails for a reason other than authentication, the server returns an error message in the standard format. For example: - HTTP/1.1 400 Bad request - Content-Type: application/json +``` +HTTP/1.1 400 Bad request +Content-Type: application/json +``` ```json { @@ -970,6 +980,129 @@ in the registration process that their token has expired. {{% http-api spec="client-server" api="registration_tokens" %}} +##### Terms of service at registration + +{{% added-in v="1.11" %}} + +| Type | Description | +|--------------------------|--------------------------------------------------------------------------| +| `m.login.terms` | Authentication requires the user to accept a set of policy documents. | + +{{% boxes/note %}} +The `m.login.terms` authentication type is only valid on the +[`/register`](#post_matrixclientv3register) endpoint. +{{% /boxes/note %}} + +This authentication type is used when the homeserver requires new users to +accept a given set of policy documents, such as a terms of service and a privacy +policy. There may be many different types of documents, all of which are +versioned and presented in (potentially) multiple languages. + +When the server requires the user to accept some terms, it does so by returning +a 401 response to the `/register` request, where the response body includes +`m.login.terms` in the `flows` list, and the `m.login.terms` property in the +`params` object has the structure [shown below](#definition-mloginterms-params). + +If a client encounters an invalid parameter, registration should stop with an +error presented to the user. + +The client should present the user with a checkbox to accept each policy, +including a link to the provided URL. Once the user has done so, the client +submits an `auth` dict with just the `type` and `session`, as follows, to +indicate that all of the policies have been accepted: + +```json +{ + "type": "m.login.terms", + "session": "" +} +``` + +The server is expected to track which document versions it presented to the +user during registration, if applicable. + + +**Example** + +1. A client might submit a registration request as follows: + + ``` + POST /_matrix/client/v3/register + ``` + ```json + { + "username": "cheeky_monkey", + "password": "ilovebananas" + } + ``` + +2. The server requires the user to accept some terms of service before + registration, so returns the following response: + + ``` + HTTP/1.1 401 Unauthorized + Content-Type: application/json + ``` + ```json + { + "flows": [ + { "stages": [ "m.login.terms" ] } + ], + "params": { + "m.login.terms": { + "policies": { + "terms_of_service": { + "version": "1.2", + "en": { + "name": "Terms of Service", + "url": "https://example.org/somewhere/terms-1.2-en.html" + }, + "fr": { + "name": "Conditions d'utilisation", + "url": "https://example.org/somewhere/terms-1.2-fr.html" + } + } + } + } + }, + "session": "kasgjaelkgj" + } + ``` + +3. The client presents the list of documents to the user, inviting them to + accept the polices. + +4. The client repeats the registration request, confirming that the user has + accepted the documents: + ``` + POST /_matrix/client/v3/register + ``` + ```json + { + "username": "cheeky_monkey", + "password": "ilovebananas", + "auth": { + "type": "m.login.terms", + "session": "kasgjaelkgj" + } + } + ``` + +5. All authentication steps have now completed, so the request is successful: + ``` + HTTP/1.1 200 OK + Content-Type: application/json + ``` + ```json + { + "access_token": "abc123", + "device_id": "GHTYAJCE", + "user_id": "@cheeky_monkey:matrix.org" + } + ``` + +{{% definition path="api/client-server/definitions/m.login.terms_params" %}} + #### Fallback Clients cannot be expected to be able to know how to process every diff --git a/data/api/client-server/definitions/m.login.terms_params.yaml b/data/api/client-server/definitions/m.login.terms_params.yaml new file mode 100644 index 000000000..67001c189 --- /dev/null +++ b/data/api/client-server/definitions/m.login.terms_params.yaml @@ -0,0 +1,82 @@ +# Copyright 2024 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 +title: m.login.terms params +description: Schema for `m.login.terms` entry in the `params` object in a User-Interactive Authentication response. +required: ['policies'] +properties: + policies: + type: object + description: | + A map from "Policy ID" to the current definition of this policy document. The Policy ID is a unique + identifier for a given policy document, using the [Opaque Identifier Grammar](/appendices/#opaque-identifiers). + additionalProperties: + type: object + title: Policy Definition + required: [version] + properties: + version: + type: string + description: | + The version of this policy document. This is provided as a convenience for the client, + and uses the [Opaque Identifier Grammar](/appendices/#opaque-identifiers). + additionalProperties: + type: object + title: Policy Translation + required: [name, url] + description: | + Map from language codes to details of the document in that language. + Language codes SHOULD be formatted as per [Section 2.2 of RFC + 5646](https://datatracker.ietf.org/doc/html/rfc5646#section-2.2), + though some implementations may use an underscore instead of dash + (for example, `en_US` instead of `en-US`). + properties: + name: + type: string + description: | + The name of this document, in the appropriate language. An + arbitrary string with no specified maximum length. + url: + type: string + description: | + A link to the text of this document, in the appropriate + language. MUST be a valid URI with scheme `https://` or + `http://`. Insecure HTTP is discouraged. +example: { + "policies": { + "terms_of_service": { + "version": "1.2", + "en": { + "name": "Terms of Service", + "url": "https://example.org/somewhere/terms-1.2-en.html" + }, + "fr": { + "name": "Conditions d'utilisation", + "url": "https://example.org/somewhere/terms-1.2-fr.html" + } + }, + "privacy_policy": { + "version": "1.2", + "en": { + "name": "Privacy Policy", + "url": "https://example.org/somewhere/privacy-1.2-en.html" + }, + "fr": { + "name": "Politique de confidentialité", + "url": "https://example.org/somewhere/privacy-1.2-fr.html" + } + } + } +} \ No newline at end of file