Skip to content

Latest commit

 

History

History
466 lines (263 loc) · 25.2 KB

content.mkd

File metadata and controls

466 lines (263 loc) · 25.2 KB

Introduction

(This document is in work and has not been submitted yet.)

WebDAV-Push is intended as a tool for WebDAV {{RFC4918}} clients to get notified about updates in collections in near time so that they can refresh their views, perform synchronization etc.

A client SHOULD 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.

Notational Conventions

{::boilerplate bcp14-tagged}

Architectural Overview

1 Figure

Terminology

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 collection (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 POSTing 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 collection for push purposes (unique per WebDAV server). A specific collection 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.

Rewrite proxy : Push services usually require authentication from their users and often consider their user to be application vendor who has control over both the server and the client.

When however the server and clients are not in control of the same entity (like it's typically the case in WebDAV context), client and server can't share the same private key to authenticate against the push service. In that case, the client vendor may need to operate a rewrite proxy that receives each push message from the WebDAV-Push server, signs it with the same private key as the client and forwards it to the 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 collections using a push transport (vs. 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

WebDAV Server with Support for WebDAV-Push

A WebDAV server that implements WebDAV-Push needs to

  • advertise WebDAV-Push features and relevant information (service detection),
  • manage subscriptions to collections and
  • send push messages when a subscribed collection changes.

In order to manage subscriptions, a WebDAV server needs to

  • provide a way for clients to subscribe to a collection (with transport-specific information),
  • provide a way for clients to unsubscribe from collections,
  • handle expired or otherwise invalid subscriptions.

Notifications about updates in collections have to be sent to all subscribed clients over the respective push transports.

The server must be prepared to handle errors. For instance, if a push transport signals that a subscription doesn't exist anymore, it must be removed and not be used again.

WebDAV Client with Support for WebDAV-Push

A WebDAV client that implements WebDAV-Push 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 collections on the server (providing push service-specific details),
  • receives push notifications that cause some client-side action (like to refresh the view or run synchronization),
  • re-subscribes to collections before the subscriptions expire,
  • unsubscribes from collections when notifications are not needed anymore.

Push Transports

WebDAV-Push is not restricted to specific push transports and allows clients to specify which push transports they support. This allows even upcoming, yet unknown push transports to be used with WebDAV-Push.

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.

For proprietary push services, client vendors may need to provide a rewrite proxy that signs and forwards the requests to the respective proprietary service (which usually accepts only authenticated requests from the client vendor).

Push transport definitions can define extra properties and additional processing rules.

Service Detection

This section describes how a client can detect

  • whether a collection supports WebDAV-Push,
  • which push services are supported (may contain service-specific information).

Collection Properties {#collection-properties}

To provide information about WebDAV-Push support, new properties are defined. A WebDAV-Push server is REQUIRED to provide the transports, topic and supported-triggers properties for collections that support WebDAV-Push.

The transports element lists available push transports. Although the property is defined on every collection, its value is usually the same for every collection on the server. Within the scope of this document, the only supported transport is web-push (see {{transport-web-push}}).

The topic is a globally unique identifier for the collection. A specific collection could be reachable at different URLs, but it can only have one push topic. A server could for instance use a server-internal ID that is not going to change or a random UUID per collection.

The supported-triggers element contains at least one of the following elements:

  • content-update if the collection supports push notifications on content updates ({{content-updates}}). It contains a {DAV:}sync-level property that indicates the maximum supported depth.
  • property-update if the collection supports push notifications on property updates ({{property-updates}}). It contains a {DAV:}depth property that indicates the maximum supported depth.

Clients can use WebDAV PROPFIND to retrieve these properties. 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 requested collection supports WebDAV-Push in general (because it has a push topic). It supports the Web Push transport. Push notifications can be requested on 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.

Subscription Management

1 Permissions / what to report when user is not allowed to register push.

Subscription Registration

To subscribe to a collection, the client sends a POST request with Content-Type: application/xml to the collection 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,
  • an optional trigger element to specify the types of events the client wants to be notified about, and
  • an optional expires element that contains the requested expiration time in the IMF-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 members of the collection change (content update).
  • A property-update element to indicate the client's interest in notifications when the WebDAV properties of the collection change (property update).

If the trigger element is missing or empty, the following default will be assumed:

<!-- default "trigger" if not specified: -->
<trigger xmlns="https://bitfire.at/webdav-push" xmlns:D="DAV:">
  <!-- client wants be notified about content updates of direct members -->
  <content-update>
    <D:sync-level>1</D:depth>
  </content-update>

   <!-- client wants to be notified about property changes of the collection -->
  <property-update>
    <D:depth>0</D:depth>
    <D:prop/>
  </property-update>
</trigger>

Content Updates {#content-updates}

A content update occurs when a member is changed or removed, as defined in {{Section 3.5 of RFC6578}} (typically when a member is added or removed or its contents are modified). If the server supports {{RFC6578}}, a content update implies that the {DAV:}sync-token changes.

The content element can contain an optional {DAV:}sync-level element (default value when missing: 1) that specifies whether the client is interested only in changes of internal members or of all members.

A server MUST support a {DAV:}sync-level of 1 and MAY support infinite. In case of 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. 1 XML error when not supported

Property Updates {#property-updates}

A property update occurs when the WebDAV properties of the collection or its members are modified. Notifications about properties update are controlled by two elements within properties:

  1. The optional {DAV:}depth element (as defined in {{Section 10.2 of RFC4918}}, value if missing: 0) specifies the depth:

    • A depth of 0 means that the client is only interested in property updates of the subscribed collection itself.
    • A depth of 1 means that the client is interested in property updates of the subscribed collection and its internal members.
    • A depth of infinite means that the client is interested in property updates of the subscribed collection and all its members.

    A server MUST support a depth of 0 and MAY support 1 and infinite. In case of 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. 1 XML error when not supported.

  2. The optional {DAV:}prop element (as it may be used in a PROPFIND request) specified a list of properties that the client is interested in. The list of properties MUST NOT contain properties that represent a content update, especially {DAV:}getetag, {DAV:}getlastmodified and {DAV:}sync-token. If the {DAV:}prop element is not present or empty, the server chooses the properties that it considers to be useful for the client. 1 XML error when not supported.

Response

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. Details have to be specified by the particular transport definition.
  • 204 if the subscription was registered
  • other response code with usual HTTP/WebDAV semantics (if possible, with DAV:error XML body)

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:

POST https://example.com/webdav/collection/
Content-Type: application/xml; charset="utf-8"

<?xml version="1.0" encoding="utf-8" ?>
{::include xml/sample-registration.xml}

HTTP/1.1 201 Created
Location: https://example.com/webdav/subscriptions/io6Efei4ooph
Expires: Wed, 02 Oct 2024 07:28:00 GMT

Subscription Updates

Every subscription has an identifier that uniquely identifies the (push transport, push service, client) triple. For Web Push, the identifier is the push resource URI.

A server MUST NOT register a subscription with the same identifier multiple times. Instead, when a client wants to register a subscription with an identifier that is already registered for the requested collection, the server MUST update the subscription with the given details and the expiration date.

Allowed response codes:

  • 201 if the registered subscription was updated and the server wants to share registration-specific details
  • 204 if the registered subscription was updated
  • 404 if the registration URL is unknown (or expired)
  • other response code with usual HTTP/WebDAV semantics (if possible, with DAV:error XML body)

The server MUST return the registration URL in the Location header.

The server MUST return a HTTP Expires header with the actual expiration date on the server.

Subscription Removal

A client can explicitly unsubscribe from a collection 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 (if possible, with DAV:error XML body)

When a subscription registration is removed, no further push messages must be sent to the subscription.

Sample request:

DELETE https://example.com/webdav/subscriptions/io6Efei4ooph

HTTP/1.1 204 Unregistered

Expiration

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.

Push Notification

A WebDAV-Push server MUST notify registered subscriptions of a subscribed collection:

  • on a content update of the collection, if this was requested during subscription registration,
  • on a property update of the collection, if this was requested during subscription registration.

Push Message

The push message body consists of a push-message element, which contains information about the affected collection:

  • 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 collection 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 for a short time,
  • omit/merge push messages.

The server MUST ensure that such measures don't 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.

Removal of Invalid Subscriptions

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 for some time. Doing so will make WebDAV-Push more reliable in case of temporary problems and avoid temporal "holes" between subscription removal and re-registration.

CalDAV/CardDAV

1 Specific implementation notes for CalDAV/CardDAV. Especially a recommendation of what clients shall subscribe to and why:

  • homesets → content updates may trigger calendar list refresh
  • calendars / address books → content updates may trigger sync, property updates may trigger calendar meta-data refresh
  • principals → keep displayed user data up-to-date

Security Considerations

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 collection.

1 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

Web Push Transport {#transport-web-push}

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 (or a redirect proxy) 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 (or redirect proxy) ↔ (Web Push) user agent

Message encryption {{RFC8291}} MUST be used. VAPID {{RFC8292}} SHOULD be used. (If other methods to provide a security context for Web Push become established, those ones can and shall 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.

Subscription Registration

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 (Web Push application server).

It contains exactly one push-resource element, which contains an absolute URI that identifies the endpoint where Web Push notifications are sent to. The push resource is used as the unique identifier for the subscription.

Example:

{::include xml/sample-web-push-subscription.xml}

VAPID

VAPID binds push subscriptions to the specific WebDAV-Push server.

A WebDAV-Push server which supports VAPID stores a key pair. The server exposes an additional transport property server-public-key (within the web-push element), which contains the VAPID public key in uncompressed form and base64url encoded. Its attribute type="p256dh" MUST be added to allow different key types in the future. See {{collection-properties}} for an example.

If available, the client SHOULD use this key to create a restricted subscription at the push service.

When the server sends a push message, it includes a corresponding Authorization header to prove its identity to the push service.

Message Encryption

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 includes additional subscription properties:

  • client-public-key – public key of the user agent's key pair in uncompressed form and base64url encoded; attribute type="p256dh" MUST be added to allow different key types in the future
  • auth-secret – authentication secret

Example for a subscription registration requesting message encryption:

{::include xml/sample-registration-with-encryption.xml}

The server uses these data to encrypt the payload and send it to the push service. The client then decrypts the payload again.

Push Message

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. Usually this means that the value is derived from the collection topic and the information whether the push message indicates a content and/or property update. The Topic header is visible to the push service, so its value MUST NOT contain sensitive information.

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 the user, for instance in slowly changing collections like a holiday calendar may be sent with Urgency: low.

XML Schema

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}

Footnotes

  1. TODO 2 3 4 5 6 7 8 9 10 11