Re: [http-state] Simple HTTP State Management

Mark Pauley <mpauley@apple.com> Mon, 26 July 2010 22:34 UTC

Return-Path: <mpauley@apple.com>
X-Original-To: http-state@core3.amsl.com
Delivered-To: http-state@core3.amsl.com
Received: from localhost (localhost [127.0.0.1]) by core3.amsl.com (Postfix) with ESMTP id CBFDA3A6872 for <http-state@core3.amsl.com>; Mon, 26 Jul 2010 15:34:17 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -103.999
X-Spam-Level:
X-Spam-Status: No, score=-103.999 tagged_above=-999 required=5 tests=[BAYES_50=0.001, RCVD_IN_DNSWL_MED=-4, USER_IN_WHITELIST=-100]
Received: from mail.ietf.org ([64.170.98.32]) by localhost (core3.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id XxIimmvMRZtN for <http-state@core3.amsl.com>; Mon, 26 Jul 2010 15:34:15 -0700 (PDT)
Received: from mail-out3.apple.com (mail-out3.apple.com [17.254.13.22]) by core3.amsl.com (Postfix) with ESMTP id C36F83A6860 for <http-state@ietf.org>; Mon, 26 Jul 2010 15:34:15 -0700 (PDT)
Received: from relay14.apple.com (relay14.apple.com [17.128.113.52]) by mail-out3.apple.com (Postfix) with ESMTP id 629769FCF682; Mon, 26 Jul 2010 15:34:37 -0700 (PDT)
X-AuditID: 11807134-b7b36ae000004afc-e7-4c4e0d7c01ec
Received: from [17.151.110.217] (Unknown_Domain [17.151.110.217]) (using TLS with cipher AES128-SHA (AES128-SHA/128 bits)) (Client did not present a certificate) by relay14.apple.com (Apple SCV relay) with SMTP id B1.FB.19196.D7D0E4C4; Mon, 26 Jul 2010 15:34:37 -0700 (PDT)
Mime-Version: 1.0 (Apple Message framework v1081)
Content-Type: text/plain; charset="windows-1252"
From: Mark Pauley <mpauley@apple.com>
In-Reply-To: <AANLkTikI3PbdZGtforTKRwzhOo6aWVju0S613arE50eO@mail.gmail.com>
Date: Mon, 26 Jul 2010 15:34:36 -0700
Content-Transfer-Encoding: quoted-printable
Message-Id: <42131B31-F6A2-4A2D-BADE-24E0084017B1@apple.com>
References: <AANLkTikI3PbdZGtforTKRwzhOo6aWVju0S613arE50eO@mail.gmail.com>
To: Adam Barth <ietf@adambarth.com>
X-Mailer: Apple Mail (2.1081)
X-Brightmail-Tracker: AAAAAQAAAZE=
Cc: http-state <http-state@ietf.org>
Subject: Re: [http-state] Simple HTTP State Management
X-BeenThere: http-state@ietf.org
X-Mailman-Version: 2.1.9
Precedence: list
List-Id: Discuss HTTP State Management Mechanism <http-state.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/listinfo/http-state>, <mailto:http-state-request@ietf.org?subject=unsubscribe>
List-Archive: <http://www.ietf.org/mail-archive/web/http-state>
List-Post: <mailto:http-state@ietf.org>
List-Help: <mailto:http-state-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/http-state>, <mailto:http-state-request@ietf.org?subject=subscribe>
X-List-Received-Date: Mon, 26 Jul 2010 22:34:17 -0000

Awesome!  This is almost exactly the thing we spoke of in anaheim :)

Cake would certainly simplify any session based web application.

This solves some of my main issues with state management via cookies:
1) Cookies are too big.  They allow naive web applications (often via lazy web frameworks implementors) to waste tremendous bandwidth.
2) Cookies are insecure, web apps often expect cookies set via https to be sent via http and vice versa.  Cookies are sometimes shared between applications on a system.
3) Cookies are too complicated.
4) Cookies apply to too many requests.  Most of the requests (for example to img.foo.com) don't actually need cookies.  To eliminate a wasted round trip we currently send them anyhow.

I think the small, fixed length of the cake nonce along with the strict partitioning of server / schemes makes sending cake without prompting a much more digestible solution.
I agree that cake would make the world a better place without much overhead.


_Mark

On Jul 17, 2010, at 2:22 PM, Adam Barth wrote:

> It's good to see various folks sending in proposals for new HTTP state
> management mechanisms.  I thought I would throw my hat in the ring
> with some ideas I've been discussing with Andrew Bortz and others:
> 
> https://docs.google.com/document/pub?id=1l_YcZzF82OJdld5cJX38abSlIwG3dfW37gZTk6PDHwU
> 
> I've also included the document inline below.  Let me know if you have
> any feedback.
> 
> Adam
> 
> 
> = Simple HTTP State Management =
> 
> Adam Barth (UC Berkeley)
> Andrew Bortz (Stanford University)
> 
> === Abstract ===
> 
> This document describes a simple HTTP state management mechanism,
> called cake, which a server can use to re-identity HTTP clients.  In
> the protocol, the user agent persists a nonce for each security
> origin.  When issuing an HTTP request for a URL, the user agent
> includes the nonce for that URL’s origin.
> 
> == Design Principles ==
> 
> There are a number of principles that have influenced the design of
> the cake state management mechanism.  In this section, we highlight
> some of those design principles.
> 
> === Cookies are here to stay ===
> 
> Cookies are very widely used on the web and support a vast array of
> use cases.  In designing an HTTP state management mechanism, we should
> consider that most user agents will continue to support cookies for
> the foreseeable future.  That means we do not need to design a
> mechanism that meets all the use cases covered by cookies.  If cookies
> are sufficient to meet a particular use case, then server can happily
> use cookies instead of our new mechanism.
> 
> === Sessions, not storage ===
> 
> Instead of trying to provide a mechanism for offloading storage from
> the server to the client (as cookies do), we should aim to provide a
> robust mechanism for session management.  In particular, we should
> help the server link a sequence of HTTP requests as originating from
> the same client.
> 
> If servers want to offload state storage to the client, servers can
> either use cookies or an application-layer storage mechanism.  For
> example, HTML applications have access to the localStorage key-value
> store or a more robust storage mechanism in the form of IndexedDB.
> Nothing we supply at the network can compete with these mechanisms on
> features or robustness.
> 
> === Minimal mechanism ===
> 
> It’s tempting to design a complex mechanism because cookies are
> complex.  However, complexity is a harsh mistress.  Whenever possible,
> we should aim to provide a minimal, hard-working primitive that
> applications can use robustly.  For every aspect of the protocol, we
> should ask ourselves whether that aspect can be removed.
> 
> In particular, we should not aim to design a mechanism that meets all
> the use cases of cookies.  Such a mechanism would be far more complex
> that we need.  Instead, we should narrow our focus to a specific set
> of use cases and design the minimal mechanism for those use cases.
> 
> === Privacy ===
> 
> One of the biggest failings of cookies is that they offer a poor
> privacy trade-off for users.  As a goal, privacy is in tension with
> state management because user’s desire not to be tracked or
> fingerprinted runs contrary to having stateful interactions with
> servers.  In designing a new state management mechanism, we should be
> mindful of its privacy implications.  In particular:
> 
> * Because cookies are here to stay, we should remember that folks that
> want to track users can use cookies to track them.  We shouldn’t
> provide a mechanism that makes tracking easier, but, by the same
> token, there’s a limit to how much we can improve privacy in the face
> of cookies.
> 
> * Most user-initiated stateful interactions with servers begin in a
> first-party context.  Safari has had success blocking servers from
> setting cookies in third-party contexts.  We should learn from our
> experience with third-party cookie blocking and consider adopting a
> similar policy of initiating a session only in a first-party context.
> 
> * Most stateful interactions between users and servers persist for a
> moderate length of time (e.g., two weeks).  Servers that require
> longer stateful interactions with users often have another mechanism
> for reestablishing the user’s state (e.g., a password).  We should
> consider letting the user agent limit how long it stores state.
> 
> === Align with browser security model ===
> 
> Cookies were designed and implemented before browsers had a clear
> security model.  Now that browsers have a clear security model (i.e.,
> the same-origin policy), we should align our state management
> mechanism with that security model.  In particular:
> 
> * Separate fully-qualified domain names should have separate state
> stores.  For example, the user’s session with foo.example.com and
> bar.example.com should not share state.  Cookies use an extremely
> dubious heuristic based on public suffixes to try to make up for their
> historical error of sharing state between hosts.  We should not repeat
> their mistake.
> 
> * Different schemes should have separate state stores.  For example,
> http://example.com and https://example.com should not share state.
> This provision is essential for providing protection from an active
> network attacker (who can control http://example.com but not
> https://example.com) and aligns with the browser security model.
> 
> * We should protect the integrity (as well as the confidentiality) of
> sessions.  Cookies provide very weak integrity guarantees, which makes
> it quite difficult to use them securely in the presence of an active
> network attacker.  If we align with the browser security model,
> integrity follows as a natural consequence.
> 
> A common objection to aligning with the browser security model is that
> many sites today share cookies between subdomains.  If sites wish to
> coordinate state across different security origins, we have some very
> nice protocols they can use, both at the network layer (e.g., OAuth)
> and at the application layer (e.g., postMessage).
> 
> == Protocol ==
> 
> === Syntax ===
> 
> The Cake protocol consists of a single HTTP request header, called Cake:
> 
> cake-header = "Cake:" OWS cake-nonce OWS
> cake-nonce  = 1*BASE64CHAR
> BASE64CHAR  = ALPHA / DIGIT / "+" / "/" / "="
> 
> === Semantics == =
> 
> The Cake header contains a nonce that identifies the network endpoint
> from which an HTTP request originated.
> 
> The user agent stores an independent random nonce for each origin#.
> When issuing an HTTP request for a URL, the user agent includes the
> nonce for that URL’s origin in the Cake header.
> 
> The user agent MAY regenerate an origin’s nonce at any time.  We
> recommend that the user agent persists an origin’s nonce for two weeks
> after the last time it issued a “first-party” request to that origin.
> 
> The user agent MAY omit the Cake header from any request.  We
> recommend that the user agent omit the header for requests to a
> particular origin until the user agent issues a “first-party” request
> to that origin.
> 
> The user agent MAY send a nonce of any non-zero length.  We recommend
> that the user agent choose a nonce that is long enough to make online
> guessing attacks extremely unlikely (e.g., 64 bits of entropy, 11
> characters, are likely sufficient).
> 
> == Discussion ==
> 
> We expect servers to use the cake nonce as a session identifier.  In
> particular, we expect the server to maintain a hash table that maps
> cakes to server-side session information.  When receiving an HTTP
> request, the server uses the nonce from the cake header to look up the
> state for the session in the hash table.
> 
> Q: Why not let the server specify the header value?
> A: Letting the server store information in the header is just an
> opportunity for the server to shoot itself in the foot.  At worst, the
> server might become vulnerable to a session fixation attack if the
> server lets the attacker pick the cake value.  Even outside of an
> attack scenario, letting the server write to global state creates a
> race condition.  Moreover, at best, the server will just store an
> opaque nonce in the header, so we might as well remove the sand traps.
> If the server wants to offload state to the client, there are plenty
> of other mechanisms designed for storing state on the client.
> 
> Q: Why not let the server specify the lifetime of the nonce?
> A: There are two cases: (1) the server wishes to have a shorter
> lifetime than the one provided by the user agent, and (2) the server
> wishes to have a longer lifetime than the one provided by the user
> agent.  In the first case, the server can just flush the entry for the
> nonce it its server-side state table.  In the second case, the default
> expiry is a balance between privacy concerns about tracking and the
> benefits of not having to constantly reestablish a session.  Note that
> the server can always store more persistent state in application-layer
> state stores, such as localStorage and IndexedDB.
> 
> Q: Why omit the nonce until the user agent issues a first-party
> request to an origin?
> A: Omitting the nonce before the user agent issues a first-party
> request to an origin serves two purposes: privacy and performance.
> For privacy, omitting the nonce provides some degree of privacy
> protection against tracking by third parties (approximately the same
> protections as Safari’s blocking writes to third-party cookies).  For
> performance, omitting the nonce reduces the size of requests for
> resources hosted on content distribution networks, which have no
> interest in stateful interactions.  For example, the user never issues
> requests to fbcdn.net in a first-party context, and so all the
> requests to Facebook’s CDN will omit the nonce.
> 
> Q: Why not wait for the server to enable the protocol?
> A: Essentially, we want the server to be able to link the first
> request to the rest of the session.  Imagine your site wants to use
> cake as a session identifier.  You receive a network request for your
> home page and you response with some HTML and a request to enable
> cake.  Now, you get a second request, this time with a cake nonce.
> How do you link the second request to the first?  By contrast, if the
> first request includes the cake nonce, then you can create an entry in
> your server-side state table and you’re off to the races.
> _______________________________________________
> http-state mailing list
> http-state@ietf.org
> https://www.ietf.org/mailman/listinfo/http-state