5Internet Engineering Task Force (IETF) K. Murchison
6Request for Comments: 8887 Fastmail
7Category: Standards Track August 2020
11 A JSON Meta Application Protocol (JMAP) Subprotocol for WebSocket
15 This document defines a binding for the JSON Meta Application
16 Protocol (JMAP) over a WebSocket transport layer. The WebSocket
17 binding for JMAP provides higher performance than the current HTTP
22 This is an Internet Standards Track document.
24 This document is a product of the Internet Engineering Task Force
25 (IETF). It represents the consensus of the IETF community. It has
26 received public review and has been approved for publication by the
27 Internet Engineering Steering Group (IESG). Further information on
28 Internet Standards is available in Section 2 of RFC 7841.
30 Information about the current status of this document, any errata,
31 and how to provide feedback on it may be obtained at
32 https://www.rfc-editor.org/info/rfc8887.
36 Copyright (c) 2020 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.
52 2. Conventions Used in This Document
53 3. Discovering Support for JMAP over WebSocket
57 4.3. WebSocket Messages
58 4.3.1. Handling Invalid Data
61 4.3.4. JMAP Request-Level Errors
62 4.3.5. JMAP Push Notifications
64 5. Security Considerations
65 5.1. Connection Confidentiality and Integrity
66 5.2. Non-browser Clients
67 6. IANA Considerations
68 6.1. Registration of the WebSocket JMAP Subprotocol
70 7.1. Normative References
71 7.2. Informative References
77 JMAP [RFC8620] over HTTP [RFC7235] requires that every JMAP API
78 request be authenticated. Depending on the type of authentication
79 used by the JMAP client and the configuration of the JMAP server,
80 authentication could be an expensive operation both in time and
81 resources. In such circumstances, reauthenticating for every JMAP
82 API request may harm performance.
84 The WebSocket [RFC6455] binding for JMAP eliminates this performance
85 hit by authenticating just the WebSocket handshake request and having
86 those credentials remain in effect for the duration of the WebSocket
87 connection. This binding supports JMAP API requests and responses,
88 with optional support for push notifications.
90 Furthermore, the WebSocket binding for JMAP can optionally compress
91 [RFC7692] both JMAP API requests and responses. Although compression
92 of HTTP responses is ubiquitous, compression of HTTP requests has
93 very low, if any, deployment and therefore isn't a viable option for
94 JMAP API requests over HTTP.
962. Conventions Used in This Document
98 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
99 "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
100 "OPTIONAL" in this document are to be interpreted as described in
101 BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all
102 capitals, as shown here.
104 This document uses the terminology defined in the core JMAP
105 specification [RFC8620].
1073. Discovering Support for JMAP over WebSocket
109 The JMAP capabilities object is returned as part of the standard JMAP
110 Session object (see Section 2 of [RFC8620]). Servers supporting this
111 specification MUST add a property named
112 "urn:ietf:params:jmap:websocket" to the capabilities object. The
113 value of this property is an object that MUST contain the following
114 information on server capabilities:
118 The wss-URI (see Section 3 of [RFC6455]) to use for initiating a
119 JMAP-over-WebSocket handshake (the "WebSocket URL endpoint"
122 * supportsPush: "Boolean"
124 This is true if the server supports push notifications over the
125 WebSocket, as described in Section 4.3.5.
129 "urn:ietf:params:jmap:websocket": {
130 "url": "wss://server.example.com/jmap/ws/",
136 The term WebSocket subprotocol refers to an application-level
137 protocol layered on top of a WebSocket connection. This document
138 specifies the WebSocket JMAP subprotocol for carrying JMAP API
139 requests, responses, and optional push notifications through a
140 WebSocket connection. Binary data is handled per Section 6 of
141 [RFC8620] (via a separate HTTP connection or stream) or per a future
142 extension to JMAP or this specification.
146 A JMAP WebSocket connection is authenticated by presenting a user's
147 credentials in the HTTP request [RFC7235] that initiates the
148 WebSocket handshake. See Section 8.2 of [RFC8620] for
149 recommendations regarding the selection of HTTP authentication
154 The JMAP WebSocket client and JMAP WebSocket server negotiate the use
155 of the WebSocket JMAP subprotocol during the WebSocket handshake,
156 either via an HTTP/1.1 Upgrade request (see Section 4 of [RFC6455])
157 or an HTTP/2 Extended CONNECT request (see Section 5 of [RFC8441]).
158 The WebSocket JMAP subprotocol is also intended to run over future
159 bindings of HTTP (e.g., HTTP/3) provided that there is a defined
160 mechanism for performing a WebSocket handshake over that binding.
162 Regardless of the method used for the WebSocket handshake, the client
163 MUST first perform a TLS handshake on a JMAP WebSocket URL endpoint
164 (Section 3) having the "wss://" scheme (WebSocket over TLS) in
165 accordance with the requirements of running the particular binding of
166 HTTP over TLS (see [RFC2818] and Section 4.1 of [RFC6455] for
167 HTTP/1.1 and Section 9.2 of [RFC7540] for HTTP/2). If the TLS
168 handshake fails, the client MUST close the connection. Otherwise,
169 the client MUST make an authenticated HTTP request [RFC7235] on the
170 encrypted connection and MUST include the value "jmap" in the list of
171 protocols for the "Sec-WebSocket-Protocol" header field.
173 The reply from the server MUST also contain a corresponding "Sec-
174 WebSocket-Protocol" header field with a value of "jmap" in order for
175 a JMAP subprotocol connection to be established.
177 Once the handshake has successfully completed, the WebSocket
178 connection is established and can be used for JMAP API requests,
179 responses, and optional push notifications. Other message types MUST
180 NOT be transmitted over this connection.
182 The credentials used for authenticating the HTTP request to initiate
183 the handshake remain in effect for the duration of the WebSocket
184 connection. If the authentication credentials for the user expire,
185 the server can either treat subsequent requests as if they are
186 unauthenticated or close the WebSocket connection. In the latter
187 case, the server MAY send a Close frame with a status code of 1008
188 (Policy Violation), as defined in Section 7.4.1 of [RFC6455].
1904.3. WebSocket Messages
192 Data frame messages in the JMAP subprotocol MUST be text frames and
193 contain UTF-8 encoded data. The messages MUST be in the form of a
194 single JMAP Request object (see Section 3.3 of [RFC8620]), JMAP
195 WebSocketPushEnable object (see Section 4.3.5.2), or JMAP
196 WebSocketPushDisable object (see Section 4.3.5.3) when sent from the
197 client to the server, and MUST be in the form of a single JMAP
198 Response object, JSON Problem Details object, or JMAP StateChange
199 object (see Sections 3.4, 3.6.1, and 7.1 of [RFC8620], respectively)
200 when sent from the server to the client.
202 Note that fragmented WebSocket messages (split over multiple text
203 frames) MUST be coalesced prior to parsing them as JSON objects.
2054.3.1. Handling Invalid Data
207 If a client or server receives a binary frame, the endpoint can
208 either ignore the frame or close the WebSocket connection. In the
209 latter case, the endpoint MAY send a Close frame with a status code
210 of 1003 (Unsupported Data), as defined in Section 7.4.1 of [RFC6455].
212 If a client receives a message that is not in the form of a JSON
213 Problem Details object, a JMAP Response object, or a JMAP StateChange
214 object, the client can either ignore the message or close the
215 WebSocket connection. In the latter case, the endpoint MAY send a
216 Close frame with a status code of 1007 (Invalid frame payload data),
217 as defined in Section 7.4.1 of [RFC6455].
219 A server MUST return an appropriate JSON Problem Details object
220 (Section 4.3.4) for any request-level errors (e.g., an invalid JMAP
221 object, an unsupported capability or method call, or exceeding a
222 server request limit).
226 The specification extends the Request object with two additional
227 arguments when used over a WebSocket:
231 This MUST be the string "Request".
233 * id: "String" (optional)
235 A client-specified identifier for the request to be echoed back in
236 the response to this request.
238 JMAP over WebSocket allows the server to process requests out of
239 order. The client-specified identifier is used as a mechanism for
240 the client to correlate requests and responses.
242 Additionally, the "maxConcurrentRequests" limit in the "capabilities"
243 object (see Section 2 of [RFC8620]) also applies to requests made on
244 the WebSocket connection. When using the WebSocket JMAP subprotocol
245 over a binding of HTTP that allows multiplexing of requests (e.g.,
246 HTTP/2), this limit applies to the sum of requests made on both the
247 JMAP API endpoint and the WebSocket connection.
251 The specification extends the Response object with two additional
252 arguments when used over a WebSocket:
256 This MUST be the string "Response".
258 * requestId: "String" (optional; MUST be returned if an identifier
259 is included in the request)
261 The client-specified identifier in the corresponding request.
2634.3.4. JMAP Request-Level Errors
265 The specification extends the Problem Details object for request-
266 level errors (see Section 3.6.1 of [RFC8620]) with two additional
267 arguments when used over a WebSocket:
271 This MUST be the string "RequestError".
273 * requestId: "String" (optional; MUST be returned if given in the
276 The client-specified identifier in the corresponding request.
2784.3.5. JMAP Push Notifications
280 JMAP-over-WebSocket servers that support push notifications on the
281 WebSocket will advertise a "supportsPush" property with a value of
282 true in the "urn:ietf:params:jmap:websocket" server capabilities
2854.3.5.1. Notification Format
287 All push notifications take the form of a standard StateChange object
288 (see Section 7.1 of [RFC8620]).
290 The specification extends the StateChange object with one additional
291 argument when used over a WebSocket:
293 * pushState: "String" (optional)
295 A (preferably short) string that encodes the entire server state
296 visible to the user (not just the objects returned in this call).
298 The purpose of the "pushState" token is to allow a client to
299 immediately get any changes that occurred while it was
300 disconnected (see Section 4.3.5.2). If the server does not
301 support "pushState" tokens, the client will have to issue a series
302 of "/changes" requests (see Section 5.2 of [RFC8620]) upon
303 reconnection to update its state to match that of the server.
3054.3.5.2. Enabling Notifications
307 A client enables push notifications from the server for the current
308 connection by sending a WebSocketPushEnable object to the server. A
309 WebSocketPushEnable object has the following properties:
313 This MUST be the string "WebSocketPushEnable".
315 * dataTypes: "String[]|null"
317 A list of data type names (e.g., "Mailbox" or "Email") that the
318 client is interested in. A StateChange notification will only be
319 sent if the data for one of these types changes. Other types are
320 omitted from the TypeState object. If null, changes will be
321 pushed for all supported data types.
323 * pushState: "String" (optional)
325 The last "pushState" token that the client received from the
326 server. Upon receipt of a "pushState" token, the server SHOULD
327 immediately send all changes since that state token.
3294.3.5.3. Disabling Notifications
331 A client disables push notifications from the server for the current
332 connection by sending a WebSocketPushDisable object to the server. A
333 WebSocketPushDisable object has the following property:
337 This MUST be the string "WebSocketPushDisable".
341 The following examples show WebSocket JMAP opening handshakes, a JMAP
342 Core/echo request and response, and a subsequent closing handshake.
343 The examples assume that the JMAP WebSocket URL endpoint has been
344 advertised in the JMAP Session object as having a path of "/jmap/ws/"
345 and that TLS negotiation has already succeeded. Note that folding of
346 header fields is for editorial purposes only.
348 WebSocket JMAP connection via HTTP/1.1 with push notifications for
349 mail [RFC8621] is enabled. This example assumes that the client has
350 cached pushState "aaa" from a previous connection.
352 [[ From Client ]] [[ From Server ]]
354 GET /jmap/ws/ HTTP/1.1
355 Host: server.example.com
358 Authorization: Basic Zm9vOmJhcg==
360 dGhlIHNhbXBsZSBub25jZQ==
361 Sec-WebSocket-Protocol: jmap
362 Sec-WebSocket-Version: 13
363 Origin: https://www.example.com
365 HTTP/1.1 101 Switching Protocols
368 Sec-WebSocket-Accept:
369 s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
370 Sec-WebSocket-Protocol: jmap
372 [WebSocket connection established]
376 "@type": "WebSocketPushEnable",
377 "dataTypes": [ "Mailbox", "Email" ],
383 "@type": "StateChange",
386 "Mailbox": "d35ecb040aab"
396 "using": [ "urn:ietf:params:jmap:core" ],
424 The quick brown fox jumps
429 "@type": "RequestError",
432 "urn:ietf:params:jmap:error:notJSON",
435 "The request did not parse as I-JSON."
438 [A new email is received]
442 "@type": "StateChange",
445 "Email": "0af7a512ce70"
455 [WebSocket connection closed]
457 WebSocket JMAP connection on an HTTP/2 stream that also negotiates
458 compression [RFC7692]:
460 [[ From Client ]] [[ From Server ]]
463 SETTINGS_ENABLE_CONNECT_PROTOCOL = 1
465 HEADERS + END_HEADERS
467 :protocol = websocket
470 :authority = server.example.com
471 origin: https://example.com
472 authorization = Basic Zm9vOmJhcg==
473 sec-websocket-protocol = jmap
474 sec-websocket-version = 13
475 sec-websocket-extensions =
477 origin = https://www.example.com
479 HEADERS + END_HEADERS
481 sec-websocket-protocol = jmap
482 sec-websocket-extensions =
485 [WebSocket connection established]
503 [WebSocket connection closed]
504 [HTTP/2 stream closed]
5065. Security Considerations
508 The security considerations for both WebSocket (see Section 10 of
509 [RFC6455]) and JMAP (see Section 8 of [RFC8620]) apply to the
510 WebSocket JMAP subprotocol. Specific security considerations are
5135.1. Connection Confidentiality and Integrity
515 To ensure the confidentiality and integrity of data sent and received
516 via JMAP over WebSocket, the WebSocket connection MUST use TLS 1.2
517 [RFC5246] or later, following the recommendations in BCP 195
518 [RFC7525]. Servers SHOULD support TLS 1.3 [RFC8446] or later.
5205.2. Non-browser Clients
522 JMAP over WebSocket can be used by clients both running inside and
523 outside of a web browser. As such, the security considerations in
524 Sections 10.2 and 10.1 of [RFC6455] apply to those respective
5276. IANA Considerations
5296.1. Registration of the WebSocket JMAP Subprotocol
531 Per this specification, IANA has registered the following in the
532 "WebSocket Subprotocol Name Registry" within the "WebSocket Protocol
535 Subprotocol Identifier: jmap
537 Subprotocol Common Name: WebSocket Transport for JMAP (JSON Meta
538 Application Protocol)
540 Subprotocol Definition: RFC 8887
5447.1. Normative References
546 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
547 Requirement Levels", BCP 14, RFC 2119,
548 DOI 10.17487/RFC2119, March 1997,
549 <https://www.rfc-editor.org/info/rfc2119>.
551 [RFC2818] Rescorla, E., "HTTP Over TLS", RFC 2818,
552 DOI 10.17487/RFC2818, May 2000,
553 <https://www.rfc-editor.org/info/rfc2818>.
555 [RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security
556 (TLS) Protocol Version 1.2", RFC 5246,
557 DOI 10.17487/RFC5246, August 2008,
558 <https://www.rfc-editor.org/info/rfc5246>.
560 [RFC6455] Fette, I. and A. Melnikov, "The WebSocket Protocol",
561 RFC 6455, DOI 10.17487/RFC6455, December 2011,
562 <https://www.rfc-editor.org/info/rfc6455>.
564 [RFC7235] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer
565 Protocol (HTTP/1.1): Authentication", RFC 7235,
566 DOI 10.17487/RFC7235, June 2014,
567 <https://www.rfc-editor.org/info/rfc7235>.
569 [RFC7525] Sheffer, Y., Holz, R., and P. Saint-Andre,
570 "Recommendations for Secure Use of Transport Layer
571 Security (TLS) and Datagram Transport Layer Security
572 (DTLS)", BCP 195, RFC 7525, DOI 10.17487/RFC7525, May
573 2015, <https://www.rfc-editor.org/info/rfc7525>.
575 [RFC7540] Belshe, M., Peon, R., and M. Thomson, Ed., "Hypertext
576 Transfer Protocol Version 2 (HTTP/2)", RFC 7540,
577 DOI 10.17487/RFC7540, May 2015,
578 <https://www.rfc-editor.org/info/rfc7540>.
580 [RFC7692] Yoshino, T., "Compression Extensions for WebSocket",
581 RFC 7692, DOI 10.17487/RFC7692, December 2015,
582 <https://www.rfc-editor.org/info/rfc7692>.
584 [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
585 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
586 May 2017, <https://www.rfc-editor.org/info/rfc8174>.
588 [RFC8441] McManus, P., "Bootstrapping WebSockets with HTTP/2",
589 RFC 8441, DOI 10.17487/RFC8441, September 2018,
590 <https://www.rfc-editor.org/info/rfc8441>.
592 [RFC8446] Rescorla, E., "The Transport Layer Security (TLS) Protocol
593 Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018,
594 <https://www.rfc-editor.org/info/rfc8446>.
596 [RFC8620] Jenkins, N. and C. Newman, "The JSON Meta Application
597 Protocol (JMAP)", RFC 8620, DOI 10.17487/RFC8620, July
598 2019, <https://www.rfc-editor.org/info/rfc8620>.
6007.2. Informative References
602 [RFC8621] Jenkins, N. and C. Newman, "The JSON Meta Application
603 Protocol (JMAP) for Mail", RFC 8621, DOI 10.17487/RFC8621,
604 August 2019, <https://www.rfc-editor.org/info/rfc8621>.
608 The author would like to thank the following individuals for
609 contributing their ideas and support for writing this specification:
610 Neil Jenkins, Robert Mueller, and Chris Newman.
616 1429 Walnut Street, Suite 1201
617 Philadelphia, PA 19102
618 United States of America
620 Email: murch@fastmailteam.com
621 URI: http://www.fastmail.com/