idnits 2.17.1 draft-ietf-jmap-websocket-03.txt: Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info): ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt: ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/checklist : ---------------------------------------------------------------------------- No issues found here. Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year == The document seems to lack the recommended RFC 2119 boilerplate, even if it appears to use RFC 2119 keywords -- however, there's a paragraph with a matching beginning. Boilerplate error? (The document does seem to have the reference to RFC 2119 which the ID-Checklist requires). -- The document date (July 22, 2019) is 1733 days in the past. Is this intentional? Checking references for intended status: Proposed Standard ---------------------------------------------------------------------------- (See RFCs 3967 and 4897 for information about using normative references to lower-maturity documents in RFCs) -- Looks like a reference, but probably isn't: '1' on line 510 ** Obsolete normative reference: RFC 7235 (Obsoleted by RFC 9110) Summary: 1 error (**), 0 flaws (~~), 2 warnings (==), 2 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 JMAP K. Murchison 3 Internet-Draft Fastmail 4 Intended status: Standards Track July 22, 2019 5 Expires: January 23, 2020 7 A JSON Meta Application Protocol (JMAP) Subprotocol for WebSocket 8 draft-ietf-jmap-websocket-03 10 Abstract 12 This document defines a binding for the JSON Meta Application 13 Protocol (JMAP) over a WebSocket transport layer. The WebSocket 14 binding for JMAP provides higher performance than the current HTTP 15 binding for JMAP. 17 Status of This Memo 19 This Internet-Draft is submitted in full conformance with the 20 provisions of BCP 78 and BCP 79. 22 Internet-Drafts are working documents of the Internet Engineering 23 Task Force (IETF). Note that other groups may also distribute 24 working documents as Internet-Drafts. The list of current Internet- 25 Drafts is at https://datatracker.ietf.org/drafts/current/. 27 Internet-Drafts are draft documents valid for a maximum of six months 28 and may be updated, replaced, or obsoleted by other documents at any 29 time. It is inappropriate to use Internet-Drafts as reference 30 material or to cite them other than as "work in progress." 32 This Internet-Draft will expire on January 23, 2020. 34 Copyright Notice 36 Copyright (c) 2019 IETF Trust and the persons identified as the 37 document authors. All rights reserved. 39 This document is subject to BCP 78 and the IETF Trust's Legal 40 Provisions Relating to IETF Documents 41 (https://trustee.ietf.org/license-info) in effect on the date of 42 publication of this document. Please review these documents 43 carefully, as they describe your rights and restrictions with respect 44 to this document. Code Components extracted from this document must 45 include Simplified BSD License text as described in Section 4.e of 46 the Trust Legal Provisions and are provided without warranty as 47 described in the Simplified BSD License. 49 Table of Contents 51 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2 52 2. Conventions Used in This Document . . . . . . . . . . . . . . 3 53 3. Discovering Support for JMAP over WebSocket . . . . . . . . . 3 54 4. JMAP Subprotocol . . . . . . . . . . . . . . . . . . . . . . 3 55 4.1. Handshake . . . . . . . . . . . . . . . . . . . . . . . . 4 56 4.2. WebSocket Messages . . . . . . . . . . . . . . . . . . . 4 57 4.2.1. JMAP Requests . . . . . . . . . . . . . . . . . . . . 4 58 4.2.2. JMAP Responses . . . . . . . . . . . . . . . . . . . 5 59 4.2.3. JMAP Request-level Errors . . . . . . . . . . . . . . 5 60 4.2.4. JMAP Push Notifications . . . . . . . . . . . . . . . 5 61 4.3. Examples . . . . . . . . . . . . . . . . . . . . . . . . 7 62 5. Security Considerations . . . . . . . . . . . . . . . . . . . 11 63 6. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 11 64 6.1. Registration of the WebSocket JMAP Subprotocol . . . . . 11 65 7. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 11 66 8. References . . . . . . . . . . . . . . . . . . . . . . . . . 11 67 8.1. Normative References . . . . . . . . . . . . . . . . . . 11 68 8.2. Informative References . . . . . . . . . . . . . . . . . 12 69 8.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 12 70 Appendix A. Change History (To be removed by RFC Editor before 71 publication) . . . . . . . . . . . . . . . . . . . . 12 72 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 13 74 1. Introduction 76 JMAP [RFC8620] over HTTP [RFC7235] requires that every JMAP API 77 request be authenticated. Depending on the type of authentication 78 used by the JMAP client and the configuration of the JMAP server, 79 authentication could be an expensive operation both in time and 80 resources. In such circumstances, authenticating every JMAP API 81 request may harm performance. 83 The WebSocket [RFC6455] binding for JMAP eliminates this performance 84 hit by authenticating just the WebSocket handshake request and having 85 those credentials remain in effect for the duration of the WebSocket 86 connection. This binding supports JMAP API requests and responses, 87 with optional support for push notifications. 89 Furthermore, the WebSocket binding for JMAP can optionally compress 90 [RFC7692] both JMAP API requests and responses. Although compression 91 of HTTP responses is ubiquitous, compression of HTTP requests has 92 very low, if any deployment, and therefore isn't a viable option for 93 JMAP API requests over HTTP. 95 2. Conventions Used in This Document 97 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 98 "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and 99 "OPTIONAL" in this document are to be interpreted as described in BCP 100 14 [1] [RFC2119] [RFC8174] when, and only when, they appear in all 101 capitals, as shown here. 103 The same terminology is used in this document as in the core JMAP 104 specification. 106 3. Discovering Support for JMAP over WebSocket 108 The JMAP capabilities object is returned as part of the standard JMAP 109 Session object (see Section 2 of [RFC8620]). Servers supporting this 110 specification MUST add a property named 111 "urn:ietf:params:jmap:websocket" to the capabilities object. The 112 value of this property is an object which MUST contain the following 113 information on server capabilities: 115 o webSocketUrl: "String" 117 The URL to use for initiating a JMAP over WebSocket handshake. 119 o supportsWebSocketPush: "Boolean" 121 This is true if the server supports push notifications over the 122 WebSocket, as described in Section 4.2.4. 124 Example: 126 "urn:ietf:params:jmap:websocket": { 127 "webSocketUrl": "https://server.example.com/jmap/ws/", 128 "supportsWebSocketPush": true 129 } 131 4. JMAP Subprotocol 133 The term WebSocket subprotocol refers to an application-level 134 protocol layered on top of a WebSocket connection. This document 135 specifies the WebSocket JMAP subprotocol for carrying JMAP API 136 requests, responses, and optional push notifications through a 137 WebSocket connection. Binary data MUST NOT be uploaded or downloaded 138 through a WebSocket JMAP connection. Binary data is handled per 139 Section 6 of [RFC8620] via a separate HTTP connection or stream. 141 4.1. Handshake 143 The JMAP WebSocket client and JMAP WebSocket server negotiate the use 144 of the WebSocket JMAP subprotocol during the WebSocket handshake, 145 either via a HTTP/1.1 Upgrade request (see Section 1.3 of [RFC6455]) 146 or a HTTP/2 Extended CONNECT request (see Section 5 of [RFC8441]). 148 Regardless of the method used for the WebSocket handshake, the client 149 MUST make an authenticated [RFC7235] HTTP request on the JMAP 150 "webSocketUrl" (Section 3), and the client MUST include the value 151 "jmap" in the list of protocols for the "Sec-WebSocket-Protocol" 152 header field. The reply from the server MUST also contain "jmap" in 153 its corresponding "Sec-WebSocket-Protocol" header field in order for 154 a JMAP subprotocol connection to be established. 156 If a client receives a handshake response that does not include 157 "jmap" in the "Sec-WebSocket-Protocol" header, then a JMAP 158 subprotocol WebSocket connection was not established and the client 159 MUST close the WebSocket connection. 161 Once the handshake has successfully completed, the WebSocket 162 connection is established and can be used for JMAP API requests, 163 responses, and optional push notifications. Other message types MUST 164 NOT be transmitted over this connection. 166 The credentials used for authenticating the HTTP request to initiate 167 the handshake remain in effect for the duration of the WebSocket 168 connection. 170 4.2. WebSocket Messages 172 Data frame messages in the JMAP subprotocol MUST be of the text type 173 and contain UTF-8 encoded data. The messages MUST be in the form of 174 a single JMAP Request object (see Section 3.2 of [RFC8620]), JMAP 175 WebSocketPushEnable object (see Section 4.2.4.2), or JMAP 176 WebSocketPushDisable object (see Section 4.2.4.3) when sent from the 177 client to the server, and in the form of a single JMAP Response 178 object, JSON Problem Details object, or JMAP StateChange object (see 179 Sections 3.3, 3.5.1, and 7.1 respectively of [RFC8620]) when sent 180 from the server to the client. 182 4.2.1. JMAP Requests 184 This specification adds two extra arguments to the Request object: 186 o @type: "String" 188 This MUST be the string "Request". 190 o id: "String" (optional) 192 A client-specified identifier for the request. 194 JMAP over WebSocket allows the server to process requests out of 195 order. The client-specified identifier is used as a mechanism for 196 the client to correlate requests and responses. 198 Additionally, the "maxConcurrentRequests" field in the "capabilities" 199 object (see Section 2 of [RFC8620]) limits the number of inflight 200 requests over the WebSocket. 202 4.2.2. JMAP Responses 204 This specification adds two extra arguments to the Response object: 206 o @type: "String" 208 This MUST be the string "Response". 210 o requestId: "String" (optional; only returned if given in the 211 request) 213 The client-specified identifier in the corresponding request. 215 4.2.3. JMAP Request-level Errors 217 This specification adds two extra arguments to the Problem Details 218 object: 220 o @type: "String" 222 This MUST be the string "RequestError". 224 o requestId: "String" (optional; only returned if given in the 225 request) 227 The client-specified identifier in the corresponding request. 229 4.2.4. JMAP Push Notifications 231 JMAP over WebSocket servers that support push notifications on the 232 WebSocket will advertise a "supportsWebSocketPush" property with a 233 value of true in the server capabilities object. 235 4.2.4.1. Notification Format 237 All push notifications take the form of a standard StateChange object 238 (see Section 7.1 of [RFC8620]). 240 This specification adds one extra argument to the StateChange object: 242 o pushState: "String" (optional) 244 A (preferably short) string representing the state on the server 245 for ALL of the data types in the account (not just the objects 246 returned in this call). 248 4.2.4.2. Enabling Notifications 250 A client enables push notifications from the server by sending a 251 WebSocketPushEnable object to the server. A WebSocketPushEnable 252 object has the following properties: 254 o @type: "String" This MUST be the string "WebSocketPushEnable". 256 o dataTypes: "String[]|null" 258 A list of data type names (e.g. "Mailbox", "Email") that the 259 client is interested in. A StateChange notification will only be 260 sent if the data for one of these types changes. Other types are 261 omitted from the TypeState object. If null, changes will be 262 pushed for all supported data types. 264 o pushState: "String" (optional) 266 The last "pushState" token that the client received from the 267 server. Upon receipt of a "pushState" token, the server SHOULD 268 immediately send all changes since that state token. 270 4.2.4.3. Disabling Notifications 272 A client disables push notifications from the server by sending a 273 WebSocketPushDisable object to the server. A WebSocketPushDisable 274 object has the following property: 276 o @type: "String" 278 This MUST be the string "WebSocketPushDisable". 280 4.3. Examples 282 The following examples show WebSocket JMAP opening handshakes, a JMAP 283 Core/echo request and response, and a subsequent closing handshake. 284 The examples assume that the JMAP "webSocketUrl" has been advertised 285 in the JMAP Session object as "/jmap/ws/". Note that folding of 286 header fields is for editorial purposes only. 288 WebSocket JMAP connection via HTTP/1.1 with push notifications for 289 mail [I-D.ietf-jmap-mail] enabled: 291 [[ From Client ]] [[ From Server ]] 293 GET /jmap/ws/ HTTP/1.1 294 Host: server.example.com 295 Upgrade: websocket 296 Connection: Upgrade 297 Authorization: Basic Zm9vOmJhcg== 298 Sec-WebSocket-Key: 299 dGhlIHNhbXBsZSBub25jZQ== 300 Sec-WebSocket-Protocol: jmap 301 Sec-WebSocket-Version: 13 302 Origin: http://www.example.com 304 HTTP/1.1 101 Switching Protocols 305 Upgrade: websocket 306 Connection: Upgrade 307 Sec-WebSocket-Accept: 308 s3pPLMBiTxaQ9kYGzzhZRbK+xOo= 309 Sec-WebSocket-Protocol: jmap 311 [WebSocket connection established] 313 WS_DATA 314 { 315 "@type": "WebSocketPushEnable", 316 "dataTypes": [ "Mailbox", "Email" ], 317 "pushState": "aaa" 318 } 320 WS_DATA 321 { 322 "@type": "StateChange", 323 "changed": { 324 "a456": { 325 "Email": "d35ecb040aab" 326 } 327 }, 328 "pushState": "bbb" 329 } 331 WS_DATA 332 { 333 "@type": "Request", 334 "id": "R1", 335 "using": [ "urn:ietf:params:jmap:core" ], 336 "methodCalls": [ 337 [ 338 "Core/echo", { 339 "hello": true, 340 "high": 5 341 }, 342 "b3ff" 343 ] 344 ] 345 } 347 WS_DATA 348 { 349 "@type": "Response", 350 "requestId": "R1", 351 "methodResponses": [ 352 [ 353 "Core/echo", { 354 "hello": true, 355 "high": 5 356 }, 357 "b3ff" 358 ] 359 ] 360 } 362 WS_DATA 363 The quick brown fox jumps 364 over the lazy dog. 366 WS_DATA 367 { 368 "@type": "RequestError", 369 "requestId": null, 370 "type": 371 "urn:ietf:params:jmap:error:notJSON", 372 "status": 400, 373 "detail": 374 "The request did not parse as I-JSON." 375 } 376 WS_DATA 377 { 378 "@type": "StateChange", 379 "changed": { 380 "a123": { 381 "Mailbox": "0af7a512ce70" 382 } 383 } 384 "pushState": "ccc" 385 } 387 WS_CLOSE 389 WS_CLOSE 391 [WebSocket connection closed] 392 WebSocket JMAP connection on a HTTP/2 stream which also negotiates 393 compression [RFC7692]: 395 [[ From Client ]] [[ From Server ]] 397 SETTINGS 398 SETTINGS_ENABLE_CONNECT_PROTOCOL = 1 400 HEADERS + END_HEADERS 401 :method = CONNECT 402 :protocol = websocket 403 :scheme = https 404 :path = /jmap/ws/ 405 :authority = server.example.com 406 authorization = Basic Zm9vOmJhcg== 407 sec-websocket-protocol = jmap 408 sec-websocket-version = 13 409 sec-websocket-extensions = 410 permessage-deflate 411 origin = http://www.example.com 413 HEADERS + END_HEADERS 414 :status = 200 415 sec-websocket-protocol = jmap 416 sec-websocket-extensions = 417 permessage-deflate 419 [WebSocket connection established] 421 DATA 422 WS_DATA 423 [compressed text] 425 DATA 426 WS_DATA 427 [compressed text] 429 ... 431 DATA + END_STREAM 432 WS_CLOSE 434 DATA + END_STREAM 435 WS_CLOSE 437 [WebSocket connection closed] 438 [HTTP/2 stream closed] 440 5. Security Considerations 442 The security considerations for both WebSocket (see Section 10 of 443 [RFC6455]) and JMAP (see Section 8 of [RFC8620]) apply to the 444 WebSocket JMAP subprotocol. 446 6. IANA Considerations 448 6.1. Registration of the WebSocket JMAP Subprotocol 450 This specification requests IANA to register the WebSocket JMAP 451 subprotocol under the "WebSocket Subprotocol Name" Registry with the 452 following data: 454 Subprotocol Identifier: jmap 456 Subprotocol Common Name: WebSocket Transport for JMAP (JSON Meta 457 Application Protocol) 459 Subprotocol Definition: RFCXXXX (this document) 461 7. Acknowledgments 463 The author would like to thank the following individuals for 464 contributing their ideas and support for writing this specification: 465 Neil Jenkins, Robert Mueller, and Chris Newman. 467 8. References 469 8.1. Normative References 471 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 472 Requirement Levels", BCP 14, RFC 2119, 473 DOI 10.17487/RFC2119, March 1997, 474 . 476 [RFC6455] Fette, I. and A. Melnikov, "The WebSocket Protocol", 477 RFC 6455, DOI 10.17487/RFC6455, December 2011, 478 . 480 [RFC7235] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer 481 Protocol (HTTP/1.1): Authentication", RFC 7235, 482 DOI 10.17487/RFC7235, June 2014, 483 . 485 [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 486 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 487 May 2017, . 489 [RFC8441] McManus, P., "Bootstrapping WebSockets with HTTP/2", 490 RFC 8441, DOI 10.17487/RFC8441, September 2018, 491 . 493 [RFC8620] Jenkins, N. and C. Newman, "The JSON Meta Application 494 Protocol (JMAP)", RFC 8620, DOI 10.17487/RFC8620, July 495 2019, . 497 8.2. Informative References 499 [I-D.ietf-jmap-mail] 500 Jenkins, N. and C. Newman, "JMAP (JSON Meta Application 501 Protocol) for Mail", draft-ietf-jmap-mail-16 (work in 502 progress), March 2019. 504 [RFC7692] Yoshino, T., "Compression Extensions for WebSocket", 505 RFC 7692, DOI 10.17487/RFC7692, December 2015, 506 . 508 8.3. URIs 510 [1] https://tools.ietf.org/html/bcp14 512 Appendix A. Change History (To be removed by RFC Editor before 513 publication) 515 Changes since ietf-02: 517 o Updated JMAP Core reference to RFC 8620. 519 o Added 'WebSocketPushDisable' object. 521 o Editorial and formatting changes. 523 Changes since ietf-01: 525 o Changed 'wsURL' to 'webSocketUrl' and removed push query option. 527 o Added 'supportsWebSocketPush' capability. 529 o Added '@type' argument to Request object. 531 o Added 'WebSocketPushEnable' object. 533 o Added 'pushState' argument to StateChange object. 535 o Updated example. 537 o Minor Editorial changes. 539 Changes since ietf-00: 541 o Added text describing advertisement of and selection of optional 542 push notifications. 544 o Minor Editorial changes. 546 Changes since murchison-02: 548 o Renamed as a JMAP WG document. 550 o Allow out of order processing. 552 o Allow push notifications. 554 o Modified examples. 556 o Add Security Considerations text. 558 o Minor Editorial changes. 560 Changes since murchison-01: 562 o Updated WebSocket over HTTP/2 reference to RFC8144. 564 Changes since murchison-00: 566 o Fleshed out section on discovery of support for JMAP over 567 WebSocket. 569 o Allow JSON Problem Details objects to be returned by the server 570 for toplevel errors. 572 o Mentioned the ability to compress JMAP API requests. 574 o Minor Editorial changes. 576 Author's Address 577 Kenneth Murchison 578 Fastmail US LLC 579 1429 Walnut Street - Suite 1201 580 Philadelphia, PA 19102 581 USA 583 Email: murch@fastmailteam.com 584 URI: http://www.fastmail.com/