One document matched: draft-ietf-httpstate-cookie-00.xml


<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt"?>
<?rfc toc="yes"?>
<?rfc symrefs="yes"?>
<!--<!DOCTYPE rfc SYSTEM "rfc2629.dtd">-->
<rfc ipr="pre5378Trust200902" docName="draft-ietf-httpstate-cookie-00">
  <front>
    <title abbrev="HTTP State Management Mechanism">
      HTTP State Management Mechanism
    </title>
    <author initials="A." surname="Barth" fullname="Adam Barth">
      <organization abbrev="U.C. Berkeley">
        University of California, Berkeley
      </organization>
      <address>
        <email>abarth@eecs.berkeley.edu</email>
        <uri>http://www.adambarth.com/</uri>
      </address>
    </author>
    <date month="December" year="2009"/>
    <workgroup>http-state</workgroup>
    <keyword>Internet-Draft</keyword>
    <abstract>
      <t>This document defines the HTTP Cookie and Set-Cookie headers.
      <list>
        <t>NOTE: If you have suggestions for improving the draft, please send
        email to http-state@ietf.org.  Suggestions with test cases are
        especially appreciated.</t>
      </list>
      </t>
    </abstract>
  </front>
  <middle>
    <section anchor="intro" title="Introduction">
      <t>This document defines the HTTP Cookie and Set-Cookie header.</t>
      
      <section anchor="syntax-notation" title="Syntax Notation">
        <t>This specification uses the Augmented Backus-Naur Form (ABNF)
        notation of <xref target="RFC5234"/>.</t>

        <t>The following core rules are included by reference, as defined in
        <xref target="RFC5234"/>, Appendix B.1: ALPHA (letters), CR (carriage
        return), CRLF (CR LF), CTL (controls), DIGIT (decimal 0-9), DQUOTE
        (double quote), HEXDIG (hexadecimal 0-9/A-F/a-f), LF (line feed), OCTET
        (any 8-bit sequence of data), SP (space), VCHAR (any visible [USASCII]
        character), and WSP (whitespace).</t>
      </section>
    </section>
    <section title="Terminology">
      <t>The terms user agent, client, server, proxy, and origin server have
      the same meaning as in the HTTP/1.0 specification.</t>

      <t>Fully-qualified host name (FQHN) means either the fully-qualified
      domain name (FQDN) of a host (i.e., a completely specified domain name
      ending in a top-level domain such as .com or .uk), or the numeric
      Internet Protocol (IP) address of a host.  The fully qualified domain
      name is preferred; use of numeric IP addresses is strongly
      discouraged.  [TODO: What does "strongly discouraged" mean?]</t>

      <t>The terms request-host and request-URI refer to the values the
      client would send to the server as, respectively, the host (but not
      port) and abs_path portions of the absoluteURI (http_URL) of the HTTP
      request line.  Note that request-host must be a FQHN.  Hosts names can
      be specified either as an IP address or a FQHN string.</t>

      <t>Because it was used in Netscape's original implementation of state
      management, we will use the term cookie to refer to the state
      information that passes between an origin server and user agent, and
      that gets stored by the user agent.</t>
    </section>
    <section title="Overview">
      <t>We outline here a way for an origin server to send state
      information to the user agent, and for the user agent to return the
      state information to the origin server.</t>

      <t>The origin server initiates a session, if it so desires, by
      including a Set-Cookie header in an HTTP response.  (Note that
      "session" here does not refer to a persistent network connection but
      to a logical session created from HTTP requests and responses.  The
      presence or absence of a persistent connection should have no effect
      on the use of cookie-derived
      sessions).</t>

      <t>A user agent returns a Cookie request header (see below) to the
      origin server if it chooses to continue a session.  The origin server
      may ignore it or use it to determine the current state of the
      session.  It may send the client a Set-Cookie response header
      with the same or different information, or it may send no Set-Cookie
      header at all.</t>

      <t>Servers may return a Set-Cookie response headers with any
      response.  User agents should send Cookie request headers, subject to
      other rules detailed below, with every request.</t>

      <t>An origin server may include multiple Set-Cookie headers in a
      response.  Note that an intervening gateway MUST NOT fold multiple
      Set-Cookie headers into a single header.</t>

      <t>[TODO: Overview the Set-Cookie and Cookie headers.]</t>

      <section title="Examples">
        <t>[TODO: Put some examples here.</t>
      </section>
    </section>
    <section title="Protocol Description">
      <t>The cookie protocol consists of two HTTP headers: the Set-Cookie
      header and the Cookie header.  The server sends the Set-Cookie header
      is to the user agent in an HTTP response, causing the user agent to
      modify the Cookie header it returns to the server.</t>

      <t>This section describes the syntax and semantics of the protocol.
      Detailed conformance requirements for user agents are given in Section
      [TODO].</t>
 
      <section title="Set-Cookie">
        <section title="Syntax">
          <t>Informally, the Set-Cookie response header comprises the token
          Set-Cookie:, followed by a cookie.  Each cookie begins with a
          name-value-pair, followed by zero or more semi-colon-separated
          attribute-value pairs.</t>

          <t>[TODO: Consider replacing this grammar with the one from
          2009-11-07-Yui-Naruse.txt.]</t>

          <figure>
            <artwork type="abnf">
              <![CDATA[
  set-cookie-header = "Set-Cookie:" name-value-pairs
  name-value-pairs  = name-value-pair *(";" name-value-pair)
  name-value-pair   = name ["=" value]        ; optional value
  name              = token
  value             = *CHAR
  token             = <token, as defined in Section 2.2 of RFC 2616>
              ]]>
            </artwork>
          </figure>

          <t>The valid character for the value production vary depending on
          the attribute name.</t>

          <t>[TODO: Investigate what token actually means.]</t>

          <t>Attributes names are case-insensitive.  White space is
          permitted between tokens.  Servers MUST NOT include two attributes
          with the same name.  Note that although the above syntax
          description shows value as optional, some attributes require
          values.</t>

          <t>The cookie-value is opaque to the user agent and MAY be
          anything the origin server chooses to send, possibly in a
          server-selected printable ASCII encoding.  "Opaque" implies that
          the content is of interest and relevance only to the origin
          server.  The content may, in fact, be readable by anyone who
          examines the Set-Cookie header.</t>

          <t>NOTE: The syntax above allows whitespace between the attribute
          and the U+3D ("=") character.  Servers wishing to interoperate
          with some legacy user agents might wish to elide this extra white
          space to maximize compatibility.</t>
        </section>
        <section title="Semantics">
          <t>When the user agent receives a Set-Cookie header, the user
          agent stores the cookie in its cookie store.  When the user agent
          makes another HTTP request to the origin server, the user agent
          returns the cookie in the Cookie header.</t>

          <t>The server can override the default handling of cookies by
          specifying cookie attributes.  User agents ignore unrecognized
          cookie attributes.</t>

          <section title="Max-Age">
            <t>[TODO: Consider removing Max-Age from the server conformance
            section because it's not supported by IE.]
            <list style="hanging">
              <t hangText="Syntax">A sequence of ASCII numerals.</t>

              <t hangText="Semantics">The value of the Max-Age attribute
              represents the maximum lifetime of the cookie, measured in
              seconds from the moment the user agent receives the cookie. If
              the server does not supply an Expires or a Max-Age attribute,
              the lifetime of the cookie is limited to the current session (as
              defined by the user agent).</t>
            </list>
            </t>
          </section>
          <section title="Expires">
            <t>
            <list style="hanging">
              <t hangText="Syntax">An RFC 1123 date [cite].  (Note that user
              agents use very forgiving date parers; see Section
              [TODO]).</t>

              <t hangText="Semantics">The value of the Expires attribute
              represents the maximum lifetime of the cookie, represented as
              the point in time at which the cookie expires. If the server
              does not supply an Expires or a Max-Age attribute, the
              lifetime of the cookie is limited to the current session (as
              defined by the user agent).</t>
            </list>
            </t>
          </section>
          <section title="Domain">
            <t>[TODO: Test Domain.]  The Domain attribute specifies the
            domain for which the cookie is valid.  The leading dot isn't
            required.  If there is no Domain attribute, the default is to
            return the cookie only to the origin server.  [TODO: You can
            only set cookies for related domains.]</t>
          </section>
          <section title="Path">
            <t>
            <list style="hanging">
              <t hangText="Syntax">A sequence of characters beginning with a
              "/" character.</t>

              <t hangText="Semantics">The Path attribute specifies the scope
              of the cookie within a given FQDN.  The user agent will
              include a cookie in an HTTP request only if the Request-URI's
              path matches, or is a subdirectory of, the cookie's Path
              attribute (where the "/" character is interpreted as a
              directory separator).  The default value for the Path
              attribute is the directory of the Request-URI when the cookie
              was received.</t>
            </list>
          </t>
          </section>
          <section title="Secure">
            <t>
            <list style="hanging">
              <t hangText="Syntax">Servers MUST NOT include a value.</t>

              <t hangText="Semantics">The user agent SHOULD protect the
              confidentiality of cookies with the Secure attribute by not
              transmitting Secure cookies over an "insecure" channel (where
              "insecure" is defined by the user agent).</t>
            </list>
            </t>
          </section>
          <section title="HttpOnly">
            <t>
            <list style="hanging">
              <t hangText="Syntax">Servers MUST NOT include a value.</t>

              <t hangText="Semantics">The user agent SHOULD protect
              confidentiality of cookies with the HttpOnly attribute by not
              revealing their contents via "non-HTTP" APIs.  (Note that this
              document does not define which APIs are "non-HTTP".)
              </t>
            </list>
            </t>
          </section>
        </section>
      </section>
      <section title="Cookie">
        <section title="Syntax">
          <t>The user agent returns stored cookies to the origin server in
          the Cookie header.  The Cookie header shares a common syntax with
          the Set-Cookie header, but the semantics of the header differ
          dramatically.</t>

          <figure>
            <artwork type="abnf">
  cookie-header     = "Cookie:" name-value-pairs
  name-value-pairs  = name-value-pair *(";" name-value-pair)
  name-value-pair   = name "=" value
  name              = token
  value             = *CHAR
            </artwork>
          </figure>

          <t>NOTE: If the server supplies a Set-Cookie header that does not
          conform to the grammar in Section [TODO], the user agent might not
          supply a Cookie header that conforms to the preceding grammar.</t>
        </section>
        <section title="Semantics">
          <t>Each name-value-pair represents a cookie stored by the user
          agent.  The cookie name is returned in as the name and the cookie
          value is returned as the value.</t>

          <t>The meaning of the cookies in the Cookie header is not defined
          by this document.  Servers are expected to imbue these cookies
          with server-specific semantics.</t>
        </section>
      </section>
      <section title="Controlling Caching">
        <t>[TODO: Should we go into this much detail here?  This seems
        redundant with the HTTP specs.]</t>

        <t>An origin server must be cognizant of the effect of possible
        caching of both the returned resource and the Set-Cookie header.
        Caching "public" documents is desirable.  For example, if the origin
        server wants to use a public document such as a "front door" page as
        a sentinel to indicate the beginning of a session for which a
        Set-Cookie response header must be generated, the page should be
        stored in caches "pre-expired" so that the origin server will see
        further requests.  "Private documents", for example those that
        contain information strictly private to a session, should not be
        cached in shared caches.</t>

        <t>If the cookie is intended for use by a single user, the Set-Cookie
        header should not be cached.  A Set-Cookie header that is intended to
        be shared by multiple users may be cached.</t>

        <t>The origin server should send the following additional HTTP/1.1
        response headers, depending on circumstances:  [TODO: Is this good
        advice?]
        <list style="symbols">
          <t>To suppress caching of the Set-Cookie header: Cache-control: no-
          cache="set-cookie".</t>
        </list>
        </t>

        <t>and one of the following:
        <list style="symbols">
          <t>To suppress caching of a private document in shared caches:
          Cache-Control: private.</t>

          <t>To allow caching of a document and require that it be validated
          before returning it to the client: Cache-Control:
          must-revalidate.</t>

          <t>To allow caching of a document, but to require that proxy caches
          (not user agent caches) validate it before returning it to the
          client: Cache-Control: proxy-revalidate.</t>

          <t>To allow caching of a document and request that it be validated
          before returning it to the client (by "pre-expiring" it):
          Cache-Control: max-age=0.  Not all caches will revalidate the
          document in every case.</t>
        </list>
        </t>

        <t>HTTP/1.1 servers must send Expires: old-date (where old-date is a
        date long in the past) on responses containing Set-Cookie response
        headers unless they know for certain (by out of band means) that
        there are no downstream HTTP/1.0 proxies.  HTTP/1.1 servers may send
        other Cache-Control directives that permit caching by HTTP/1.1
        proxies in addition to the Expires: old-date directive; the
        Cache-Control directive will override the Expires: old-date for
        HTTP/1.1 proxies.</t>
      </section>
    </section>
    <section title="User Agent Conformance">
      <t>Not all origin servers conform to the behavior specified in the
      previous section.  To ensure interoperability, user agents MUST
      process cookies in a manner that is "black-box" indistinguishable from
      the requirements in this section.</t>

      <section title="Parsing the Set-Cookie Header">
        <t>Let an LWS character be either a U+20 (SPACE) or a U+09 (TAB)
        character.</t>

        <t>When a user agent receives an Set-Cookie header in an HTTP
        response, the user agent *receives a set-cookie-string*
        consisting of the value of the header.</t>

        <t>A user agent MUST use the following algorithm to parse
        set-cookie-strings:
        <list style="numbers">
          <t>[TODO: Deal with "," characters.  My current thinking is that
          we don't actually have to do anything special for them.]</t>

          <t>If the header contains a U+3B (";") character:
          <list style="empty">
            <t>the name-value-pair string is characters up to, but not
            including, the first U+3B (";"), and the
            unparsed-cookie-attributes are the remainder of the header
            (including the U+3B (";") in question).</t>
          </list>
          Otherwise:
          <list style="empty">
            <t>the name-value-pair string is all the character contained in
            the header, and the unparsed-cookie-attributes is the empty
            string.</t>
          </list>
          </t>

          <t>If the name-value-pair string contains a U+3D ("=") character:
          <list style="empty">
            <t>the (possibly empty) name string is the characters up to, but
            not including, the first U+3D ("=") character, and the (possibly
            empty) value string is the characters after the first U+3D ("=")
            character.</t>
          </list>
          Otherwise:
          <list style="empty">
            <t>the name string is empty, and the value string is the entire
            name-value-pair string.</t>
          </list>
          </t>

          <t>Remove any leading or trailing space from the name
          string and the value string.</t>

          <t>The cookie-name is the name string, and the cookie-value is the
          value string.</t>
        </list>
        </t>

        <t>The user agent MUST use the following algorithm to parse the
        unparsed-attributes:
        <list style="numbers">
          <t>If the unparsed-attributes string is empty, skip the rest of these
          steps.</t>

          <t>Consume the first character of the unparsed-attributes (which
          will be a U+3B (";") character).</t>

          <t>If the remaining unparsed-attributes contains a U+3B (";")
          character:
          <list style="empty">
            <t>Consume the characters of the unparsed-attributes up to, but
            not including, the first U+3B (";") character.</t>
          </list>
          Otherwise:
          <list style="empty">
            <t>Consume the remainder of the unparsed-attributes.</t>
          </list>
          The characters consumed in this step comprise the
          attribute-value-pair string.</t>

          <t>If the attribute-value-pair string contains a U+3D ("=")
          character:
          <list style="empty">
            <t>the (possibly empty) name string is the characters up to, but
            not including, the first U+3D ("=") character, and the (possibly
            empty) value string is the characters after the first U+3D ("=")
            character .</t>
          </list>
          Otherwise:
          <list style="empty">
            <t>the name string is the entire attribute-value-pair string,
            and the value string is empty.  (Note that this step differs
            from the analogous step when parsing the name-value-pair
            string.)</t>
          </list>
          </t>

          <t>Remove any leading or trailing space from the name string and
          the value string.</t>

          <t>If the name is a ASCII case-insensitive match for an entry in
          the following table, process the value string as instructed.
          <figure>
            <artwork>
              <![CDATA[
       Attribute  |  Instruction
      ------------+---------------------
       Max-Age    |  See Section [TODO]
       Expires    |  See Section [TODO] 
       Domain     |  See Section [TODO]
       Path       |  See Section [TODO]
       Secure     |  See Section [TODO]
       HttpOnly   |  See Section [TODO]
              ]]>
            </artwork>
          </figure>
          </t>

          <t>Return to Step 1.</t>
        </list>
        </t>

        <t>[TODO: Can parsing a cookie ever fail?  Doesn't look like
        it!  Well, unless you count "Set-Cookie: " as a fail...]</t>

        <t>When the user agent finishes parsing the set-cookie-string
        header, the user agent *receives a cookie* from the origin server
        with name cookie-name, value cookie-value, and attributes
        cookie-attribute-list.</t>

        <section title="The Max-Age Attribute">
          <t>When the user agent receives a cookie attribute with a name
          string that case-insensitively matches the string "Max-Age", the
          user agent MUST process the value string as follows.</t>

          <t>If the first character of the value string is not a DIGIT or a
          "-" character, the user agent MUST ignore the attribute.</t>

          <t>If the remainder of value string contains a non-DIGIT
          character, the user agent MUST ignore the attribute.</t>

          <t>Let delta-seconds be the contents of the value string converted
          to an integer.</t>

          <t>If delta-seconds is less than or equal to 0, then append an
          attribute named Expires (note the name conversion) to the
          cookie-attribute-list with a value equal to the current date and
          time.</t>

          <t>If delta-seconds is strictly greater than 0, then append an
          attribute named Expires (note the name conversion) to the
          cookie-attribute-list with a value equal to the current date and
          time plus delta-seconds seconds.</t>
        </section>
        <section title="The Expires Attribute">
          <t>Unfortunately, cookie dates are quite complex for historical
          reasons.</t>

          <t>When the user agent receives a cookie attribute with a name
          string that case-insensitively matches the string "Expires", the
          user agent MUST process the value string as follows.</t>

          <t>If the attribute lacks a value or the value is the empty string,
          abort these steps.</t>

          <t>Using the grammar below, divide the value of the attribute into
          date-tokens.
          <figure>
            <artwork type="abnf">
              <![CDATA[
      cookie-date     = date-token-list
      date-token-list = date-token [ delimiter date-token-list ]
      delimiter       = %x09 / %x20 / %x21 / %x22 / %x23 / %x24 /
                        %x25 / %x26 / %x27 / %x28 / %x29 / %x2A /
                        %x2B / %x2C / %x2D / %x2E / %x2F / %x3B /
                        %x3C / %x3D / %x3E / %x3F / %x40 / %x5B /
                        %x5C / %x5D / %x5E / %x5F / %x60 / %x7B /
                        %x7C / %x7D / %x7E
      date-token      = day-of-month / month / year / time / mystery
      day-of-month    = 2DIGIT / DIGIT
      month           = "jan" [ mystery ] / "feb" [ mystery ] /
                        "mar" [ mystery ] / "apr" [ mystery ] /
                        "may" [ mystery ] / "jun" [ mystery ] /
                        "jul" [ mystery ] / "aug" [ mystery ] /
                        "sep" [ mystery ] / "oct" [ mystery ] /
                        "nov" [ mystery ] / "dec" [ mystery ]
      year            = 5DIGIT / 4DIGIT / 3DIGIT / 2DIGIT / DIGIT
      time            = 2DIGIT ":" 2DIGIT ":" 2DIGIT
      mystery         = <anything except a delimiter>
              ]]>
            </artwork>
          </figure>
          </t>

          <t>Process each data-token sequentially in the order the
          date-tokens appear in the attribute value:
          <list style="numbers">
            <t>If the found-day-of-month flag is not set and the token matches
            the day-of-month production, set the found-day-of-month flag and set
            the day-of-month-value to the number denoted by the token.  Skip
            the remaining sub-steps and continue to the next token.</t>

            <t>If the found-month flag is not set and the token matches the
            month production, set the found-month flag and set the month-value
            to the month denoted by the token.  Skip the remaining sub-steps
            and continue to the next token.</t>

            <t>If the found-year flag is not set and the token matches the
            year production, set the found-year flag and set the year-value
            to the number denoted by the token.  Skip the remaining sub-steps
            and continue to the next token.</t>

            <t>If the found-time flag is not set and the token matches the
            time production, set the found-time flag and set the hour-value,
            minute-value, and second-value to the numbers denoted by the
            digits in the token, respectively.  Skip the remaining sub-steps
            and continue to the next token.</t>
          </list>
          </t>

          <t>Abort these steps if
          <list style="symbols">
            <t>at least one of the found-day-of-month, found-month,
            found-year, or found-time flags is not set,</t>

            <t>the day-of-month-value is less than 1 or greater than 31,</t>

            <t>the year-value is less than 1601 or greater than 30827,</t>

            <t>the hour-value is greater than 23,</t>

            <t>the minute-value is greater than 59, or</t>

            <t>the second-value is greater than 59.</t>
          </list>
          </t>

          <t>If the year-value is greater than 68 and less than 100, increment
          the year-value by 1900.</t>

          <t>If the year-value is greater than or equal to 0 and less than
          69, increment the year-value by 2000.</t>

          <t>Let the expiry-time be the date whose day-of-month,
          month, year, hour, minute, and second (in GMT) are the
          day-of-month-value, the month-value, the year-value, the hour-value,
          the minute-value, and the second-value, respectively.</t>

          <t>If the expiry-time is later than the last date the user agent
          can represent, the user agent MAY replace the expiry-time with the
          last representable date.</t>

          <t>If the expiry-time is earlier than the first date the user agent
          can represent, the user agent MAY replace the expiry-time with the
          first representable date.</t>

          <t>Append an attribute named Expires to the cookie-attribute-list
          with a value equal to expiry-time.</t>          
        </section>
        <section title="The Domain Attribute">
          <t>When the user agent receives a cookie attribute with a name
          string that case-insensitively matches the string "Domain", the user
          agent MUST process the value string as follows:
          <list style="symbols">
            <t>If the value string is empty, then ignore the attribute.
            [TODO: Add a test for this with multiple Domain attributes.]</t>

            <t>If the first character of the value string is ".", then append
            an attribute named Domain to the cookie-attribute-list with a
            value equal to value string excluding the leading "." character.</t>

            <t>If the first character of the value string is not ".", then append
            an attribute named Domain to the cookie-attribute-list with a
            value equal to value string and mark the attribute as host-only.</t>

            <t>[TODO: Deal with domains that have an insufficient number of
            fields.]</t>

            <t>Otherwise, ignore the attribute.</t>
          </list>
          </t>
        </section>
        <section title="The Path Attribute">
          <t>The user agent MUST use the following algorithm to compute the
          default-path of a cookie:
          <list style="numbers">
            <t>Let uri-path be the path portion of the URI from which the
            user agent received the cookie.  [TODO: Define this more
            precisely.]</t>

            <t>If the first character of the uri-path is not a "/"
            character, output "/" and skip the remaining steps.</t>

            <t>If the uri-path contains only a single "/" character, output
            "/" and skip the remaining steps.</t>

            <t>Output the characters of the uri-path from the first
            character up to, and but not including, the right-most "/".</t>
          </list>
          </t>

          <t>A request-path path-matches a cookie-path if the cookie-path is
          a prefix of the request-path and at least one of the following
          conditions hold:
          <list style="symbols">
            <t>The last character of the cookie-path is "/".</t>

            <t>The first character of the request-path that is not
            included in the cookie-path is a "/" character.</t>
          </list>
          </t>

          <t>When the user agent receives a cookie attribute with a name
          string that case-insensitively matches the string "Path", the user
          agent MUST process the value string as follows:
          <list style="symbols">
            <t>If the value string is empty, then append an attribute named
            Path to the cookie-attribute-list with a value equal to
            default-path of the cookie.  [TODO: Is this right if there are
            more than one path attribute?]</t>

            <t>If the value string is non-empty and the first character is
            "/", then append an attribute named Path to the
            cookie-attribute-list with a value equal to value string.</t>

            <t>Otherwise, ignore the attribute.</t>
          </list>
          </t>

          <t>[TODO: Test \ ? ; # $ % etc]</t> 
        </section>
        <section title="The Secure Attribute">
          <t>When the user agent receives a cookie attribute with a name
          string that case-insensitively matches the string "Secure", the
          user agent MUST append an attribute named Secure to the
          cookie-attribute-list with an empty value regardless of the value
          string.</t>
        </section>
        <section title="The HttpOnly Attribute">
          <t>When the user agent receives a cookie attribute with a name
          string that case-insensitively matches the string "HttpOnly", the
          user agent MUST append an attribute named HttpOnly to the
          cookie-attribute-list with an empty value regardless of the value
          string.</t>
        </section>
      </section>
      <section title="Storage Model">
        <t>When the user agent receives a cookie, the user agent SHOULD
        record the cookie in its cookie store as follows.</t>

        <t>A user agent MAY ignore received cookies in their entirety if the
        user agent is configured to block receiving cookie for a particular
        response.  For example, the user agent might wish to block receiving
        cookies from "third-party" responses.</t>

        <t>The user agent stores the following fields about each cookie:
        <list style="symbols">
          <t>name (a sequence of bytes)</t>
          <t>value (a sequence of bytes)</t>
          <t>expiry (a date)</t>
          <t>domain (a cookie-domain)</t>
          <t>path (a sequence of bytes)</t>
          <t>creation (a date)</t>
          <t>last-access (a date)</t>
          <t>persistent (a Boolean)</t>
          <t>host-only (a Boolean)</t>
          <t>secure-only (a Boolean)</t>
          <t>http-only (a Boolean)</t>
        </list>
        </t>

        <t>When the user agent receives a cookie, the user agent MUST follow
        the following algorithm:
        <list style="numbers">
          <t>Create a new cookie based on the parsed Set-Cookie
          header:
          <list style="numbers">
            <t>Create a new cookie with the following default field values:
            <list style="symbols">
              <t>name = the cookie-name</t>
              <t>value = the cookie-value</t>
              <t>expiry = the latest representable date</t>
              <t>domain = the request-host</t>
              <t>path = the cookie's default-path</t>
              <t>last-access = the date and time the cookie was received</t>
              <t>persistent = false</t>
              <t>host-only = true</t>
              <t>secure-only = false</t>
              <t>http-only = false</t>
            </list>
            </t>

            <t>Update the default field values according to the
            cookie-attributes:
            <list style="hanging">
              <t hangText="expiry">If the cookie-attributes contains at least
              one valid Expires attribute, store the expiry-value of the last
              such attribute in the expiry field. Store the value true in the
              persistent field. [TODO: Test that this really works when mixing
              Max-Age and Expires.]</t>

              <t hangText="domain">If the cookie-attributes contains at least
              one Domain attribute, store the value of the last such
              attribute in the domain field.  Store the value false in the
              host-only field.  [TODO: Reject cookies for unrelated
              domains.] [TODO: If the URL's host is an IP address, let
              Domain to be an IP address if it matches the URL's host
              exactly, but set the host-only flag. ]</t>

              <t hangText="path">If the cookie-attributes contains at least
              one Path attribute, store the value of the last such attribute
              in the path field.</t>

              <t hangText="secure-only">If the cookie-attributes contains at
              least one Secure attribute, store the value true in the
              secure-only field.</t>

              <t hangText="http-only">If the cookie-attributes contains at
              least one HttpOnly attribute, store the value true in the
              http-only field.</t>
            </list>
            </t>
          </list>
          </t>

          <t>Remove from the cookie store all cookies that have the share
          the same name, domain, path, and host-only fields as the newly
          created cookie.  [TODO: Validate this list!]  [TODO: There's some
          funny business around http-only here.]</t> 

          <t>Insert the newly created cookie into the cookie store.</t>
        </list>
        </t>

        <t>The user agent MUST evict a cookie from the cookie store if A
        cookie exists in the cookie store with an expiry date in the
        past.</t>

        <t>The user agent MAY evict a cookie from the cookie store if the
        number of cookies sharing a domain field exceeds some predetermined
        upper bound (such as 50 cookies).  [TODO: Explain where 50 comes
        from.]</t>

        <t>The user agent MAY evict cookies from the cookie store if the
        cookie store exceeds some maximum storage bound (such as 3000
        cookies).  [TODO: Explain where 3000 comes from.]</t>

        <t>When the user agent evicts cookies from the cookie store, the
        user agent MUST evict cookies in the following priority order:
        <list style="numbers">
          <t>Cookies with an expiry date in the past.</t>

          <t>Cookies that share a domain field more than a predetermined
          number of other cookies.</t>

          <t>All other cookies.</t>
        </list>
        </t>

        <t>If two cookies have the same removal priority, the user agent
        MUST evict the cookie with the least recent last-access date
        first.</t>

        <t>When "the current session is over", the user agent MUST remove from
        the cookie store all cookies with the persistent field set to
        false.
        <list>
          <t>NOTE: This document does not define when "the current session
          is over."  Many user agents remove non-persistent cookies when
          they exit.  However, other user agent expire non-persistent
          cookies using other heuristics.</t>
        </list> 
        </t>
      </section>
      <section title="The Cookie Header">
        <t>When the user agent generates an HTTP request for a particular
        URI, the user agent SHOULD attach exactly one HTTP header named
        Cookie if the cookie-string (defined below) for that URI is
        non-empty.</t>

        <t>A user agent MAY elide the Cookie header in its entirety if the
        user agent is configured to block sending cookie for a particular
        request.  For example, the user agent might wish to block sending
        cookies during "third-party" requests.</t>

        <t>The user agent MUST use the following algorithm to compute the
        cookie-string from a cookie store and a URI:
        <list style="numbers">
          <t>Let cookie-list be the set of cookies from the cookie store
          that meet the following requirements:
          <list style="symbols">
            <t>The cookie's domain field must domain-match the URI's
            host. [TODO: Spec me]</t>

            <t>The cookie's path field must path-match the URI's path.</t>

            <t>If the cookie's host-only flag is set, the cookie's domain
            field must denote exactly the same FQDN as the URI's host.
            [TODO: Internet Explorer does not implement this requirement but
            most other major implementations do.]</t>

            <t>If the cookie's secure-only field is true, then 
            the URI's scheme must denote a "secure" protocol.
            <list style="empty">
              <t>NOTE: The notion of an "secure" protocol is not defined by
              this document.  Typically, user agents consider a protocol
              secure if the protocol makes use of transport-layer security,
              such as TLS.  For example, most user agents consider "https"
              to be a scheme that denotes a secure protocol.</t>
            </list>
            </t>

            <t>If the cookie's http-only field is true, then include the
            cookie unless the cookie-string is begin generated for a
            "non-HTTP" API.  (Note that this document does not define which
            APIs are "non-HTTP".)</t>
          </list>
          NOTE: The Cookie header will not contain any expired cookies
          because cookies past their expiry date are removed from the cookie
          store immediately.</t>

          <t>Sort the cookie-list in the following order:
          <list style="symbols">
            <t>Cookies with longer path fields are listed before cookies
            with shorter path field.</t>

            <t>Among cookies that have equal length path fields, cookies
            with earlier creation dates are listed before cookies with later
            creation dates.</t>
          </list>
          </t>

          <t>Update the last-access field of each cookie in the cookie-list
          to the current date.</t>

          <t>Serialize the cookie-list into a cookie-string by processing each
          cookie in the cookie-list in order:
          <list style="numbers">
            <t>If the cookie's name and value fields are both empty, skip the
            remaining steps for this cookie and continue to the next cookie,
            if any.</t>

            <t>If the cookie's name field is non-empty, output the cookie's
            name field followed by the character U+3D ("=").</t>

            <t>Output the cookie's value field.</t>

            <t>If there is an unprocessed cookie in the cookie-list, output
            the characters U+3B and U+20 ("; ")</t>
          </list>
          </t>
        </list>
        </t>
      </section>
    </section>
    <section title="Implementation Considerations">
      <section title="Set-Cookie Content">
        <t>An origin server's content should probably be divided into disjoint
        application areas, some of which require the use of state information.
        The application areas can be distinguished by their request URLs.  The
        Set-Cookie header can incorporate information about the application
        areas by setting the Path attribute for each one.</t>

        <t>The session information can obviously be clear or encoded text that
        describes state.  However, if it grows too large, it can become
        unwieldy.  Therefore, an implementor might choose for the session
        information to be a key to a server-side resource.  [TODO: Describe
        briefly how to generate a decent session key.]</t>

        <t>[TODO: We could recommend that servers encrypt and mac their cookie
        data.]</t>

        <t>[TODO: Mention issues that arise from having multiple concurrent
        sessions.]</t>
      </section>
      <section title="Implementation Limits">
        <t>Practical user agent implementations have limits on the number
        and size of cookies that they can store.  General-use user agents
        SHOULD provide each of the following minimum capabilities:
        <list style="symbols">
          <t>At least 4096 bytes per cookie (as measured by the size of the
          characters that comprise the cookie non-terminal in the syntax
          description of the Set-Cookie header).  [TODO: Validate]</t>

          <t>At least 50 cookies per domain.  [TODO: History lesson]</t>

          <t>At least 3000 cookies total.</t>
        </list>
        </t>

        <t>The information in a Set-Cookie response header must be retained
        in its entirety.  If for some reason there is inadequate space to
        store the cookie, the cookie must be discarded, not truncated.</t>

        <t>Applications should use as few and as small cookies as possible, and
        they should cope gracefully with the loss of a cookie.  [TODO: Could
        mention latency issues that arise from having tons of cookies.] </t>
      </section>
    </section>
    <section title="Security Considerations">
      <section title="Clear Text">
        <t>The information in the Set-Cookie and Cookie headers is
        transmitted in the clear.  Three consequences are:
        <list style="numbers">
          <t>Any sensitive information that is conveyed in in the headers is
          exposed to an eavesdropper.</t>

          <t>A malicious intermediary could alter the headers as they travel
          in either direction, with unpredictable results.</t>

          <t>A malicious client could alter the Cookie header before
          transmission, with unpredictable results.</t>
        </list>
        </t>

        <t>These facts imply that information of a personal and/or financial
        nature should be sent over a secure channel.  For less sensitive
        information, or when the content of the header is a database key, an
        origin server should be vigilant to prevent a bad Cookie value from
        causing failures.</t>
      </section>
      <section title="Weak Isolation">
        <t>[TODO: Weak isolation by port.]</t>

        <t>[TODO: Weak isolation by scheme (e.g., ftp, gopher, etc).]</t>
      </section>
      <section title="Cookie Spoofing">
        <t>[TODO: Mention integrity issue where a sibling domain can inject
        cookies.]</t>

        <t>[TODO: Mention integrity issue where a HTTP can inject cookies
        into HTTPS.]</t>
      </section>
    </section>
    <section title="Other, Similar, Proposals">
      <t>[TODO: Describe relation to the Netscape Cookie Spec, RFC 2109,
      RFC 2629, and cookie-v2.]</t>
    </section>
  </middle>
  <back>
    <references title="Normative References">

      <reference anchor="RFC2616">
        <front>
          <title>Hypertext Transfer Protocol -- HTTP/1.1</title>
          <author initials="R." surname="Fielding" fullname="R. Fielding">
            <organization>University of California, Irvine</organization>
            <address><email>fielding@ics.uci.edu</email></address>
          </author>
          <author initials="J." surname="Gettys" fullname="J. Gettys">
            <organization>W3C</organization>
            <address><email>jg@w3.org</email></address>
          </author>
          <author initials="J." surname="Mogul" fullname="J. Mogul">
            <organization>Compaq Computer Corporation</organization>
            <address><email>mogul@wrl.dec.com</email></address>
          </author>
          <author initials="H." surname="Frystyk" fullname="H. Frystyk">
            <organization>MIT Laboratory for Computer Science</organization>
            <address><email>frystyk@w3.org</email></address>
          </author>
          <author initials="L." surname="Masinter" fullname="L. Masinter">
            <organization>Xerox Corporation</organization>
            <address><email>masinter@parc.xerox.com</email></address>
          </author>
          <author initials="P." surname="Leach" fullname="P. Leach">
            <organization>Microsoft Corporation</organization>
            <address><email>paulle@microsoft.com</email></address>
          </author>
          <author initials="T." surname="Berners-Lee" fullname="T. Berners-Lee">
            <organization>W3C</organization>
            <address><email>timbl@w3.org</email></address>
          </author>
          <date month="June" year="1999"/>
        </front>
        <seriesInfo name="RFC" value="2616"/>
      </reference>

      <reference anchor="RFC5234">
        <front>
          <title abbrev="ABNF for Syntax Specifications">Augmented BNF for Syntax Specifications: ABNF</title>
          <author initials="D." surname="Crocker" fullname="Dave Crocker" role="editor">
            <organization>Brandenburg InternetWorking</organization>
            <address>
              <email>dcrocker@bbiw.net</email>
            </address>  
          </author>
          <author initials="P." surname="Overell" fullname="Paul Overell">
            <organization>THUS plc.</organization>
            <address>
              <email>paul.overell@thus.net</email>
            </address>
          </author>
          <date month="January" year="2008"/>
        </front>
        <seriesInfo name="STD" value="68"/>
        <seriesInfo name="RFC" value="5234"/>
      </reference>
    </references>
  
  
    <section title="Acknowledgements">
      <t>This document borrows heavily from RFC 2109.  [TODO: Figure out the
      proper way to credit the authors of RFC 2109.]</t>
    </section>
    <section title="Tabled Items">
      <t>Tabled items:
      <list style="symbols">
        <t>Public suffix.</t>
      </list>
      </t>
    </section>
  </back>
</rfc>

PAFTECH AB 2003-20262026-04-23 18:30:21