rfc8887xml2.original.xml   rfc8887.xml 
<?xml version="1.0" encoding="utf-8"?> <?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc SYSTEM 'rfc2629.dtd' <!DOCTYPE rfc SYSTEM "rfc2629-xhtml.ent">
[
<!ENTITY rfc2119 PUBLIC '' <rfc xmlns:xi="http://www.w3.org/2001/XInclude" category="std"
'http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml'> ipr="trust200902" docName="draft-ietf-jmap-websocket-07" obsoletes=""
<!ENTITY rfc2818 PUBLIC '' updates="" submissionType="IETF" xml:lang="en" tocInclude="true"
'http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.2818.xml'> symRefs="true" sortRefs="true" tocDepth="3" version="3" number="8887"
<!ENTITY rfc5246 PUBLIC '' consensus="true">
'http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.5246.xml'> <!-- xml2rfc v2v3 conversion 2.43.0 -->
<!ENTITY rfc6455 PUBLIC ''
'http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.6455.xml'>
<!ENTITY rfc6570 PUBLIC ''
'http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.6570.xml'>
<!ENTITY rfc7230 PUBLIC ''
'http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7230.xml'>
<!ENTITY rfc7235 PUBLIC ''
'http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7235.xml'>
<!ENTITY rfc7525 PUBLIC ''
'http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7525.xml'>
<!ENTITY rfc7540 PUBLIC ''
'http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7540.xml'>
<!ENTITY rfc7692 PUBLIC ''
'http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7692.xml'>
<!ENTITY rfc8174 PUBLIC ''
'http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml'>
<!ENTITY rfc8441 PUBLIC ''
'http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8441.xml'>
<!ENTITY rfc8446 PUBLIC ''
'http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8446.xml'>
<!ENTITY rfc8620 PUBLIC ''
'http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8620.xml'>
<!ENTITY rfc8621 PUBLIC ''
'http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8621.xml'>
]>
<?xml-stylesheet type='text/xsl' href='rfc2629.xslt' ?>
<?rfc toc="yes"?>
<?rfc comments="yes"?>
<?rfc inline="yes"?>
<?rfc symrefs="yes"?>
<?rfc sortrefs="yes"?>
<?rfc compact="yes"?>
<?rfc subcompact="no"?>
<?rfc tocdepth="3"?>
<?rfc strict="yes"?>
<rfc category="std" ipr='trust200902'
docName='draft-ietf-jmap-websocket-07'>
<front> <front>
<title abbrev="JMAP Over WebSocket"> <title abbrev="JMAP over WebSocket">
A JSON Meta Application Protocol (JMAP) Subprotocol for WebSocket A JSON Meta Application Protocol (JMAP) Subprotocol for WebSocket
</title> </title>
<author initials="K." surname="Murchison" <seriesInfo name="RFC" value="8887"/>
fullname="Kenneth Murchison"> <author initials="K." surname="Murchison" fullname="Kenneth Murchison">
<organization abbrev="Fastmail">Fastmail US LLC</organization> <organization abbrev="Fastmail">Fastmail US LLC</organization>
<address> <address>
<postal> <postal>
<street>1429 Walnut Street - Suite 1201</street> <street>1429 Walnut Street, Suite 1201</street>
<city>Philadelphia</city> <region>PA</region> <city>Philadelphia</city>
<code>19102</code> <country>USA</country> <region>PA</region>
<code>19102</code>
<country>United States of America</country>
</postal> </postal>
<email>murch@fastmailteam.com</email> <email>murch@fastmailteam.com</email>
<uri>http://www.fastmail.com/</uri> <uri>http://www.fastmail.com/</uri>
</address> </address>
</author> </author>
<date month="August" year="2020"/>
<date />
<area>ART</area> <area>ART</area>
<workgroup>JMAP</workgroup> <workgroup>JMAP</workgroup>
<keyword>jmap</keyword> <keyword>jmap</keyword>
<keyword>websocket</keyword> <keyword>websocket</keyword>
<abstract> <abstract>
<t>This document defines a binding for the JSON Meta Application <t>This document defines a binding for the JSON Meta Application
Protocol (JMAP) over a WebSocket transport layer. The WebSocket Protocol (JMAP) over a WebSocket transport layer. The WebSocket
binding for JMAP provides higher performance than the current binding for JMAP provides higher performance than the current
HTTP binding for JMAP. HTTP binding for JMAP.
</t> </t>
</abstract> </abstract>
<!--
<note title="Open Issues">
<t>
<list style="symbols">
<t>Still need to craft some text to discuss/address
potential security risks of using WebSocket compression.</t>
</list>
</t>
</note>
</front>
</front>
<middle> <middle>
<section title='Introduction'> <section numbered="true" toc="default">
<t><xref target='RFC8620'>JMAP</xref> <name>Introduction</name>
over <xref target='RFC7235'>HTTP</xref> requires that every <t><xref target="RFC8620" format="default">JMAP</xref>
JMAP API request be authenticated. over <xref target="RFC7235" format="default">HTTP</xref> requires that
every JMAP API request be authenticated.
Depending on the type of authentication used by Depending on the type of authentication used by
the JMAP client and the configuration of the JMAP server, the JMAP client and the configuration of the JMAP server,
authentication could be an expensive operation both in time and authentication could be an expensive operation both in time and
resources. In such circumstances, reauthenticating for every resources. In such circumstances, reauthenticating for every
JMAP API request may harm performance.</t> JMAP API request may harm performance.</t>
<t>The <xref target="RFC6455" format="default">WebSocket</xref>
<t>The <xref target='RFC6455'>WebSocket</xref>
binding for JMAP eliminates this performance binding for JMAP eliminates this performance
hit by authenticating just the WebSocket handshake request and hit by authenticating just the WebSocket handshake request and
having those credentials remain in effect for the duration of having those credentials remain in effect for the duration of
the WebSocket connection. This binding supports JMAP API the WebSocket connection. This binding supports JMAP API
requests and responses, with optional support for push requests and responses, with optional support for push
notifications.</t> notifications.</t>
<t>Furthermore, the WebSocket binding for JMAP can optionally <t>Furthermore, the WebSocket binding for JMAP can optionally
<xref target='RFC7692'>compress</xref> both JMAP API requests <xref target="RFC7692" format="default">compress</xref> both JMAP API
and responses. requests and responses.
Although compression of HTTP responses is ubiquitous, Although compression of HTTP responses is ubiquitous,
compression of HTTP requests has very low, if any deployment, compression of HTTP requests has very low, if any, deployment
and therefore isn&apos;t a viable option for JMAP API requests and therefore isn't a viable option for JMAP API requests
over HTTP.</t> over HTTP.</t>
</section>
<!-- Intro -->
</section> <!-- Intro --> <section numbered="true" toc="default">
<name>Conventions Used in This Document</name>
<section title='Conventions Used in This Document'> <t>
<t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>",
NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
"MAY", and "OPTIONAL" in this document are to be interpreted as NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>",
described in BCP&nbsp;14 "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
<xref target='RFC2119' /> <xref target='RFC8174' /> "<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are
when, and only when, they appear in all capitals, as shown to be interpreted as
here.</t> described in BCP&nbsp;14 <xref target="RFC2119"/> <xref target="RFC8174"/>
when, and only when, they appear in all capitals, as shown here.
<t>The same terminology is used in this document as in the core </t>
JMAP specification.</t> <t>This document uses the terminology defined in the core JMAP
specification <xref target="RFC8620"/>.</t>
</section> <!-- Conventions --> </section>
<!-- Conventions -->
<section anchor='discovery' <section anchor="discovery" numbered="true" toc="default">
title='Discovering Support for JMAP over WebSocket'> <name>Discovering Support for JMAP over WebSocket</name>
<t>The JMAP capabilities object is returned as part of the <t>The JMAP capabilities object is returned as part of the
standard JMAP Session object (see Section 2 of standard JMAP Session object (see
<xref target='RFC8620' />). <xref target="RFC8620" sectionFormat="of" section="2"/>).
Servers supporting this specification MUST add a property named Servers supporting this specification <bcp14>MUST</bcp14> add a property n
amed
"urn:ietf:params:jmap:websocket" to the capabilities object. "urn:ietf:params:jmap:websocket" to the capabilities object.
The value of this property is an object which MUST contain the The value of this property is an object that <bcp14>MUST</bcp14> contain t he
following information on server capabilities: following information on server capabilities:
<list style='symbols'> </t>
<t>url: "String" <ul spacing="normal">
<vspace blankLines="1"/> <li>
The wss-URI (see Section 3 of <xref target='RFC6455' />) <t>url: "String"</t>
to use for initiating a JMAP over WebSocket handshake <t>The wss-URI (see <xref target="RFC6455" sectionFormat="of"
(the "WebSocket URL endpoint" colloquially). section="3"/>) to use for initiating a JMAP-over-WebSocket
</t> handshake (the "WebSocket URL endpoint" colloquially).</t>
</li>
<t>supportsPush: "Boolean" <li>
<vspace blankLines="1"/> <t>supportsPush: "Boolean"</t>
This is true if the server supports push <t>This is true if the server supports push notifications over the
notifications over the WebSocket, as described in WebSocket, as described in <xref target="push"
<xref target='push' />. format="default"/>.</t>
</t> </li>
</list> </ul>
<t keepWithNext="true"> Example:</t>
<figure> <artwork name="" type="" align="left" alt=""><![CDATA[
<preamble>
Example:
</preamble>
<artwork><![CDATA[
"urn:ietf:params:jmap:websocket": { "urn:ietf:params:jmap:websocket": {
"url": "wss://server.example.com/jmap/ws/", "url": "wss://server.example.com/jmap/ws/",
"supportsPush": true "supportsPush": true
} }
]]></artwork> ]]></artwork>
</figure></t> </section>
</section> <!-- discovery --> <!-- discovery -->
<section anchor='jmap' title='JMAP Subprotocol'> <section anchor="jmap" numbered="true" toc="default">
<name>JMAP Subprotocol</name>
<t>The term WebSocket subprotocol refers to an application-level <t>The term WebSocket subprotocol refers to an application-level
protocol layered on top of a WebSocket connection. This protocol layered on top of a WebSocket connection. This
document specifies the WebSocket JMAP subprotocol for carrying document specifies the WebSocket JMAP subprotocol for carrying
JMAP API requests, responses, and optional push notifications JMAP API requests, responses, and optional push notifications
through a WebSocket connection. through a WebSocket connection.
Binary data is handled per Section 6 Binary data is handled per <xref target="RFC8620" sectionFormat="of"
of <xref target='RFC8620' /> via a separate HTTP section="6"/> (via a separate HTTP connection or stream)
connection or stream.</t> or per a future extension to JMAP or this specification.</t>
<section anchor="authentication" numbered="true" toc="default">
<section anchor='authentication' title='Authentication'> <name>Authentication</name>
<t>A JMAP WebSocket connection is authenticated by presenting <t>A JMAP WebSocket connection is authenticated by presenting
a user&apos;s <xref target='RFC7235'>credentials in the a user's <xref target="RFC7235" format="default">credentials in the
HTTP request</xref> that initiates the WebSocket handshake. HTTP request</xref> that initiates the WebSocket handshake.
See Section 8.2 of <xref target='RFC8620' /> for See <xref target="RFC8620" sectionFormat="of" section="8.2"/> for
recommendations regarding the selection of HTTP authentication recommendations regarding the selection of HTTP authentication
schemes.</t> schemes.</t>
</section> <!-- authentication --> </section>
<!-- authentication -->
<section anchor='handshake' title='Handshake'> <section anchor="handshake" numbered="true" toc="default">
<name>Handshake</name>
<t>The JMAP WebSocket client and JMAP WebSocket server <t>The JMAP WebSocket client and JMAP WebSocket server
negotiate the use of the WebSocket JMAP subprotocol during negotiate the use of the WebSocket JMAP subprotocol during
the WebSocket handshake, either via a HTTP/1.1 Upgrade request the WebSocket handshake, either via an HTTP/1.1 Upgrade request
(see Section 4 of <xref target='RFC6455' />) (see <xref target="RFC6455" sectionFormat="of" section="4"/>)
or a HTTP/2 Extended CONNECT request (see Section 5 of or an HTTP/2 Extended CONNECT request (see
<xref target='RFC8441' />). <xref target="RFC8441" sectionFormat="of" section="5"/>).
The WebSocket JMAP subprotocol is also intended to run The WebSocket JMAP subprotocol is also intended to run
over future bindings of HTTP (e.g. HTTP/3) provided that there over future bindings of HTTP (e.g., HTTP/3) provided that there
is a defined mechanism for performing a WebSocket handshake is a defined mechanism for performing a WebSocket handshake
over that binding.</t> over that binding.</t>
<t>Regardless of the method used for the WebSocket handshake, <t>Regardless of the method used for the WebSocket handshake,
the client MUST first perform a TLS handshake on a the client <bcp14>MUST</bcp14> first perform a TLS handshake on a
JMAP <xref target='discovery'>WebSocket URL endpoint</xref> JMAP <xref target="discovery" format="default">WebSocket URL endpoint</x
ref>
having the "wss://" scheme (WebSocket over TLS) in having the "wss://" scheme (WebSocket over TLS) in
accordance with the requirements of running the particular accordance with the requirements of running the particular
binding of HTTP over TLS (see <xref target='RFC2818' /> binding of HTTP over TLS (see <xref target="RFC2818" format="default"/>
and Section 4.1 of <xref target='RFC6455' /> for HTTP/1.1 and <xref target="RFC6455" sectionFormat="of" section="4.1"/> for HTTP/1
and Section 9.2 of <xref target='RFC7540' /> for HTTP/2). .1
and <xref target="RFC7540" sectionFormat="of" section="9.2"/> for HTTP/2
If the TLS handshake fails, the client MUST close the ).
connection. If the TLS handshake fails, the client <bcp14>MUST</bcp14> close the
connection. Otherwise, the client <bcp14>MUST</bcp14> make an
Otherwise, the client MUST make an <xref target="RFC7235" format="default">authenticated HTTP request</xref
<xref target='RFC7235'>authenticated</xref> HTTP request >
on the encrypted connection, and MUST include the value "jmap" on the encrypted connection and <bcp14>MUST</bcp14> include the value "j
map"
in the list of protocols for the "Sec-WebSocket-Protocol" in the list of protocols for the "Sec-WebSocket-Protocol"
header field.</t> header field.</t>
<t>The reply from the server <bcp14>MUST</bcp14> also contain a
<t>The reply from the server MUST also contain a
corresponding "Sec-WebSocket-Protocol" header field with a corresponding "Sec-WebSocket-Protocol" header field with a
value of "jmap" in order value of "jmap" in order
for a JMAP subprotocol connection to be established.</t> for a JMAP subprotocol connection to be established.</t>
<t>Once the handshake has successfully completed, the <t>Once the handshake has successfully completed, the
WebSocket connection is established and can be used for JMAP WebSocket connection is established and can be used for JMAP
API requests, responses, and optional push notifications. API requests, responses, and optional push notifications.
Other message types MUST NOT be transmitted over this Other message types <bcp14>MUST NOT</bcp14> be transmitted over this
connection.</t> connection.</t>
<t>The credentials used for authenticating the HTTP request <t>The credentials used for authenticating the HTTP request
to initiate the handshake remain in effect for the duration to initiate the handshake remain in effect for the duration
of the WebSocket connection. If the authentication of the WebSocket connection. If the authentication
credentials for the user expire, the server can either treat credentials for the user expire, the server can either treat
subsequent requests as if they are unauthenticated or close subsequent requests as if they are unauthenticated or close
the WebSocket connection. the WebSocket connection.
In the latter case, the server MAY send a Close frame with a In the latter case, the server <bcp14>MAY</bcp14> send a Close frame wit
status code of 1008 (Policy Violation) as defined in Section h a
7.4.1 of <xref target='RFC6455' />.</t> status code of 1008 (Policy Violation), as defined in
<xref target="RFC6455" sectionFormat="of" section="7.4.1"/>.</t>
</section> <!-- handshake --> </section>
<!-- handshake -->
<section anchor='messages' title='WebSocket Messages'> <section anchor="messages" numbered="true" toc="default">
<t>Data frame messages in the JMAP subprotocol MUST be <name>WebSocket Messages</name>
text frames and contain UTF-8 encoded data. The messages MUST <t>Data frame messages in the JMAP subprotocol <bcp14>MUST</bcp14> be
be in the form of a single JMAP Request object (see Section text frames and contain UTF-8 encoded data. The messages <bcp14>MUST</b
3.3 of <xref target='RFC8620' />), cp14>
JMAP WebSocketPushEnable object (see <xref target='pushenable' />), be in the form of a single JMAP Request object (see
or JMAP WebSocketPushDisable object (see <xref target='pushdisable' />) <xref target="RFC8620" sectionFormat="of" section="3.3"/>),
JMAP WebSocketPushEnable object (see <xref target="pushenable" format="d
efault"/>),
or JMAP WebSocketPushDisable object (see <xref target="pushdisable" form
at="default"/>)
when sent from when sent from
the client to the server, and in the form of a single JMAP the client to the server, and MUST be in the form of a single JMAP
Response object, JSON Problem Details object, or JMAP StateChange Response object, JSON Problem Details object, or JMAP StateChange
object (see Sections 3.4, 3.6.1, and 7.1 respectively of object (see Sections <xref target="RFC8620" section="3.4"
<xref target='RFC8620' />) when sent from the sectionFormat="bare"/>, <xref target="RFC8620" section="3.6.1"
server to the client.</t> sectionFormat="bare"/>, and <xref target="RFC8620" section="7.1"
sectionFormat="bare"/> of <xref target="RFC8620" format="default"/>,
respectively) when sent from the server to the client.</t>
<t>Note that fragmented WebSocket messages (split over <t>Note that fragmented WebSocket messages (split over
multiple text frames) MUST be coalesced prior to parsing them multiple text frames) <bcp14>MUST</bcp14> be coalesced prior to parsing them
as JSON objects.</t> as JSON objects.</t>
<section anchor="invalid" numbered="true" toc="default">
<section anchor='invalid' title='Handling Invalid Data'> <name>Handling Invalid Data</name>
<t>If a client or server receives a binary frame, the endpoint <t>If a client or server receives a binary frame, the endpoint
can either ignore the frame or close the WebSocket connection. can either ignore the frame or close the WebSocket connection.
In the latter case, the endpoint MAY send a Close frame with a In the latter case, the endpoint <bcp14>MAY</bcp14> send a Close frame
status code of 1003 (Unsupported Data) as defined in Section with a
7.4.1 of <xref target='RFC6455' />.</t> status code of 1003 (Unsupported Data), as defined in
<xref target="RFC6455" sectionFormat="of" section="7.4.1"/>.</t>
<t>If a client receives a message that is not in the form of <t>If a client receives a message that is not in the form of
either a JSON Problem Details object, a JMAP Response a JSON Problem Details object, a JMAP Response
object, or a JMAP StateChange object, the client can either object, or a JMAP StateChange object, the client can either
ignore the message or close the WebSocket connection. ignore the message or close the WebSocket connection.
In the latter case, the endpoint MAY send a Close frame with a In the latter case, the endpoint <bcp14>MAY</bcp14> send a Close frame
status code of 1007 (Invalid frame payload data Data) as with a
defined in Section 7.4.1 of <xref target='RFC6455' />. status code of 1007 (Invalid frame payload data), as
</t> defined in <xref target="RFC6455" sectionFormat="of"
section="7.4.1"/>.</t>
<t>A server MUST return an appropriate <t>A server <bcp14>MUST</bcp14> return an appropriate
<xref target='errors'>JSON Problem Details object</xref> <xref target="errors" format="default">JSON Problem Details object</xr
ef>
for any request-level errors for any request-level errors
(E.g. an invalid JMAP object, an unsupported capability or (e.g., an invalid JMAP object, an unsupported capability or
method call, or exceeding a server request limit).</t> method call, or exceeding a server request limit).</t>
</section>
<!-- invalid -->
</section> <!-- invalid --> <section anchor="requests" numbered="true" toc="default">
<name>JMAP Requests</name>
<section anchor='requests' title='JMAP Requests'>
<t>The specification extends the Request object with two <t>The specification extends the Request object with two
additional arguments when used over a WebSocket: additional arguments when used over a WebSocket:
</t>
<list style='symbols'> <ul spacing="normal">
<t>@type: "String" <li>
<vspace blankLines="1"/> <t>@type: "String"</t>
This MUST be the string "Request".</t> <t>This <bcp14>MUST</bcp14> be the string "Request".</t>
</li>
<t>id: "String" (optional) <li>
<vspace blankLines="1"/> <t>id: "String" (optional)</t>
A client-specified identifier for the request <t>A client-specified identifier for the request to be echoed
to be echoed back in the response to this request.</t> back in the response to this request.</t>
</list></t> </li>
</ul>
<t>JMAP over WebSocket allows the server to process requests <t>JMAP over WebSocket allows the server to process requests
out of order. The client-specified identifier is used as a out of order. The client-specified identifier is used as a
mechanism for the client to correlate requests and mechanism for the client to correlate requests and
responses.</t> responses.</t>
<t>Additionally, the "maxConcurrentRequests" limit in the <t>Additionally, the "maxConcurrentRequests" limit in the
"capabilities" object (see Section 2 of "capabilities" object (see <xref target="RFC8620" sectionFormat="of"
<xref target='RFC8620' />) also applies to requests made on section="2"/>) also applies to requests made on
the WebSocket connection. When using the WebSocket JMAP the WebSocket connection. When using the WebSocket JMAP
subprotocol over a binding of HTTP that allows multiplexing subprotocol over a binding of HTTP that allows multiplexing
of requests (e.g. HTTP/2), this limit applies to the the sum of requests (e.g., HTTP/2), this limit applies to the sum
of requests made on both the JMAP API endpoint and the of requests made on both the JMAP API endpoint and the
WebSocket connection.</t> WebSocket connection.</t>
</section> <!-- requests --> </section>
<!-- requests -->
<section anchor='responses' title='JMAP Responses'> <section anchor="responses" numbered="true" toc="default">
<name>JMAP Responses</name>
<t>The specification extends the Response object with two <t>The specification extends the Response object with two
additional arguments when used over a WebSocket: additional arguments when used over a WebSocket:
<list style='symbols'> </t>
<t>@type: "String" <ul spacing="normal">
<vspace blankLines="1"/> <li>
This MUST be the string "Response".</t> <t>@type: "String"</t>
<t>This <bcp14>MUST</bcp14> be the string "Response".</t>
<t>requestId: "String" (optional; MUST be returned if an </li>
id is included in the request) <li>
<vspace blankLines="1"/> <t>requestId: "String" (optional; <bcp14>MUST</bcp14> be
The client-specified identifier in the corresponding request.</t> returned if an identifier is included in the request)</t>
</list></t> <t>The client-specified identifier in the corresponding
</section> <!-- responses --> request.</t>
</li>
</ul>
</section>
<!-- responses -->
<section anchor='errors' title='JMAP Request-Level Errors'> <section anchor="errors" numbered="true" toc="default">
<name>JMAP Request-Level Errors</name>
<t>The specification extends the Problem Details object <t>The specification extends the Problem Details object
for request-level errors for request-level errors (see <xref target="RFC8620"
(see Section 3.6.1 of <xref target='RFC8620' />) sectionFormat="of" section="3.6.1"/>) with two additional arguments
with two additional arguments when used over a WebSocket: when used over a WebSocket:</t>
<ul spacing="normal">
<list style='symbols'> <li>
<t>@type: "String" <t>@type: "String"</t>
<vspace blankLines="1"/> <t>This <bcp14>MUST</bcp14> be the string "RequestError".</t>
This MUST be the string "RequestError".</t> </li>
<li>
<t>requestId: "String" (optional; MUST be returned if given <t>requestId: "String" (optional; <bcp14>MUST</bcp14> be
in the request) returned if given in the request)</t>
<vspace blankLines="1"/> <t>The client-specified identifier in the corresponding
The client-specified identifier in the corresponding request.</t> request.</t>
</list></t> </li>
</section> <!-- errors --> </ul>
</section>
<!-- errors -->
<section anchor='push' title='JMAP Push Notifications'> <section anchor="push" numbered="true" toc="default">
<t>JMAP over WebSocket servers that support push <name>JMAP Push Notifications</name>
<t>JMAP-over-WebSocket servers that support push
notifications on the WebSocket will advertise a notifications on the WebSocket will advertise a
"supportsPush" property with a value of true in "supportsPush" property with a value of true in
the "urn:ietf:params:jmap:websocket" server capabilities the "urn:ietf:params:jmap:websocket" server capabilities
object.</t> object.</t>
<section anchor="pushformat" numbered="true" toc="default">
<section anchor='pushformat' title='Notification Format'> <name>Notification Format</name>
<t>All push notifications take the form of a standard <t>All push notifications take the form of a standard
StateChange object (see Section 7.1 of StateChange object (see <xref target="RFC8620" sectionFormat="of"
<xref target='RFC8620' />).</t> section="7.1"/>).</t>
<t>The specification extends the StateChange object with one <t>The specification extends the StateChange object with one
additional argument when used over a WebSocket: additional argument when used over a WebSocket:
</t>
<ul spacing="normal">
<li>
<t>pushState: "String" (optional)</t>
<t>A (preferably short) string that encodes the entire server
state visible to the user (not just the objects returned in
this call).</t>
<t>The purpose of the "pushState" token is to allow a client
to immediately get any changes that occurred while it was
disconnected (see <xref target="pushenable"
format="default"/>). If the server does not support
"pushState" tokens, the client will have to issue a series of
"/changes" requests (see <xref target="RFC8620"
sectionFormat="of" section="5.2"/>) upon reconnection to
update its state to match that of the server.</t>
</li>
</ul>
</section>
<!-- format -->
<list style='symbols'> <section anchor="pushenable" numbered="true" toc="default">
<t>pushState: "String" (optional) <name>Enabling Notifications</name>
<vspace blankLines="1"/>
A (preferably short) string that encodes the entire
server state visible to the user (not
just the objects returned in this call).
<vspace blankLines="1"/>
The purpose of the "pushState" token is to allow a
client to immediately get any changes that occurred
while is was disconnected (see <xref target='pushenable'/>).
If the server does not support "pushState" tokens, the
client will have issue a series of "/changes" requests
(see Section 5.2 of <xref target='RFC8620' />)
upon reconnection to update its state to match that of
the server.</t>
</list></t>
</section> <!-- format -->
<section anchor='pushenable' title='Enabling Notifications'>
<t>A client enables push notifications from the server for <t>A client enables push notifications from the server for
the current connection by the current connection by
sending a WebSocketPushEnable object to the server. A sending a WebSocketPushEnable object to the server. A
WebSocketPushEnable object has the following properties: WebSocketPushEnable object has the following properties:
<list style='symbols'> </t>
<t>@type: "String" <ul spacing="normal">
<vspace blankLines="1"/> <li>
This MUST be the string "WebSocketPushEnable".</t> <t>@type: "String"</t>
<t>This <bcp14>MUST</bcp14> be the string
<t>dataTypes: "String[]|null" "WebSocketPushEnable".</t>
<vspace blankLines="1"/> </li>
A list of data type names (e.g. "Mailbox", <li>
"Email") that the client is interested in. <t>dataTypes: "String[]|null"</t>
A StateChange notification will only be sent if the data <t>A list of data type names (e.g., "Mailbox" or "Email") that
for one of these types changes. Other types are omitted the client is interested in. A StateChange notification will
from the TypeState object. If null, changes will be only be sent if the data for one of these types changes.
pushed for all supported data types.</t> Other types are omitted from the TypeState object. If null,
changes will be pushed for all supported data types.</t>
<t>pushState: "String" (optional) </li>
<vspace blankLines="1"/> <li>
The last "pushState" token <t>pushState: "String" (optional)</t>
that the client received from the server. <t>The last "pushState" token that the client received from
Upon receipt of a "pushState" token, the server the server. Upon receipt of a "pushState" token, the server
SHOULD immediately send all changes since that state <bcp14>SHOULD</bcp14> immediately send all changes since that
token.</t> state token.</t>
</list></t> </li>
</section> <!-- enabling --> </ul>
</section>
<!-- enabling -->
<section anchor='pushdisable' title='Disabling Notifications'> <section anchor="pushdisable" numbered="true" toc="default">
<name>Disabling Notifications</name>
<t>A client disables push notifications from the server <t>A client disables push notifications from the server
for the current connection by for the current connection by
sending a WebSocketPushDisable object to the server. A sending a WebSocketPushDisable object to the server. A
WebSocketPushDisable object has the following property: WebSocketPushDisable object has the following property:
<list style='symbols'> </t>
<t>@type: "String" <ul spacing="normal">
<vspace blankLines="1"/> <li>
This MUST be the string "WebSocketPushDisable".</t> <t>@type: "String"</t>
</list></t> <t>This <bcp14>MUST</bcp14> be the string "WebSocketPushDisable"
</section> <!-- disabling --> .</t>
</li>
</ul>
</section>
<!-- disabling -->
</section> <!-- push --> </section>
<!-- push -->
</section> <!-- messages --> </section>
<!-- messages -->
<section title='Examples'> <section numbered="true" toc="default">
<name>Examples</name>
<t>The following examples show WebSocket JMAP opening <t>The following examples show WebSocket JMAP opening
handshakes, a JMAP Core/echo request and response, and a handshakes, a JMAP Core/echo request and response, and a
subsequent closing handshake. subsequent closing handshake.
The examples assume that the JMAP WebSocket URL endpoint has been The examples assume that the JMAP WebSocket URL endpoint has been
advertised in the JMAP Session object as having a path of advertised in the JMAP Session object as having a path of
"/jmap/ws/" and that TLS negotiation has already succeeded. "/jmap/ws/" and that TLS negotiation has already succeeded.
Note that folding of header fields is for editorial purposes Note that folding of header fields is for editorial purposes
only.</t> only.</t>
<t keepWithNext="true">
<figure>
<preamble>
WebSocket JMAP connection via HTTP/1.1 with push WebSocket JMAP connection via HTTP/1.1 with push
notifications for mail notifications for mail <xref target="RFC8621" format="default"/>
<xref target='RFC8621' /> enabled. is enabled. This example assumes that the client has cached
This example assumes that the client has cached pushState pushState "aaa" from a previous connection.
"aaa" from a previous connection. </t>
</preamble> <artwork name="" type="" align="left" alt=""><![CDATA[
<artwork><![CDATA[
[[ From Client ]] [[ From Server ]] [[ From Client ]] [[ From Server ]]
GET /jmap/ws/ HTTP/1.1 GET /jmap/ws/ HTTP/1.1
Host: server.example.com Host: server.example.com
Upgrade: websocket Upgrade: websocket
Connection: Upgrade Connection: Upgrade
Authorization: Basic Zm9vOmJhcg== Authorization: Basic Zm9vOmJhcg==
Sec-WebSocket-Key: Sec-WebSocket-Key:
dGhlIHNhbXBsZSBub25jZQ== dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Protocol: jmap Sec-WebSocket-Protocol: jmap
skipping to change at line 557 skipping to change at line 519
} }
"pushState": "ccc" "pushState": "ccc"
} }
WS_CLOSE WS_CLOSE
WS_CLOSE WS_CLOSE
[WebSocket connection closed] [WebSocket connection closed]
]]></artwork> ]]></artwork>
</figure> <t keepWithNext="true">
WebSocket JMAP connection on an HTTP/2 stream that also
<figure> negotiates <xref target="RFC7692" format="default">compression</xref
<preamble> >:
WebSocket JMAP connection on a HTTP/2 stream which also </t>
negotiates <xref target='RFC7692'>compression</xref>: <artwork name="" type="" align="left" alt=""><![CDATA[
</preamble>
<artwork><![CDATA[
[[ From Client ]] [[ From Server ]] [[ From Client ]] [[ From Server ]]
SETTINGS SETTINGS
SETTINGS_ENABLE_CONNECT_PROTOCOL = 1 SETTINGS_ENABLE_CONNECT_PROTOCOL = 1
HEADERS + END_HEADERS HEADERS + END_HEADERS
:method = CONNECT :method = CONNECT
:protocol = websocket :protocol = websocket
:scheme = https :scheme = https
:path = /jmap/ws/ :path = /jmap/ws/
skipping to change at line 612 skipping to change at line 570
DATA + END_STREAM DATA + END_STREAM
WS_CLOSE WS_CLOSE
DATA + END_STREAM DATA + END_STREAM
WS_CLOSE WS_CLOSE
[WebSocket connection closed] [WebSocket connection closed]
[HTTP/2 stream closed] [HTTP/2 stream closed]
]]></artwork> ]]></artwork>
</figure> </section>
<!-- examples -->
</section> <!-- examples -->
</section> <!-- jmap -->
<section title='Security Considerations' anchor='security'> </section>
<t>The security considerations for both WebSocket (see Section <!-- jmap -->
10 of <xref target='RFC6455' />) and JMAP (see Section 8 of
<xref target='RFC8620' />) apply to the WebSocket
JMAP subprotocol.
Specific security considerations are described in subsections of
this section.</t>
<section title='Connection Confidentiality and Integrity'> <section anchor="security" numbered="true" toc="default">
<name>Security Considerations</name>
<t>The security considerations for both WebSocket (see <xref
target="RFC6455" sectionFormat="of" section="10"/>) and JMAP (see <xref
target="RFC8620" sectionFormat="of" section="8"/>) apply to the
WebSocket JMAP subprotocol. Specific security considerations are
described below.</t>
<section numbered="true" toc="default">
<name>Connection Confidentiality and Integrity</name>
<t>To ensure the confidentiality and integrity of <t>To ensure the confidentiality and integrity of
data sent and received via JMAP over WebSocket, the WebSocket data sent and received via JMAP over WebSocket, the WebSocket
connection MUST use <xref target='RFC5246'>TLS 1.2</xref> connection <bcp14>MUST</bcp14> use <xref target="RFC5246" format="defaul
or later, following the recommendations in <xref t">TLS 1.2</xref>
target='RFC7525'>BCP 195</xref>. or later, following the recommendations in <xref target="RFC7525" format
Servers SHOULD support <xref target='RFC8446'>TLS 1.3</xref> or ="default">BCP 195</xref>.
Servers <bcp14>SHOULD</bcp14> support <xref target="RFC8446" format="def
ault">TLS 1.3</xref> or
later.</t> later.</t>
</section> </section>
<section numbered="true" toc="default">
<section title='Non-Browser Clients'> <name>Non-browser Clients</name>
<t>JMAP over WebSocket can be used by clients both running <t>JMAP over WebSocket can be used by clients both running
inside and outside of a web browser. As such, the security inside and outside of a web browser. As such, the security
considerations in Sections 10.2 and 10.1 of considerations in Sections <xref target="RFC6455" section="10.2"
<xref target='RFC6455' /> apply to those respective sectionFormat="bare"/> and <xref target="RFC6455" section="10.1"
environments.</t> sectionFormat="bare"/> of <xref target="RFC6455" format="default"/>
apply to those respective environments.</t>
</section> </section>
</section> </section>
<!-- <!--
<section title='Privacy Considerations' anchor='privacy'> <section title='Privacy Considerations' anchor='privacy'>
<t>TODO</t> <t>TODO</t>
</section> </section>
--> -->
<section title='IANA Considerations' anchor='iana'> <section anchor="iana" numbered="true" toc="default">
<name>IANA Considerations</name>
<section title='Registration of the WebSocket JMAP Subprotocol'> <section numbered="true" toc="default">
<t>This specification requests IANA to register the WebSocket <name>Registration of the WebSocket JMAP Subprotocol</name>
JMAP subprotocol under the "WebSocket Subprotocol Name" <t>Per this specification, IANA has registered the following in the
Registry with the following data: "WebSocket Subprotocol Name Registry" within the "WebSocket Protocol
Registries".
<list style="hanging">
<t hangText="Subprotocol Identifier:">jmap</t>
<t hangText="Subprotocol Common Name:">
WebSocket Transport for JMAP (JSON Meta Application Protocol)</t>
<t hangText="Subprotocol Definition:">RFCXXXX (this document)</t>
</list></t>
</t>
<dl newline="false" spacing="normal">
<dt>Subprotocol Identifier:</dt>
<dd>jmap</dd>
<dt>Subprotocol Common Name:</dt>
<dd>WebSocket Transport for JMAP (JSON Meta Application
Protocol)</dd>
<dt>Subprotocol Definition:</dt>
<dd>RFC 8887</dd>
</dl>
</section> </section>
</section> <!-- IANA -->
<section title='Acknowledgments'>
<t>The author would like to thank the following individuals for
contributing their ideas and support for writing this
specification: Neil Jenkins, Robert Mueller, and Chris Newman.</t>
</section> </section>
<!-- IANA -->
</middle> </middle>
<back> <back>
<references title='Normative References'> <references>
&rfc2119; <name>References</name>
&rfc2818; <references>
&rfc5246; <name>Normative References</name>
&rfc6455; <xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/refer
&rfc7235; ence.RFC.2119.xml"/>
&rfc7525; <xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/refer
&rfc7540; ence.RFC.2818.xml"/>
&rfc7692; <xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/refer
&rfc8174; ence.RFC.5246.xml"/>
&rfc8441; <xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/refer
&rfc8446; ence.RFC.6455.xml"/>
&rfc8620; <xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/refer
ence.RFC.7235.xml"/>
</references> <xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/refer
ence.RFC.7525.xml"/>
<references title='Informative References'> <xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/refer
&rfc8621; ence.RFC.7540.xml"/>
<xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/refer
ence.RFC.7692.xml"/>
<xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/refer
ence.RFC.8174.xml"/>
<xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/refer
ence.RFC.8441.xml"/>
<xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/refer
ence.RFC.8446.xml"/>
<xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/refer
ence.RFC.8620.xml"/>
</references>
<references>
<name>Informative References</name>
<xi:include href="https://xml2rfc.tools.ietf.org/public/rfc/bibxml/refer
ence.RFC.8621.xml"/>
</references>
</references> </references>
<section numbered="false" toc="default">
<section title="Change History (To be removed by RFC Editor before <name>Acknowledgments</name>
publication)"> <t>The author would like to thank the following individuals for
<t>Changes since ietf-06: contributing their ideas and support for writing this
<list style='symbols'> specification: <contact fullname="Neil Jenkins"/>, <contact
<t>Removed open issue on security of WebSocket compression, fullname="Robert Mueller"/>, and <contact fullname="Chris Newman"/>.</t>
per Alexey Melnikov.</t> </section>
</list>
</t>
<t>Changes since ietf-05:
<list style='symbols'>
<t>Renamed "webSocketUrl" to "url" and "supportsWebSocketPush"
to "supportsPush", per Benjamin Schwartz.</t>
<t>Added a security subsection with a nod to Sections 10.1 and
10.2 of RFC6455, per Leif Johansson.</t>
<t>Clarified "unsupported JMAP" vs "unsupported JSON", per
Benjamin Kaduk.</t>
<t>Refer to RFC 7525 as BCP 195, per Benjamin Kaduk.</t>
<t>Several editorial improvements from Benjamin Kaduk.</t>
<t>Several editorial improvements from Murray Kucherawy.</t>
</list>
</t>
<t>Changes since ietf-04:
<list style='symbols'>
<t>Require the use of TLS for JMAP over WebSocket
(per Alissa Cooper and others).</t>
<t>Added a section explaining how to handle unsupported messages
(per Bob Briscoe).</t>
<t>Added a section specifically addressing authentication of
the WebSocket (per Leif Johansson).</t>
<t>Corrected references into specific sections of RFC 8620
(per Martin Vigoureax).</t>
<t>Made RFC 7692 a normative reference (per Barry Leiba).</t>
<t>Clarified that the "maxConcurrentRequests" limit applies to
the sum of all requests on the current connection (per
Benjamin Kaduk).</t>
<t>Clarified that the "pushState" token represents the entire
server state visible to the user (per Banjamin Kaduk).</t>
<t>Clarified that "WebSocketPushEnable/Disable" only
effect the current connection (per Benjamin Kaduk).</t>
<t>Several editorial improvements from Benjamin Kaduk.</t>
</list>
</t>
<t>Changes since ietf-03:
<list style='symbols'>
<t>Updated JMAP Mail reference to RFC 8621.</t>
<t>Specified that requestId MUST be present in a response if
given in the request.</t>
</list>
</t>
<t>Changes since ietf-02:
<list style='symbols'>
<t>Updated JMAP Core reference to RFC 8620.</t>
<t>Added 'WebSocketPushDisable' object.</t>
<t>Editorial and formatting changes.</t>
</list>
</t>
<t>Changes since ietf-01:
<list style='symbols'>
<t>Changed 'wsURL' to 'webSocketUrl' and removed push query option.</t>
<t>Added 'supportsWebSocketPush' capability.</t>
<t>Added '@type' argument to Request object.</t>
<t>Added 'WebSocketPushEnable' object.</t>
<t>Added 'pushState' argument to StateChange object.</t>
<t>Updated example.</t>
<t>Minor Editorial changes.</t>
</list>
</t>
<t>Changes since ietf-00:
<list style='symbols'>
<t>Added text describing advertisement of and selection of optional
push notifications.</t>
<t>Minor Editorial changes.</t>
</list>
</t>
<t>Changes since murchison-02:
<list style='symbols'>
<t>Renamed as a JMAP WG document.</t>
<t>Allow out of order processing.</t>
<t>Allow push notifications.</t>
<t>Modified examples.</t>
<t>Add Security Considerations text.</t>
<t>Minor Editorial changes.</t>
</list>
</t>
<t>Changes since murchison-01:
<list style='symbols'>
<t>Updated WebSocket over HTTP/2 reference to RFC8144.</t>
</list>
</t>
<t>Changes since murchison-00:
<list style='symbols'>
<t>Fleshed out section on discovery of support for JMAP over
WebSocket.</t>
<t>Allow JSON Problem Details objects to be returned by the
server for toplevel errors.</t>
<t>Mentioned the ability to compress JMAP API requests.</t>
<t>Minor Editorial changes.</t>
</list>
</t>
</section>
</back> </back>
</rfc> </rfc>
 End of changes. 86 change blocks. 
488 lines changed or deleted 372 lines changed or added

This html diff was produced by rfcdiff 1.48. The latest version is available from http://tools.ietf.org/tools/rfcdiff/