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