| rfc9670.original | rfc9670.txt | |||
|---|---|---|---|---|
| JMAP N.M. Jenkins, Ed. | Internet Engineering Task Force (IETF) N. Jenkins, Ed. | |||
| Internet-Draft Fastmail | Request for Comments: 9670 Fastmail | |||
| Updates: 8620 (if approved) 18 April 2024 | Updates: 8620 November 2024 | |||
| Intended status: Standards Track | Category: Standards Track | |||
| Expires: 20 October 2024 | ISSN: 2070-1721 | |||
| JMAP Sharing | JSON Meta Application Protocol (JMAP) Sharing | |||
| draft-ietf-jmap-sharing-09 | ||||
| Abstract | Abstract | |||
| This document specifies a data model for sharing data between users | This document specifies a data model for sharing data between users | |||
| using JMAP. Future documents can reference this document when | using the JSON Meta Application Protocol (JMAP). Future documents | |||
| defining data types to support a consistent model of sharing. | can reference this document when defining data types to support a | |||
| consistent model of sharing. | ||||
| Status of This Memo | Status of This Memo | |||
| This Internet-Draft is submitted in full conformance with the | This is an Internet Standards Track document. | |||
| provisions of BCP 78 and BCP 79. | ||||
| Internet-Drafts are working documents of the Internet Engineering | ||||
| Task Force (IETF). Note that other groups may also distribute | ||||
| working documents as Internet-Drafts. The list of current Internet- | ||||
| Drafts is at https://datatracker.ietf.org/drafts/current/. | ||||
| Internet-Drafts are draft documents valid for a maximum of six months | This document is a product of the Internet Engineering Task Force | |||
| and may be updated, replaced, or obsoleted by other documents at any | (IETF). It represents the consensus of the IETF community. It has | |||
| time. It is inappropriate to use Internet-Drafts as reference | received public review and has been approved for publication by the | |||
| material or to cite them other than as "work in progress." | Internet Engineering Steering Group (IESG). Further information on | |||
| Internet Standards is available in Section 2 of RFC 7841. | ||||
| This Internet-Draft will expire on 20 October 2024. | Information about the current status of this document, any errata, | |||
| and how to provide feedback on it may be obtained at | ||||
| https://www.rfc-editor.org/info/rfc9670. | ||||
| Copyright Notice | Copyright Notice | |||
| Copyright (c) 2024 IETF Trust and the persons identified as the | Copyright (c) 2024 IETF Trust and the persons identified as the | |||
| document authors. All rights reserved. | document authors. All rights reserved. | |||
| This document is subject to BCP 78 and the IETF Trust's Legal | This document is subject to BCP 78 and the IETF Trust's Legal | |||
| Provisions Relating to IETF Documents (https://trustee.ietf.org/ | Provisions Relating to IETF Documents | |||
| license-info) in effect on the date of publication of this document. | (https://trustee.ietf.org/license-info) in effect on the date of | |||
| Please review these documents carefully, as they describe your rights | publication of this document. Please review these documents | |||
| and restrictions with respect to this document. Code Components | carefully, as they describe your rights and restrictions with respect | |||
| extracted from this document must include Revised BSD License text as | to this document. Code Components extracted from this document must | |||
| described in Section 4.e of the Trust Legal Provisions and are | include Revised BSD License text as described in Section 4.e of the | |||
| provided without warranty as described in the Revised BSD License. | Trust Legal Provisions and are provided without warranty as described | |||
| in the Revised BSD License. | ||||
| Table of Contents | Table of Contents | |||
| 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 | 1. Introduction | |||
| 1.1. Notational Conventions . . . . . . . . . . . . . . . . . 3 | 1.1. Notational Conventions | |||
| 1.2. Terminology . . . . . . . . . . . . . . . . . . . . . . . 3 | 1.2. Terminology | |||
| 1.3. Data Model Overview . . . . . . . . . . . . . . . . . . . 4 | 1.3. Data Model Overview | |||
| 1.4. Subscribing to Shared Data . . . . . . . . . . . . . . . 4 | 1.4. Subscribing to Shared Data | |||
| 1.5. Addition to the Capabilities Object . . . . . . . . . . . 5 | 1.5. Addition to the Capabilities Object | |||
| 1.5.1. urn:ietf:params:jmap:principals . . . . . . . . . . . 5 | 1.5.1. urn:ietf:params:jmap:principals | |||
| 1.5.2. urn:ietf:params:jmap:principals:owner . . . . . . . . 5 | 1.5.2. urn:ietf:params:jmap:principals:owner | |||
| 2. Principals . . . . . . . . . . . . . . . . . . . . . . . . . 6 | 2. Principals | |||
| 2.1. Principal/get . . . . . . . . . . . . . . . . . . . . . . 7 | 2.1. Principal/get | |||
| 2.2. Principal/changes . . . . . . . . . . . . . . . . . . . . 7 | 2.2. Principal/changes | |||
| 2.3. Principal/set . . . . . . . . . . . . . . . . . . . . . . 7 | 2.3. Principal/set | |||
| 2.4. Principal/query . . . . . . . . . . . . . . . . . . . . . 7 | 2.4. Principal/query | |||
| 2.4.1. Filtering . . . . . . . . . . . . . . . . . . . . . . 7 | 2.4.1. Filtering | |||
| 2.5. Principal/queryChanges . . . . . . . . . . . . . . . . . 8 | 2.5. Principal/queryChanges | |||
| 3. Share Notifications . . . . . . . . . . . . . . . . . . . . . 8 | 3. ShareNotifications | |||
| 3.1. Auto-deletion of Notifications . . . . . . . . . . . . . 9 | 3.1. ShareNotification/get | |||
| 3.2. Object Properties . . . . . . . . . . . . . . . . . . . . 9 | 3.2. ShareNotification/changes | |||
| 3.3. ShareNotification/get . . . . . . . . . . . . . . . . . . 10 | 3.3. ShareNotification/set | |||
| 3.4. ShareNotification/changes . . . . . . . . . . . . . . . . 10 | 3.4. ShareNotification/query | |||
| 3.5. ShareNotification/set . . . . . . . . . . . . . . . . . . 10 | 3.4.1. Filtering | |||
| 3.6. ShareNotification/query . . . . . . . . . . . . . . . . . 10 | 3.4.2. Sorting | |||
| 3.6.1. Filtering . . . . . . . . . . . . . . . . . . . . . . 10 | 3.5. ShareNotification/queryChanges | |||
| 3.6.2. Sorting . . . . . . . . . . . . . . . . . . . . . . . 11 | 4. Framework for Shared Data | |||
| 3.7. ShareNotification/queryChanges . . . . . . . . . . . . . 11 | 4.1. Example | |||
| 4. Framework for Shared Data . . . . . . . . . . . . . . . . . . 11 | 5. Internationalization Considerations | |||
| 4.1. Example . . . . . . . . . . . . . . . . . . . . . . . . . 11 | 6. Security Considerations | |||
| 5. Internationalisation Considerations . . . . . . . . . . . . . 15 | 6.1. Spoofing | |||
| 6. Security Considerations . . . . . . . . . . . . . . . . . . . 15 | 6.2. Unnoticed Sharing | |||
| 6.1. Spoofing . . . . . . . . . . . . . . . . . . . . . . . . 15 | 6.3. Denial of Service | |||
| 6.2. Unnoticed Sharing . . . . . . . . . . . . . . . . . . . . 16 | 6.4. Unauthorized Principals | |||
| 6.3. Denial of Service . . . . . . . . . . . . . . . . . . . . 16 | 7. IANA Considerations | |||
| 6.4. Unauthorised Principals . . . . . . . . . . . . . . . . . 16 | 7.1. JMAP Capability Registration for "principals" | |||
| 7. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 16 | 7.2. JMAP Capability Registration for "principals:owner" | |||
| 7.1. JMAP Capability Registration for "principals" . . . . . . 16 | 7.3. JMAP Data Type Registration for "Principal" | |||
| 7.2. JMAP Capability Registration for "principals:owner" . . . 17 | 7.4. JMAP Data Type Registration for "ShareNotification" | |||
| 7.3. JMAP Data Type Registration for "Principal" . . . . . . . 17 | 8. References | |||
| 7.4. JMAP Data Type Registration for "ShareNotification" . . . 17 | 8.1. Normative References | |||
| 8. Normative References . . . . . . . . . . . . . . . . . . . . 17 | 8.2. Informative References | |||
| 9. Informative References . . . . . . . . . . . . . . . . . . . 18 | Author's Address | |||
| Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 18 | ||||
| 1. Introduction | 1. Introduction | |||
| JMAP ([RFC8620] JSON Meta Application Protocol) is a generic protocol | The JSON Meta Application Protocol (JMAP) [RFC8620] is a generic | |||
| for synchronizing data, such as mail, calendars or contacts, between | protocol for synchronizing data, such as mail, calendars, or | |||
| a client and a server. It is optimized for mobile and web | contacts, between a client and a server. It is optimized for mobile | |||
| environments, and provides a consistent interface to query, read, and | and web environments and provides a consistent interface to query, | |||
| modify different data types, including comprehensive error handling. | read, and modify different data types, including comprehensive error | |||
| handling. | ||||
| This specification defines a data model to represent entities in a | This specification defines a data model to represent entities in a | |||
| collaborative environment, and a framework for sharing data between | collaborative environment and a framework for sharing data between | |||
| them that can be used to provide a consistent sharing model for | them that can be used to provide a consistent sharing model for | |||
| different data types. It does not define _what_ may be shared, or | different data types. It does not define _what_ may be shared or the | |||
| the granularity of permissions, as this will depend on the data in | granularity of permissions, as this will depend on the data in | |||
| question. | question. | |||
| 1.1. Notational Conventions | 1.1. Notational Conventions | |||
| The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", | |||
| "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and | "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and | |||
| "OPTIONAL" in this document are to be interpreted as described in BCP | "OPTIONAL" in this document are to be interpreted as described in | |||
| 14 [RFC2119] [RFC8174] when, and only when, they appear in all | BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all | |||
| capitals, as shown here. | capitals, as shown here. | |||
| Type signatures, examples, and property descriptions in this document | Type signatures, examples, and property descriptions in this document | |||
| follow the conventions established in Section 1.1 of [RFC8620]. Data | follow the conventions established in Section 1.1 of [RFC8620]. Data | |||
| types defined in the core specification are also used in this | types defined in the core specification are also used in this | |||
| document. | document. | |||
| Examples of API exchanges only show the methodCalls array of the | Examples of API exchanges only show the methodCalls array of the | |||
| Request object or the methodResponses array of the Response object. | Request object or the methodResponses array of the Response object. | |||
| For compactness, the rest of the Request/Response object is omitted. | For compactness, the rest of the Request/Response object is omitted. | |||
| 1.2. Terminology | 1.2. Terminology | |||
| The same terminology is used in this document as in the core JMAP | The same terminology is used in this document as in the core JMAP | |||
| specification, see [RFC8620], Section 1.6. | specification. See [RFC8620], Section 1.6. | |||
| The terms Principal, and ShareNotification (with these specific | The terms "Principal" and "ShareNotification" (with this specific | |||
| capitalizations) are used to refer to the data types defined in this | capitalization) are used to refer to the data types defined in this | |||
| document and instances of those data types. | document and instances of those data types. | |||
| 1.3. Data Model Overview | 1.3. Data Model Overview | |||
| A Principal (see Section 2) represents an individual, team, or | A Principal (see Section 2) represents an individual, team, or | |||
| resource (e.g., a room or projector). The object contains | resource (e.g., a room or projector). The object contains | |||
| information about the entity being represented, such as a name, | information about the entity being represented, such as a name, | |||
| description, and time zone. It may also hold domain-specific | description, and time zone. It may also hold domain-specific | |||
| information. A Principal may be associated with zero or more | information. A Principal may be associated with zero or more | |||
| Accounts (see [RFC8620], Section 1.6.2) containing data belonging to | Accounts (see [RFC8620], Section 1.6.2) containing data belonging to | |||
| skipping to change at page 4, line 25 ¶ | skipping to change at line 151 ¶ | |||
| is likely to map directly from a directory service or other user | is likely to map directly from a directory service or other user | |||
| management system. | management system. | |||
| Data types may allow users to share data with others by assigning | Data types may allow users to share data with others by assigning | |||
| permissions to Principals. When a user's permissions are changed, a | permissions to Principals. When a user's permissions are changed, a | |||
| ShareNotification object is created for them so a client can inform | ShareNotification object is created for them so a client can inform | |||
| the user of the changes. | the user of the changes. | |||
| 1.4. Subscribing to Shared Data | 1.4. Subscribing to Shared Data | |||
| Permissions determine whether a user _may_ access data, but not | Permissions determine whether a user _may_ access data but not | |||
| whether they _want_ to. Some shared data is of equal importance as | whether they _want_ to. Some shared data is of equal importance as | |||
| the user's own, while other data is just there should the user wish | the user's own, while other data is just there should the user wish | |||
| to explicitly go find it. Clients will often want to differentiate | to explicitly go find it. Clients will often want to differentiate | |||
| the two. For example, a company may share mailing list archives for | the two. For example, a company may share mailing list archives for | |||
| all departments with all employees, but a user may only generally be | all departments with all employees, but a user may only generally be | |||
| interested in the few they belong to. They would have _permission_ | interested in the few they belong to. They would have _permission_ | |||
| to access many mailboxes, but can _subscribe_ to just the ones they | to access many mailboxes but can _subscribe_ to just the ones they | |||
| care about. The client would provide separate interfaces for reading | care about. The client would provide separate interfaces for reading | |||
| mail in subscribed mailboxes and browsing all mailboxes they have | mail in subscribed mailboxes and browsing all mailboxes they have | |||
| permission to access in order to manage which they are subscribed to. | permission to access in order to manage those that they are | |||
| subscribed to. | ||||
| The JMAP Session object (see [RFC8620], Section 2) is defined to | The JMAP Session object (see [RFC8620], Section 2) is defined to | |||
| include an object in the accounts property for every account that the | include an object in the "accounts" property for every Account that | |||
| user has access to. Collaborative systems may share data between a | the user has access to. Collaborative systems may share data between | |||
| very large number of Principals, most of which the user does not care | a very large number of Principals, most of which the user does not | |||
| about day-to-day. For servers implementing this specification, the | care about day to day. For servers implementing this specification, | |||
| Session object MUST only include Accounts where either the user is | the Session object MUST only include Accounts where either the user | |||
| subscribed to at least one record (see [RFC8620], Section 1.6.3) in | is subscribed to at least one record (see [RFC8620], Section 1.6.3) | |||
| the account, or the account belongs to the user. StateChange events | in the Account or the Account belongs to the user. StateChange | |||
| ([RFC8620], Section 7.1) for changes to data SHOULD only be sent for | events ([RFC8620], Section 7.1) for changes to data SHOULD only be | |||
| data the user has subscribed to and MUST NOT be sent for any account | sent for data the user has subscribed to and MUST NOT be sent for any | |||
| where the user is not subscribed to any records in the account, | Account where the user is not subscribed to any records in the | |||
| except where that account belongs to the user. | Account, except where that Account belongs to the user. | |||
| The server MAY reject the user's attempt to subscribe to some | The server MAY reject the user's attempt to subscribe to some | |||
| resources even if they have permission to access them (e.g., a | resources even if they have permission to access them (e.g., a | |||
| calendar representing a location). | calendar representing a location). | |||
| A user can query the set of Principals they have access to with | A user can query the set of Principals they have access to with | |||
| "Principal/query" (see Section 2.4). The Principal object will | "Principal/query" (see Section 2.4). The Principal object will | |||
| contain an Account object for all accounts where the user has | contain an Account object for all Accounts where the user has | |||
| permission to access data for that Principal, even if they are not | permission to access data for that Principal, even if they are not | |||
| yet subscribed. | yet subscribed. | |||
| 1.5. Addition to the Capabilities Object | 1.5. Addition to the Capabilities Object | |||
| The capabilities object is returned as part of the JMAP Session | The capabilities object is returned as part of the JMAP Session | |||
| object; see [RFC8620], Section 2. This document defines two | object; see [RFC8620], Section 2. This document defines two | |||
| additional capability URIs. | additional capability URIs. | |||
| 1.5.1. urn:ietf:params:jmap:principals | 1.5.1. urn:ietf:params:jmap:principals | |||
| The urn:ietf:params:jmap:principals capability represents support for | The urn:ietf:params:jmap:principals capability represents support for | |||
| the Principal and ShareNotification data types and associated API | the Principal and ShareNotification data types and associated API | |||
| methods. | methods. | |||
| The value of this property in the JMAP Session capabilities property | The value of this property in the JMAP Session "capabilities" | |||
| is an empty object. | property is an empty object. | |||
| The value of this property in an account’s accountCapabilities | The value of this property in an Account's "accountCapabilities" | |||
| property is an object that MUST contain the following information on | property is an object that MUST contain the following information on | |||
| server capabilities and permissions for that account: | server capabilities and permissions for that Account: | |||
| * *currentUserPrincipalId*: Id|null | *currentUserPrincipalId*: Id|null | |||
| The id of the Principal in this account that corresponds to the | The id of the Principal in this Account that corresponds to the | |||
| user fetching this object, if any. | user fetching this object, if any. | |||
| 1.5.2. urn:ietf:params:jmap:principals:owner | 1.5.2. urn:ietf:params:jmap:principals:owner | |||
| The URI urn:ietf:params:jmap:principals:owner is solely used as a key | The URI urn:ietf:params:jmap:principals:owner is solely used as a key | |||
| in an account’s accountCapabilities property. It does not appear in | in an Account's "accountCapabilities" property. It does not appear | |||
| the JMAP Session capabilities — support is indicated by the | in the JMAP Session capabilities -- support is indicated by the | |||
| urn:ietf:params:jmap:principals URI being present in the session | urn:ietf:params:jmap:principals URI being present in the session | |||
| capabilities. | capabilities. | |||
| If urn:ietf:params:jmap:principals:owner is a key in an account’s | If urn:ietf:params:jmap:principals:owner is a key in an Account's | |||
| accountCapabilities, that account (and data therein) is owned by a | "accountCapabilities" property, that Account (and the data therein) | |||
| Principal. Some accounts may not be owned by a Principal (e.g., the | is owned by a Principal. Some Accounts may not be owned by a | |||
| account that contains the data for the Principals themselves), in | Principal (e.g., the Account that contains the data for the | |||
| which case this property is omitted. | Principals themselves), in which case this property is omitted. | |||
| The value of this property is an object with the following | The value of this property is an object with the following | |||
| properties: | properties: | |||
| * *accountIdForPrincipal*: Id | *accountIdForPrincipal*: Id | |||
| The id of an account with the urn:ietf:params:jmap:principals | The id of an Account with the urn:ietf:params:jmap:principals | |||
| capability that contains the corresponding Principal object. | capability that contains the corresponding Principal object. | |||
| * *principalId*: Id | ||||
| The id of the Principal that owns this account. | *principalId*:Id | |||
| The id of the Principal that owns this Account. | ||||
| 2. Principals | 2. Principals | |||
| A Principal represents an individual, group, location (e.g., a room), | A Principal represents an individual, a group, a location (e.g., a | |||
| resource (e.g., a projector) or other entity in a collaborative | room), a resource (e.g., a projector), or another entity in a | |||
| environment. Sharing in JMAP is generally configured by assigning | collaborative environment. Sharing in JMAP is generally configured | |||
| rights to certain data within an account to other Principals. For | by assigning rights to certain data within an Account to other | |||
| example, a user may assign permission to read their calendar to a | Principals. For example, a user may assign permission to read their | |||
| Principal representing another user or their team. | calendar to a Principal representing another user or their team. | |||
| In a shared environment such as a workplace, a user may have access | In a shared environment, such as a workplace, a user may have access | |||
| to a large number of Principals. | to a large number of Principals. | |||
| In most systems, the user will have access to a single Account | In most systems, the user will have access to a single Account | |||
| containing Principal objects. In some situations, for example when | containing Principal objects. In some situations, for example, when | |||
| aggregating data from different places, there may be multiple | aggregating data from different places, there may be multiple | |||
| Accounts containing Principal objects. | Accounts containing Principal objects. | |||
| A *Principal* object has the following properties: | A *Principal* object has the following properties: | |||
| * *id*: Id (immutable; server-set) | *id*: Id (immutable; server-set) | |||
| The id of the Principal. | The id of the Principal. | |||
| * *type*: String | ||||
| *type*: String | ||||
| This MUST be one of the following values: | This MUST be one of the following values: | |||
| - individual: This represents a single person. | ||||
| - group: This represents a group of other Principals. | * "individual": This represents a single person. | |||
| - resource: This represents some resource, e.g., a projector. | * "group": This represents a group of other Principals. | |||
| - location: This represents a location. | * "resource": This represents some resource, e.g., a projector. | |||
| - other: This represents some other undefined Principal. | * "location": This represents a location. | |||
| * *name*: String | * "other": This represents some other undefined Principal. | |||
| The name of the Principal, e.g., "Jane Doe", or "Room 4B". | ||||
| * *description*: String|null | *name*: String | |||
| A longer description of the Principal, for example details about | The name of the Principal, e.g., "Jane Doe" or "Room 4B". | |||
| the facilities of a resource, or null if no description available. | ||||
| * *email*: String|null | *description*: String|null | |||
| A longer description of the Principal, for example, details about | ||||
| the facilities of a resource, or null if no description is | ||||
| available. | ||||
| *email*: String|null | ||||
| An email address for the Principal, or null if no email is | An email address for the Principal, or null if no email is | |||
| available. If given, the value MUST conform to the "addr-spec" | available. If given, the value MUST conform to the "addr-spec" | |||
| syntax, as defined in [RFC5322], Section 3.4.1. | syntax, as defined in [RFC5322], Section 3.4.1. | |||
| * *timeZone*: String|null | ||||
| *timeZone*: String|null | ||||
| The time zone for this Principal, if known. If not null, the | The time zone for this Principal, if known. If not null, the | |||
| value MUST be a time zone name from the IANA Time Zone Database | value MUST be a time zone name from the IANA Time Zone Database | |||
| TZDB (https://www.iana.org/time-zones). | [IANA-TZDB]. | |||
| * *capabilities*: String[Object] (server-set) | ||||
| A map of JMAP capability URIs to domain specific information about | *capabilities*: String[Object] (server-set) | |||
| A map of JMAP capability URIs to domain-specific information about | ||||
| the Principal in relation to that capability, as defined in the | the Principal in relation to that capability, as defined in the | |||
| document that registered the capability. | document that registered the capability. | |||
| * *accounts*: Id[Account]|null (server-set) | ||||
| A map of account id to Account object for each JMAP Account | *accounts*: Id[Account]|null (server-set) | |||
| A map of Account id to Account object for each JMAP Account | ||||
| containing data for this Principal that the user has access to, or | containing data for this Principal that the user has access to, or | |||
| null if none. | null if none. | |||
| 2.1. Principal/get | 2.1. Principal/get | |||
| This is a standard "/get" method as described in [RFC8620], | This is a standard "/get" method as described in [RFC8620], | |||
| Section 5.1. | Section 5.1. | |||
| 2.2. Principal/changes | 2.2. Principal/changes | |||
| This is a standard "/changes" method as described in [RFC8620], | This is a standard "/changes" method as described in [RFC8620], | |||
| Section 5.2. Note: implementations backed by an external directory | Section 5.2. | |||
| may be unable to calculate changes. In this case, they will always | ||||
| return a "cannotCalculateChanges" error as described in the core JMAP | | Note: Implementations backed by an external directory may be | |||
| specification. | | unable to calculate changes. In this case, they will always | |||
| | return a "cannotCalculateChanges" error as described in the | ||||
| | core JMAP specification. | ||||
| 2.3. Principal/set | 2.3. Principal/set | |||
| This is a standard "/set" method as described in [RFC8620], | This is a standard "/set" method as described in [RFC8620], | |||
| Section 5.3. | Section 5.3. | |||
| Managing Principals is likely tied to a directory service or some | Managing Principals is likely tied to a directory service or some | |||
| other vendor-specific solution. This management may occur out-of- | other vendor-specific solution. This management may occur out of | |||
| band, or via an additional capability defined elsewhere. Allowing | band or via an additional capability defined elsewhere. Allowing | |||
| direct user modification of properties has security considerations, | direct user modification of properties has security considerations, | |||
| as noted in Section 6. Servers MUST reject any change it doesn’t | as noted in Section 6. A server MUST reject any change it doesn't | |||
| allow with a forbidden SetError. | allow with a "forbidden" SetError. | |||
| Where a server does support changes via this API, it SHOULD allow an | Where a server does support changes via this API, it SHOULD allow an | |||
| update to the "name", "description" and "timeZone" properties of the | update to the "name", "description", and "timeZone" properties of the | |||
| Principal with the same id as the "currentUserPrincipalId" in the | Principal with the same id as the "currentUserPrincipalId" in the | |||
| Account capabilities. This allows the user to update their own | Account capabilities. This allows the user to update their own | |||
| details. | details. | |||
| 2.4. Principal/query | 2.4. Principal/query | |||
| This is a standard "/query" method as described in [RFC8620], | This is a standard "/query" method as described in [RFC8620], | |||
| Section 5.5 | Section 5.5. | |||
| 2.4.1. Filtering | 2.4.1. Filtering | |||
| A *FilterCondition* object has the following properties, all of which | A *FilterCondition* object has the following properties, all of which | |||
| are optional: | are optional: | |||
| * *accountIds*: String[] | *accountIds*: String[] | |||
| A list of account ids. The Principal matches if any of the ids in | A list of Account ids. The Principal matches if any of the ids in | |||
| this list are keys in the Principal's "accounts" property (i.e., | this list are keys in the Principal's "accounts" property (i.e., | |||
| if any of the account ids belong to the Principal). | if any of the Account ids belong to the Principal). | |||
| * *email*: String | ||||
| *email*: String | ||||
| The email property of the Principal contains the given string. | The email property of the Principal contains the given string. | |||
| * *name*: String | ||||
| *name*: String | ||||
| The name property of the Principal contains the given string. | The name property of the Principal contains the given string. | |||
| * *text* String | ||||
| *text*: String | ||||
| The name, email, or description property of the Principal contains | The name, email, or description property of the Principal contains | |||
| the given string. | the given string. | |||
| * *type*: String | ||||
| *type*: String | ||||
| The type must be exactly as given to match the condition. | The type must be exactly as given to match the condition. | |||
| * *timeZone*: String | ||||
| *timeZone*: String | ||||
| The timeZone must be exactly as given to match the condition. | The timeZone must be exactly as given to match the condition. | |||
| All given conditions in the FilterCondition object must match for the | All given conditions in the FilterCondition object must match for the | |||
| Principal to match. | Principal to match. | |||
| Text matches for "contains" SHOULD be simple substring matches. | Text matches for "contains" SHOULD be simple substring matches. | |||
| 2.5. Principal/queryChanges | 2.5. Principal/queryChanges | |||
| This is a standard "/queryChanges" method as described in [RFC8620], | This is a standard "/queryChanges" method as described in [RFC8620], | |||
| Section 5.6. Note: implementations backed by an external directory | Section 5.6. | |||
| may be unable to calculate changes. In this case, they will always | ||||
| return a "cannotCalculateChanges" error as described in the core JMAP | ||||
| specification. | ||||
| 3. Share Notifications | | Note: Implementations backed by an external directory may be | |||
| | unable to calculate changes. In this case, they will always | ||||
| | return a "cannotCalculateChanges" error as described in the | ||||
| | core JMAP specification. | ||||
| 3. ShareNotifications | ||||
| The ShareNotification data type records when the user's permissions | The ShareNotification data type records when the user's permissions | |||
| to access a shared object changes. ShareNotification are only | to access a shared object changes. ShareNotifications are only | |||
| created by the server; users cannot create them explicitly. | created by the server; users cannot create them explicitly. They are | |||
| Notifications are stored in the same Account as the Principals. | stored in the same Account as the Principals. | |||
| Clients may present the list of notifications to the user and allow | Clients may present the list of notifications to the user and allow | |||
| them to dismiss them. To dismiss a notification you use a standard | the user to dismiss them. To dismiss a notification, use a standard | |||
| "/set" call to destroy it. | "/set" call to destroy it. | |||
| The server SHOULD create a ShareNotification whenever the user's | The server SHOULD create a ShareNotification whenever the user's | |||
| permissions change on an object. It MAY choose not to create a | permissions change on an object. It MAY choose not to create a | |||
| notification for permission changes to a group Principal, even if the | notification for permission changes to a group Principal, even if the | |||
| user is in the group, if this is more likely to be overwhelming than | user is in the group, if this is more likely to be overwhelming than | |||
| helpful, or would create excessive notifications within the system. | helpful, or if it would create excessive notifications within the | |||
| system. | ||||
| 3.1. Auto-deletion of Notifications | ||||
| The server MAY limit the maximum number of notifications it will | The server MAY limit the maximum number of notifications it will | |||
| store for a user. When the limit is reached, any new notification | store for a user. When the limit is reached, any new notification | |||
| will cause the previously oldest notification to be automatically | will cause the previously oldest notification to be automatically | |||
| deleted. | deleted. | |||
| The server MAY coalesce notifications if appropriate, or remove | The server MAY coalesce notifications if appropriate or remove | |||
| notifications that it deems are no longer relevant or after a certain | notifications after a certain period of time or that it deems are no | |||
| period of time. | longer relevant. | |||
| 3.2. Object Properties | ||||
| The *ShareNotification* object has the following properties: | A *ShareNotification* object has the following properties: | |||
| * *id*: String (immutable; server-set) | *id*: String (immutable; server-set) | |||
| The id of the ShareNotification. | The id of the ShareNotification. | |||
| * *created*: UTCDate (immutable; server-set) | ||||
| *created*: UTCDate (immutable; server-set) | ||||
| The time this notification was created. | The time this notification was created. | |||
| * *changedBy*: Entity (immutable; server-set) | ||||
| Who made the change. | *changedBy*: Entity (immutable; server-set) | |||
| - *name*: String | Who made the change. An *Entity* object has the following | |||
| properties: | ||||
| *name*: String | ||||
| The name of the entity who made the change. | The name of the entity who made the change. | |||
| - *email*: String|null | *email*: String|null | |||
| The email of the entity who made the change, or null if no | The email of the entity who made the change, or null if no | |||
| email is available. | email is available. | |||
| - *principalId*: Id|null | *principalId*: Id|null | |||
| The id of the Principal corresponding to the entity who made | The id of the Principal corresponding to the entity who made | |||
| the change, or null if no associated Principal. | the change, or null if no associated Principal. | |||
| * *objectType*: String (immutable; server-set) | ||||
| *objectType*: String (immutable; server-set) | ||||
| The name of the data type for the object whose permissions have | The name of the data type for the object whose permissions have | |||
| changed, as registered in the IANA JMAP Data Types registry | changed, as registered in the IANA "JMAP Data Types" registry | |||
| (https://www.iana.org/assignments/jmap/jmap.xhtml#jmap-data- | [IANA-JMAP], e.g., "Calendar" or "Mailbox". | |||
| types). e.g., "Calendar" or "Mailbox". | ||||
| * *objectAccountId*: Id (immutable; server-set) | *objectAccountId*: Id (immutable; server-set) | |||
| The id of the account where this object exists. | The id of the Account where this object exists. | |||
| * *objectId*: Id (immutable; server-set) | ||||
| *objectId*: Id (immutable; server-set) | ||||
| The id of the object that this notification is about. | The id of the object that this notification is about. | |||
| * *oldRights*: String[Boolean]|null (immutable; server-set) | ||||
| *oldRights*: String[Boolean]|null (immutable; server-set) | ||||
| The "myRights" property of the object for the user before the | The "myRights" property of the object for the user before the | |||
| change. | change. | |||
| * *newRights*: String[Boolean]|null (immutable; server-set) | ||||
| *newRights*: String[Boolean]|null (immutable; server-set) | ||||
| The "myRights" property of the object for the user after the | The "myRights" property of the object for the user after the | |||
| change. | change. | |||
| * *name*: String (immutable; server-set) | ||||
| *name*: String (immutable; server-set) | ||||
| The name of the object at the time the notification was made. | The name of the object at the time the notification was made. | |||
| Determining the name will depend on the data type in question. | Determining the name will depend on the data type in question. | |||
| For example, it might be the "title" property of a CalendarEvent | For example, it might be the "title" property of a CalendarEvent | |||
| or the "name" of a Mailbox. The name is to show to users who have | or the "name" of a Mailbox. The name is to show users who have | |||
| had their access rights to the object removed, so that these users | had their access rights to the object removed what it is that they | |||
| know what it is they can no longer access. | can no longer access. | |||
| 3.3. ShareNotification/get | 3.1. ShareNotification/get | |||
| This is a standard "/get" method as described in [RFC8620], | This is a standard "/get" method as described in [RFC8620], | |||
| Section 5.1. | Section 5.1. | |||
| 3.4. ShareNotification/changes | 3.2. ShareNotification/changes | |||
| This is a standard "/changes" method as described in [RFC8620], | This is a standard "/changes" method as described in [RFC8620], | |||
| Section 5.2. | Section 5.2. | |||
| 3.5. ShareNotification/set | 3.3. ShareNotification/set | |||
| This is a standard "/set" method as described in [RFC8620], | This is a standard "/set" method as described in [RFC8620], | |||
| Section 5.3. | Section 5.3. | |||
| Only destroy is supported; any attempt to create/update MUST be | Only destroy is supported; any attempt to create/update MUST be | |||
| rejected with a forbidden SetError. | rejected with a "forbidden" SetError. | |||
| 3.6. ShareNotification/query | 3.4. ShareNotification/query | |||
| This is a standard "/query" method as described in [RFC8620], | This is a standard "/query" method as described in [RFC8620], | |||
| Section 5.5. | Section 5.5. | |||
| 3.6.1. Filtering | 3.4.1. Filtering | |||
| A *FilterCondition* object has the following properties, all of which | A *FilterCondition* object has the following properties, all of which | |||
| are optional: | are optional: | |||
| * *after*: UTCDate|null | *after*: UTCDate|null | |||
| The creation date must be on or after this date to match the | The creation date must be on or after this date to match the | |||
| condition. | condition. | |||
| * *before*: UTCDate|null | ||||
| *before*: UTCDate|null | ||||
| The creation date must be before this date to match the condition. | The creation date must be before this date to match the condition. | |||
| * *objectType*: String | ||||
| *objectType*: String | ||||
| The objectType value must be identical to the given value to match | The objectType value must be identical to the given value to match | |||
| the condition. | the condition. | |||
| * *objectAccountId*: Id | ||||
| *objectAccountId*: Id | ||||
| The objectAccountId value must be identical to the given value to | The objectAccountId value must be identical to the given value to | |||
| match the condition. | match the condition. | |||
| All given conditions in the FilterCondition object must match for the | All given conditions in the FilterCondition object must match for the | |||
| ShareNotification to match. | ShareNotification to match. | |||
| 3.6.2. Sorting | 3.4.2. Sorting | |||
| The "created" property MUST be supported for sorting. | The "created" property MUST be supported for sorting. | |||
| 3.7. ShareNotification/queryChanges | 3.5. ShareNotification/queryChanges | |||
| This is a standard "/queryChanges" method as described in [RFC8620], | This is a standard "/queryChanges" method as described in [RFC8620], | |||
| Section 5.6. | Section 5.6. | |||
| 4. Framework for Shared Data | 4. Framework for Shared Data | |||
| Shareable data types MUST define the following three properties: | Shareable data types MUST define the following three properties: | |||
| * *isSubscribed*: Boolean | *isSubscribed*: Boolean | |||
| > The value true indicates the user wishes to subscribe to see | The value true indicates that the user wishes to subscribe to see | |||
| this data. The value false indicates the user does not wish to | this data. The value false indicates that the user does not wish | |||
| subscribe to see this data. The initial value for this property | to subscribe to see this data. The initial value for this | |||
| when data is shared by another user is implementation dependent, | property when data is shared by another user is implementation | |||
| although data types may give advice on appropriate defaults. | dependent, although data types may give advice on appropriate | |||
| * *myRights*: String[Boolean] | defaults. | |||
| *myRights*: String[Boolean] | ||||
| The set of permissions the user currently has. Appropriate | The set of permissions the user currently has. Appropriate | |||
| permissions are domain specific and must be defined per data type. | permissions are domain specific and must be defined per data type. | |||
| Each key is the name of a permission defined for that data type. | Each key is the name of a permission defined for that data type. | |||
| The value for the key is true if the user has the permission, or | The value for the key is true if the user has the permission or | |||
| false if they do not. | false if they do not. | |||
| * *shareWith*: Id[String[Boolean]]|null | ||||
| *shareWith*: Id[String[Boolean]]|null | ||||
| The value of this property is null if the data is not shared with | The value of this property is null if the data is not shared with | |||
| anyone. Otherwise, it is a map where each key is the id of a | anyone. Otherwise, it is a map where each key is the id of a | |||
| Principal with which this data is shared, and the value associated | Principal with which this data is shared, and the value associated | |||
| with that key is the rights to give that Principal, in the same | with that key is the rights to give that Principal, in the same | |||
| format as the myRights property. The account id for the Principal | format as the "myRights" property. The Account id for the | |||
| id can be found in the capabilities of the Account this object is | Principal id can be found in the capabilities of the Account this | |||
| in (see Section 1.5.2). | object is in (see Section 1.5.2). | |||
| Users with appropriate permission may set this property to modify | Users with appropriate permission may set this property to modify | |||
| who the data is shared with. The Principal that owns the account | who the data is shared with. The Principal that owns the Account | |||
| this data is in MUST NOT be in the set of sharees since the | that this data is in MUST NOT be in the map, since the owner's | |||
| owner's rights are implicit. | rights are implicit. | |||
| 4.1. Example | 4.1. Example | |||
| Suppose we are designing a data model for a very simple todo list. | Suppose we are designing a data model for a very simple to-do list. | |||
| There is a Todo data type representing a single item to do, each of | There is a Todo data type representing a single item to do, each of | |||
| which belongs to a single TodoList. The specification makes the | which belongs to a single TodoList. The specification makes the | |||
| lists shareable by referencing this document and defining the common | TodoLists shareable by referencing this document and defining the | |||
| properties. | common properties. | |||
| First it would define a set of domain-specific rights. For example, | First, it would define a set of domain-specific rights. For example, | |||
| a TodoListRights object may have the following properties: | a TodoListRights object may have the following properties: | |||
| * *mayRead*: Boolean | *mayRead*: Boolean | |||
| The user may fetch this TodoList, and any Todos that belong to | The user may fetch this TodoList and any Todos that belong to this | |||
| this TodoList. | TodoList. | |||
| * *mayWrite*: Boolean | ||||
| *mayWrite*: Boolean | ||||
| The user may create, update, or destroy Todos that belong to this | The user may create, update, or destroy Todos that belong to this | |||
| TodoList, and may change the "name" property of this TodoList. | TodoList and may change the "name" property of this TodoList. | |||
| * *mayAdmin*: Boolean | ||||
| *mayAdmin*: Boolean | ||||
| The user may see and modify the "myRights" property of this | The user may see and modify the "myRights" property of this | |||
| TodoList, and may destroy this TodoList. | TodoList and may destroy this TodoList. | |||
| Then in the TodoList data type, we would include the three common | Then in the TodoList data type, we would include the three common | |||
| properties, in addition to any type-specific properties (like "name" | properties described in Section 4, in addition to any type-specific | |||
| in this case): | properties (like "name" in this case): | |||
| * *id*: Id (immutable; server-set) | *id*: Id (immutable; server-set) | |||
| The id of the object. | The id of the object. | |||
| * *name*: String | ||||
| A name for this list of todos. | *name*: String | |||
| * *isSubscribed*: Boolean | A name for this list of Todos. | |||
| *isSubscribed*: Boolean | ||||
| True if the user has indicated they wish to see this list. If | True if the user has indicated they wish to see this list. If | |||
| false, clients should not display this todo list with the user's | false, clients should not display this TodoList with the user's | |||
| other lists, but should provide a means for users to see and | other TodoLists but should provide a means for users to see and | |||
| subscribe to all lists that have been shared with them. | subscribe to all TodoLists that have been shared with them. | |||
| * *myRights*: TodoListRights | ||||
| The set of permissions the user currently has for this todo list. | ||||
| * *shareWith*: Id[TodoListRights]|null | ||||
| A map of Principal id to rights to give that Principal, or null if | ||||
| not shared with anyone or the user does not have the "mayAdmin" | ||||
| right for this list. Users with the "mayAdmin" right may set this | ||||
| property to modify who the data is shared with. The Principal | ||||
| that owns the account this data is in MUST NOT be in the set of | ||||
| sharees; their rights are implicit. | ||||
| We would define a new Principal capability with two properties: | *myRights*: TodoListRights | |||
| The set of permissions the user currently has for this TodoList. | ||||
| * *accountId*: Id|null | *shareWith*: Id[TodoListRights]|null | |||
| The accountId containing the todo data for this Principal, if it | If not shared with anyone, the value is null. Otherwise, it's a | |||
| map where the keys are Principal ids and the values are the rights | ||||
| given to those Principals. Users with the "mayAdmin" right may | ||||
| set this property to modify who the data is shared with. The | ||||
| Principal that owns the Account that this data is in MUST NOT be | ||||
| in the map; their rights are implicit. | ||||
| We would also define a new Principal capability with two properties: | ||||
| *accountId*: Id|null | ||||
| The accountId containing the Todo data for this Principal, if it | ||||
| has been shared with the requesting user. | has been shared with the requesting user. | |||
| * *mayShareWith*: Boolean | ||||
| May the user add this Principal as a sharee of a todo list? | *mayShareWith*: Boolean | |||
| The user may give this Principal permission to access a TodoList. | ||||
| A client wishing to let the user configure sharing would look at the | A client wishing to let the user configure sharing would look at the | |||
| account capabilities for the Account containing the user's Todo data, | "capabilities" for the Account containing the user's Todo data and | |||
| and find the "urn:ietf:params:jmap:principals:owner" property, as per | find the "urn:ietf:params:jmap:principals:owner" property, as per | |||
| Section 1.5.2. For example, the JMAP Session object might contain: | Section 1.5.2. For example, the JMAP Session object might contain: | |||
| { | { | |||
| "accounts": { | "accounts": { | |||
| "u12345678": { | "u12345678": { | |||
| "name": "jane.doe@example.com", | "name": "jane.doe@example.com", | |||
| "isPersonal": true, | "isPersonal": true, | |||
| "isReadOnly": false, | "isReadOnly": false, | |||
| "accountCapabilities": { | "accountCapabilities": { | |||
| "urn:com.example:jmap:todo": {}, | "urn:com.example:jmap:todo": {}, | |||
| skipping to change at page 13, line 24 ¶ | skipping to change at line 618 ¶ | |||
| "accountIdForPrincipal": "u33084183", | "accountIdForPrincipal": "u33084183", | |||
| "principalId": "P105aga511jaa" | "principalId": "P105aga511jaa" | |||
| } | } | |||
| } | } | |||
| }, | }, | |||
| ... | ... | |||
| }, | }, | |||
| ... | ... | |||
| } | } | |||
| Figure 1 | Figure 1: Part of a JMAP Session Object | |||
| From this it now knows which account has the Principal data, and can | From this, the client now knows which Account has the Principal data, | |||
| fetch the list of Principals to offer the user to share the list | and it can fetch the list of Principals and offer to share it with | |||
| with, making an API request like this: | the user by making an API request like this: | |||
| [[ "Principal/get", { | [[ "Principal/get", { | |||
| "accountId": "u33084183", | "accountId": "u33084183", | |||
| "ids": null | "ids": null | |||
| }, "0" ]] | }, "0" ]] | |||
| Figure 2 | Figure 2: "methodCalls" Property of a JMAP Request | |||
| Here's an example response (where Joe Bloggs is another user that | Here's an example response (where "Joe Bloggs" is another user that | |||
| this user could share their todo list with, but who has not shared | this user could share their TodoList with; Joe has not shared any of | |||
| any data in their own account with this user): | their own data with this user, so the "accounts" property is null): | |||
| [[ "Principal/get", { | [[ "Principal/get", { | |||
| "accountId": "u33084183", | "accountId": "u33084183", | |||
| "state": "7b8eff5zz", | "state": "7b8eff5zz", | |||
| "list": [{ | "list": [{ | |||
| "id": "P2342fnddd20", | "id": "P2342fnddd20", | |||
| "type": "individual", | "type": "individual", | |||
| "name": "Joe Bloggs", | "name": "Joe Bloggs", | |||
| "description": null, | "description": null, | |||
| "email": "joe.bloggs@example.com", | "email": "joe.bloggs@example.com", | |||
| skipping to change at page 14, line 31 ¶ | skipping to change at line 661 ¶ | |||
| "accounts": null | "accounts": null | |||
| }, { | }, { | |||
| "id": "P674pp24095qo49pr", | "id": "P674pp24095qo49pr", | |||
| "name": "Board room", | "name": "Board room", | |||
| "type": "location", | "type": "location", | |||
| ... | ... | |||
| }, ... ], | }, ... ], | |||
| "notFound": [] | "notFound": [] | |||
| }, "0" ]] | }, "0" ]] | |||
| Figure 3 | Figure 3: "methodResponses" Property of a JMAP Response | |||
| A todo list can be shared with Joe Bloggs by updating its shareWith | A TodoList can be shared with "Joe Bloggs" by updating its shareWith | |||
| property, as in this example request: | property, as in this example request: | |||
| [[ "TodoList/set", { | [[ "TodoList/set", { | |||
| "accountId": "u12345678", | "accountId": "u12345678", | |||
| "update": { | "update": { | |||
| "tl01n231": { | "tl01n231": { | |||
| "shareWith": { | "shareWith": { | |||
| "P2342fnddd20": { | "P2342fnddd20": { | |||
| "mayRead": true, | "mayRead": true, | |||
| "mayWrite": true, | "mayWrite": true, | |||
| "mayAdmin": false | "mayAdmin": false | |||
| } | } | |||
| } | } | |||
| } | } | |||
| } | } | |||
| }, "0" ]] | }, "0" ]] | |||
| Figure 4 | Figure 4: "methodCalls" Property of a JMAP Request | |||
| 5. Internationalisation Considerations | 5. Internationalization Considerations | |||
| Experience has shown that unrestricted use of Unicode can lead to | Experience has shown that unrestricted use of Unicode can lead to | |||
| problems such as inconsistent rendering, users reading text and | problems such as inconsistent rendering, users reading text and | |||
| interpreting it differently than intended, and unexpected results | interpreting it differently than intended, and unexpected results | |||
| when copying text from one location to another. Servers MAY choose | when copying text from one location to another. Servers MAY choose | |||
| to mitigate this by restricting the set of characters allowed in | to mitigate this by restricting the set of characters allowed in | |||
| otherwise unconstrained String fields. The FreeformClass, as | otherwise unconstrained String fields. The FreeformClass, as | |||
| documented in [RFC8264], Section 4.3 might be a good starting point | documented in [RFC8264], Section 4.3, might be a good starting point | |||
| for this. | for this. | |||
| Attempts to set a value containing code points outside of the | Attempts to set a value containing code points outside of the | |||
| permissible set can be handled in a few ways by the server. The | permissible set can be handled in a few ways by the server. The | |||
| first option is to simply strip the forbidden characters and store | first option is to simply strip the forbidden characters and store | |||
| the resulting string. This is likely to be appropriate for control | the resulting string. This is likely to be appropriate for control | |||
| characters for example, where they can end up in data accidentally | characters, for example, where they can end up in data accidentally | |||
| due to copy-and-paste issues, and are probably invisible to the end | due to copy-and-paste issues and are probably invisible to the end | |||
| user. JMAP allows the server to transform data on create/update, as | user. JMAP allows the server to transform data on create/update, as | |||
| long as any changed properties are returned to the client in the /set | long as any changed properties are returned to the client in the | |||
| response, so it knows what has changed, as per [RFC8620], | "/set" response so it knows what has changed, as per [RFC8620], | |||
| Section 5.3. Alternatively, the server MAY just reject the create/ | Section 5.3. Alternatively, the server MAY just reject the create/ | |||
| update with an invalidProperties SetError. | update with an "invalidProperties" SetError. | |||
| 6. Security Considerations | 6. Security Considerations | |||
| All security considerations of JMAP [RFC8620] apply to this | All security considerations of JMAP [RFC8620] apply to this | |||
| specification. Additional considerations are detailed below. | specification. Additional considerations are detailed below. | |||
| 6.1. Spoofing | 6.1. Spoofing | |||
| Allowing users to edit their own Principal's name (and, to a lesser | Allowing users to edit their own Principal's name (and, to a lesser | |||
| extent, email, description, or type) could allow a user to change | extent, email, description, or type) could allow a user to change | |||
| their Principal to look like another user in the system, potentially | their Principal to look like another user in the system, potentially | |||
| tricking others into sharing private data with them. Servers may | tricking others into sharing private data with them. Servers may | |||
| choose to forbid this, and SHOULD keep logs of such changes to | choose to forbid this and SHOULD keep logs of such changes to provide | |||
| provide an audit trail. | an audit trail. | |||
| Note that simply forbidding the use of a name already in the system | Note that simply forbidding the use of a name already in the system | |||
| is insufficient protection, as a malicious user could still change | is insufficient protection, as a malicious user could still change | |||
| their name to something easily confused with the existing name by | their name to something easily confused with the existing name by | |||
| using trivial misspellings or visually similar Unicode characters. | using trivial misspellings or visually similar Unicode characters. | |||
| 6.2. Unnoticed Sharing | 6.2. Unnoticed Sharing | |||
| Sharing data with another user allows someone to turn a transitory | Sharing data with another user allows someone to turn a transitory | |||
| account compromise (e.g., brief access to an unlocked or logged-in | account compromise (e.g., brief access to an unlocked or logged-in | |||
| client) into a persistent compromise (by setting up sharing with a | client) into a persistent compromise (by setting up sharing with a | |||
| user that is controlled by the attacker). This can be mitigated by | user that is controlled by the attacker). This can be mitigated by | |||
| requiring further authorisation for configuring sharing, or sending | requiring further authorization for configuring sharing or sending | |||
| notifications to the sharer via another channel whenever a new sharee | notifications to the sharer via another channel whenever a new | |||
| is added. | permission is added. | |||
| 6.3. Denial of Service | 6.3. Denial of Service | |||
| By creating many changes to the sharing status of objects, a user can | By creating many changes to the sharing status of objects, a user can | |||
| cause many ShareNotifications to be generated, which could lead to | cause many ShareNotifications to be generated, which could lead to | |||
| resource exhaustion. Servers can mitigate this by coalescing | resource exhaustion. Servers can mitigate this by coalescing | |||
| multiple changes to the same object into a single notification, | multiple changes to the same object into a single notification, | |||
| limiting the maximum number of notifications it stores per user, and/ | limiting the maximum number of notifications it stores per user and/ | |||
| or rate limiting the changes to sharing permissions in the first | or rate-limiting the changes to sharing permissions in the first | |||
| place. Automatically deleting older notifications after reaching a | place. Automatically deleting older notifications after reaching a | |||
| limit can mean the user is not made aware of a sharing change, which | limit can mean the user is not made aware of a sharing change, which | |||
| can itself be a security issue. For this reason, it is better to | can itself be a security issue. For this reason, it is better to | |||
| coalesce changes and use other mitigation strategies. | coalesce changes and use other mitigation strategies. | |||
| 6.4. Unauthorised Principals | 6.4. Unauthorized Principals | |||
| The set of Principals within a shared environment MUST be strictly | The set of Principals within a shared environment MUST be strictly | |||
| controlled. If adding a new Principal is open to the public, risks | controlled. If adding a new Principal is open to the public, risks | |||
| include: | include: | |||
| * An increased risk of a user accidentally sharing data with an | * An increased risk of a user accidentally sharing data with an | |||
| unintended person. | unintended person. | |||
| * An attacker may share unwanted or offensive information with the | * An attacker sharing unwanted or offensive information with the | |||
| user. | user. | |||
| * An attacker may share items with spam content in the names in | * An attacker sharing items with spam content in the names in order | |||
| order to generate ShareNotification objects, which are likely to | to generate ShareNotification objects, which are likely to be | |||
| be prominently displayed to the sharee. | prominently displayed to the user receiving them. | |||
| 7. IANA Considerations | 7. IANA Considerations | |||
| 7.1. JMAP Capability Registration for "principals" | 7.1. JMAP Capability Registration for "principals" | |||
| IANA will register the "principals" JMAP Capability as follows: | IANA has registered "principals" in the "JMAP Capabilities" registry | |||
| as follows: | ||||
| Capability Name: urn:ietf:params:jmap:principals | ||||
| Specification document: this document | ||||
| Intended use: common | ||||
| Change Controller: IETF | ||||
| Security and privacy considerations: this document, Section 6 | Capability Name: urn:ietf:params:jmap:principals | |||
| Intended Use: common | ||||
| Change Controller: IETF | ||||
| Security and Privacy Considerations: RFC 9670, Section 6 | ||||
| Reference: RFC 9670 | ||||
| 7.2. JMAP Capability Registration for "principals:owner" | 7.2. JMAP Capability Registration for "principals:owner" | |||
| IANA will register the "principals:owner" JMAP Capability as follows: | IANA has registered "principals:owner" in the "JMAP Capabilities" | |||
| registry as follows: | ||||
| Capability Name: urn:ietf:params:jmap:principals:owner | ||||
| Specification document: this document | ||||
| Intended use: common | ||||
| Change Controller: IETF | ||||
| Security and privacy considerations: this document, Section 6 | Capability Name: urn:ietf:params:jmap:principals:owner | |||
| Intended Use: common | ||||
| Change Controller: IETF | ||||
| Security and Privacy Considerations: RFC 9670, Section 6 | ||||
| Reference: RFC 9670 | ||||
| 7.3. JMAP Data Type Registration for "Principal" | 7.3. JMAP Data Type Registration for "Principal" | |||
| IANA will register the "Principal" JMAP Data Type as follows: | IANA has registered "Principal" in the "JMAP Data Types" registry as | |||
| follows: | ||||
| Type Name: Principal | ||||
| Can reference blobs: no | ||||
| Can Use for State Change: yes | ||||
| Capability: urn:ietf:params:jmap:principals | ||||
| Specification document: this document | Type Name: Principal | |||
| Can Reference Blobs: No | ||||
| Can Use for State Change: Yes | ||||
| Capability: urn:ietf:params:jmap:principals | ||||
| Reference: RFC 9670 | ||||
| 7.4. JMAP Data Type Registration for "ShareNotification" | 7.4. JMAP Data Type Registration for "ShareNotification" | |||
| IANA will register the "ShareNotification" JMAP Data Type as follows: | IANA has registered "ShareNotification" in the "JMAP Data Types" | |||
| registry as follows: | ||||
| Type Name: ShareNotification | ||||
| Can reference blobs: no | ||||
| Can Use for State Change: yes | ||||
| Capability: urn:ietf:params:jmap:principals | Type Name: ShareNotification | |||
| Can Reference Blobs: No | ||||
| Can Use for State Change: Yes | ||||
| Capability: urn:ietf:params:jmap:principals | ||||
| Reference: RFC 9670 | ||||
| Specification document: this document | 8. References | |||
| 8. Normative References | 8.1. Normative References | |||
| [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate | [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate | |||
| Requirement Levels", BCP 14, RFC 2119, | Requirement Levels", BCP 14, RFC 2119, | |||
| DOI 10.17487/RFC2119, March 1997, | DOI 10.17487/RFC2119, March 1997, | |||
| <https://www.rfc-editor.org/info/rfc2119>. | <https://www.rfc-editor.org/info/rfc2119>. | |||
| [RFC5322] Resnick, P., Ed., "Internet Message Format", RFC 5322, | [RFC5322] Resnick, P., Ed., "Internet Message Format", RFC 5322, | |||
| DOI 10.17487/RFC5322, October 2008, | DOI 10.17487/RFC5322, October 2008, | |||
| <https://www.rfc-editor.org/info/rfc5322>. | <https://www.rfc-editor.org/info/rfc5322>. | |||
| [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC | [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC | |||
| 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, | 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, | |||
| May 2017, <https://www.rfc-editor.org/info/rfc8174>. | May 2017, <https://www.rfc-editor.org/info/rfc8174>. | |||
| [RFC8620] Jenkins, N. and C. Newman, "The JSON Meta Application | [RFC8620] Jenkins, N. and C. Newman, "The JSON Meta Application | |||
| Protocol (JMAP)", RFC 8620, DOI 10.17487/RFC8620, July | Protocol (JMAP)", RFC 8620, DOI 10.17487/RFC8620, July | |||
| 2019, <https://www.rfc-editor.org/info/rfc8620>. | 2019, <https://www.rfc-editor.org/info/rfc8620>. | |||
| 9. Informative References | 8.2. Informative References | |||
| [IANA-JMAP] | ||||
| IANA, "JMAP Data Types", | ||||
| <https://www.iana.org/assignments/jmap>. | ||||
| [IANA-TZDB] | ||||
| IANA, "Time Zone Database", | ||||
| <https://www.iana.org/time-zones>. | ||||
| [RFC8264] Saint-Andre, P. and M. Blanchet, "PRECIS Framework: | [RFC8264] Saint-Andre, P. and M. Blanchet, "PRECIS Framework: | |||
| Preparation, Enforcement, and Comparison of | Preparation, Enforcement, and Comparison of | |||
| Internationalized Strings in Application Protocols", | Internationalized Strings in Application Protocols", | |||
| RFC 8264, DOI 10.17487/RFC8264, October 2017, | RFC 8264, DOI 10.17487/RFC8264, October 2017, | |||
| <https://www.rfc-editor.org/info/rfc8264>. | <https://www.rfc-editor.org/info/rfc8264>. | |||
| Author's Address | Author's Address | |||
| Neil Jenkins (editor) | Neil Jenkins (editor) | |||
| Fastmail | Fastmail | |||
| PO Box 234, Collins St West | PO Box 234, Collins St West | |||
| Melbourne VIC 8007 | Melbourne VIC 8007 | |||
| Australia | Australia | |||
| Email: neilj@fastmailteam.com | Email: neilj@fastmailteam.com | |||
| URI: https://www.fastmail.com | URI: https://www.fastmail.com | |||
| End of changes. 126 change blocks. | ||||
| 331 lines changed or deleted | 368 lines changed or added | |||
This html diff was produced by rfcdiff 1.48. | ||||