(This document is in work and subject of ongoing modification.)
WebDAV-Push is intended as a tool for WebDAV {{RFC4918}} clients to get notified about updates in resources (usually collections) in near time so that they can refresh their views, perform synchronization etc.
A client MUST NOT rely solely on WebDAV-Push, so it should also perform regular polling like when WebDAV-Push is not available. However if WebDAV-Push is available, the polling frequency can be significantly reduced.
Typical use cases:
- A mobile app synchronizes calendars/address books with device-local storage and wants to be notified on collection updates in order to re-synchronize.
- A desktop file manager shows contents of a WebDAV collection and wants to be notified on updates in order to refresh the view.
- A calendar Web app shows a CalDAV collection and wants to be notified on updates in order to refresh the view.
{::boilerplate bcp14-tagged}
.--------------------. .--------------. .--------------------.
| WebDAV-Push Server | | Push Service | | WebDAV-Push Client |
'--------------------' '--------------' '--------------------'
Create subscription
.----------------------o
'---------------------->
Register subscription
<-------------------------------------------o
Content update notification
o------------------->*---------------------->
{: title="Basic WebDAV-Push Workflow"}
A WebDAV-Push server needs to
- advertise WebDAV-Push and relevant information (service detection),
- manage subscriptions to resources (usually collections), and
- send push messages when a subscribed resource changes.
In order to manage subscriptions, a WebDAV server needs to
- provide a way for clients to subscribe to a resource (with transport-specific information),
- provide a way for clients to unsubscribe from a resource, and
- handle expired or otherwise invalid subscriptions.
Notifications about updated resources have to be sent to all subscribed clients over the respective push transports.
A WebDAV-Push client typically
- detects whether the server supports WebDAV-Push and which push transports,
- connects to a push service (which is usually not operated by the same party as the WebDAV server),
- subscribes to one or more resources on the server (with the data received from the push service),
- receives push notifications that cause some client-side action (like to refresh the view or run synchronization),
- re-subscribes to resources before the registrations expire,
- unsubscribes from resources when notifications are not needed anymore.
WebDAV-Push is not restricted to a specific push transport. This allows even upcoming, yet unknown push transports to be used with WebDAV-Push. Push transport definitions can define extra properties and additional processing rules.
WebDAV-Push implementations SHOULD implement at least the Web Push transport (defined in {{transport-web-push}}). If possible, other push transports SHOULD be connected over a Web Push gateway instead of defining a new WebDAV-Push transport.
To use a proprietary push service, a client vendor may need to provide a rewrite proxy that offers a Web Push endpoint which signs and forwards the requests to the respective push service. If possible, VAPID should be used instead of such a proxy.
If parts of a term are in brackets, it means that those parts may or may not be written together with the other parts. However it means the same in any case.
Push notification : push message or delivery of a push message
Push message : Actual network message that is sent from the server over a push transport to the client. Notifies the client that a specific resource (identified by its push topic) has changed.
In Web Push context, a WebDAV-Push server can send a push message (more exact, "request delivery of a push message") over the push service by POST
ing the message to the client's subscription URL.
Push service : Infrastructure that implements a specific push transport. The push service is the actual network service between WebDAV-Push server and WebDAV-Push client.
For instance, if the push transport is Web Push is a Web app, the push service would be provided by the vendor of the browser that the client runs in.
(Push) subscription (URL)
: The information that the client needs to provide to the server so that the server can send push notifications. The server can POST
a push message to that URL.
If the transport is Web Push, the term "(push) subscription (URL)" as used in this document is equivalent to the Web Push term "push resource".
(Push) topic : Character sequence that identifies a WebDAV resource for push purposes (unique per WebDAV server). A specific resource could be reachable at different URLs, but it can only have one push topic.
(Push) transport : Protocol that defines an actual push mechanism. In this document, Web Push is the only defined push transport (see {{transport-web-push}}). However, WebDAV-Push may also be used with other push transports like proprietary or yet unknown protocols. In that case, it has to be specified how to use that protocol with WebDAV-Push. A push transport typically involves a push service.
Web Push : "Protocol for the delivery of real-time events to user agents", defined by {{RFC8030}}. Usually implemented in browsers (which means that major browser vendors provide their own push services), but there are also other implementations like {{UnifiedPush}}. Some parts (namely push message delivery from the push service to the client) specify implementation details that may be done by other means without changing the meaning of the RFC for WebDAV-Push servers and clients.
There are also additional standards that can be considered to belong to Web Push, especially VAPID ({{RFC8292}}) and Message Encryption ({{RFC8291}}).
WebDAV-Push : WebDAV-based protocol to notify clients about updates in resource using a push transport (in contrast to polling). Specified in this document.
(WebDAV-Push) client : WebDAV client that supports WebDAV-Push, for instance a CalDAV/CardDAV app on a mobile device
(WebDAV-Push) server : WebDAV server (for instance a CalDAV/CardDAV server) that implements WebDAV-Push
A server that supports WebDAV-Push MUST include "webdav-push" in the DAV
header of an OPTIONS
response for any resource that supports WebDAV-Push. The "webdav-push" value MUST indicate that all MUST level requirements of this document are met.
Example:
OPTIONS /calendars/
Host: caldav.example.com
HTTP/1.1 200 OK
Allow: OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, COPY, MOVE
Allow: PROPFIND, PROPPATCH, LOCK, UNLOCK, REPORT, ACL
DAV: 1, 2, access-control, calendar-access, webdav-push
Content-Length: 0
Here, the OPTIONS response contains "webdav-push" in the DAV header to indicate that the resource supports the properties and operations defined in this document.
To provide information about WebDAV-Push support, new properties are defined. A server MUST provide the transports
, topic
and supported-triggers
properties for resources that support WebDAV-Push. A server MUST NOT provide the topic
and supported-triggers
properties for resources that don't support WebDAV-Push (for instance for non-collection resources, if they're not supported).
The transports
element lists available push transports. Within the scope of this document, the only supported transport is web-push
(see {{transport-web-push}}). Although the property is defined on every Push-capable resource, its value is usually the same for every resource on the server.
The topic
is a globally unique identifier for the resource. A specific resource could be reachable with different URLs, but it can have only one push topic. A server could for instance use a random UUID or a canonical URL that won't change over the lifetime of the resource. The value should be globally unique because a client can subscribe to resources from multiple servers and needs to be able to determine the correct one when it receives a push message.
The supported-triggers
element MUST contain at least one of the following elements:
content-update
if the resource supports push notifications on content updates (see {{content-updates}}). It contains a{DAV:}depth
property that indicates the maximum supported depth.property-update
if the resource supports push notifications on property updates (see {{property-updates}}). It contains a{DAV:}depth
property that indicates the maximum supported depth.
Clients can use WebDAV PROPFIND
to retrieve these properties. WebDAV-Push SHOULD only be advertised to clients which are actually allowed to use it.
Example:
PROPFIND https://example.com/webdav/collection/
<?xml version="1.0" encoding="utf-8" ?>
<propfind xmlns="DAV:" xmlns:P="https://bitfire.at/webdav-push">
<prop>
<P:transports/>
<P:topic/>
<P:supported-triggers/>
</prop>
</propfind>
HTTP/1.1 207 Multi-Status
<?xml version="1.0" encoding="utf-8" ?>
{::include xml/sample-propfind-multistatus.xml}
In this case, the queried collection supports WebDAV-Push in general and thus has a push topic. It supports the Web Push transport and provides a VAPID public key. Push notifications are supported for content updates of internal members and on property updates of the collection itself.
The comment shows how support for some other (not yet defined) transport could be advertised together with additional specific information that is required to use it.
To subscribe to a resource, the client sends a POST
request with Content-Type: application/xml
to the resource it wants to subscribe. The root XML element of the XML body is push-register
and can be used to distinguish between WebDAV-Push and other requests.
The push-register
element contains:
- exactly one
subscription
element, which contains all information the server needs to send a push message, - exactly one
trigger
element to specify the type of updates the client wants to be notified about, and - an optional
expires
element that contains the requested expiration time in theIMF-fixdate
format (as defined in {{Section 5.6.7 of RFC9110}}).
The subscription
element specifies a subscription that shall be notified on updates and contains exactly one element with details about a specific subscription type. Within the scope of this document, only the web-push-subscription
child element is defined (see {{transport-web-push}}).
To specify which updates the client wants to be notified about, it uses the trigger
element, which itself can contain:
- A
content-update
element to indicate the client's interest in notifications when the contents of the subscribed resource or its members change ("content update"). - A
property-update
element to indicate the client's interest in notifications when the WebDAV properties of the subscribed resource or its members change ("property update").
WebDAV-Push is intended more as a helpful tool to speed up things (like synchronization) than a strict query processor. So subscriptions are processed in a relaxed way: the server does its best to fulfill the request, but if a certain trigger is not available, it's downgraded or ignored instead of rejected with an error response. If a client needs to know which triggers are supported, it can use PROPFIND
with supported-triggers
. A client MUST expect the server to downgrade or ignore certain triggers when they're not (fully) supported, and MUST be prepared to receive an error when it registers a subscription with only unsupported triggers.
A "content update" occurs when the subscribed resource or a member is changed or removed, as defined in {{Section 3.5 of RFC6578}}. Typically, this is the case when the resource itself is modified or removed, or when a member is added or removed or its contents are modified. If the server supports {{RFC6578}}, a content update of a collection usually implies that the {DAV:}sync-token
changes.
The content
element contains a {DAV:}depth
element that specifies whether the client is interested
- only in content updates of the subscribed resource (depth:
0
), - only in content updates of the subscribed resource and its internal members (depth:
1
), or - in content updates of the subscribed resource and its members (depth:
infinite
).
A content update of a collection itself (not of a member) only occurs when the collection has an entity body that is returned by GET
and that body changes. A server MAY ignore such changes and not send notifications in that case.
A server SHOULD support content update notifications with a depth of at least 1
for every Push-capable collection.
If the subscribed resource doesn't support the content update trigger with the requested depth, the server MUST fall back to the lowest supported value instead. If the content update trigger isn't supported for the subscribed resource at all, it MUST be ignored.
In case the depth is infinite
, the limitations described in {{Section 3.3 of RFC6578}} apply: notifications about changes in members which are not supported by the DAV:sync-collection
report may not be sent.
A "property update" occurs when the WebDAV properties of the subscribed resource or its members are modified. Properties update notifications are controlled by two elements within the property-update
element:
-
The
{DAV:}depth
element specifies whether the client is interested- only in property updates of the subscribed resource (depth:
0
), - only in property updates of the subscribed resource and its internal members (depth:
1
), or - in property updates of the subscribed resource and its members (depth:
infinite
).
If the subscribed resource doesn't support the content update trigger with the requested depth, the server MUST fall back to the lowest supported value instead. If the content update trigger isn't supported for the subscribed resource at all, it MUST be ignored.
In case the depth is
infinite
, the limitations described in {{Section 3.3 of RFC6578}} apply: notifications about changes in members which are not supported by theDAV:sync-collection
report may not be sent. - only in property updates of the subscribed resource (depth:
-
The optional
{DAV:}prop
element (as used in aPROPFIND
request) specifies a list of properties that the client is interested in.If the
{DAV:}prop
element is empty or not present, the server chooses a list of properties that it considers to be useful for the client. If the{DAV:}prop
element is present and contains properties for which property update notifications are not supported, the server MUST ignore those unsupported properties. Also, a server MAY ignore the contents of a{DAV:prop}
element at all and treat it like if it was empty or not present.Neither a server nor a client SHOULD use property update notifications for properties that automatically change on a content update, like
{DAV:}getetag
,{DAV:}getlastmodified
and{DAV:}sync-token
, because this would implicitly cause a property update for every content update. Notifications about content updates should instead be requested/sent explicitly as content update notifications.
The removal of a resource, including the subscribed resource, is not considered as a property update but as a content update.
Allowed response codes:
- 201 if the subscription was registered and the server wants to return additional information, like encryption details that are only valid for this subscription. The format of these details is specified by the respective transport definition.
- 204 if the subscription was registered without additional information
- 403 with precondition
invalid-subscription
when the request doesn't contain a validsubscription
- 403 with precondition
push-not-available
if WebDAV-Push is not available for this resource or if the user is not allowed to register a push subscription for it - 403 with precondition
no-supported-trigger
when the request doesn't contain a trigger or when all requested triggers are ignored (because they're not supported) - other response code with usual HTTP/WebDAV semantics
When a subscription is registered the first time, the server creates a URL that identifies that registration (registration URL) which can be used to remove the subscription. The server MUST send the registration URL in the Location
header.
The server MUST return a HTTP Expires
header (as defined in {{Section 5.3 of RFC9111}}) in the IMF-fixdate
format with the actual expiration date on the server, which may be shorter than the expiration requested by the client.
Example 1 (successful registration):
POST https://example.com/webdav/collection/
Content-Type: application/xml; charset="utf-8"
<?xml version="1.0" encoding="utf-8" ?>
{::include xml/sample-push-register.xml}
HTTP/1.1 204 No Content
Location: https://example.com/webdav/subscriptions/io6Efei4ooph
Expires: Wed, 02 Oct 2024 07:28:00 GMT
Example 2: A client registers a content update trigger with a depth of infinite
and a property update trigger with a depth of 1
, but the collection supports only content update triggers with a depth of 1
and doesn't support the property update trigger at all, it registers the subscription and responds with 201. Notifications will then only be sent on content updates with a depth of 1
(trigger downgraded by server). On property updates, notifications will not be sent (trigger ignored by server).
Example 3: A client registers a property update trigger with a depth of 0
and the collection doesn't support property update triggers at all, the server ignores the trigger. So all triggers of the request are ignored and the server responds with 403 with no-supported-trigger
.
Every subscription has a transport-specific unique identifier (the push resource in case of Web Push).
A server MUST NOT register a subscription with the same identifier multiple times for the same resource. Instead, when a client wants to register a subscription with an identifier that is already registered for the requested resource, the server MUST update the registration with the given details and the expiration date.
The response is the same as for subscription registration.
A client can explicitly unsubscribe from a resource by sending a DELETE
request to the previously acquired registration URL.
Allowed response codes:
- 204 if the registered subscription was removed.
- 404 if the registration URL is unknown (or expired).
- other response code with usual HTTP/WebDAV semantics
Sample request:
DELETE https://example.com/webdav/subscriptions/io6Efei4ooph
HTTP/1.1 204 Unregistered
Clients MAY specify an expiration date-time when they register a subscription.
A server SHOULD take the expiration specified by a client into consideration, but MAY impose its own (often stricter) expiration rules, for instance to keep their database clean or because the client has specified an implausible late expiration. A server MUST allow subscriptions to be valid at least three days.
Clients have to refresh their registrations regularly and before the expiration date to keep them working. They can expect that subscriptions usually stay valid until their expiration, although there may be special circumstances that cause all subscriptions to be reset, like when the server software is changed.
Expired subscriptions MUST NOT be used anymore as chances are high that doing so would cause errors.
A WebDAV-Push server MUST notify registered subscriptions of a subscribed resource:
- on a content update, if this was requested during subscription registration,
- on a property update, if this was requested during subscription registration.
The push message body consists of a push-message
element, which contains information about the affected resource:
- a
topic
element with the push topic, - a
content-update
element in case of a content update, and/or - a
property-update
element in case of a property update.
The content-update
element SHOULD contain a {DAV:}sync-token
element so that a client can ignore the push message when it already knows the latest state.
Example:
{::include xml/sample-push-message.xml}
Here, both the contents and the properties of the resource (or its members, depending on the registered trigger) with topic O7M1nQ7cKkKTKsoS_j6Z3w
have changed. The new sync-token (after the change) is http://example.com/sync/10
.
When necessary or useful, a server MAY
- impose a rate limit for push messages,
- delay push messages (usually for a short time, for instance to avoid multiple push messages for ongoing changes in the user interface),
- merge/omit push messages.
Such measures SHOULD not change the overall meaning of the push notifications so that the client can still perform its desired action. For instance, of a series of push messages that contain only content updates and occur shortly after each other, all but the last message can be omitted. If one of the push messages signals a property update, it can't be just omitted because the client then wouldn't know that a property update happened.
A WebDAV-Push server MUST ensure that invalid subscriptions (encountered when trying to sending a push notification) are removed at some time.
An invalid subscription is a subscription that push notifications can't be delivered to. Usually the push service returns an HTTP error code like 404 when it receives a notification for an invalid subscription. There may also be other conditions that render a subscription invalid, like a non-resolvable hostname or an encryption handshake error.
A server MAY use some logic like remembering the last successful delivery plus some tolerance interval to defer removal of an invalid subscription. Doing so will make WebDAV-Push more reliable in case of temporary problems and avoid temporal "holes" between subscription removal and re-registration.
WebDAV-Push can be used with CalDAV ({{RFC4791}}) and CardDAV ({{RFC6352}}) to provide short-time update notifications when collections (calendars, address books) or entries (contacts, events, …) change.
Depending on the features of a CalDAV/CardDAV client, it could for instance subscribe to:
- content updates of a home-set to become notified about new collections,
- content updates of a collection (usually with a depth of
1
) to become notified about modified entries, - property updates of a collection (usually with a depth of
0
) to become notified about changes of properties like display name, calendar color and access permissions, - property updates (for instance display name) of a principal to update real names of collection owners.
CalDAV/CardDAV servers that support WebDAV-Push SHOULD support:
- content updates with a
{DAV:}depth
of at least 1 oncalendar-home-set
andaddressbook-home-set
collections,- calendars and address books (collections which have a
{DAV:}resourcetype
of{CALDAV:}calendar
or{CARDDAV:}addressbook
), - scheduling inbox and outbox collections (collections which have a
{DAV:}resourcetype
of{CALDAV:}schedule-inbox
or{CALDAV:}schedule-outbox
as defined in {{Section 2 of RFC6638}});
- property updates with a
{DAV:}depth
of at least 0 on- calendars and address books,
- principals (collections with have a
{DAV:}resourcetype
of{DAV:}principal
as defined in {{Section 4 of RFC3744}}).
The general requirements from {{Section 8 of RFC8030}} apply regardless of which transport is used. Especially:
- HTTP over TLS MUST be used for all communications.
- Mechanisms that provide end-to-end confidentiality, integrity and data origin authentication MUST be used.
Push services could relate clients over metadata and heuristics. For instance, clients which are at the same time notified by a specific WebDAV-Push server have probably subscribed the same resource.
See RFC 3552 and RFC 6973 1
Topic
header, don't use insecure hashes 1
How sensitive are the data, how to minimize risks 1
What happens when information leaks 1
What happens when some component is hacked 1
WebDAV-Push can be used with Web Push {{RFC8030}} as a transport to deliver WebDAV-Push notifications directly to compliant user agents, like Web browsers which come with their own push service infrastructure.
When the Web Push transport is used for WebDAV-Push,
- {{RFC8030}} defines how to generate subscriptions and send push messages,
- the WebDAV-Push server acts as Web Push application server,
- the WebDAV client acts as Web Push user agent.
Corresponding terminology:
- (WebDAV-Push) push subscription ↔ (Web Push) push resource
- (WebDAV-Push) push server ↔ (Web Push) application server
- (WebDAV-Push) push client ↔ (Web Push) user agent
Message encryption ({{message-encryption}}) MUST be used. VAPID ({{vapid}}) SHOULD be used. (If other methods to provide a security context for Web Push become established, those can be used and necessary WebDAV properties shall be added to this document.)
A server that supports the Web Push transport MUST list the web-push
element in the transports
property.
.--------------------. .--------------. .--------------------.
| | | Web Push | | |
| WebDAV-Push Server | | Service | | WebDAV-Push Client |
'--------------------' '--------------' '--------------------'
Get VAPID public key
.-------------------------------------------o
'------------------------------------------->
Create restricted subscription
.----------------------o
'---------------------->
Register subscription (with encryption)
<-------------------------------------------o
Content/property update notification
o---(encrypted)----->*------(encrypted)----->
{: title="WebDAV-Push over Web Push with VAPID and Message Encryption"}
To register a Web Push subscription, the subscription
element of the push-register
request contains exactly one web-push-subscription
.
The web-push-subscription
element represents the public information of a Web Push subscription that is shared with the WebDAV-Push server.
It contains exactly one push-resource
element, which specifies the absolute URI that identifies the endpoint where Web Push notifications are sent to.
A Web Push subscription is uniquely identified by its push resource.
VAPID {{RFC8292}} binds push subscriptions to the specific WebDAV-Push server.
A WebDAV-Push server that supports VAPID stores a key pair. It exposes an additional transport property vapid-public-key
within the web-push
element, which contains the VAPID public key in uncompressed form and base64url encoded. The attribute type="p256ecdsa"
MUST be added to allow different key types in the future. See {{push-properties}} for an example.
If available, the client MUST use this key to create a restricted subscription at the push service, except when it knows that the push service doesn't support VAPID.
A client can expect the VAPID public key to be the same for all resources on the server. However the VAPID public key can still sometimes change (for instance when the server or user data is moved to another machine). In that case a client has to create new restricted subscriptions because the old ones won't work anymore.
When the server provides a VAPID public key, it MUST include a corresponding Authorization
header when sending a push message in order to prove its identity to the push service.
Message encryption hides details of push messages from the push services. Before creating the subscription, the client generates a key pair as defined in {{RFC8291}}.
When the client then registers this subscription at the server, it MUST include these subscription properties:
content-encoding
– how the encrypted content is encoded; currently onlyaes128gcm
is supportedsubscription-public-key
– public key of the user agent's key pair in uncompressed form and base64url encoded; attributetype="p256dh"
MUST be added to allow different key types in the futureauth-secret
– authentication secret
These properties are bound to the subscription (which is identified by the push resource). A server doesn't need to store these properties for every registration, but only once for the subscription.
The server uses these data to encrypt the payload before sending it to the push service. The client then decrypts the payload again.
The push message is delivered via POST
to the push resource, with Content-Type: application/xml; charset="UTF-8"
.
The server MAY send the push message with a Topic
header so that an undelivered push message can be replaced by an updated one. The server MUST ensure that the meaning doesn't change when a push message is potentially replaced. The Topic
header is visible to the push service, so its value MUST NOT contain sensitive information.
For instance, the header value could be derived with a secure hash function from
- the collection topic,
- whether the push message contains a content update,
- whether the push message contains a property update, and
- a secret that is only used for this purpose.
The server MAY use the Urgency
header to set the priority of the push message. For instance, a CalDAV server may send push notifications for new/changed events with alarms that are scheduled within the next 15 minutes with Urgency: high
so that users receive the alarm as soon as possible. Updates that are not that time-critical, for instance in slowly changing collections like a holiday calendar could be sent with Urgency: low
.
When XML element names are used without namespace in this document, they are in the WebDAV-Push namespace: https://bitfire.at/webdav-push
All XML elements defined by this document reside in this namespace.
To reference element names in another namespace, the {ns}element
syntax is used. For instance, {DAV:}prop
means the prop
XML element in the DAV:
namespace.
The XML schema formally defines the XML elements used by this document and is expressed in {{RELAXNG}}.
{::include xml/webdav-push.rng}