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. |