<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
  <!ENTITY % ents SYSTEM 'xep.ent'>
%ents;
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep>
<header>
  <title>Verifying HTTP Requests via XMPP</title>
  <abstract>This specification defines an XMPP protocol extension that enables verification of an HTTP request via XMPP.</abstract>
  &LEGALNOTICE;
  <number>0070</number>
  <status>Draft</status>
  <type>Standards Track</type>
  <sig>Standards</sig>
  <dependencies>
    <spec>XMPP Core</spec>
    <spec>RFC 2616</spec>
    <spec>RFC 2617</spec>
    <spec>XEP-0030</spec>
  </dependencies>
  <supersedes/>
  <supersededby/>
  <shortname>http-auth</shortname>
  <schemaloc>
    <url>http://www.xmpp.org/schemas/http-auth.xsd</url>
  </schemaloc>
  &linuxwolf;
  &hildjj;
  &dizzyd;
  &stpeter;
  <revision>
    <version>1.0</version>
    <date>2005-12-14</date>
    <initials>psa</initials>
    <remark>Per a vote of the Jabber Council, advanced status to Draft.</remark>
  </revision>
  <revision>
    <version>0.10</version>
    <date>2005-12-01</date>
    <initials>psa</initials>
    <remark>Corrected several errors in the text.</remark>
  </revision>
  <revision>
    <version>0.9</version>
    <date>2005-11-09</date>
    <initials>psa</initials>
    <remark>Changed use of transaction identifier from SHOULD to MUST; removed x-xmpp-auth scheme; clarified requirements, business rules, and confirm element syntax; added several more examples; more clearly specified how HTTP server communicates with XMPP server; updated schema and security considerations.</remark>
  </revision>
  <revision>
    <version>0.8</version>
    <date>2005-10-19</date>
    <initials>psa</initials>
    <remark>Changed use of transaction identifier from MAY to SHOULD; updated and clarified security considerations.</remark>
  </revision>
  <revision>
    <version>0.7</version>
    <date>2005-10-11</date>
    <initials>psa</initials>
    <remark>Added more HTTP examples to illustrate process flow; updated IANA considerations and security considerations.</remark>
  </revision>
  <revision>
    <version>0.6</version>
    <date>2005-07-21</date>
    <initials>psa</initials>
    <remark>Updated references; clarified several points in the text; rewrote introduction.</remark>
  </revision>
  <revision>
    <version>0.5</version>
    <date>2004-04-27</date>
    <initials>psa</initials>
    <remark>Added optional id attribute in order to track requests, described in new implementation note.</remark>
  </revision>
  <revision>
    <version>0.4</version>
    <date>2004-01-14</date>
    <initials>psa/dss/jh</initials>
    <remark>Incorporated results of IRL and IM discussions: simplified the flow; added x-xmpp-auth authentication scheme.</remark>
  </revision>
  <revision>
    <version>0.3</version>
    <date>2003-06-27</date>
    <initials>lw</initials>
    <remark>Removed hashing requirements; added/clarified JID fields in HTTP headers; added XML Schema; added XMPP error conditions; added more descriptions for confirm and accept tokens; fixed discrepancies in examples.</remark>
  </revision>
  <revision>
    <version>0.2</version>
    <date>2003-06-26</date>
    <initials>lw</initials>
    <remark>Updated to reflect feedback received (moved to using standard HTTP authentication headers; included token-authority JID in HTTP header; removed example involving deprecated protocol).</remark>
  </revision>
  <revision>
    <version>0.1</version>
    <date>2003-01-31</date>
    <initials>lw</initials>
    <remark>Initial draft.</remark>
  </revision>
</header>
<section1 topic='Introduction' anchor='intro'>
  <p>HTTP (see &rfc2616;) is a nearly-ubiquitous mechanism for the publication and retrieval of information over the Internet. Sometimes it is appropriate for an HTTP Server to allow access to that information only if the HTTP Client first provides authentication credentials. While there exist several standardized HTTP authentication schemes (see &rfc2617;), it may be useful in some applications to enforce verification of an HTTP request by requiring an XMPP entity (normally an IM user) to confirm that it made the request. This request verification can be combined with native HTTP authentication to provide a stronger association between the request and a particular user, as well as to take advantage of the strong user authentication provided in XMPP (see &rfc3920;).</p>
</section1>
<section1 topic='Terminology' anchor='terms'>
  <section2 topic='HTTP Terms' anchor='terms-http'>
    <p>This document inherits terminology about the HyperText Transfer Protocol from <cite>RFC 2616</cite> and <cite>RFC 2617</cite>.</p>
  </section2>
  <section2 topic='Entities' anchor='terms-entities'>
    <table caption='Terms for Entities Described Herein'>
      <tr>
        <th>Term</th>
        <th>Definition</th>
      </tr>
      <tr>
        <td>HTTP Client</td>
        <td>A client that implements the HyperText Transfer Protocol (HTTP)</td>
      </tr>
      <tr>
        <td>HTTP Server</td>
        <td>A server that implements the HyperText Transfer Protocol (HTTP)</td>
      </tr>
      <tr>
        <td>XMPP Client</td>
        <td>A client that implements the Extensible Messaging and Presence Protocol (XMPP) or its antecedents</td>
      </tr>
      <tr>
        <td>XMPP Server</td>
        <td>A server that implements the Extensible Messaging and Presence Protocol (XMPP) or its antecedents</td>
      </tr>
    </table>
    <p>Note well that an XMPP Client can simultaneously be an HTTP Client (or vice-versa), and that an XMPP Server can simultaneously be an HTTP Server (or vice-versa). However, for the purposes of this discussion, we assume that these entities are logically if not physically separate and distinct.</p>
  </section2>
</section1>
<section1 topic='Requirements' anchor='reqs'>
  <p>The motivations for this document are to:</p>
  <ul>
    <li>Use an existing XMPP connection to associate an HTTP request with an XMPP entity.</li>
    <li>Require confirmation of the request by the XMPP entity before allowing access.</li>
    <li>Ensure that the HTTP request was generated by the principal controlling the XMPP entity.</li>
  </ul>
</section1>
<section1 topic='Use Case' anchor='usecase'>
  <p>The process flow for this protocol is as follows:</p>
  <ol>
    <li>HTTP Client requests object via HTTP.</li>
    <li>HTTP Server sends Authenticate Response via HTTP.</li>
    <li>HTTP Client sends Authorization Request via HTTP (E1).</li>
    <li>HTTP Server processes request and forwards it to XMPP Server.</li>
    <li>XMPP Server requests confirmation via XMPP (E2).</li>
    <li>XMPP Client confirms request via XMPP.</li>
    <li>XMPP Server delivers confirmation to HTTP Server.</li>
    <li>HTTP Server allows HTTP Client to access object (E3).</li>
  </ol>
  <p>Error cases:</p>
  <ul>
    <li><b>E1:</b> HTTP Client does not understand the presented authentication scheme.</li>
    <li><b>E2:</b> HTTP Server does not recognize or understand the request.</li>
    <li><b>E3:</b> HTTP Server denies access.</li>
  </ul>
  <p>This process flow is described in more detail in the following sections.</p>
  <section2 topic='HTTP Client Sends Request via HTTP' anchor='http-request'>
    <p>Let us stipulate that an XMPP user (say, &lt;juliet@capulet.com&gt;) learns of an HTTP URL (e.g., &lt;https://files.shakespeare.lit:9345/missive.html&gt;). The user then attempts to retrieve the URL using her HTTP Client, which opens a TCP connection to the appropriate port of the host and sends an HTTP request as defined in <cite>RFC 2616</cite>. The request method MAY be any valid HTTP request method, including user-defined methods.</p>
    <p>An example is provided below:</p>
    <example caption='HTTP Client Makes Request (No Credentials)'><![CDATA[
GET https://files.shakespeare.lit:9345/missive.html HTTP/1.1
    ]]></example>
    <p>In order to avoid a round trip, the initial request MAY contain HTTP authorization credentials as described below.</p>
  </section2>
  <section2 topic='HTTP Server Returns Authenticate Response via HTTP' anchor='http-response'>
    <p>If the user did not provide authorization credentials in the initial request, the HTTP Server then MUST respond with a (401) Authenticate response as defined in <cite>RFC 2616</cite>. The response MUST contain an HTTP 401 error and one WWW-Authenticate header for each authentication scheme recognized by the HTTP Server. In order to provide verification via XMPP, at least one of these headers MUST specify a realm of "xmpp" (case-sensitive).</p>
    <example caption='HTTP Server Returns Authenticate Response'><![CDATA[
401 Unauthorized HTTP/1.1
WWW-Authenticate: Basic realm="xmpp"
WWW-Authenticate: Digest realm="xmpp", 
                  domain="files.shakespeare.lit", 
                  stale=false, 
                  nonce="ec2cc00f21f71acd35ab9be057970609", 
                  qop="auth", 
                  algorithm="MD5"
    ]]></example>
  </section2>
  <section2 topic='HTTP Client Sends Authorization Request via HTTP' anchor='http-authz'>
    <p>The HTTP Client responds with an Authorization Request as defined in <cite>RFC 2616</cite>. The following rules apply:</p>
    <ol>
      <li>The request MUST include the Jabber Identifier (JID) of the user making the request. This SHOULD be the full JID (&lt;user@host/resource&gt;) of a client that supports the protocol defined herein, although it MAY be the user's bare JID (&lt;user@host&gt;) instead.</li>
      <li>The request MUST include a transaction identifier for the request. This identifier MUST be unique within the context of the HTTP Client's interaction with the HTTP Server. If the HTTP request is generated by the XMPP Client (e.g., because the HTTP URL was discovered via &xep0066;) then the transaction identifier SHOULD be generated by the client; if not, the transaction identifier SHOULD be provided by the human user who controls the HTTP Client.</li>
    </ol>
    <p>The Authorization Request process is described in the following subsections.</p>
    <section3 topic='Basic Access Authentication Scheme' anchor='http-authz-basic'>
      <p>The Basic Access Authentication scheme is defined in <cite>RFC 2617</cite>. This scheme specifies that the authorization information shall consist of a userid and password, separated by a ':' character and then encoded using Base64. When the realm is "xmpp", the profile defined herein further specifies that the userid MUST be a valid JID as described above, that the password entity MUST be a transaction identifier as described above, that any character in the JID or transaction identifier that is outside the range of the US-ASCII coded character set MUST be transformed into a percent-encoded octet as specified in Section 2.1 of &rfc3986; prior to Base64 encoding, and that Base64 encoding MUST adhere to Section 4 of &rfc4648;.</p>
      <p>(Refer to <cite>RFC 2617</cite> for specification of the syntax of the Basic Access Authentication scheme; that information is not duplicated here.)</p>
      <example caption='HTTP Client Makes Basic Authorization Request'><![CDATA[
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
      ]]></example>
    </section3>
    <section3 topic='Digest Access Authentication Scheme' anchor='http-authz-digest'>
      <p>The Digest Access Authentication scheme is defined in <cite>RFC 2617</cite>. This scheme specifies that the authorization information shall consist of the MD5 checksum of the username, a cnonce generated by the client, a nonce value provided in the challenge, the HTTP method, and the requested URL. When the realm is "xmpp", the profile defined herein further specifies that prior to creating the MD5 checksum the username MUST be a valid JID as described above, that the cnonce MUST be a transaction identifier as described above, and that any character in the JID or transaction identifier that is outside the range of the US-ASCII coded character set MUST be transformed into a percent-encoded octet as specified in Section 2.1 of <cite>RFC 3986</cite>.</p>
      <p>(Refer to <cite>RFC 2617</cite> for specification of the syntax of the Digest Access Authentication scheme; that information is not duplicated here.)</p>
      <example caption='HTTP Client Makes Digest Authorization Request'><![CDATA[
Authorization: Digest username="juliet@capulet.com",
               realm="xmpp",
               nonce="ec2cc00f21f71acd35ab9be057970609", 
               uri="missive.html",
               qop=auth,
               nc=00000001,
               cnonce="0a4f113b",
               response="6629fae49393a05397450978507c4ef1",
               opaque="5ccc069c403ebaf9f0171e9517f40e41" 
      ]]></example>
    </section3>
    <section3 topic='Additional Authentication Schemes' anchor='http-authz-add'>
      <p>The HTTP Server MAY offer any other valid authentication scheme, instead of or in addition to the Basic and Digest schemes mentioned above, as long as the scheme makes it possible to specify a userid (JID) and transaction identifier as described above. However, it is RECOMMENDED to implement both the Basic and Digest authentication schemes.</p>
    </section3>
  </section2>
  <section2 topic='HTTP Server Processes Request' anchor='http-process'>
    <p>Once the HTTP Client has communicated the JID and transaction identifier to the HTTP Server, the HTTP Server MUST verify that the JID is authorized to access the HTTP resource. This may involve JID-level or domain-level access checks, or (depending on local service policies) potentially no access checks at all if only verification is required.</p>
    <p>If the JID is authorized to access the HTTP resource, the HTTP Server MUST pass the URL, method, JID, and transaction identifier to the XMPP Server for confirmation. Exactly how this is done is up to the implementation. It is RECOMMENDED for the HTTP Server to connect to the XMPP Server as a trusted server component and to itself generate the confirmation request as described below.</p>
  </section2>
  <section2 topic='XMPP Server Requests Confirmation via XMPP' anchor='xmpp-request'>
    <p>Upon receiving the JID and transaction identifier from the HTTP Server, the XMPP Server MUST send a confirmation request (via XMPP) to the XMPP Client (or route the confirmation request generated by the HTTP Server acting as a trusted XMPP server component).</p>
    <p>The confirmation request shall consist of an empty &lt;confirm/&gt; element qualified by the ''http://jabber.org/protocol/http-auth' namespace. This element MUST possess a 'method' attribute whose value is the method of the HTTP request, MUST possess a 'url' attribute whose value is the full HTTP URL that was requested, and MUST possess an 'id' attribute whose value is the transaction identifier provided in the HTTP Authorization Request.</p>
    <p>If the JID provided was a full JID, the confirmation request SHOULD be sent in an &IQ; stanza of type "get" whose 'to' attribute is set to the full JID, but MAY be sent in a &MESSAGE; stanza.</p>
    <p>If the JID provided was a bare JID, the confirmation request MUST be sent in a &MESSAGE; stanza whose 'to' attribute is set to the bare JID; this enables delivery to the "most available" resource for the user (however "most available" is determined by the XMPP Server). The &MESSAGE; stanza SHOULD include a &THREAD; element for tracking purposes and MAY include a &BODY; element that provides human-readable information or instructions.</p>
    <example caption='Confirmation Request Sent via IQ'><![CDATA[
<iq type='get' 
    from='files.shakespeare.lit' 
    to='juliet@capulet.com/balcony' 
    id='ha000'>
  <confirm xmlns='http://jabber.org/protocol/http-auth'
           id='a7374jnjlalasdf82'
           method='GET'
           url='https://files.shakespeare.lit:9345/missive.html'/>
</iq>
    ]]></example>
    <example caption='Confirmation Request Sent via Message'><![CDATA[
<message type='normal'
         from='files.shakespeare.lit' 
         to='juliet@capulet.com'>
  <thread>e0ffe42b28561960c6b12b944a092794b9683a38</thread>
  <body>
    Someone (maybe you) has requested the following file:

       https://files.shakespeare.lit:9345/missive.html.

    The transaction identifier is:

       a7374jnjlalasdf82

    If you wish to confirm the request, please reply
    to this message by typing "OK". If not, please 
    reply with "No".
  </body>
  <confirm xmlns='http://jabber.org/protocol/http-auth'
           id='a7374jnjlalasdf82'
           method='GET'
           url='https://files.shakespeare.lit:9345/missive.html'/>
</message>
    ]]></example>
  </section2>
  <section2 topic='XMPP Client Confirms Request via XMPP' anchor='xmpp-confirm'>
    <p>If the confirmation request was provided via an &IQ; stanza, the XMPP Client MUST respond to the request by sending an &IQ; stanza back to the XMPP Server. If the user wishes to confirm the request, the &IQ; response stanza MUST be of type "result" and MAY contain the original &lt;confirm/&gt; child element (although this is not necessary since the XMPP 'id' attribute can be used for tracking purposes):</p>
    <example caption='XMPP Client Confirms Request via IQ'><![CDATA[
<iq type='result' 
    from='juliet@capulet.com/balcony' 
    to='files.shakespeare.lit' 
    id='ha000'/>
    ]]></example>
    <p>If the user wishes to deny the request, the &IQ; response stanza MUST be of type "error", MAY contain the original &lt;confirm/&gt; child element (although this is not necessary since the XMPP 'id' attribute can be used for tracking purposes), and MUST specify an error, which SHOULD be &notauthorized;:</p>
    <example caption='XMPP Client Denies Request via IQ'><![CDATA[
<iq type='error' 
    from='juliet@capulet.com/balcony' 
    to='files.shakespeare.lit' 
    id='ha000'>
  <confirm xmlns='http://jabber.org/protocol/http-auth'
           id='a7374jnjlalasdf82'
           method='GET'
           url='https://files.shakespeare.lit:9345/missive.html'/>
  <error code='401' type='auth'>
    <not-authorized xmlns='urn:ietf:params:xml:xmpp-stanzas'/>
  </error>
</iq>
    ]]></example>
    <p>If the confirmation request was provided via a &MESSAGE; stanza and the &MESSAGE; contains a human-readable &BODY; or does not contain a &BODY; but the XMPP Client understands the 'http://jabber.org/protocol/http-auth' namespace, the XMPP Client SHOULD respond to the request by sending a &MESSAGE; stanza back to the XMPP Server. If the user wishes to confirm the request, the &MESSAGE; response stanza SHOULD be of type "normal", MUST mirror the &lt;thread/&gt; ID (if provided by the XMPP Server), and MUST contain the original &lt;confirm/&gt; child element:</p>
    <example caption='XMPP Client Confirms Request via Message'><![CDATA[
<message from='juliet@capulet.com/balcony'
         to='files.shakespeare.lit'>
  <thread>e0ffe42b28561960c6b12b944a092794b9683a38</thread>
  <confirm xmlns='http://jabber.org/protocol/http-auth'
           id='a7374jnjlalasdf82'
           method='GET'
           url='https://files.shakespeare.lit:9345/missive.html'/>
</message>
    ]]></example>
    <p>If the user wishes to deny the request, the &MESSAGE; response stanza MUST be of type "error", MUST mirror the &lt;thread/&gt; ID (if provided by the XMPP Server), MUST contain the original &lt;confirm/&gt; child element, and MUST specify an error, which SHOULD be &notauthorized;:</p>
    <example caption='XMPP Client Denies Request via Message'><![CDATA[
<message type='error' 
         from='juliet@capulet.com/balcony'
         to='files.shakespeare.lit'>
  <thread>e0ffe42b28561960c6b12b944a092794b9683a38</thread>
  <confirm xmlns='http://jabber.org/protocol/http-auth'
           id='a7374jnjlalasdf82'
           method='GET'
           url='https://files.shakespeare.lit:9345/missive.html'/>
  <error code='401' type='auth'>
    <not-authorized xmlns='urn:ietf:params:xml:xmpp-stanzas'/>
  </error>
</message>
    ]]></example>
  </section2>
  <section2 topic='HTTP Server Allows HTTP Client to Access Object' anchor='http-access'>
    <p>Once the XMPP Client has successfully confirmed the request, the XMPP Server forwards that confirmation to the HTTP Server, which allows access:</p>
    <example caption='HTTP Server Allows Access to Object'><![CDATA[
200 OK HTTP/1.1
Content-Type: text/html
Content-Length: 3032

...
    ]]></example>
    <p>If the XMPP Client denied the request, the HTTP Server MUST return a Forbidden error:</p>
    <example caption='HTTP Server Denies Access to Object'><![CDATA[
403 Forbidden HTTP/1.1
    ]]></example>
  </section2>
</section1>
<section1 topic='Implementation Notes' anchor='impl'>
  <section2 topic='Interaction of HTTP methods' anchor='impl-methods'>
    <p>For the HEAD and OPTIONS methods, the credentials SHOULD be usable for a subsequent request from the same entity. This enables an entity to both determine support for the mechanism defined herein and start the authentication process.</p>
    <p>For the POST and PUT methods (or any method containing a message body), clients MUST send all data with each request (if needed, the client should obtain credentials with a previous HEAD or OPTIONS method).</p>
  </section2>
</section1>
<section1 topic='Security Considerations' anchor='security'>
  <section2 topic='Association of Request' anchor='security-association'>
    <p>In order to associate the HTTP request with the XMPP confirmation, a transaction identifier MUST be provided by the user in the HTTP Authorization Request, then passed unchanged to the XMPP Client as the value of the &lt;confirm/&gt; element's 'id' attribute. If the XMPP Client generated the HTTP request, it MUST check the transaction identifier against the requests it has made to verify that the request has not yet been confirmed. If the XMPP Client did not generate the HTTP request, it MUST present the transaction identifier to the user for confirmation. If the XMPP Client or User confirms the request, the XMPP Client MUST then return a confirmation to the XMPP Server for delivery to the HTTP Server.</p>
  </section2>
  <section2 topic='Channel Encryption' anchor='security-channel'>
    <p>To reduce the likelihood of man-in-the-middle attacks, channel encryption SHOULD be used for both the XMPP channel and the HTTP channel. In particular:</p>
    <ol>
      <li>The channel used for HTTP requests and responses SHOULD be encrypted via SSL (secure HTTP via https: URLs) or TLS (&rfc2817;).</li>
      <li>If the standard binding of XMPP to TCP is used, TLS SHOULD be negotiated for the XMPP channel in accordance with <cite>RFC 3920</cite>.</li>
      <li>If a binding of XMPP to HTTP is used (e.g., as specified in <cite>XEP-0124</cite>), exchanges between the XMPP Client and XMPP Server (connection manager) SHOULD be sent over a channel that is encrypted using SSL or TLS.</li>
    </ol> 
  </section2>
  <section2 topic='End-to-End Encryption' anchor='security-e2e'>
    <p>For added security, the XMPP Server and XMPP Client may wish to communicate using end-to-end encryption. Methods for doing so are outside the scope of this proposal.</p>
  </section2>
</section1>
<section1 topic='IANA Considerations' anchor='iana'>
  <p>This document requires no interaction with &IANA;.</p>
</section1>
<section1 topic='XMPP Registrar Considerations' anchor='registrar'>
  <section2 topic='Protocol Namespaces' anchor='registrar-ns'>
    <p>The &REGISTRAR; includes "http://jabber.org/protocol/http-auth" in its registry of protocol namespaces.</p>
  </section2>
</section1>
<section1 topic='XML Schema' anchor='schema'>
  <code><![CDATA[
<?xml version='1.0' encoding='UTF-8'?>

<xs:schema
    xmlns:xs='http://www.w3.org/2001/XMLSchema'
    targetNamespace='http://jabber.org/protocol/http-auth'
    xmlns='http://jabber.org/protocol/http-auth'
    elementFormDefault='qualified'>
  
  <xs:annotation>
    <xs:documentation>
      The protocol documented by this schema is defined in
      XEP-0070: http://www.xmpp.org/extensions/xep-0070.html
    </xs:documentation>
  </xs:annotation>

  <xs:element name='confirm'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='id' use='required' type='xs:string'/>
          <xs:attribute name='method' use='required' type='xs:NCName'/>
          <xs:attribute name='url' use='required' type='xs:anyURI'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
  
  <xs:simpleType name='empty'>
    <xs:restriction base='xs:string'>
      <xs:enumeration value=''/>
    </xs:restriction>
  </xs:simpleType>

</xs:schema>
  ]]></code>
</section1>
</xep>
