summaryrefslogtreecommitdiff
path: root/doc/rfc/rfc9670.txt
blob: 13dd6891b02e2f590a6721649bac96142008f446 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
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