XEP-0124: HTTP Binding

This document defines a binding of XMPP communications to a transport layer of HTTP rather than TCP.


NOTICE: The protocol defined herein is a Draft Standard of the XMPP Standards Foundation. Implementations are encouraged and the protocol is appropriate for deployment in production systems, but some changes to the protocol are possible before it becomes a Final Standard.


Document Information

Series: XEP
Number: 0124
Publisher: XMPP Standards Foundation
Status: Draft
Type: Standards Track
Version: 1.5
Last Updated: 2006-04-28
Approving Body: XMPP Council
Dependencies: XMPP Core, RFC 1945, RFC 2068, RFC 3174
Supersedes: None
Superseded By: None
Short Name: httpbind
Schema: <http://www.xmpp.org/schemas/httpbind.xsd>
Wiki Page: <http://wiki.jabber.org/index.php/HTTP Binding (XEP-0124)>

Author Information

Ian Paterson

Email: ian.paterson@clientside.co.uk
JID: ian@zoofy.com

Dave Smith

Email: dizzyd@jabber.org
JID: dizzyd@jabber.org

Peter Saint-Andre

Email: stpeter@jabber.org
JID: stpeter@jabber.org

Legal Notice

This XMPP Extension Protocol is copyright 1999 - 2007 by the XMPP Standards Foundation (XSF) and is in full conformance with the XSF's Intellectual Property Rights Policy <http://www.xmpp.org/extensions/ipr-policy.shtml>. This material may be distributed only subject to the terms and conditions set forth in the Creative Commons Attribution License (<http://creativecommons.org/licenses/by/2.5/>).

Discussion Venue

The preferred venue for discussion of this document is the Standards discussion list: <http://mail.jabber.org/mailman/listinfo/standards>.

Given that this XMPP Extension Protocol normatively references IETF technologies, discussion on the XSF-IETF list may also be appropriate (see <http://mail.jabber.org/mailman/listinfo/jsf-ietf> for details).

Relation to XMPP

The Extensible Messaging and Presence Protocol (XMPP) is defined in the XMPP Core (RFC 3920) and XMPP IM (RFC 3921) specifications contributed by the XMPP Standards Foundation to the Internet Standards Process, which is managed by the Internet Engineering Task Force in accordance with RFC 2026. Any protocol defined in this document has been developed outside the Internet Standards Process and is to be understood as an extension to XMPP rather than as an evolution, development, or modification of XMPP itself.

Conformance Terms

The following keywords as used in this document are to be interpreted as described in RFC 2119: "MUST", "SHALL", "REQUIRED"; "MUST NOT", "SHALL NOT"; "SHOULD", "RECOMMENDED"; "SHOULD NOT", "NOT RECOMMENDED"; "MAY", "OPTIONAL".


Table of Contents

1. Introduction
2. Terminology
2.1. HTTP Terms
3. Requirements
4. Architectural Assumptions
5. HTTP Version and HTTP Headers
6. Compression
7. <body/> Wrapper Element
8. Initiating an HTTP Session
8.1. Requesting a Session
8.2. Session Creation
8.3. Communication of Stream Features
9. Additional Preconditions
9.1. XMPP Methods
9.2. jabber:iq:auth
10. Sending and Receiving XML Stanzas
11. Terminating the HTTP Session
12. Request IDs
12.1. Syntax
12.2. In-Order Message Forwarding
12.3. Broken Connections
13. Protecting Insecure Sessions
13.1. Applicability
13.2. Introduction
13.3. Generating the Key Sequence
13.4. Use of Keys
13.5. Switching to Another Key Sequence
14. Multiple Streams
14.1. Introduction
14.2. Discovery
14.3. Adding Streams To A Session
14.4. Transmitting Stanzas
14.5. Closing a Stream
14.6. Error Conditions
15. Error and Status Codes
15.1. HTTP Conditions
15.2. Terminal Binding Conditions
15.3. Recoverable Binding Conditions
15.4. XMPP Stanza Conditions
16. Implementation Notes
17. Security Considerations
18. IANA Considerations
19. XMPP Registrar Considerations
19.1. Protocol Namespaces
20. XML Schema
Notes
Revision History


1. Introduction

XMPP Core [1] defines XML streams bound to TCP (see RFC 793 [2]) as the standard transport layer for Jabber/XMPP communications. However, the binding of XMPP to TCP is not always feasible because of client runtime environment and/or network constraints. This document describes the usage of the Hypertext Transfer Protocol (HTTP, see RFC 2068 [3] and RFC 1945 [4]) as an alternative transport binding that supports such constrained environments, normally via deployment of a specialized server-side connection manager that communicates with clients via HTTP rather than TCP.

Before the authors pursued publication of this document, other approaches were explored. One possible approach might have been to apply state to a series of HTTP transactions via HTTP "cookies" as specified in RFC 2965 [5]. However, there are several significant computing platforms which provide only limited access to underlying HTTP requests/responses; worse, some platforms hide or remove cookie-related headers. Therefore the cookie approach was rejected.

Another approach might have been to modify or extend Jabber HTTP Polling [6]. This informational protocol has been used by Jabber clients without runtime constraints to access XMPP servers from behind firewalls. Unfortunately, the method defined in XEP-0025 also depends on cookies, does not meet most of the requirements described below, and cannot be extended without breaking all existing implementations.

Therefore, this document specifies a new way of transporting XMPP via HTTP. All information is encoded in the body of standard HTTP POST requests and responses. Each HTTP body contains a single <body/> XML wrapper element (not to be confused with the <body/> child of the <message/> stanza as defined in XMPP IM [7]), which encapsulates zero or more XML stanzas.

Although this specification documents some XMPP-specific features, the binding is not part of XMPP. In fact, the protocol is extensible and could be used to implement any bidirectional stream of XML stanzas.

2. Terminology

2.1 HTTP Terms

This document inherits terminology regarding the Hypertext Transport Protocol from RFCs 1945 and 2068.

3. Requirements

Platform limitiations, security restrictions, and other constraints imply that many clients can connect to Internet resources (e.g., Jabber servers) only via HTTP. The following design requirements reflect the need to offer performance as close as possible to a standard TCP connection.

  1. Compatible with constrained runtime environments (e.g., mobile and browser-based clients).
  2. Compatible with restricted network connections (e.g., firewalls, proxies, and gateways).
  3. Fault tolerant (e.g., session recovers after an underlying TCP connection breaks during an HTTP request).
  4. Extensible (based on XML).
  5. Consume significantly less bandwidth than polling-based solutions.
  6. Significantly more responsive than polling-based solutions.
  7. Support for polling (for clients that are limited to one HTTP connection at a time).
  8. XML stanzas should arrive at the server in the order they were sent by the client.
  9. Protect against unauthorized users interjecting HTTP requests into a session.

Compatibility with constrained runtime environments implies the following restrictions:

4. Architectural Assumptions

The binding of XMPP to HTTP assumes a different architecture from that described for the binding of XMPP to TCP as defined in RFC 3920. In particular, because HTTP is not the native binding for XMPP, we assume that most XMPP implementations will utilize a specialized "connection manager" to handle HTTP connections rather than the usual TCP connections. Effectively, such a connection manager will be a specialized HTTP server that translates between the HTTP requests and responses defined herein and the XML streams (or a server API) implemented by the XMPP server or servers with which it communicates, thus enabling an HTTP client to connect to an XMPP server. We can illustrate this graphically as follows:

  XMPP Server
      |
      |  [XML streams or server API]
      |
Connection Manager
      |
      |  [HTTP + <body/> wrapper]
      |
  HTTP Client
    

This document addresses communications between an HTTP client and the connection manager only. It does not address communications between the connection manager and the XMPP server, since such communications are implementation-specific (e.g., the connection manager and the XMPP server may use Jabber Component Protocol [8] or an API defined by the XMPP server implementation in order to communicate; alternatively, the XMPP server may natively support the HTTP binding, in which case the connection manager will be a logical entity rather than a physical entity).

Furthermore, no aspect of the HTTP binding limits its use to client-to-server communications; i.e., it could be used for server-to-server or component-to-server communications as well (probably through a slight change to the XML schema). However, this document focuses exclusively on use of the HTTP binding by clients that cannot maintain persistent TCP connections to a server and that therefore cannot use the TCP binding defined in RFC 3920. We assume that servers and components are under no such restrictions and thus would use the TCP binding.

5. HTTP Version and HTTP Headers

Clients SHOULD send HTTP requests over persistent HTTP/1.1 connections. However, a constrained client MAY open a new HTTP/1.0 connection (as defined in RFC 1945) to send each request.

Requests and responses MAY include HTTP headers not specified herein. The receiver SHOULD ignore any such headers.

6. Compression

Clients MAY include an HTTP Accept-Encoding header in any request. If the connection manager receives a request with an Accept-Encoding header, it MAY include an HTTP Content-Encoding header in the response (indicating one of the encodings specified in the request) and compress the response body accordingly.

TLS compression (as defined in RFC 3920) and Stream Compression (as defined in Stream Compression [9]) are NOT RECOMMENDED since compression SHOULD be negotiated at the HTTP layer and with the 'accept' attribute (see the Session Creation section below). TLS compression and Stream Compression SHOULD NOT be used simultaneously with HTTP content encoding.

7. <body/> Wrapper Element

The body of each HTTP request and response contains a single <body/> wrapper element. The <body/> element MUST contain zero or more complete XML elements. It MUST NOT contain partial XML elements.

If the <body/> wrapper element is not empty, then it MUST contain one of the following:

Note: Inclusion of TLS negotiation elements is allowed but is NOT RECOMMENDED (see Additional Preconditions below).

The <body/> wrapper element SHOULD be qualified by the 'http://jabber.org/protocol/httpbind' namespace, and child elements SHOULD be qualified by their respective namespaces (e.g., 'http://etherx.jabber.org/streams' for stream features, 'urn:ietf:params:xml:ns:xmpp-sasl' for SASL negotiation, and 'jabber:client' for XML stanzas). However, even if the client does not specify the namespaces, the connection manager MUST ensure that the XMPP it provides to the XMPP server or other entities on the network meets the namespacing requirements of RFC 3920.

The <body/> element of every client request MUST possess a sequential request ID encapsulated via the 'rid' attribute; For details, refer to the Request IDs section of this document.

8. Initiating an HTTP Session

8.1 Requesting a Session

The first request from the client to the connection manager creates a new session.

The <body/> element of the first request SHOULD possess the following attributes (they SHOULD NOT be included in any other requests except as specified in the Adding Streams To A Session section below):

Note: Clients that only support polling behavior MAY prevent the connection manager from waiting by setting 'wait' or 'hold' to "0". However, polling is NOT RECOMMENDED since the associated increase in bandwidth consumption and the decrease in responsiveness are typically one or two orders of magnitude!

A connection manager MAY be configured to enable sessions with more than one XMPP server in different domains. When requesting a session with such a 'proxy' connection manager, a client SHOULD include a 'route' attribute that specifies the protocol, hostname, and port of the server with which it wants to communicate, formatted as "proto:host:port" (e.g., "xmpp:jabber.org:9999"). [11] A connection manager that is configured to work only with a single XMPP server (or only with a defined list of XMPP domains and their respective hosts and ports) MAY ignore the 'route' attribute. (Note that the 'to' attribute specifies the XMPP domain, not the host machine.)

A client MAY include a 'secure' attribute to specify that communications between the connection manager and the XMPP server must be "secure". (Note: The 'secure' attribute is of type xs:boolean (see XML Schema Part 2 [12]) and the default value is "false". [13]) If a connection manager receives a session request with the 'secure' attribute set to 'true' or '1', then it MUST respond to the client with a remote-connection-failed error as soon as it determines that it cannot communicate in a secure way with the XMPP server. A connection manager SHOULD consider communications with the XMPP server to be "secure" if they are encrypted using SSL or TLS with verified certificates, or if it is running on the same physical machine as the XMPP server. A connection manager MAY consider communications over a "private" network to be secure, even without SSL or TLS; however, a network SHOULD be considered "private" only if the administrator of the connection manager is sure that unknown individuals or processes do not have access to the network (i.e., individuals or processes who do not have access to either the connection manager or the XMPP server). The connection manager SHOULD try to establish a secure connection with the XMPP server even if the client does not specifically require it.

Some clients are constrained to only accept HTTP responses with specific Content-Types (e.g., "text/html"). The <body/> element of the first request MAY possess a 'content' attribute. This specifies the value of the HTTP Content-Type header that MUST appear in all the connection manager's responses during the session. If the client request does not possess a 'content' attribute, then the HTTP Content-Type of responses MUST be "text/xml; charset=utf-8".

Note: The HTTP Content-Type of client requests SHOULD also be "text/xml; charset=utf-8". Clients MAY specify another value if they are constrained to do so (e.g., "application/x-www-form-urlencoded" or "text/plain"). The client and connection manager SHOULD ignore all HTTP Content-Type headers they receive.

Example 1. Requesting an HTTP session

POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 104

<body content='text/xml; charset=utf-8'
      hold='1'
      rid='1573741820'
      to='jabber.org'
      route='xmpp:jabber.org:9999'
      secure='true'
      wait='60'
      xml:lang='en'
      xmlns='http://jabber.org/protocol/httpbind'/>

Note: Unlike the protocol defined in XEP-0025, an opening <stream:stream> tag is not sent. The protocol defined herein abstracts from XML streams between the connection manager and the client. Any XML streams between the connection manager and an XMPP server are the responsibility of the connection manager.

Note: All requests after the first one MUST include a valid 'sid' attribute (provided by the connection manager in the session creation response below). The initialization request is unique in that the <body/> element MUST NOT possess a 'sid' attribute.

8.2 Session Creation

After receiving a new session request, the connection manager MUST generate an opaque, unpredictable session identifier (or SID). The SID MUST be unique within the context of the connection manager application. The connection manager then returns that SID to the client in a response <body/> element.

The connection manager MUST specify a 'wait' attribute. This is the longest time (in seconds) that it will wait before responding to any request during the session. The time MUST be less than or equal to the value specified in the session request.

The connection manager MAY limit the number of simultaneous requests the client makes with the 'requests' attribute. The RECOMMENDED value is "2". Servers that only support polling behavior MUST prevent clients from making simultaneous requests by setting the 'requests' attribute to a value of "1" (however, polling is NOT RECOMMENDED). In any case, clients MUST NOT make more simultaneous requests than specified by the connection manager.

The connection manager SHOULD include two additional attributes in the session creation response element, specifying the shortest allowable polling interval and the longest allowable inactivity period (both in seconds). Communication of these parameters enables the client to engage in appropriate behavior (e.g., not sending empty request elements more often than desired, and ensuring that the periods with no requests pending are never too long).

The connection manager MAY include an 'accept' attribute in the session creation response element, to specify the content encodings it can decompress. After receiving a session creation response with an 'accept' attribute, clients MAY include an HTTP Content-Encoding header in subsequent requests (indicating one of the encodings specified in the 'accept' attribute) and compress the bodies of the requests accordingly.

For both requests and responses, the <body/> element and its content SHOULD be UTF-8 encoded. If the HTTP Content-Type header of a request/response specifies a character encoding other than UTF-8, then the connection manager MAY convert between UTF-8 and the other character encoding. However, even in this case, it is OPTIONAL for the connection manager to convert between encodings. The connection manager MAY inform the client which encodings it can convert by setting the optional 'charsets' attribute in the session creation response element to a space-separated list of encodings. [14]

Example 2. Session creation response

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 128

<body authid='ServerStreamID'
      wait='60'
      inactivity='30'
      polling='5'
      requests='2'
      accept='deflate,gzip'
      sid='SomeSID'
      secure='true'
      charsets='ISO_8859-1 ISO-2022-JP'
      xmlns='http://jabber.org/protocol/httpbind'/>

Note: The 'authid' attribute contains the value of the XMPP stream ID generated by the XMPP server. The connection manager MUST retrieve the stream ID and pass it unmodified to the client. This value is needed by the client to successfully complete digest authentication using Non-SASL Authentication [16] (see the jabber:iq:auth section below).

Note: If the 'authid' attribute is not included in the connection manager's response to the session creation request (e.g., because the connection manager has not yet received a stream ID from the XMPP server), then the client SHOULD send empty request elements (see the "Requesting XML Stanzas" example below) until it receives a response with an 'authid' attribute. In any case, the connection manager MUST return the 'authid' in a response to the client as soon as possible after it receives the stream ID from the XMPP server.

Separate 'sid' and 'authid' attributes are required because the connection manager is not necessarily part of a single XMPP server (e.g., it may handle HTTP connections on behalf of multiple XMPP servers).

If it established a secure connection to the XMPP server (as defined in Initiating an HTTP Session), then the connection manager SHOULD include the 'secure' attribute set to 'true' or '1' in the response to the client that contains the 'authid' attribute.

8.3 Communication of Stream Features

As an immediate child of the response that contains the 'authid' attribute, the connection manager SHOULD include a stream features element, as defined by RFC 3920.

Example 3. Session creation response with stream features

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 417

<body authid='ServerStreamID'
      wait='60'
      inactivity='30'
      polling='5'
      requests='2'
      accept='deflate,gzip'
      sid='SomeSID'
      charsets='ISO_8859-1 ISO-2022-JP'
      xmlns='http://jabber.org/protocol/httpbind'
      xmlns:stream='http://etherx.jabber.org/streams'>
  <stream:features>
    <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
      <mechanism>DIGEST-MD5</mechanism>
      <mechanism>PLAIN</mechanism>
    </mechanisms>
    <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
    <session xmlns='urn:ietf:params:xml:ns:xmpp-session'>
  </stream:features>
</body>

The stream features SHOULD NOT include a feature for Transport Layer Security (TLS), since channel encryption SHOULD be negotiated at the HTTP layer (see the Security Considerations section below).

9. Additional Preconditions

Initializing an HTTP session is the first precondition to sending XML message, presence, and IQ stanzas. However, before processing XML stanzas from the client, the connection manager MUST require completion of additional preconditions using either of the following methods:

It is RECOMMENDED to use the XMPP methods as defined in RFC 3920 and RFC 3921, rather than using older non-SASL authentication.

9.1 XMPP Methods

A success case for authentication, resource binding, and IM session establishment using the XMPP protocols is shown below. For detailed specification of these protocols (including error cases) and for specification of TLS negotiation, refer to RFC 3920 and RFC 3921.

Example 4. SASL authentication step 1

POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 172

<body rid='1573741821'
      sid='SomeSID'
      xmlns='http://jabber.org/protocol/httpbind'>
  <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'/>
</body>

Example 5. SASL authentication step 2

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 250

<body xmlns='http://jabber.org/protocol/httpbind'>
  <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
    cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOXRFUUdtMmhoIixxb3A9
    ImF1dGgiLGNoYXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNzCg==
  </challenge>
</body>

Example 6. SASL authentication step 3

POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 418

<body rid='1573741822'
      sid='SomeSID'
      xmlns='http://jabber.org/protocol/httpbind'>
  <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
    dXNlcm5hbWU9InNvbWVub2RlIixyZWFsbT0ic29tZXJlYWxtIixub25jZT0i
    T0E2TUc5dEVRR20yaGgiLGNub25jZT0iT0E2TUhYaDZWcVRyUmsiLG5jPTAw
    MDAwMDAxLHFvcD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5jb20i
    LHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwYTE1MjMyMWYyMTQzYWY3LGNo
    YXJzZXQ9dXRmLTgK
  </response>
</body>

Example 7. SASL authentication step 4

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 190

<body xmlns='http://jabber.org/protocol/httpbind'>
  <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
    cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZAo=
  </challenge>
</body>

Example 8. SASL authentication step 5

POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 152

<body rid='1573741823'
      sid='SomeSID'
      xmlns='http://jabber.org/protocol/httpbind'>
  <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
</body>

Example 9. SASL authentication step 6

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 121

<body xmlns='http://jabber.org/protocol/httpbind'>
  <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
</body>

Note: Because the context for a client's communication with a connection manager in the HTTP transport binding is HTTP rather than XML streams (as in the TCP binding), there is no need to re-start communications (e.g., by generating a new SID) at this point.

Example 10. Resource binding request

POST /webclient HTTP/1.1
Content-Type: text/xml; charset=utf-8
Content-Length: 240

<body rid='1573741824'
      sid='SomeSID'
      xmlns='http://jabber.org/protocol/httpbind'>
  <iq id='bind_1'
      type='set'
      xmlns='jabber:client'>
    <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
      <resource>httpclient</resource>
    </bind>
  </iq>
</body>

Example 11. Resource binding result

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 221

<body xmlns='http://jabber.org/protocol/httpbind'>
  <iq id='bind_1'
      type='result'
      xmlns='jabber:client'>
    <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
      <jid>stpeter@jabber.org/httpclient</jid>
    </bind>
  </iq>
</body>

Example 12. IM session request

POST /webclient HTTP/1.1
Content-Type: text/xml; charset=utf-8
Content-Length: 261

<body rid='1573741825'
      sid='SomeSID'
      xmlns='http://jabber.org/protocol/httpbind'>
  <iq from='stpeter@jabber.org/httpclient'
      id='sess_1'
      to='jabber.org'
      type='set'
      xmlns='jabber:client'>
    <session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>
  </iq>
</body>

Example 13. IM session result

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 175

<body xmlns='http://jabber.org/protocol/httpbind'>
  <iq from='jabber.org'
      id='sess_1'
      to='stpeter@jabber.org/httpclient'
      type='result'
      xmlns='jabber:client'/>
</body>

9.2 jabber:iq:auth

A success case for simultaneous authentication, resource binding, and IM session creation using the original "jabber:iq:auth" protocol is shown below. For further details regarding use of this protocol, refer to XEP-0078. If digest authentication is used, then the stream ID value used to compute the hashed password MUST be the value of the 'authid' attribute provided by the connection manager in the response to the initialization element or in a subsequent response (see the Session Creation section above).

Example 14. Non-SASL authentication request

POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 281

<body rid='1249243561'
      sid='SomeSID'
      xmlns='http://jabber.org/protocol/httpbind'>
  <iq id='A01'
      type='set'
      xmlns='jabber:client'>
    <query xmlns='jabber:iq:auth'>
      <username>stpeter</username>
      <resource>httpclient</resource>
      <password>jabber-rocks</password>
    </query>
  </iq>
</body>

Example 15. Authentication result (success)

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 144

<body xmlns='http://jabber.org/protocol/httpbind'>
  <iq id='A01'
      type='result'
      xmlns='jabber:client'/>
</body>

Example 16. Authentication result (failure)

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 226

<body xmlns='http://jabber.org/protocol/httpbind'>
  <iq id='A01'
      type='error'
      xmlns='jabber:client'>
    <error code='401' type='auth'>
      <not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    </error>
  </iq>
</body>

10. Sending and Receiving XML Stanzas

After the client has successfully completed all required preconditions, it can send and receive XML stanzas via the HTTP binding.

Example 17. Transmitting stanzas

POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 188

<body rid='1249243562'
      sid='SomeSID'
      xmlns='http://jabber.org/protocol/httpbind'>
  <message to='contact@example.com'
           xmlns='jabber:client'>
    <body>Hi there!</body>
  </message>
  <message to='friend@example.com'
           xmlns='jabber:client'>
    <body>Hi there!</body>
  </message>
</body>

Upon receipt of a request, the connection manager MUST forward the content of the <body/> element to the XMPP server as soon as possible. However, it must forward the content from different requests in the order specified by their 'rid' attributes.

The connection manager MUST also return an HTTP 200 OK response with a <body/> element to the client. Note: This does not indicate that the stanzas have been successfully delivered to the destination Jabber endpoint.

It is RECOMMENDED that the connection manager not return an HTTP result until a stanza has arrived from the XMPP server for delivery to the client. However, the connection manager SHOULD NOT wait longer than the time specified by the client in the 'wait' attribute of its session creation request, and it SHOULD NOT keep more HTTP requests waiting at a time than the number specified in the 'hold' attribute of the session creation request. In any case it MUST respond to requests in the order specified by their 'rid' attributes.

If there are no stanzas waiting or ready to be delivered within the waiting period, then the connection manager SHOULD include an empty <body/> element in the HTTP result:

Example 18. Empty response

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 64

<body xmlns='http://jabber.org/protocol/httpbind'/>

If the connection manager has received one or more stanzas from the XMPP server for delivery to the client, then it SHOULD return the stanzas in the body of its response as soon as possible after receiving them from the XMPP server.

Example 19. Response with queued stanza

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 185

<body xmlns='http://jabber.org/protocol/httpbind'>
  <message from='contact@example.com'
           to='user@example.com'
           xmlns='jabber:client'>
    <body>Hi yourself!</body>
  </message>
  <message from='friend@example.com'
           to='user@example.com'
           xmlns='jabber:client'>
    <body>Hi yourself!</body>
  </message>
</body>

The client MAY poll the connection manager for incoming stanzas by sending an empty <body/> element.

Example 20. Requesting XML Stanzas

POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 88

<body rid='1249243563'
      sid='SomeSID'
      xmlns='http://jabber.org/protocol/httpbind'/>

The connection manager MUST wait and respond in the same way as it does after receiving stanzas from the client.

If the client sends two consecutive empty requests within a period shorter than that specified by the 'polling' attribute in the session creation response, then the connection manager SHOULD terminate the HTTP session and return an HTTP 403 (Forbidden) error to the client.

Example 21. Too frequent polling response

HTTP/1.1 403 Forbidden
Content-Type: text/xml; charset=utf-8
Content-Length: 0

If the connection manager did not specify a shortest allowable polling interval in the session creation response, then it MUST allow the client to poll as frequently as it chooses.

After receiving a response from the connection manager, if no other requests are pending and the client did not specify polling behavior in the session creation request (by setting 'wait' or 'hold' to "0"), it SHOULD make a new request as soon as possible. In any case, if no requests are pending, the client MUST make a new request before the maximum inactivity period has expired. This period is specified by the 'inactivity' attribute in the session creation response.

If the connection manager has responded to all the requests it has received and the time since its last response is longer than the maximum inactivity period, then it SHOULD terminate the session without informing the client (if the client makes another request, the connection manager SHOULD respond as if the session does not exist).

If the connection manager did not specify a maximum inactivity period in the session creation response, then it MUST allow the client to be inactive for as long as it chooses.

11. Terminating the HTTP Session

At any time, the client MAY gracefully terminate the session by sending a <body/> element with a 'type' attribute set to "terminate". The termination request SHOULD include an XMPP presence stanza of type "unavailable" to ensure graceful logoff with the XMPP server.

Example 22. Session termination by client

POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 153

<body rid='1249243564'
      sid='SomeSID'
      type='terminate'
      xmlns='http://jabber.org/protocol/httpbind'>
  <presence type='unavailable'
            xmlns='jabber:client'/>
</body>

The connection manager SHOULD return an HTTP 200 OK response with an empty <body/> element. Upon receiving the response, the client MUST consider the HTTP session to have been terminated.

12. Request IDs

12.1 Syntax

The client MUST generate a large, random, positive integer for the initial 'rid' (see Security Considerations) and then increment that value by one for each subsequent request. The client MUST take care to choose an initial 'rid' that will never be incremented above 9007199254740991 [17] within the session. In practice, a session would have to be extraordinarily long (or involve the exchange of an extraordinary number of packets) to exceed the defined limit.

12.2 In-Order Message Forwarding

When a client makes simultaneous requests, the connection manager may receive them out of order. The connection manager MUST forward the stanzas to the XMPP server and respond to the client requests in the order specified by the 'rid' attributes. The client MUST process responses received from the connection manager in the order the requests were made.

The connection manager SHOULD expect the 'rid' attribute to be within a window of values greater than the 'rid' of the previous request. The size of the window is equal to the maximum number of simultaneous requests allowed by the connection manager. If it receives a request with a 'rid' greater than the values in the window, then the connection manager MUST terminate the session with an error:

Example 23. Unexpected rid error

HTTP/1.1 404 Not Found
Content-Type: text/xml; charset=utf-8
Content-Length: 0

12.3 Broken Connections

Unreliable network communications or client constraints can result in broken connections. The connection manager SHOULD remember the 'rid' and the associated HTTP response body of the client's most recent requests which did not result in an HTTP or binding error. The number of responses kept in the buffer should be the same as the maximum number of simultaneous requests allowed by the connection manager.

If the network connection is broken or closed before the client receives a response to a request from the connection manager, then the client MAY resend an exact copy of the original request. Whenever the connection manager receives a request with a 'rid' that it has already received, it SHOULD return an HTTP 200 (OK) response that includes the buffered copy of the original XML response to the client (i.e., a <body/> wrapper element possessing appropriate attributes and optionally containing one or more XML stanzas or other allowable XML elements). If the original response is not available (e.g., it is no longer in the buffer), then the connection manager MUST return an HTTP 404 (Not Found) error:

Example 24. Response not in buffer error

HTTP/1.1 404 Not Found
Content-Type: text/xml; charset=utf-8
Content-Length: 0

Note: The error is the same whether the 'rid' is too large or too small. This makes it more difficult for an attacker to discover an acceptable value.

13. Protecting Insecure Sessions

13.1 Applicability

The OPTIONAL key sequencing mechanism described here MAY be used if the client's session with the connection manager is not secure. The session should be considered secure only if all client requests are made via SSL (or TLS) HTTP connections and the connection manager generates an unpredictable session ID. If the session is secure, it is not necessary to use this key sequencing mechanism.

Even if the session is not secure, the unpredictable session and request IDs specified in the preceding sections of this document already provide a level of protection similar to that provided by a standard XMPP connection bound to a single pair of persistent TCP/IP connections, and thus provide sufficient protection against a 'blind' attacker. However, in some circumstances, the key sequencing mechanism defined below helps to protect against a more determined and knowledgeable attacker.

It is important to recognize that the key sequencing mechanism defined below helps to protect only against an attacker who is able to view the contents of all requests or responses in an insecure session but who is not able to alter the contents of those requests (in this case, the mechanism prevents the attacker from interjecting HTTP requests into the session, e.g., termination requests or responses). However, the key sequencing mechanism does not provide any protection when the attacker is able to alter the contents of insecure requests or responses.

13.2 Introduction

The HTTP requests of each session MAY be spread across a series of different socket connections. This would enable an unauthorized user that obtains the session ID and request ID of a session and then use their own socket connection to interject <body/> request elements into the session and receive the corresponding responses.

The key sequencing mechanism below protects against such attacks by enabling a connection manager to detect <body/> request elements interjected by a third party.

13.3 Generating the Key Sequence

Prior to requesting a new session, the client MUST select an unpredictable counter ("n") and an unpredictable value ("seed"). The client then processes the "seed" through a cryptographic hash and converts the resulting 160 bits to a hexadecimal string K(1). It does this "n" times to arrive at the initial key K(n). The hashing algorithm MUST be SHA-1 as defined in RFC 3174 [18].

Example 25. Creating the key sequence

        K(1) = hex(SHA-1(seed))
        K(2) = hex(SHA-1(K(1)))
        ...
        K(n) = hex(SHA-1(K(n-1)))
      

13.4 Use of Keys

The client MUST set the 'newkey' attribute of the first request in the session to the value K(n).

Example 26. Session Request with Initial Key

POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 104

<body content='text/xml; charset=utf-8'
      hold='1'
      rid='1573741820'
      to='jabber.org'
      wait='60'
      xml:lang='en'
      newkey='ca393b51b682f61f98e7877d61146407f3d0a770'
      xmlns='http://jabber.org/protocol/httpbind'/>

The client MUST set the 'key' attribute of all subsequent requests to the value of the next key in the generated sequence (decrementing from K(n-1) towards K(1) with each request sent).

Example 27. Request with Key

POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 88

<body rid='1573741821'
      sid='SomeSID'
      key='bfb06a6f113cd6fd3838ab9d300fdb4fe3da2f7d'
      xmlns='http://jabber.org/protocol/httpbind'/>

The connection manager MAY verify the key by calculating the SHA-1 hash of the key and comparing it to the 'newkey' attribute of the previous request (or the 'key' attribute if the 'newkey' attribute was not set). If the values do not match (or if it receives a request without a 'key' attribute and the 'newkey' or 'key' attribute of the previous request was set), then the connection manager MUST NOT process the element, MUST terminate the session, and MUST return an HTTP 404 (Not Found) error.

Example 28. Invalid Key Sequence Error

HTTP/1.1 404 Not Found
Content-Type: text/xml; charset=utf-8
Content-Length: 0

13.5 Switching to Another Key Sequence

A client SHOULD choose a high value for "n" when generating the key sequence. However, if the session lasts long enough that the client arrives at the last key in the sequence K(1) then the client MUST switch to a new key sequence.

The client MUST:

  1. Choose new values for "seed" and "n".
  2. Generate a new key sequence using the algorithm defined above.
  3. Set the 'key' attribute of the request to the next value in the old sequence (i.e. K(1), the last value).
  4. Set the 'newkey' attribute of the request to the value K(n) from the new sequence.

Example 29. New Key Sequence

POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 188

<body rid='1573741822'
      sid='SomeSID'
      key='6f825e81f4532b2c5fa2d12457d8a1f22e8f838e'
      newkey='113f58a37245ec9637266cf2fb6e48bfeaf7964e'
      xmlns='http://jabber.org/protocol/httpbind'>
  <message to='contact@example.com'
           xmlns='jabber:client'>
    <body>Hi there!</body>
  </message>
</body>

14. Multiple Streams

14.1 Introduction

The OPTIONAL feature described in this section enables multiple XMPP streams to be contained within a single HTTP session. This feature is essential in runtime environments that constrain the number of simultaneous HTTP requests a client may make to each connection manager, since clients running in such environments need multi-stream sessions if they are to connect using more than one account at the same time. This feature also reduces network traffic for any client that needs to establish parallel streams over HTTP.

14.2 Discovery

If a connection manager supports the multi-streams feature, it MUST include a 'stream' attribute in its session creation response. If a client does not receive the 'stream' attribute then it MUST assume that the connection manager does not support the feature. [19]

The 'stream' attribute identifies the first stream to be opened for the session. The value of each 'stream' attribute MUST be an opaque and unpredictable name that is unique within the context of the connection manager application.

Example 30. Session creation response with stream name

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 128

<body authid='ServerStreamID'
      wait='60'
      inactivity='30'
      polling='5'
      requests='2'
      accept='deflate,gzip'
      sid='SomeSID'
      secure='true'
      stream='firstStreamName'
      charsets='ISO_8859-1 ISO-2022-JP'
      xmlns='http://jabber.org/protocol/httpbind'/>

14.3 Adding Streams To A Session

If the connection manager included a 'stream' attribute in its session creation response then the client MAY ask it to open another stream at any time by sending it an empty <body/> element with a 'to' attribute. The request MUST include valid 'sid' and 'rid' [20] attributes, it SHOULD also include an 'xml:lang' attribute. The request MAY include 'route' and 'secure' attributes (see Requesting a Session above), but it SHOULD NOT include 'content', 'hold' or 'wait' attributes.

Example 31. Requesting another stream

POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 104

<body sid='SomeSID'
      rid='1573741820'
      to='jabber.org'
      route='xmpp:jabber.org:9999'
      secure='true'
      xml:lang='en'
      xmlns='http://jabber.org/protocol/httpbind'/>

If the connection manager did not indicate its support for multiple streams at the start of the session then it MUST ignore the extra attributes and treat the request as a normal empty request for stanzas (see Sending and Receiving XML Stanzas above). [21] Otherwise it MUST open a new stream with the specified server (see Session Creation above), generate a new stream name and respond to the client with the name. The response MAY also include 'authid' and 'secure' attributes, but it SHOULD NOT include 'sid', 'requests', 'polling', 'inactivity', 'accept', 'charsets' or 'wait' attributes.

Example 32. Add stream response

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 128

<body stream='secondStreamName'
      authid='ServerStreamID'
      secure='true'
      xmlns='http://jabber.org/protocol/httpbind'/>

Note: If the response did not include an 'authid' then the attribute (and any associated 'secure' attribute) MUST be sent in a subsequent response instead (see Session Creation above). In that case the 'stream' attribute MUST also be specified.

14.4 Transmitting Stanzas

If more than one stream has been opened within a session, then all non-empty <body/> elements sent by the connection manager MUST include a 'stream' attribute that specifies which stream all the stanzas it contains belong to. The client SHOULD include a 'stream' attribute for the same purpose. The client MAY omit the 'stream' attribute if it wants the connection manager to broadcast the stanzas over all open streams. Note: A <body/> element MUST NOT contain different stanzas for different streams.

If a stream name does not correspond to one of the session's open streams, then the receiving connection manager SHOULD return an HTTP 404 (Not Found) error, or the receiving client SHOULD terminate the session. However, if the receiving entity has only just closed the stream (and the sender may not have been aware of that when it sent the stanzas), then it MAY instead simply silently ignore any stanzas the <body/> element contains.

Note: Empty <body/> elements that do not include an 'authid' attribute SHOULD NOT include a 'stream' attribute (since nothing is being transmitted for any stream). If such a <body/> element does include a 'stream' attribute then the receiving entity SHOULD ignore the attribute.

Example 33. Client sends stanza with a stream name

POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 188

<body rid='1249243562'
      sid='SomeSID'
      stream='secondStreamName'
      xmlns='http://jabber.org/protocol/httpbind'>
  <message to='contact@example.com'
           xmlns='jabber:client'>
    <body>Hi there!</body>
  </message>
</body>

Note: The value of the 'stream' attribute of the response MAY be different to the corresponding request. [22]

Example 34. Connection manager responds with a different stream name

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 185

<body stream='firstStreamName'
      xmlns='http://jabber.org/protocol/httpbind'>
  <message from='contact@example.com'
           to='user@example.com'
           xmlns='jabber:client'>
    <body>Hi yourself!</body>
  </message>
</body>

If no stream name is specified by the connection manager then the client MUST assume the stanzas are associated with the first stream (even if the first stream has been closed - see the 404 error above).

If no stream name is specified by the client then the connection manager MUST broadcast the stanzas over all open streams. [23]

Example 35. Client asks for a stanza to be broadcast

POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 188

<body rid='1249243562'
      sid='SomeSID'
      xmlns='http://jabber.org/protocol/httpbind'>
  <presence xmlns='jabber:client'>
    <show>away</show>
  </presence>
</body>

14.5 Closing a Stream

If more than one stream is open within a session, the client MAY close one open stream at any time using the procedure described in the section Terminating the HTTP Session above, taking care to specify the stream name with a 'stream' attribute. If the client closes the last stream the connection manager MUST terminate the session. If the client does not specify a stream name then the connection manager MUST close all open streams (sending any stanzas the terminate request contains to all streams), and terminate the session.

Example 36. Client closes one stream

POST /webclient HTTP/1.1
Host: httpcm.jabber.org
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
Content-Length: 153

<body rid='1249243564'
      sid='SomeSID'
      stream='secondStreamName'
      type='terminate'
      xmlns='http://jabber.org/protocol/httpbind'>
  <presence type='unavailable'
            xmlns='jabber:client'/>
</body>

14.6 Error Conditions

If more than one stream is open within a session, the connection manager MAY include a 'stream' attribute in a fatal binding error (see Terminal Binding Conditions below). If a 'stream' attribute is specified then the stream MUST be closed by both entities but the session SHOULD NOT be terminated.

Example 37. Fatal stream error

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 68

<body type='terminate'
      condition='remote-connection-failed'
      stream='secondStreamName'
      xmlns='http://jabber.org/protocol/httpbind'/>

Note: If the connection manager does not include a 'stream' attribute in a fatal binding error then all the session's open streams MUST be closed by both entities and the session MUST be terminated.

15. Error and Status Codes

There are four types of error and status reporting in HTTP responses:

Table 1: Error Condition Types

Condition Type Description
HTTP Conditions The connection manager responds to an invalid client request with a standard HTTP error. These are used for binding syntax errors, possible attacks, etc. Note that constrained clients are unable to differentiate between HTTP errors.
Terminal Binding Conditions These error conditions may be read by constrained clients. They are used for connection manager problems, abstracting stream errors, and communication problems between the connection manager and the XMPP server.
Recoverable Binding Conditions These report communication problems between the connection manager and the client. They do not terminate the session. Clients recover from these errors by resending all the preceding <body/> wrapper elements that have not received responses.
XMPP Stanza Conditions XMPP errors relating to XML stanzas within <body/> wrapper elements are, in general, defined in the appropriate RFC or XEP. They do not terminate the session. (An example of such usage is shown in jabber:iq:auth above.)

Full descriptions are provided below.

15.1 HTTP Conditions

The following HTTP error and status codes are used in particular ways by this protocol (other HTTP error and status codes may be used as appropriate). Upon receiving an HTTP error (400, 403, 404), the HTTP client MUST consider the HTTP session to be null and void.

Note: These are pure HTTP codes as defined in the HTTP specification, and are not to be confused with the HTTP-style error codes traditionally used in Jabber protocols and documented in Error Condition Mappings [24].

Table 2: HTTP Error and Status Codes

Code Name Purpose
200 OK Response to valid client request.
400 Bad Request Inform client that the format of an HTTP header or binding element is unacceptable (e.g., syntax error).
403 Forbidden Inform client that it has broken the session rules (polling too-frequently, too many simultaneous connections).
404 Not Found Inform client that (1) 'sid' is not valid, (2) 'stream' is not valid, (3) 'rid' is larger than the upper limit of the expected window, (4) connection manager is unable to resend response, (5) 'key' sequence is invalid.

15.2 Terminal Binding Conditions

In any response it sends to the client, the connection manager MAY return a fatal error by setting a 'type' attribute of the <body/> element to "terminate". These binding errors imply that the HTTP session is terminated (unless a 'stream' attribute is specified - see Multiple Stream Error Conditions above). (Note: Many of these conditions correspond to the relevant XMPP stream error conditions specified in RFC 3920, but actual XMPP stream error conditions experienced between the connection manager and the server are contained only in the "remote-stream-error" condition as described below.)

Example 38. Remote connection failed error

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 68

<body type='terminate'
      condition='remote-connection-failed'
      xmlns='http://jabber.org/protocol/httpbind'/>

The following values of the 'condition' attribute are defined:

Table 3: Binding Error Conditions

Condition Purpose
host-gone The target domain specified in the 'to' attribute or the target host or port specified in the 'route' attribute is no longer serviced by the connection manager.
host-unknown The target domain specified in the 'to' attribute or the target host or port specified in the 'route' attribute is unknown to the connection manager.
improper-addressing The initialization element lacks a 'to' or 'route' attribute (or the attribute has no value) but the connection manager requires one.
internal-server-error The connection manager has experienced an internal error that prevents it from servicing the request.
other-request Another request being processed at the same time as this request caused the session to terminate.
remote-connection-failed The connection manager was unable to connect to, or unable to connect securely to, or has lost its connection to, the XMPP server.
remote-stream-error Encapsulates an XMPP stream error. The content of the binding is a copy of the content of the <stream:error/> element received from the XMPP server.
see-other-uri The connection manager does not operate at this URI (e.g., the connection manager accepts only SSL or TLS connections at some https: URI rather than the http: URI requested by the client). The client may try POSTing to the URI in the content of the <uri/> child element.
system-shutdown The connection manager is being shut down. All active HTTP sessions are being terminated. No new sessions can be created.
undefined-condition The error is not one of those defined herein; the connection manager SHOULD include application-specific information in the content of the <body/> wrapper element.

The following is an example of a "see-other-uri" condition:

Example 39. See other URI error

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 68

<body condition='see-other-uri'
      type='terminate'
      xmlns='http://jabber.org/protocol/httpbind'>
  <uri>https://secure.jabber.org/xmppcm</uri>
</body>

The following is an example of a "remote-stream-error" condition:

Example 40. Remote error

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 68

<body condition='remote-stream-error'
      type='terminate'
      xmlns='http://jabber.org/protocol/httpbind'>
  <xml-not-well-formed xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
  <text xmlns='urn:ietf:params:xml:ns:xmpp-streams'
        xml:lang='en'>
    Some special application diagnostic information!
  </text>
  <escape-your-data xmlns='application-ns'/>
</body>

Naturally, the client MAY report binding errors to the connection manager as well, although this is unlikely.

15.3 Recoverable Binding Conditions

In any response it sends to the client, the connection manager MAY return a recoverable error by setting a 'type' attribute of the <body/> element to "error". These errors do not imply that the HTTP session is terminated.

If it decides to recover from the error, then the client MUST repeat the HTTP request and all the preceding HTTP requests that have not received responses. The content of these requests MUST be identical to the <body/> elements of the original requests. This allows the connection manager to recover a session after the previous request was lost due to a communication failure.

Example 41. Recoverable error

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 68

<body type='error'
      xmlns='http://jabber.org/protocol/httpbind'/>

15.4 XMPP Stanza Conditions

Application-level error conditions will normally be generated by a third entity (e.g., an IM contact) and routed to the client through the connection manager; therefore they are out of scope for the transport binding defined herein and are described in the appropriate RFC or XEP.

However, it is possible that a connection manager will receive a stanza for delivery to a client even though the client connection is no longer active (e.g., before the connection manager is able to inform a server that the connection has died). In this case, the connection manager would return an error to the server; it is RECOMMENDED that the connection manager proceed as follows, since the situation is similar to that addressed by point #2 of Section 11.1 of RFC 3921:

  1. If the delivered stanza was <presence/>, silently drop the stanza and do not return an error to the sender.
  2. If the delivered stanza was <iq/>, return a <service-unavailable/> error to the sender.
  3. If the delivered stanza was <message/>, return a <recipient-unavailable/> error to the sender.

When a server receives a <message/> stanza of type "error" containing a <recipient-unavailable/> condition from a connection manager, it SHOULD store the message for later delivery if offline storage is enabled, otherwise route the error stanza to the sender.

16. Implementation Notes

While it is currently envisioned that implementations of the protocol specified herein will mostly be used as connection managers for XMPP servers, management of connections to non-XMPP implementations is also possible. Furthermore, a connection manager that implements the HTTP Binding will simply act as a pass-through mechanism for XML (not necessarily XML that conforms to the schemas for the 'jabber:client' and 'jabber:server' namespaces as specified in RFC 3920 and RFC 3921). Therefore, the XML schemas defined herein are explicitly not limited to XMPP. Any error handling for non-XMPP elements and attributes is the responsibility of the application using such a connection manager, not the connection manager itself.

17. Security Considerations

All communications SHOULD occur over encrypted HTTP connections. Negotiation of encryption between the client and the connection manager SHOULD occur at the transport layer or the HTTP layer, not the application layer; such negotiation SHOULD follow the HTTP/SSL protocol defined in SSL [25], it MAY follow the HTTP/TLS protocol defined in RFC 2818 [26] or the TLS Within HTTP protocol defined in RFC 2817 [27].

If the HTTP connection used to send the initial session request is encrypted, then all the other connections used within the session SHOULD also be encrypted. Furthermore, if authentication certificates are exchanged when establishing the encrypted connection that is used to send the initial session request, then the client and/or connection manager SHOULD ensure that the same authentication certificates are employed for all subsequent connections used by the session. Once such a 'secure session' has been established:

The session identifier (SID) and initial request identifier (RID) are security-critical and therefore MUST be both unpredictable and nonrepeating (see RFC 1750 [28] for recommendations regarding randomness of SIDs and initial RIDs for security purposes).

In cases where the connection manager acts as a 'proxy' independent of the XMPP server, it creates another security vulnerability in addition to those on the XMPP servers. It is RECOMMENDED that clients ensure the security of stanzas sent through the connection manager (and XMPP servers) in both directions by encrypting them end-to-end (e.g., by establishing Encrypted Session Negotiation [29]).

18. IANA Considerations

This document requires no interaction with the Internet Assigned Numbers Authority (IANA) [30].

19. XMPP Registrar Considerations

19.1 Protocol Namespaces

The XMPP Registrar [31] includes 'http://jabber.org/protocol/httpbind' in its registry of protocol namespaces.

20. XML Schema

<?xml version='1.0' encoding='UTF-8'?>

<xs:schema
    xmlns:xs='http://www.w3.org/2001/XMLSchema'
    xmlns:stream='http://etherx.jabber.org/streams'
    targetNamespace='http://jabber.org/protocol/httpbind'
    xmlns='http://jabber.org/protocol/httpbind'
    elementFormDefault='qualified'>

  <xs:annotation>
    <xs:documentation>
      The protocol documented by this schema is defined in
      XEP-0124: http://www.xmpp.org/extensions/xep-0124.html
    </xs:documentation>
  </xs:annotation>

  <xs:import namespace='http://etherx.jabber.org/streams'
             schemaLocation='http://www.xmpp.org/schemas/streams.xsd'/>

  <xs:element name='body'>
    <xs:complexType>
      <xs:choice xmlns:stream='http://etherx.jabber.org/streams'>
        <xs:element ref='stream:features'
                minOccurs='0'
                maxOccurs='1'/>
        <xs:any namespace='urn:ietf:params:xml:ns:xmpp-tls'
                minOccurs='0'
                maxOccurs='1'/>
        <xs:any namespace='urn:ietf:params:xml:ns:xmpp-sasl'
                minOccurs='0'
                maxOccurs='1'/>
        <xs:any namespace='urn:ietf:params:xml:ns:xmpp-streams'
                minOccurs='0'
                maxOccurs='1'/>
        <xs:any namespace='jabber:client'
                minOccurs='0'
                maxOccurs='unbounded'/>
        <xs:element name='uri'
                minOccurs='0'
                maxOccurs='1'
                type='xs:string'/>
        <xs:any namespace='##other'
                minOccurs='0'
                maxOccurs='unbounded'
                processContents='lax'/>
      </xs:choice>
      <xs:attribute name='accept' type='xs:string' use='optional'/>
      <xs:attribute name='authid' type='xs:string' use='optional'/>
      <xs:attribute name='charsets' type='xs:NMTOKENS' use='optional'/>
      <xs:attribute name='condition' use='optional'>
        <xs:simpleType>
          <xs:restriction base='xs:NCName'>
            <xs:enumeration value='host-gone'/>
            <xs:enumeration value='host-unknown'/>
            <xs:enumeration value='improper-addressing'/>
            <xs:enumeration value='internal-server-error'/>
            <xs:enumeration value='remote-connection-failed'/>
            <xs:enumeration value='remote-stream-error'/>
            <xs:enumeration value='see-other-uri'/>
            <xs:enumeration value='system-shutdown'/>
            <xs:enumeration value='undefined-condition'/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
      <xs:attribute name='content' type='xs:string' use='optional'/>
      <xs:attribute name='hold' type='xs:byte' use='optional'/>
      <xs:attribute name='inactivity' type='xs:short' use='optional'/>
      <xs:attribute name='key' type='xs:string' use='optional'/>
      <xs:attribute name='newkey' type='xs:string' use='optional'/>
      <xs:attribute name='polling' type='xs:short' use='optional'/>
      <xs:attribute name='requests' type='xs:byte' use='optional'/>
      <xs:attribute name='rid' type='xs:positiveInteger' use='optional'/>
      <xs:attribute name='route' type='xs:string' use='optional'/>
      <xs:attribute name='secure' type='xs:boolean' use='optional' default='false'/>
      <xs:attribute name='sid' type='xs:string' use='optional'/>
      <xs:attribute name='stream' type='xs:string' use='optional'/>
      <xs:attribute name='to' type='xs:string' use='optional'/>
      <xs:attribute name='type' type='xs:string' use='optional'>
        <xs:simpleType>
          <xs:restriction base='xs:NCName'>
            <xs:enumeration value='error'/>
            <xs:enumeration value='terminate'/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
      <xs:attribute name='wait' type='xs:short' use='optional'/>
      <xs:attribute name='xml:lang' type='xs:string' use='optional'/>
      <xs:anyAttribute namespace='##other' processContents='lax'/>
    </xs:complexType>
  </xs:element>

</xs:schema>
    


Notes

1. RFC 3920: Extensible Messaging and Presence Protocol (XMPP): Core <http://www.ietf.org/rfc/rfc3920.txt>.

2. RFC 793: Transmission Control Protocol <http://www.ietf.org/rfc/rfc0793.txt>.

3. RFC 2068: Hypertext Transport Protocol -- HTTP/1.1 <http://www.ietf.org/rfc/rfc2068.txt>.

4. RFC 1945: Hypertext Transfer Protocol -- HTTP/1.0 <http://www.ietf.org/rfc/rfc1945.txt>.

5. RFC 2965: HTTP State Management Mechanism <http://www.ietf.org/rfc/rfc2965.txt>.

6. XEP-0025: Jabber HTTP Polling <http://www.xmpp.org/extensions/xep-0025.html>.

7. RFC 3921: Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence <http://www.ietf.org/rfc/rfc3921.txt>.

8. XEP-0114: Jabber Component Protocol <http://www.xmpp.org/extensions/xep-0114.html>.

9. XEP-0138: Stream Compression <http://www.xmpp.org/extensions/xep-0138.html>.

10. Extensible Markup Language (XML) 1.0 (Fourth Edition) <http://www.w3.org/TR/REC-xml/>.

11. Although the syntax of the 'route' attribute bears a superficial resemblance to a URI or IRI, it is not a URI/IRI and MUST NOT be processed in accordance with the rules specified in RFC 3986, RFC 3987, or draft-saintandre-xmpp-iri.

12. XML Schema Part 2: Datatypes <http://www.w3.org/TR/xmlschema-2/>.

13. In accordance with Section 3.2.2.1 of XML Schema Part 2: Datatypes, the allowable lexical representations for the xs:boolean datatype are the strings "0" and "false" for the concept 'false' and the strings "1" and "true" for the concept 'true'; implementations MUST support both styles of lexical representation.

14. Each character set name (or character encoding name -- we use the terms interchangeably) SHOULD be of type NMTOKEN, where the names are separated by the white space character #x20, resulting in a tokenized attribute type of NMTOKENS (see Section 3.3.1 of XML 1.0 [15]). Strictly speaking, the Character Sets registry maintained by the Internet Assigned Numbers Authority (see <http://www.iana.org/assignments/character-sets>) allows a character set name to contain any printable US-ASCII character, which might include characters not allowed by the NMTOKEN construction of XML 1.0; however, the only existing character set name which includes such a character is "NF_Z_62-010_(1973)".

15. Extensible Markup Language (XML) 1.0 (Fourth Edition) <http://www.w3.org/TR/REC-xml/>.

16. XEP-0078: Non-SASL Authentication <http://www.xmpp.org/extensions/xep-0078.html>.

17. 9007199254740991 is 253-1. Some weakly typed languages use IEEE Standard 754 Doubles to represent all numbers. These Doubles cannot represent integers above 253 accurately.

18. RFC 3174: US Secure Hash Algorithm 1 (SHA1) <http://www.ietf.org/rfc/rfc3174.txt>.

19. Therefore a client and a connection manager will be compatible even if one or the other offers no support for multi-stream sessions.

20. The 'rid' attribute is always incremented normally without reference to any 'stream' attribute.

21. This helps to ensure backwards-compatibility with older implementations.

22. Each HTTP response MUST belong to the same session as the request that triggered it, but not necessarily to the same stream.

23. The broadcast stanzas may be of any type.

24. XEP-0086: Error Condition Mappings <http://www.xmpp.org/extensions/xep-0086.html>.

25. SSL V3.0 <http://wp.netscape.com/eng/ssl3/draft302.txt>.

26. RFC 2818: HTTP Over TLS <http://www.ietf.org/rfc/rfc2818.txt>.

27. RFC 2817: Upgrading to TLS Within HTTP/1.1 <http://www.ietf.org/rfc/rfc2817.txt>.

28. RFC 1750: Randomness Recommendations for Security <http://www.ietf.org/rfc/rfc1750.txt>.

29. XEP-0116: Encrypted Session Negotiation <http://www.xmpp.org/extensions/xep-0116.html>.

30. The Internet Assigned Numbers Authority (IANA) is the central coordinator for the assignment of unique parameter values for Internet protocols, such as port numbers and URI schemes. For further information, see <http://www.iana.org/>.

31. The XMPP Registrar maintains a list of reserved protocol namespaces as well as registries of parameters used in the context of XMPP extension protocols approved by the XMPP Standards Foundation. For further information, see <http://www.xmpp.org/registrar/>.


Revision History

Version 1.5 (2006-04-28)

Added optional Multiple Streams section; added security considerations about encrypted HTTP connections; recommended use of SSL rather than HTTP over TLS; specified that request ID values must not exceed 9007199254740991; corrected datatypes of inactivity, polling, rid, and wait attributes in the schema; added <any/> and <anyAttribute/> elements to schema to optionally support non-XMPP XML elements and attributes. (ip/psa)

Version 1.4 (2005-12-14)

Modified syntax of route attribute to be proto:host:port rather than XMPP URI/IRI. (psa)

Version 1.3 (2005-11-02)

Corrected stream:features namespace and the Recoverable Binding Conditions section; recommended that connection manager shall return secure attribute to client; recommended end-to-end encryption through proxy connection managers. (ip)

Version 1.2 (2005-06-16)

Specified optional use of route and secure attributes in session request. Minor correction: the stream features element should be included in the response that contains the authid attribute (this is not necessarily the session creation response). (ip)

Version 1.1 (2005-06-02)

Specified optional use of HTTP Accept-Encoding and Content-Encoding headers for compression at HTTP binding level. (ip)

Version 1.0 (2005-03-03)

Per a vote of the Jabber Council, advanced status to Draft. (psa)

Version 0.10 (2004-11-08)

Changed HTTP 401 errors to HTTP 404. (ip)

Version 0.9 (2004-10-26)

Added charset attribute. (ip/psa)

Version 0.8 (2004-10-26)

Specified that wait attribute must be included in the session creation response. (ip)

Version 0.7 (2004-08-12)

Defined appropriate XMPP stanza error conditions. (psa/ip)

Version 0.6 (2004-07-19)

Added xml:lang attribute to the session request; added recoverable binding error conditions. (ip)

Version 0.5 (2004-05-07)

Protocol refactored to enable simultaneous requests (request identifier attribute, wait attribute, hold attribute, requests attribute) and recovery of broken connections; added content attribute; removed all wrapper types except 'terminate'; updated error handling; made key mechanism optional (should use SSL/TLS instead). (ip/psa)

Version 0.4 (2004-02-23)

Fixed typos; removed "resource-constraint" binding error; added HTTP 403 error to table. (psa/ip)

Version 0.3 (2004-02-19)

Added 'authid' attribute to enable communication of XMPP stream ID (used in digest authentication); specified that Content-Types other than "text/xml" are allowed to support older HTTP clients; specified business rule for connection manager queueing of client requests; changed <packet/> to <body/> to support older HTTP clients; changed 'to' attribute on initialization element from MAY to SHOULD; recommended inclusion of unavailable presence in termination element sent from client; described architectural assumptions; specified binding-specific error handling. (psa/ip)

Version 0.2 (2004-01-13)

Added 'to' attribute on the initialization element; specified that 'text/html' is allowable for backwards-compatibility. (dss/psa/ip)

Version 0.1 (2003-11-06)

Initial version. (dss/psa)


END