
How to build (and how not to build) a secure “remember me” feature - troyhunt
http://www.troyhunt.com/2013/07/how-to-build-and-how-not-to-build.html
======
WA
Good article, but one thing is explained in a weird way:

Don't bother with cookie expiration. That's the wrong approach, _because the
cookie is controlled by the user_. Always do a server-side check whether or
not the auth token in the cookie is allowed to continue the session.

So you could simply set the expiration date for a cookie until 2030 but make
sure that the auth token from that cookie cannot be used after
$EXPIRATION_TIMESTAMP on the server.

You could also follow a layered approach:

If the user logs in every few days, re-authenticate him using the auth token
from the cookie. But if the user was seen more than $MAX_INACTIVE_DAYS ago, do
not re-authenticate and terminate all sessions, even if the "remember me"
function is set to half a year or so.

~~~
kijin
Good point, but your explanation is also a bit confusing. If I understand
correctly, your point is not so much "don't bother with cookie expiration" as
"don't trust cookies to expire when you tell them to". In other words, the
server should double-check cookie expiration dates because you don't want
somebody fudging your 7-day cookie and using it to log in next year. Am I
right?

~~~
j_s
Implement cookie expiration server-side.

~~~
jessaustin
Would anyone be tempted to do this "client-side"? What would that even mean,
besides what the browser does automatically? Or are we just saying, "don't
trust that the client won't send expired cookies"?

------
kijin
> _A more pragmatic mitigation is to still separate the auth cookie from a
> dedicated “remember me” cookie and use the latter to re-authenticate the
> user but impose some restrictions._

What are the benefits of using a separate cookie for the "remember me"
feature, provided that you impose the same restrictions (e.g. requiring the
password again before accessing sensitive areas of the website) and same
security measures like "httponly" & "secure"?

I've been using a single cookie with a randomly generated and periodically
replaced session identifier, which expires at the end of the session by
default but lasts longer if the user selects "remember me". I'd like to know
whether there is a compelling reason to switch to two cookies.

~~~
dasil003
One significant benefit is being able to enforce a one-time use policy the
remember-me cookie. If you only utilize it when the user is not logged in,
then you use it to authenticate, set a regular session cookie, and generate a
new remember-me cookie. If an old remember-me cookie is ever used that means
someone probably sniffed the cookie, and you can invalidate all sessions at
that point and even force a password reset if you are particularly paranoid.
You can't do this with the regular session cookie because a user might have
multiple tabs open. For remember-me the same effect is only a race condition
if the user opens two tabs simultaneously.

~~~
kijin
> _You can 't do this with the regular session cookie because a user might
> have multiple tabs open._

Why not? It's considered standard practice to refresh regular session
identifiers every X minutes, and this rarely causes race conditions unless
your app is AJAX-heavy.

My apps regenerate the session identifier every time it detects that it has
been more than 5 minutes since the last regeneration. So if a user who has
been away for a few hours returns to the site, his session identifier will be
immediately regenerated and the old one will become useless. If race
conditions become a serious issue, I can allow the old session identifier to
continue to work for the next 30 seconds or so. It also shouldn't be too
difficult to add a feature that throws tantrums if someone continues to use
the old one much later than that.

~~~
mmcnickle
If an attacker uses a compromised session id before it is regenerated, the
attacker will receive the regenerated session too. They'll have a long-lived
session to the victims account.

~~~
kijin
If the attacker uses a compromised remember-me cookie, it will also be
regenerated for him. Same problem.

~~~
mmcnickle
If you use the scheme described linked from the article, when the legitimate
user logs in again, the attacker will lose access to the session permanently.

~~~
kijin
Oh, I see. A separate cookie makes it easier for you to check for compromised
sessions. I suppose you could also do that with regular session cookies if you
keep good track of identifier history, but it'd be a lot more hassle.

------
sehrope
Remember me cookies are a specific case of some data sent to the client that
the server would like to verify at a later point in time. The most direct way
that comes to mind for solving this type of problem is to send the client just
a random identifier and have the server look it up in a persistent store upon
use.

The other way of solving it is to have the server sign whatever data is sent
to the client via an HMAC. That combined with some basic serialization gets
you a generic approach that you can use for all kinds of things. This also has
the scalable benefit that it doesn't require a centralize persistent store.

Here's a high level summary of how we handle these use cases:

# Server -> Client (Assume server wants to round trip object X)

    
    
      1. Server serializes X to a URL friendly string (JSON + Base64 works well enough for this)
      2. Server calls generateToken(type, message, expiration) which signs the message/expiration with secretKey+type. It then returns a JSON/Base64 serialized map containing message/expiration/hmac.
    

# Client -> Server

    
    
      1. Client sends back the final JSON/Base64 string
      2. Server decodes and extracts the message, expiration, and hmac
      3. Server verifies the HMAC by regenerating it and comparing it against the client supplied one
      4. Server verifies the expiration date hasn't passed
      5. Server returns back the deserialized object
    

Couple of notes:

* The HMAC prevents the client from tampering with the message

* The 'type' field is so that tokens generated for one request type cannot be accepted somewhere else in the application. It's kind of like namespacing.

* The 'type' field does not need to be included in the message itself. It's inferred by the server based on the client request type.

* The object/message itself can be blank. In that case this becomes a secure expiring token.

Couple of possible extensions/improvements:

* If the data being sent back/forth is particularly sensitive you could also have the server encrypt either it or the entire message itself. If it's not though then it would be overkill.

* Including the requesting clients IP in the HMAC generation to further limit the set of user's it would validate against is an option as well though generally that's a bad idea. People's IP addresses change fairly often and that kills the basic use case of taking your work home with you.

~~~
jacques_chester
This is where most cookie schemes wind up -- sending and retrieving HMACs.

I wrote my honours dissertation on an opt-in scheme that used cookies, HTTPS
and javascript to track users visiting multiple websites.

What you have here is what I called "Protocol 1": the first elaboration of the
naive protocol. An additional elaboration (Protocols 2 and 3) is to remove
user identification from cookies entirely. Each cookie is regenerated on each
HTTP request with a new ID and HMAC. This means that if a cookie is
successfully harvested, its useful lifetime is limited.

There are more attacks after this. I got as far as Protocol 10; it transpires
that Protocol 10 is broken anyhow. Depending on the sophistication of your
attacker, there's no safe way to do what I was trying to do.

~~~
jessaustin
This sounds interesting. Can you provide a link to this dissertation?

~~~
jacques_chester
Email me (in profile).

------
mmahemoff
Regarding how long to keep the "remember me" cookie for, this is one of the
overlooked reasons why native apps are eating the web's breakfast. When was
the last time you have to re-authenticate on a native mobile app?

Maybe it happens on some finance/banking apps, but I don't recall seeing it on
apps like Facebook or Kindle for example.

Web developers could, for example, add longer times if the user agent is
mobile.

And Troy is spot on about the middle ground of "logged-in-ness". Developers
are finally realising what Amazon knew all along, that it's not binary. You
can keep the user partially logged in, while requiring authentication to
perform sensitive tasks.

~~~
winthrowe
> When was the last time you have to re-authenticate on a native mobile app?

All the time. The Facebook android app is horrible.

~~~
randomchars
Not for me. Did you by any chance move the app to your SD card? Apps that use
the android Sync provider don't work if they're moved.

------
brown9-2
How does the "reference implementation" of ASP.NET actually work? Is the
cookie's value mapped to some in-memory entry in the application server, is it
stored in a database, etc? It seems that the article doesn't say.

~~~
sigil
> Is the cookie's value mapped to some in-memory entry in the application
> server, is it stored in a database, etc?

Neither. At login the server signs the new session cookie with a secret
application key. Later, when a client requests a page and sends over the
session cookie, the server verifies the signature. If it matches, the data in
the session cookie -- which usually includes the username, whether they're
logged in, and for how long -- can be trusted.

This is nice because it makes scaling a stateful site easier. Server-side
session stores often become the bottleneck. Also, from a REST standpoint,
updating a session database during a GET request (eg to freshen the session)
is problematic.

ASP.net was the first time I remember seeing the signed session cookie trick,
but most web frameworks have it now:

django --
[https://docs.djangoproject.com/en/dev/topics/http/sessions/#...](https://docs.djangoproject.com/en/dev/topics/http/sessions/#using-
cookie-based-sessions)

rails -- [http://guides.rubyonrails.org/security.html#session-
storage](http://guides.rubyonrails.org/security.html#session-storage)

flask --
[http://flask.pocoo.org/docs/api/#sessions](http://flask.pocoo.org/docs/api/#sessions)

node -- [https://github.com/mozilla/node-client-
sessions](https://github.com/mozilla/node-client-sessions)

mojolicious -- [http://toroid.org/ams/etc/mojolicious-session-
cookies](http://toroid.org/ams/etc/mojolicious-session-cookies)

------
graycat
Help!

Most of this discussion I understand. One point is, it all involves lots of
work with browser cookies stored on the user's computer.

My approach so far is to send the user the character string version of a GUID
(globally unique identifier, supposely unique in all space and time, on all
computers or some such) in an HTML text box marked as "hidden" so that it
doesn't show on the screen. Then I use that GUID value as a key in a key-value
store where the value keeps the short term info I want on the user and their
'session'. I wrote my own little key-value store with TCP/IP, some class
instance de/serialization, and two instances of a .NET collection class.

However, my understanding is that some browsers are willing to help implement
the function "Remmeber me on this computer" without help of cookies. How? My
guess: For the text boxes on the login in Web page, in the HTML use names for
the boxes that the browser interprets as 'user name' and 'password', and then
the browser stores the contents in its dedicated disk space by Web page.
Right?

So, there's a 'security hole' here if the user is on a computer shared with
other people!

Also, my understanding is that so far on mobile devices, the browsers do not
permit cookies. True? And if so, do mobile browsers permit the function of
remember me I described above?

Thanks.

~~~
yread
You are a bit confused, but I'm not sure why you're being downvoted...

> GUID

GUIDs are really not the best idea, they can be (sort of) predicted - an
attacker can guess which GUIDs are in use as session identifiers. Better to
use a random string (generated by a cryptographic random number generator)

> without cookies

Browsers can store user's password when they request it. It is a security
hole, consciously made by the user for added convenience. Also, only the user
who made this decision can fall into this hole - it's his credentials that get
stolen.

> mobile devices ... do not permit cookies

they do (although some might not store the cookies for as long as the
expiration would require). However, they don't allow the user to store the
password (as in the previous paragraph, the remember me function as you call
it)

To round it up, it's a good thing you're experimenting with your own key/value
store and session implementation, but it's usually better to use tested
components in production (especially for the session stuff - it's very easy to
get wrong). Anyway, keep experimenting, that's the best way to learn - I just
hope somebody reviews your stuff before you shoot yourself in the foot :)

~~~
graycat
Thanks, I needed that!

I've done a lot of programming, some quite advanced, and likely for longer
than 99% of the HN audience. But this is my first effort with a Web site,
HTML, CSS, etc. So, I believe I can write good code and think through design
issues well enough, but I am missing some information about mobile devices and
browsers.

My little session state store code is working great. It was fast, fun, and
easy to write, and it's been working flawlessly as I use it while developing
more code.

My main alternative was to use what Microsoft's ASP.NET offered. First they
offered storing session state in the same _application_ (whatever that is,
maybe just an address space). That alternative would give problems once my
site is busy enough to need more than one Web server unless I had some front
end box, maybe from Cisco, implement something like _session affinity_. The
second alternative was using SQL Server. I'm trying to keep down the use of
SQL Server, especially for something as _light_ as a session state store where
relational database, with ACID, etc. is gross overkill.

Thanks for the information on cookies: I don't want to assume or ask that a
user's Web browser accept cookies.

When my site goes live, there will be no reason for users to have a user ID or
password or log in -- later there will be. So, when I have some users log in,
there is some question just how to handle that in a way both secure enough and
also really easy for the users. If the user lets their Web browser store the
user ID and password (not in a cookie) and a user wants to use that facility,
so far fine with me -- that browser functionality is an industry standard and,
thus, not to be too embarrassed about. Maybe I can get some actual
documentation of that browser feature in pages for programmers at Web sites of
the Web browsers -- Firefox, IE, Chrome, etc.

For using a GUID as a random key, I don't see what's wrong. I just ask for a
new GUID whenever I need one. I use GUIDs for so many things inside my server
code that no user can see a sequence of GUIDs from one of my servers. So, all
a user could see would be just a few GUID values and should have one heck of a
time guessing GUID values for other users. But, a well regarded generator of
random strings would be easy to use also. I'm familiar with high quality
random number generation, mostly would want assembler code for the arithmetic,
don't want to try to write Intel x86 assembler to be called from Microsoft's
Visual Basic .NET, would not want to use such a random number generator for
session ID, and am not thrilled about writing my own random string generator.
That's why for now I used GUIDs for session IDs. But I could ask ASP.NET to
encrypt the GUIDs. Then a user could grab the encrypted string and maybe reuse
it but would have to decrypt to see a GUID to guess the GUID sequence and
extrapolate to a GUID of another connected user and then encrypt! Seems a bit
much! Besides, they'd also have to guess the IP address of the other connected
user and fake the IP/TCP/HTTP or whatever headers that report IP address.
Maybe the NSA, some guys in a big basement in China, or some brilliant, bored
wacko in Belarus wouldn't have anything better to do!

For what is stored in session state, I add to that right along as I write the
rest of my Web pages. So I have a class, marked as

    
    
      <Serializable()> 
    

and add properties to it as I want something _persistent_ during the user's
logical _session_.

I read somewhere that Web browsers on smart phones don't support cookies. Good
to learn that this is not correct.

Since cookies are now a privacy concern, I'm still reluctant to ask my users
to have cookies enabled for my site. For persistence a session ID, I don't
need a cookie and can use just a GUID (or a random string) in a hidden field.
For persistence for user ID and password, my site doesn't use those yet!

Thanks for the answers!

~~~
yread
You're welcome. I had a look at your comment history and I sincerely apologize
for calling you confused, I'm probably more confused than you in a lot of
things. Also I appreciate your "long form" style of commenting :)

As for using either in process or SQL Server way of storing the session tokens
- there is also a third way and that is writing your own session storage
provider, it should be relatively easy and have all the advantages of rolling
your own solution and ASP.NET session ID strength
[http://msdn.microsoft.com/en-
us/library/ms178587(v=vs.100).a...](http://msdn.microsoft.com/en-
us/library/ms178587\(v=vs.100\).aspx)

I don't believe you need to do anything special for the password storing (in
browser) to work - just keep the same name or id on the HTML elements which
accept the username and password and the URL of the login page.

An attacker can just fire as many requests as your simplest page can handle
with incrementing GUIDs (not necessarily incrementing by one, GUIDs are made
of some machine identification and current time so there is probably even
smarter way). If any of the requests doesn't result in "Session expired" page,
the attacker has just defeat your session ID because of using GUID. If you go
with the custom session storage you can avoid this problem.

When you store stuff in the HttpSessionState, it gets stored (by default) in
the memory of the process, it will use the custom session storage provider, if
you write one.

I believe that 100% of users accept cookies. But it's true that for storing
session id you don't really need it. Also in the EU we now have this stupid
law requiring websites to inform users that they use cookies...
[http://econsultancy.com/nl/blog/9202-eu-cookie-law-three-
app...](http://econsultancy.com/nl/blog/9202-eu-cookie-law-three-approaches-
to-compliance)

Good luck with the website - you sound like you're just the right amount of
crazy for changing the world :)

~~~
graycat
"Confused" is not the worst I've been called, and at times it's, i.e.,
"confused", been correct!

Thanks for the feedback.

For the link to MSDN, checking my collection of such Web pages, I downloaded
that page on 3/15/2012 as file number 739 from MSDN in my collection of
documentation for ASP.NET, TCP/IP, etc. of the 4000+ Web pages of
documentation I have so far!

Reading some of that Web page again, it looks complicated, more work to make
use of their _provider framework_ than just write my own code.

For using my code for session state store, in a Web page just write early in
the execution of the Web page code

    
    
        result_code = SSS_retrieve( )
    

make whatever use want of

    
    
         Public users_session_state As New SPP_session
    

for an instance of my class

    
    
         SPP_session
    

and near the end of the execution of the Web page write

    
    
        result_code = SSS_store( )
    

Simple.

My code for making session state persistent enough, still available anywhere
in my server farm with no issues about concurrency or locking, and nicely fast
is really simple: So, the session state store is just a little program in
Visual Basic .NET (apparently as good as anything else at making use of the
common language runtime, CLR, and .NET Framework).

The program runs as just a console application started just from a command
line, actually from a short scripting program (in ObjectRexx, my favorite
scripting language until I convert over to Power Shell).

The program implements just a _key-value_ store. To this program, each key is
just an array of type byte; similarly for each value. The implementation is
just via an instance of a .NET collection class, hopefully AVL trees or red-
black trees. There is a second instance of that collection class used for
handling session time outs, as I recall, hard coded at 40 minutes. We're
taking simple, dirt simple, here!

The program just listens on a dedicated (hard coded!) IP port number for a
connection request. Since the program is single threaded, there are no
problems with concurrency or locking. That is, the program serves just one
customer at a time!

From timings, on a single core, 3.0 GHz processor, the program should be able
to do the work needed for a site to send 1000+ Web pages a second. If my Web
site needs more capacity, then just do _sharding_ , that is, in the code for a
Web page, given a session ID, do a look up and find the IP address and port
number of the executing instance of the session state store program that
handles that session ID.

Keep 512 such instances busy, and could have a really busy Web site! With 16
threads and instances per processor, that would be 32 processors which would
fit easily in just two standard racks. A big Web site and session state
handled with just two racks! Nice!

Microsoft has a collection class in storage with scope the 'application',
i.e., all Web pages in one instance of IIS, and I tried to use that storage
for my session state store. The first bad news was that during development
something got confused raising an exception "invalid cast". So each time I
changed the code for a Web page I had to issue Microsoft command

    
    
         iisreset /restart
    

to get everything working again.

It is true that my way of handling session state makes my Web page code look
different.

So far I'm happy with how I'm handling session state.

Thanks for the detail on how the next GUID is generated -- just add 1, which
is less obscure than I had hoped.

So, maybe for a GUID start with the MAC address of a network adapter, use some
time and/or date, and then increment or some such.

If a malicious user wants to break into my site, then they will have to guess
both the GUID of the session ID of a current user and also that user's IP
address. If that is not secure enough, then I can just ask ASP.NET to encrypt
the data in the hidden field. Then a malicious user would have to decrypt to
find a legal GUID, generate some trial GUIDs, encrypt, guess an IP address,
and post the data back to my server. And at that point, all they have managed
to do is to have my server send some confused response to the IP address of
the real user with that session ID. No biggie. Besides, my Web site is not for
a bank or trading Bitcoins, etc.!

For "crazy", it can look that way to others. To me I just saw an unsolved
problem, turned it into a math problem, got a math solution, and wrote some
code. I believe that the problem is important and my solution good. We will
see, at least see if users like my solution.

------
dendory
I tend to like doing: sha256(sha256($password) . $ip)

This encrypts the password and makes the cookie only usable by the IP it was
set for. Then to verify the cookie, since I already store sha256 of the
password, it's trivial to do, without having to store an additional token for
persistence. Of course you can replace sha256 with your fav hashing function.

~~~
atburrow
What if the user gets their session hijacked when they're on a static or long-
term dynamic IP? If the user were to relogin, their session ID would be the
same. I think it would be beneficial to at least store a salt associated with
their session and regenerate the salt when authenticating.

sha256($password . $ip . $random_salt)

You could also regenerate the salt periodically.

~~~
stouset
No. None of these. Please stop. The system is _entirely broken_. No amount of
tweaking is going to fix it.

------
danielweber
Remembering the username _can_ be pretty useful, especially if you find
yourself in a place where you common usernames are taken on other sites and
you have to use different usernames in different places.

~~~
dmckeon
Being reminded of a username could also be helpful if you have more than one
username at a given site - for instance, personal and business accounts for a
bank or credit card site, per-project accounts for a contractor, etc.

------
scotty79
Or you can do this:

Client generates random value, puts it into cookie and passes it to server
along with valid credentials. Server remebers it for this user and whenever at
later time it sees this value in the cookie it logs in this user. Server
forgets this value when this user logs out and after some time.

If client does't have javascript or you don't trust randomness it can generate
you can create this value on server and make the server set this cookie when
it responds to login.

~~~
brown9-2
What is the point of generating this value on the client? The second scenario
you describe seems to work the same, minus the need to generate values on the
client, with the same outcome.

~~~
scotty79
I guess no point. Pick the one that you feel better with.

~~~
scotty79
Also the server should keep it hmac-ed in case db silently leaked.

------
stouset
There's a lot of misinformation in this thread, so I'm going to describe best
practice for this sort of thing.

    
    
      1. The client authenticates, and asks to be remembered.
      2. The server generates a cryptographically random token of at least 128 bits in length. This token is *never* directly stored server-side.
      3. The hash (or, possibly, a slow-hash) of the token is saved in the database along with a time of expiry
      4. The non-hashed token is sent to the client as a cookie completely independent of the session cookie
    

When the client visits the website:

    
    
      1. The server checks for the presence of the remember-me cookie
      2. If the cookie is set, it is hashed and this hash is searched for in the database (and filtered to tokens with expiry times after now)
      3. If the user is successfully logged in, the old token is deleted from the database. A new token is generated and sent to the client by the previously-described process
    

Now for a little bit of explanation.

This process completely isolates the authentication token from the session. If
a token is somehow intercepted or discovered by an attacker, it is _only_
usable for a single session. Such tokens should never be allowed to serve as
permanent entry points into a user's account.

The token is never directly stored server-side. This confers two benefits.
First, these tokens should be considered password-equivalent — if someone
manages to steal your table of remember-me tokens, they would be completely
unable to use them to log into a user's account. Second, this prevents timing
attacks; if you simply looked for matching tokens in your database, an
attacker can (shockingly simply) use timing information to guess a user's
remember-me token in O(n) time.

~~~
jessaustin
I don't see why you have to store the hash of the token. You know the key you
used for HMACing, why can't you just check that the cookie contains a valid
hash of the rest of its data (which is as extensive as you need: session id,
expiry, IP, whatever)? To prevent the use of old sessions just make the
session id a counter. A single session counter per user is probably less
hassle (and more useful) to store than the whole hash.

~~~
stouset
To avoid the problem of storing the token's hash, you have introduced:

    
    
      * parsing a structured cookie, vs a meaningless 128-bit string
      * securely storing and managing a secret HMAC key (which may be used to forge or modify credentials)
      * securely verifying an HMAC using a constant-time string comparision
    

So what, exactly, is the benefit of your proposal over mine? You've removed
the (useful) distinction between an authentication token and the user's
session. You've introduced significant additional complication and moving
components. And you've increased the attack surface for security
vulnerabilities. For what?

Doing all that to store a 32-bit integer is somehow _less_ hassle than hashing
and storing a 128-bit string?

~~~
jessaustin
_you have introduced: parsing a structured cookie, vs a meaningless 128-bit
string_

You're going to need some logic for dealing with session, user, etc. metadata.
Stipulating that parsing metadata out of a cookie is in some sense harder than
reading it from a DB, keeping it in the database requires more storage (in
_addition_ to the 128-bit hash), more syncing among the various masters and
slaves, and higher security. (An attacker who gets a DB dump can't see account
metadata that isn't stored in the DB. Sure I'm storing a counter but what can
he do with that?)

 _securely storing and managing a secret HMAC key_

How do you run an online service without doing key management? Whatever
techniques you use for your other keys, use them for this key too. It isn't as
if we need a separate key for each user.

 _You 've removed the (useful) distinction between an authentication token and
the user's session._

I don't understand this claim. If I want to generate a new token for the
current session, what's stopping me?

 _And you 've increased the attack surface for security vulnerabilities._

Because HMAC collisions are easy now? I've moved some things around, but I'd
say there is a tradeoff between the CAP costs of the "store everything"
technique you propose and the slightly more involved validation process I
describe. It's cool if you prefer your method for your situation, but can't we
admit that "I'm going to describe best practice" was a bit overstated?

~~~
stouset
> Because HMAC collisions are easy now?

When you get the details wrong? Relatively so. And even experienced people get
this shit wrong more often than they get it right. Rails had this
vulnerability. Google's KeyCzar had this vulnerability. The average, non-
crypto-enthusiast has effectively zero chance of getting this right out of the
box.

Comparing server-computed hashes is inherently safer and less error-prone than
comparing client-controlled HMACs.

    
    
      * https://github.com/rails/rails/commit/5e6dab8b34152bc48c89032d20e5bda1511e28fb
      * http://rdist.root.org/2009/05/28/timing-attack-in-google-keyczar-library/
    

> but can't we admit that "I'm going to describe best practice" was a bit
> overstated?

Not when it _is_ accepted as best practice.

    
    
      * http://fishbowl.pastiche.org/2004/01/19/persistent_login_cookie_best_practice/
      * http://stackoverflow.com/questions/549/the-definitive-guide-to-forms-based-website-authentication
    

The only difference between my description is I do not store the username with
the cookie; it is unnecessary and confers no discernable security benefit. I
also avoid associating multiple remember-me tokens with a user, so an attacker
who intercepts one must use it before the user next logs in.

Is your approach _wrong_? No. But it is more difficult for the average
programmer to do securely and correctly, and confers few (if any) real
benefits.

~~~
jessaustin
Thanks for the thoughtful responses!

------
thesis
Can someone explain how the example of the JSON encoded cookie could be used
for XSS?

~~~
yahelc
> What this means is that client script can access those cookies which means
> that if you can get a piece of XSS onto the site – just as you can on the
> Aussie Farmers site – you can steal cookies containing passwords if you can
> get a customer to load the XSS payload

The author is saying that, putting the password in a cookie means that, if
there is an XSS vulnerability somewhere, it can be trivially used to steal
usernames and passwords, since the XSS can be used to inject code on the site
that can grab the values from document.cookie and append them to a hidden
iframe.

