Signed Cookies (ticket #3285)

3 views
Skip to first unread message

Gulopine

unread,
Jan 11, 2007, 2:29:43 PM1/11/07
to Django developers
I've taken the liberty of writing up a contrib middleware to
transparently implement signed cookies in a Django app. It autmatically
signs and validates all cookies on its own, without any other code
needing to know a thing about it. That is, it cleans up after itself,
so that views and other middlewares receive the original cookie value,
without the signature. It is able to just be dropped into
MIDDLEWARE_CLASSES prior to any other middlewares that use cookies, in
order for those middlewares (and views) to have validated data.

There are a few notes worth mentioning.

The signed cookies are 33 characters longer than they were intended to
be when written (due to the signature written out by this middleware).
This technically does impose a slight increase in bandwidth on each
subsequent user request, and can also become a more serious problem if
the cookie is exceptionally long (since the signature might push it
over a browser's cookie length limit).

This can be avoided for middlewares that use cookies, by placing those
middlewares ahead of this one in MIDDLEWARE_CLASSES. Of course, this
means that those middlewares will not receive signature validation, and
must therefore remain suspicious of the cookies' values.

Another side-effect of the above action is that any cookies generated
outside this middleware's control (e.g., prior to it in
MIDDLEWARE_CLASSES) will be removed from request.COOKIES once this
middleware is processed (note that this will not remove it from the
client's browser, just from the HttpRequest instance). Therefore, any
cookie-using middlewares processed before this one must store their
cookies' values elsewhere if they are to be used by views.

Thankfully, SessionMiddleware can safely be placed prior to
SignedCookiesMiddleware in MIDDLEWARE_CLASSES, since it:
- only stores an ID, which is already presumed safe enough, without
signing
- adds a separate session object to the request, so views don't need
the session ID anyway
- adds the session ID to the session object anyway, just in case a
view wants to use it

My recommendation, therefore (and yeah, this is probably all
unnecessary anyway), is that SignedCookiesMiddleware be placed after
SessionMiddleware, but before any others that use cookies. This will
allow session cookies to avoid the 33-character overhead, while still
protecting the rest of the cookie operations.

I appreciate any feedback that can be offered, and I'd like to thank
you all for giving me such a great framework to work with!

Andrew Durdin

unread,
Jan 12, 2007, 8:14:43 AM1/12/07
to Django developers
Gulopine wrote:
> I've taken the liberty of writing up a contrib middleware to
> transparently implement signed cookies in a Django app. It autmatically
> signs and validates all cookies on its own, without any other code
> needing to know a thing about it.

Can you explain the reasons why one would want to use signed cookies?
What (presumably security) issues are they intended to overcome?

Andrew

David Anderson

unread,
Jan 12, 2007, 9:15:00 AM1/12/07
to django-d...@googlegroups.com
On 1/12/07, Andrew Durdin <adu...@gmail.com> wrote:
> Can you explain the reasons why one would want to use signed cookies?
> What (presumably security) issues are they intended to overcome?

Stateless server. Rather than provide a randomized session token to
the user and associate that token with a set of data on the server
side, put the dataset in the cookie and sign it. Only accept it back
if the signature checks out. For most people, the tradeoff isn't worth
it, but past a certain (large) number of active users, it's better to
sacrifice a little bandwidth and store client state on the client
side.

So yes, in a way, you are right. Storing state on the client side is
only possible and sane if you can verify the authenticity of the
state.

- Dave

Gulopine

unread,
Jan 12, 2007, 12:53:57 PM1/12/07
to Django developers
> Can you explain the reasons why one would want to use signed cookies?
> What (presumably security) issues are they intended to overcome?

Yes, the main concept here is security. Since the signature is based on
name and value of the cookie as well as the project's SECRET_KEY, a
change to any one of the those three values would invalidate the
cookie. The most likely use is for any time a site wants to store data
for a user more persistently than a session, but without requiring the
user to manually supply any additional information to retrieve that
data.

This sounds vague, but that's because I won't pretend to limit its
potential uses to only those I know of. It could be some data for a
mildly dynamic site without a database, or it could be a shopping cart
ID for an online store that wants to retrieve the cart immediately when
the user returns to the site.

> Rather than provide a randomized session token to
> the user and associate that token with a set of data on the server
> side, put the dataset in the cookie and sign it.

That's one possible use, yes, but potential uses go beyond simple
session cookies. There's been some recent activity elsewhere, regarding
the use of signed cookies for authentication purposes
(django/contrib/auth/__init__.py:51 even mentions them). In theory, a
username could be stored in a signed cookie and used to authenticate
that user upon each request to the site.

I don't know if the username alone would suffice, or if some
password-based hash would accompany it, but if the username alone
proves secure enough, users could be authenticated without touching the
database.

It would then be possible to add a second AuthenticationMiddleware
(CookieAuthenticationMiddleware, perhaps) that checks for a cookie in
the right format. Then it could be protected simply by placing that
middleware after SignedCookiesMiddleware.

I'm not a security expert, and I won't pretend to be. This patch is
simply intended to provide a tool for something that's been getting
some attention recently.

I should note, however, that security extends only so far as preventing
a user from tampering with the cookie. If the cookie itself is
compromised and removed from the computer by an attacker, it would
presumably still be considered valid if it accompanied a request from
the attacker's computer.

One potential tactic for this case would be to include an extra field
in the user's db record that could be set to a random string, something
of a per-user secret. If the cookie is stolen, that user's secret key
could be reset by an admin (after noticing suspicious activity), or
directly by the user (after validation of the user's account password).

This would hardly be a real solution, though, since it relies on
someone noticing the cookie has been stolen and taken action
appropriately. It would also require a hit to the database each time as
well, regardless of whether the password is stored in the cookie.

At any rate, I know I'm not a security expert, and the use of signed
cookies in authentication is outside the scope of this patch.

Jeremy Dunck

unread,
Jan 12, 2007, 2:05:07 PM1/12/07
to django-d...@googlegroups.com
On 1/12/07, Gulopine <gulo...@gmail.com> wrote:
...

> I should note, however, that security extends only so far as preventing
> a user from tampering with the cookie. If the cookie itself is
> compromised and removed from the computer by an attacker, it would
> presumably still be considered valid if it accompanied a request from
> the attacker's computer.

That's true with existing session-key cookies, of course.

> ...If the cookie is stolen, that user's secret key


> could be reset by an admin (after noticing suspicious activity), or
> directly by the user (after validation of the user's account password).
>
> This would hardly be a real solution, though, since it relies on
> someone noticing the cookie has been stolen and taken action
> appropriately. It would also require a hit to the database each time as
> well, regardless of whether the password is stored in the cookie.

Well, right now, stolen session keys can be made invalid simply by
removing them from the session table. Any signed-cookie auth should
probably include something like this in order to have the same ability
to revoke.

Reply all
Reply to author
Forward
0 new messages