<?xml version="1.0"?>
<?rfc toc="yes"?>
<?xml-stylesheet type="text/xml" href="rfc2629.xslt"?>
<!DOCTYPE rfc SYSTEM "rfc2629.dtd">
<rfc ipr="pre5378Trust200902" docName="draft-abarth-cookie-01">
  <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="August" year="2009"/>
    <workgroup>http-state Working Group</workgroup>
    <keyword>Internet-Draft</keyword>
    <abstract>
      <t>This document defines the HTTP Cookie and Set-Cookie headers.</t>

      <t>NOTE:
      <list>
        <t>This document is currently a "straw-man" cookie proposal.  Much of
        the text herein is completely wrong.  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>
    <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.  Sometimes we compare one host
      name with another.  Host A's name domain-matches host B's if
      <list style="symbols">
        <t>both host names are IP addresses and their host name strings match
        exactly; or</t>

        <t>both host names are FQDN strings and their host name strings match
        exactly; or</t>

        <t>A is a FQDN string and has the form NB, where N is a non-empty name
        string, B has the form .B, and B is a FQDN string.  (So, x.y.com
        domain-matches .y.com but not y.com.)</t>
      </list>
      </t>

      <t>Note that domain-match is not a commutative operation: a.b.c.com
      domain-matches .c.com, but not the reverse.</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="State and Sessions">
      <t>This document describes a way to create stateful sessions with HTTP
      requests and responses.  HTTP servers respond to each client request
      without relating that request to previous or subsequent requests; the
      technique allows clients and servers that wish to exchange state
      information to place HTTP requests and responses within a larger context,
      which we term a "session".  This context might be used to create, for
      example, a "shopping cart", in which user selections can be aggregated
      before purchase, or a magazine browsing system, in which a user's
      previous reading affects which offerings are presented.</t>

      <t>There are, of course, many different potential contexts and thus many
      different potential types of session.  The designers' paradigm for
      sessions created by the exchange of cookies has these key attributes:
      <list style="numbers">
        <t>Each session has a beginning and an end.</t>

        <t>Each session is relatively short-lived.</t>

        <t>Either the user agent or the origin server may terminate a
        session.</t>

        <t>The session is implicit in the exchange of state information.</t>
      </list>
      </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 two state management headers, Set-Cookie and Cookie, have common
      syntactic properties involving attribute-value pairs.  The following
      grammar uses the notation, and tokens DIGIT (decimal digits) and token
      (informally, a sequence of non-special, non-white space characters) from
      the HTTP/1.1 specification [RFC 2068] to describe their syntax.</t>

      <section title="Examples">
      </section>

    </section>
    <section title="Server Conformance">
      <section title="General">
        <t>The origin server initiates a session, if it so desires.  (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).  To
        initiate a session, the origin server returns an extra response
        header to the client, Set-Cookie.  (The details follow later.)</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.  The origin server effectively ends a session by
        sending the client a Set-Cookie header with Max-Age=0.  [TODO: Need
        to say something about Expires here.]</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.  [TODO: Investigate how UAs
        cope with folded headers.]</t>
      </section>
      <section title="Set-Cookie">
        <section title="Syntax">
          <t>Informally, the Set-Cookie response header comprises the token
          Set-Cookie:, followed by a comma-separated list of one or more
          cookies.  Each cookie begins with a name-value-pair, followed by
          zero or more semi-colon-separated attribute-value pairs.  The
          NAME=VALUE attribute-value pair must come first in each
          cookie.</t>

          <figure>
            <artwork>
              <![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             = token
              ]]>
            </artwork>
          </figure>

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

          <t>Attributes names are case-insensitive.  White space is
          permitted between tokens.  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 = sign.  Servers wishing to interoperate with some legacy user agents
          might wish to elide this extra white space to maximize compatibility.</t>
        </section>
      </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 will return the cookie in the Cookie header.</t>

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

        <section title="Cookie Attributes">
          <t>This section describes the semantics of a number of cookie attributes.</t>

          <section title="Max-Age">
            <t>
            <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].  (User agents use a
              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>[TODO: Test path.]  The Path attribute specifies the subset of
            URLs to which this cookie applies.</t>
          </section>
          <section title="Secure">
            <t>
            <list style="hanging">
              <t hangText="Syntax">The empty string.</t>

              <t hangText="Semantics">The user agent SHOULD protect the
              confidentiality of cookies with the Secure attribute.</t>
            </list>
            </t>
          </section>
          <section title="HttpOnly">
            <t>
            <list style="hanging">
              <t hangText="Syntax">The empty string.</t>

              <t hangText="Semantics">The user agent SHOULD protect
              confidentiality of cookies with the HttpOnly attribute by
              including HttpOnly cookies only when generating cookie strings
              for use in HTTP requests.</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>
              <![CDATA[
          cookie-header     = "Cookie:" name-value-pairs
          name-value-pairs  = name-value-pair *(";" name-value-pair)
          name-value-pair   = name "=" value
          name              = token
          value             = token
              ]]>
            </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 grammar in this
          Section.</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>
        </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 downsteam 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>A user agent MUST use the following algorithm to parse the
        Set-Cookie header:
        <list style="numbers">
          <t>[TODO: Deal with ',' characters.]</t>

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

          <t>If the first non-LWS character of the name-value string is
          '=', remove it.</t>

          <t>If the name-value string contains a '=' character:
          <list style="empty">
            <t>the name string is the characters up to, but not including, the first '='
            character, and the value string is the characters after the
            first '=' character .</t>
          </list>
          Otherwise:
          <list style="empty">
            <t>the name string is empty, and the value string is the entire
            name-value string.</t>
          </list>
          </t>

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

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

          <t>The cookie-name is the name string.</t>

          <t>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>[TODO: Figure out how to parse cookie attributes.]</t>
        </list>
        </t>

        <t>[TODO: Can parsing a cookie ever fail?]</t>

        <t>[TODO: Convert Max-Age to a date during parsing.]</t>

        <t>When the user agent finishes parsing the Set-Cookie header, the
        user agent *receives a cookie* from the origin server with name
        cookie-name, value cookie-value, and attributes
        cookie-attributes.</t>
      </section>
      <section title="Parsing Cookie Dates">
        <t>Basically, cookie dates are a mess for historical reasons.</t>

        <t>To be compatible with legacy servers, however, user agents should
        accept dates formated according to this grammar:
        <figure>
          <artwork>
            <![CDATA[
      cookie-date       = rfc1123-like-date / mystery-date
      rfc1123-like-date = weekday "," SP rfc1123-like-dmy SP time SP "GMT"
      weekday           = "Monday" / "Mon" / "Tuesday" / "Tue" / ...
      rfc1123-like-dmy  = day dmy-div month dmy-div year
      dmy-div           = SP / "-"
      day               = 2DIGIT / *1SP DIGIT
      month             = "Jan" / "Feb" / ...
      year              = 2DIGIT / 4DIGIT
      time              = 2DIGIT ":" 2DIGIT ":" 2DIGIT

      mystery-date      = *CHAR ; see below
            ]]>
          </artwork>
        </figure>
        </t>

        <t>[TODO: More information about mystery-date.]</t>
      </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 cookie-path)</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 path of the request URL that generated the
              Set-Cookie response, up to, but not including, the right-most
              /  [TODO: Test!  This seems wrong for paths that are just a
              single slash]</t>
              <t>last-access = the date and time the cookie was received</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 Expires or a Max-Age attribute, store the value of the
              [TODO: first] such attribute in the expiry field.  Store the
              value true in the persistent field.</t>

              <t hangText="domain">If the cookie-attributes contains at least
              one Domain attribute, store the value of the [TODO: first] 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 [TODO: first] 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: Valiate 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
        either of the following conditions are met:
        <list style="symbols">
          <t>A cookie exists in the cookie store with an expiry date in the
          past.</t>

          <t>More than 50 cookies exist in the cookie store with the same
          domain field.</t>
        </list>
        </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).</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>A cookie with an expiry date in the past.</t>

          <t>A cookie that shares a domain field with more than 50 other
          cookies in the cookie store.</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 user agent exits, the user agent MUST remove from the
        cookie store all cookies with the persistent field set to false.</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 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>When generating a cookie-string from a URI with a "secure"
        scheme, the user agent MUST set the SECURE flag to true.  Otherwise,
        the user agent MUST set the SECURE flag to false.
        <list style="empty">
          <t>NOTE: The notion of an "secure" scheme is not defined by this
          document.  Typically, user agents consider a scheme secure if
          the scheme refers to a protocol that makes use of
          transport-layer security, such as TLS.  For example, most user
          agents consider "https" to be a secure scheme.</t>
        </list>
        </t>

        <t>When generating a cookie-string for use in an HTTP request,
        the user agent MUST set the HTTP flag to true.  Otherwise, the user
        agent MUST set the HTTP flag to false.</t>

        <t>The user agent MUST use the following algorithm to compute the
        cookie-string from a cookie store and from 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.
            [TODO: Spec me]</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 SECURE
            flag must be true.</t>
            
            <t>If the cookie's http-only field is true, then the HTTP flag
            must be true.</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>Output the cookie's name field.</t>

            <t>Output 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="Caching Proxy Conformance">
      <t>One reason for separating state information from both a URL and
      document content is to facilitate the scaling that caching permits.  To
      support cookies, a caching proxy must obey these rules already in the
      HTTP specification [TODO: If they're already in the HTTP specification,
      aren't they redundant here?]:
      <list style="symbols">
        <t>Honor requests from the cache, if possible, based on cache
        validity rules.</t>

        <t>Pass along a Cookie request header in any request that the proxy
        must make of another server.</t>

        <t>Return the response to the client.  Include any Set-Cookie
        response header.</t>

        <t>Cache the received response subject to the control of the usual
        headers, such as Expires, Cache-Control: no-cache, and Cache-Control:
        private.</t>

        <t>Cache the Set-Cookie subject to the control of the usual header,
        Cache-Control: no-cache="set-cookie".  (The Set-Cookie header should
        usually not be cached.)</t>
      </list>
      </t>

      <t>Proxies must not introduce Set-Cookie (Cookie) headers of their own
      in proxy responses (requests).</t>
    </section>
    <section title="Examples">
      <t>[TODO: Write sensible examples.]</t>
    </section>
    <section title="Implementation Considerations">
      <t>Here we speculate on likely or desirable details for an origin server
      that implements state management.</t>

      <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.  In general, user agents' cookie
        support should have no fixed limits.  [TODO: Why not?]  They should
        strive to store as many frequently-used cookies as possible.
        Furthermore, general-use user agents should provide each of the
        following minimum capabilities individually, although not necessarily
        simultaneously:  [TODO: Where do these numbers come from?]
        <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)</t>
        </list>
        </t>

        <t>User agents created for specific purposes or for limited-capacity
        devices should provide at least 50 cookies of 4096 bytes, to ensure
        that the user can interact with a session-based origin server.</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, it 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 title="Denial of Service Attacks">
          <t>User agents may choose to set an upper bound on the number of
          cookies to be stored from a given host or domain name or on the size
          of the cookie information.  Otherwise, a malicious server could
          attempt to flood a user agent with many cookies, or large cookies, on
          successive responses, which would force out cookies the user agent
          had received from other servers.  However, the minima specified above
          should still be supported.  [TODO: These minima still let an attacker
          exhaust the entire cookie store.  There's not much we can do about it
          though.]</t>
        </section>
      </section>
    </section>
    <section title="Privacy">
      <section title="User Agent Control">
        <t>An origin server could create a Set-Cookie header to track the path
        of a user through the server.  Users may object to this behavior as an
        intrusive accumulation of information, even if their identity is not
        evident.  (Identity might become evident if a user subsequently fills
        out a form that contains identifying information.)  This state
        management specification therefore requires that a user agent give the
        user control over such a possible intrusion, although the interface
        through which the user is given this control is left unspecified.
        However, the control mechanisms provided shall at least allow the user
        <list style="symbols">
          <t>to completely disable the sending and saving of cookies,</t>

          <t>to determine whether a stateful session is in progress, and</t>

          <t>to control the saving of a cookie on the basis of the cookie's
          Domain attribute.</t>
        </list>
        </t>

        <t>Such control could be provided by, for example, mechanisms
        <list style="symbols">
          <t>to notify the user when the user agent is about to send a cookie
          to the origin server, offering the option not to begin a session,</t>

          <t>to display a visual indication that a stateful session is in
          progress,</t>

          <t>to let the user decide which cookies, if any, should be saved when
          the user concludes a window or user agent session, or</t>

          <t>to let the user examine the contents of a cookie at any time.</t>
        </list>
        </t>

        <t>A user agent usually begins execution with no remembered state
        information.  It should be possible to configure a user agent never to
        send Cookie headers, in which case it can never sustain state with an
        origin server.  (The user agent would then behave like one that is
        unaware of how to handle Set-Cookie response headers.)</t>

        <t>When the user agent terminates execution, it should let the user
        discard all state information.  Alternatively, the user agent may ask
        the user whether state information should be retained.  If the user
        chooses to retain state information, it would be restored the next time
        the user agent runs.</t>
      </section>
      <section title="Protocol Design">
        <t>The restrictions on the value of the Domain attribute are meant to
        reduce the ways that cookies can "leak" to the "wrong" site.  The
        intent is to restrict cookies to one, or a closely related set of
        hosts.  Therefore a request-host is limited as to what values it can
        set for Domain.</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 easedropper.</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="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 title="Unexpected Cookie Sharing">
        <t>A user agent should make every attempt to prevent the sharing of
        session information between hosts that are in different domains.
        Embedded or inlined objects may cause particularly severe privacy
        problems if they can be used to share cookies between disparate
        hosts.  For example, a malicious server could embed cookie
        information for host a.com in a URI for host b.com.  User agent
        implementors are strongly encouraged to prevent this sort of
        exchange whenever possible.  [TODO: How are they supposed to do
        this?  This section makes little sense.]</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>
    <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>
