Network Working Group | M. Gajda |
Internet-Draft | dmfs |
Intended status: Standards Track | May 3, 2017 |
Expires: November 4, 2017 |
Push Discovery and Notification Dispatch Protocol
draft-gajda-dav-push-00
This specification defines a framework and protocols for a push notification system that allows clients, application servers and push notification servers to interact with each other in a standardized manner.
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at http://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."
This Internet-Draft will expire on November 4, 2017.
Copyright (c) 2017 IETF Trust and the persons identified as the document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.
In a client/server protocol, clients can typically create, update, delete "resources" (data) on the server, as well as retrieve data on the server.
In many cases, data can appear on the server as the result of some other client or server-side process interacting with the server. Thus clients need a way to detect when the data on the server has changed.
Most protocols provide a data synchronization mechanism to support that, but typically clients need to "poll" the server to find out when changes have occurred. Network based polling is inefficient, and instead push notifications are preferred as a way of alerting clients to new data or changes to existing data on the server
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119]
When XML element types in the namespaces "DAV:" and "urn:ietf:params:xml:ns:dav-push" are referenced in this document outside of the context of an XML fragment, the string "DAV:" and "DAV-PUSH:" will be prefixed to the element type names respectively.
This document introduces an entity called "Push Gateway" which acts as a proxy between an application server and a push delivery service. A Push Gateway provides at least one Transport. Each Transport is identified by a URI and connects to exactly one Push Delivery Service.
Push Gateways MAY support relaying, so a push gateway might forward all or some notifications to another push gateway.
+----------------------------+ | Application Server | +-----------------------+----+ ^ | | | | | | | | v | +-------------------------+ | | Push Gateway | | +---------+---------------+ | | | | | | | v | +-------------------------+ | | Push delivery Service | | +---------+---------------+ | | | | | | | | | v +-----+--------------------+ | Client Application | +--------------------------+
The server is responsible for generating push topics and sending update notifications to the Push Gateway. A push topic is a unique token that identifies the update notification feed of a resource or a group of resources. The topic is forwarded to the Push Gateway whenever a relevant change in one of these resources occurs.
This document doesn't specify how topics are generated. However, for privacy reasons the topic MUST NOT contain user names, user data (like folder/collection names) or URLs in plain text. If a server doesn't maintain opaque, anonymous identifiers it SHOULD use a hash algorithm, like SHA256, to generate an opaque identifier from resource properties.
Push topics MAY be generated on a per-user base for shared resources.
A server MAY change push topics at any time to improve privacy. If doing so the server MUST continue to send out push notifications for the old topic until all subscriptions to that topic have expired.
The application server maintains a mapping of subscribed push topics to a list of push gateways. It updates this mapping whenever
The application server doesn't maintain references to push clients, because this information is opaque to the application server.
The Push Gateway maintains a mapping of push-topics to a list of subscribed clients and expiration times. It updates the list whenever
If a push message for a specific topic is received the push gateway will notify all clients with an active (not expired) subscription for that topic.
A push gateway may relay messages for other gateways. A gateway that supports relaying MUST maintain a map of topics to gateways just like an application server.
TBD: Minimum requirements for PDS to support this protocol. Describe what state information the PDS needs to maintain.
TBD: what information does the client need to maintain
This protocol allows an application server to initialize the supported push transports by querying a set of configured push gateways. This requires that the application server knows the root URL of each configured gateway. In order to retrieve the list of supported transports it posts a JSON object with an empty list of push-transports to each gateway.
POST /gateway Host: push.example.com Content-Type: application/json Content-Length: xxx { "push-transports": []}
HTTP/1.1 200 OK Content-Type: application/json Content-Length: xxx { "push-transports": [ { "transport": { "transport-uri": "https://push.example.com/transport", "refresh-interval": 172800, "transport-data" : { ... } } },{ "transport": { "transport-uri": "urn:uuid:01234567-0123-0123-0123-0123456789ab", "refresh-interval": 172800, "transport-data" : { ... } } }] }
The following request shows the bootstrap request of an application server that was configured with the Push Gateway URL https://push.example.com/gateway
The communication between Client and Application Server is defined in the respective application protocol. The application protocol needs to be extended in order to support push.
This document describes the general idea behind the required extensions and gives a concrete definition for a WebDAV extension.
TBD:
This document doesn't specify an explicit unsubscribe method. A client that doesn't wish to receive any further push notifications for a specific topic, MAY send a subscription with an expiration date in the past.
An application server which receives such a subscription MUST handle it like any other subscription. In particular the Application Server MUST
A Push Gateway which receives a subscription with a passed expiration date MUST
PROPFIND http://calendar.example.com/calendars/ Content-Type: application/xml Depth: 0 Content-Length: xxx <D:propfind xmlns:D="DAV:" xmlns:P="urn:ietf:params:xml:ns:dav-push"> <D:prop> <P:subscribe-URL> /> <P:supported-transport-set /> <P:topic /> <P:version /> </D:prop> </D:propfind>
HTTP/1.1 207 Multistatus Content-Type: application/xml; charset=UTF-8 Content-Length: xxx <D:multistatus xmlns:D="DAV:"> <D:response> <D:href>/calendars/</D:href> <D:propstat> <D:prop> <P:subscribe-URL> <D:href>https://calendar.example.com/subscribe</D:href> </P:subscribe-URL> <P:supported-transport-set> <P:transport /> <P:transport> <P:transport-uri >urn:uuid:01234567-0123-0123-0123-0123456789ab</P:transport-uri> <P:transport-data> ... </P:transport-data> <P:refresh-interval>172800</P:refresh-interval> </P:transport> <P:transport> <P:transport-uri >https://push.example.com/transport</P:transport-uri> <P:transport-data> ... </P:transport-data> <P:refresh-interval>172800</P:refresh-interval> </P:transport> </P:supported-transport-set> <P:topic>123</P:topic> <P:version>1</P:version> </D:prop> <D:status>HTTP/1.1 200 OK</D:status> </D:propstat> </D:response> </D:multistatus>
The following example shows a PROPFIND request on a user's calendar home to discover push support.
POST /subscribe HTTP/1.1 Host: calendar.example.com Content-Type: application/xml; charset=UTF-8 <P:subscribe xmlns:P="urn:ietf:params:xml:ns:dav-push"> <P:topic>123<P:topic> <P:topic>abc<P:topic> <P:selected-transport> <P:transport-uri >https://push.example.com/transport</D:transport-uri> <P:client-data>XYZ</D:client-data> </P:selected-transport> <P:expires>2017-10-07T12:00:00Z</P:expires> </P:subscribe>
Calendar server -> Client - CS server advertises its supported push mechanisms Clients request POST to P:subscribe-URL - does the actual subscription to the calendar server:
TBD: response
When a client sends a request to subscribe to specific topics, the application server MUST foward the subscription to the chosen gateway or to the gateway that announced itself as a proxy for the chosen gateway.
If a gateway acts as a proxy for another gateway it MUST forward the request to the proxied gateway.
POST / HTTP/1.1 Host: push.example.com Content-Type: application/json { "push-subscribe": { "topics": [ "123", "abc" ], "transport": { "transport-uri": "https://push.example.com/transport", "client-data": "XYZ" }, "expires": "2017-10-07T12:00:00Z" } }
The following example shows a request to subscribe to two topics.
HTTP/1.1 200 OK Content-Type: application/json { "push-url": "https://push.example.com/" }
TBD: responses A successful response containt the URL to send update messages to. The URL may be different than the transport URL. An Application Server MUST use this URL when sending push notifications to transports provided by clients.
POST / HTTP/1.1 Host: push.example.com Content-Type: application/json { "push": { "messages" : [{ "topic": "123", "priority": 100, "timestamp": "2017-10-01T14:00:52Z", "client-id": "xyz" }, { "topic": "abc", "priority": 0, "timestamp": "2017-10-01T14:00:53Z" }] } }
HTTP/1.1 200 OK Content-Type: application/json { "push-response": {} }
HTTP/1.1 200 OK Content-Type: application/json { "push-response": { "no-subscribers": [ { "topic": "123"} ] } }
Whenever a substantial change occurs in any of the resources, the application server sends a Push Message to the gateway containing the Topics of the resources that have changed. The following example sends a push notification for the Topics "123" and "abc". The message for Topic "123" also contains a "client-id" to omit any notification to the sole client that modified the resource and caused this push message. The second message has a low priority and no "client-id". Such a message could be generated by multiple clients acknowledging an alarm on a shared calendar.
; root element root { push-transports } ; a list of push transports supported by a gateway ; in the request sent by the application server this is empty push-transports "push-transports" [ * transport ] transport "transport" { ; The uri of the transport. "transport-uri" : uri, transport-data? } ; optional data the client needs to know in order to subscribe ; to allow easy conversion to other formats, ; this object MUST NOT contain structured data. transport-data "transport-data" { ^"": any }
; root element root { push-subscribe } ; the object describing the subscription push-subscribe "push-subscribe" { topic-list, selected-transport, expires } ; The list of topics to subscribe to. Unless a previous ; subscription is updated by a request, existing ; subscriptions won't be affected by new subscriptions. topic-list "topics" [ * topic } ; The chosen transport type selected-transport "selected-transport" { ; The transport-uri of the chosen transport "transport-uri" : uri, ; The client-data string as sent by the client "client-data" : string } ; The time of when the subscription expires ; must be a UTC timestamp following ; https://tools.ietf.org/html/rfc3339 expires "expires" : RFC 3339 timestamp
; root element root { error } ; the object describing the failure error "error" { invalid-topic-list } ; The list of topics that the user can't subscribe to invalid-topic-list "invalid-topics" [ 1* topic }
; The root object root { "push" [ 1* message ] } ; A message object, describing the update message { topic, ? priority, timestamp, ? client-id } ; The topic of the resource that has been updated topic "topic" : string ; The priority of the change, with 0 being the lowest and 100 ; being the highest priority ; If omitted, implementations SHOULD default to 50. priority "priority" : integer 0..100 ; The time of when the change occurred. The value MUST be a ; timestamp in UTC following https://tools.ietf.org/html/rfc3339 ; If the server aggregated multiple updates before sending the push ; message, this MUST be the timestamp of the most recent update. timestamp "timestamp" : RFC 3339 timestamp ; An optional id that identifies the client that triggered the update ; notification. Push gateways can use this information to suppress ; push messages to this particular client, in order to avoid ; unnecessary sync operations. ; If the server aggregated multiple updates from different clients ; into one message, it MUST omit the client-id to ensure all clients ; receive the push message. client-id "client-id": string ; root element of the push subscribe response root { ? no-subscribers-list } ; A list of topics without active subscribers. ; Applications servers SHOULD not send further push messages for the ; enlisted topics to this transport unless a new client subscribes on ; this transport. no-subscribers-list "no-subscribers" [ 1* topic } ]
<!ELEMENT push-subscribe-URL (DAV:href)>
<!ELEMENT supported-transport-set (transport*)>
<!ELEMENT transport (transport-uri, transport-data, refresh-interval)?>
<!ELEMENT transport-uri (#PCDATA)> PCDATA value: The URI identifying the transport.
<!ELEMENT transport-data ANY>
<!ELEMENT refresh-interval (#PCDATA)> PCDATA value: the maximum refresh interval in seconds
<!ELEMENT topic (#PCDATA)> PCDATA value: the push topic
<!ELEMENT push-version (#PCDATA)> PCDATA value: the highest push protocol version number supported by the application server
<!ELEMENT subscribe (topic+, selected-transport, expires)>
<!ELEMENT selected-transport (transport-uri, client-data)>
<!ELEMENT client-data (#PCDATA)> PCDATA value: client data as required by the push gateway
<!ELEMENT invalid-topics (topic+)>
Push-Client-Id = "Push-Client-Id" ":" token
The client sends this header to identify itself to the application server as the modifying instance. If the application server didn't coalesce multiple updates from different clients into a single push message, it SHOULD include the value in the update notification message. The provided token ([RFC7230]) MUST be percent-encoded as per[RFC3986]. Gateways can use this information to suppress push messages to this particular client.
The actual value of token is part of the contract between client and gateway. The token MUST NOT contain any sensitive data like user name or device identifiers. It SHOULD be either a random or an obfuscated token (using a cryptographic hash function).
Servers may want to implement some form of "keep-alive" within the push protocol to ensures clients know they are still connected in cases where actual data changes happen at long intervals (e.g., a calendar user who only makes changes once a day)
Priorities: Range 0 - 100 - 0 is lowest and 100 is highest e.g.: low priority - updates due to other attendees changing their partstat high priority - updates to events ocurring in the next 24 hours Priority is used by a client to indicate what level of push they want at a specific time. It can also be used by the push gateway or push delivery system to throttle push notifications to the client based on load.
Servers MAY delay the delivery of push notifications for several seconds in order to coalesce notifications. This is useful to give the server a certain amount of control over the client's behavior during times of high load.
Servers MUST NOT coalesce push notifications based on priority.
Application servers MAY allow clients to provide their own transports. If the transport-uri is not among the transport-uris as advertised by the application server, the transport-uri MUST be an HTTPS URL. If a client sends such a transport-uri, the application server SHOULD perform a transport discovery on the provided URL to discover all transports supported on this gateway.
Clients MUST be prepared that they might receive an initial push notification that acknowledges the subscription before the response to the push-subscribe request has been received.
Clients SHOULD NOT rely solely on push notifications. The framework described in this document does not make any guarantees about the delivery of a push notification. Clients should be prepared to trigger a synchronization themselves if no push message has been received within some time period.
Clients can expect that sometimes they will get a push but then not detect any actual changes when they sync (i.e., "no-op" push from server as a "keep-alive" mechanism).
A Push Gateway SHOULD require some kind of authentication to be encoded in the client-data string. This document doesn't specify any authentication methods. However, among others, encrypting the client-data string with a shared secret and digitally signing the data are two possible options to achieve this.
Client data MAY contain additional per-client preferences, like minimum priority to deliver or maximum delay of notifications when doing coalescing. This is part of the contract between client and transport an not subject of this specification.
Gateways MAY coalesce push notifications based on priority.
To prevent abuse of the service, Push Gateways SHOULD require either servers or clients or both to authenticate. Servers SHOULD authenticate every request of Protocol #2 via HTTP.
Push Gateways use the <gateway-data> information to authenticate subscription requests from a Server by relating them to Client authorization requests. Clients will typically be authenticating to Servers to access protected data on the server and thus SHOULD authenticate when using Protocol #1.
This document uses a URN to describe a new XML namespace conforming to the registry mechanism described in[RFC3688].
Registration request for the push namespace:
URI: urn:ietf:params:xml:ns:dav-push
Registrant Contact: The IESG <iesg@ietf.org>
XML: None - not applicable for namespace registrations.
[RFC2119] | Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997. |
[RFC3339] | Klyne, G. and C. Newman, "Date and Time on the Internet: Timestamps", RFC 3339, DOI 10.17487/RFC3339, July 2002. |
[RFC3688] | Mealling, M., "The IETF XML Registry", BCP 81, RFC 3688, DOI 10.17487/RFC3688, January 2004. |
[RFC3986] | Berners-Lee, T., Fielding, R. and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005. |
[RFC7230] | Fielding, R. and J. Reschke, "Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing", RFC 7230, DOI 10.17487/RFC7230, June 2014. |
Changes in -01: