
A practical proposal for migrating to safe long sessions on the web - kinlan
https://developers.google.com/web/updates/2016/06/2-cookie-handoff
======
bryanlarsen
Note that the article buries a much easier way to deal with this problem:

"some websites don’t verify the user’s authentication on each request (i.e.
there is no way to revoke the session cookie once issued)"

Which implies that if you do verify the session on the server and have a
mechanism for invalidating these sessions on password change, etc, you can
just use very long cookies and you're done.

There are very good reasons for doing that anyways, so no need for this hack.

~~~
mark242
You don't need to verify the session on the server all the time. Session
verification very quickly becomes a bottleneck to app performance, since
you're doing a separate database/cache lookup for each rest endpoint request.
It's far easier, and provides much better performance, to just
cryptographically sign a cookie that says "I'm this user".

This is where the short/long-term cookie comes into play, and is actually a
neat idea to take care of the "how do I periodically check that the user
hasn't logged out/changed their password/invalidated their sessions/etc"
problem that the cryptographically-signed cookie brings up.

~~~
bradleyjg
That sounds like a time-space trade-off to me. I'd think cryptographic
signature verification would be more expensive computationally than a cache
lookup and compare, but not require much space. Also, and maybe this is the
key part, it would be more distributable since you don't need shared state.

~~~
mark242
Yes; and CPU is cheap as hell. Round trips to a cache are _expensive_.

~~~
carterehsmith
That depends on where your cache is.

If your cache is on a separate box and you have to make a network round trip,
yeah it is expensive.

But if your cache is in-process, the access is cheap.

------
zeveb
I wonder why this couldn't just be handled with two cookies, period: one a
short-lived authentication token; one a long-lived revalidation token.

The former could be self-certifying (i.e., trusted if it's properly signed,
with no auth service round-trip); the second could require a round-trip to the
auth service). On a request, when the server see that the short-lived token
has timed out, it checks the long-lived token; if still valid, then it
reissues a short-lived token and sends it as a cookie value replacing the old
short-lived token.

If multiple requests are in-flight, no matter — short-lived tokens require no
session state, so all that happens is generating a few too many signatures.

Am I missing something?

~~~
StavrosK
Isn't the original problem that someone could steal the long-lived cookie in
the first place?

~~~
crashedsnow
The intent is not to provide an "unstealable" token, but a revocable one. You
can't (don't need to) revoke the refresh token but you can revoke the access
token by disallowing refresh.

------
azdle
I don't really understand what the service worker that makes an extra network
request adds here.

Why not just have the code that validates the session just do an `if
(short_session != valid) { lookup_long_session_in_db() }` then return a fresh
short session cookie with whatever request you're currently handling?

~~~
dpark
1\. This assumes that every page you might make the request to can issue auth
tokens. This might be fine for small sites where auth isn't a concern (but
then just issue a long-lived token and don't bother with all this), but for
larger sites, capability to issue auth tokens is generally isolated from the
rest of the services.

2\. Your pseudo-code returns a legitimate short session cookie in response to
gibberish. I'm hoping that this is just because you elided a lot of detail.

~~~
azdle
1\. Why does every end-point being able to refresh a token (or whatever you
want to call it) imply that auth must not be a concern? I will fully admit
that I've never worked on really large scale web services, so hopefully that's
not a super obvious thing.

I would think that having all pages be able to handle auth is just a
architecture question. Maybe I've just been too deep for too long in writing a
webserver in Iron [0], but the way you handle auth in it, by using middleware
and wrapping any endpoint that needs auth with an auth handler, makes doing
something like this trivial.

2\. Definitely left out a lot, I mean it doesn't really return anything at
all. Just meant it as some shorthand pseudo code to make explaining it
shorter. :)

[0] [https://github.com/iron/iron](https://github.com/iron/iron)

EDIT: Actually now I'm not sure if you're talking server-side or client-side,
but I think the argument still stands. I was assuming auth "tokens" could
actually be cookies, but even if not, your API library just needs to have a
check to see the the request returned updated auth. It's still just in one
place, handled in all calls, rather than just the single call that would
otherwise handle it.

~~~
dpark
I was referring to server side. If you're really serious about security, you
probably want to isolate the login process to a dedicated server. If your web
server is breached, do you really want your auth keys leaked? And do you
really want access to your user's creds available en masse to the breached
server?

If you're running a small scale service, you're unlikely to build a dedicated
login service. If you're running a large scale service, you probably should.

Edit: Based on Thomas's answers here, I am wrong about this, so I guess take
my thoughts with a grain of salt.

------
mcculley
> We all love how native apps will ask you to login only once and then
> remember you until you tell them you want to log out.

I wish that were true more often. There's a handful of native apps that don't
remember my credentials and I have to go look them up on the desktop in my
password manager. For example, I installed Pokémon Go but haven't looked into
it further because I don't have my Google password memorized; it's a randomly
generated password that I expect my computer to remember for me.

It seems like every native IoT widget controller I try wants me to remember
more credentials.

~~~
NickBusey
Get a password manager that syncs to your phone. I'd be completely lost
without it. I love 1Password for syncing. Just pop it open, copy/paste, done.

~~~
j_jochem
I use KeePassX and Keepass2Android, with the database file stored on Dropbox.
It's free and runs natively on Linux.

~~~
StavrosK
Since upvotes are invisible, I will comment to say I second this.
Keepass2Android is a amazing and I love this solution, even though I've always
otherwise hated password managers.

------
cpeterso
You don't necessarily need to authenticate every request. For example,
Amazon.com allows a user to be "semi-logged in", but forces you to
authenticate yourself when doing something like making a purchase.

------
merb
That's what we did except that the short lived token is a GWT no in a Cookie.
While the Long Lived Hash is a Cookie with a database. But the Cookie will
only live for the session of your browser. Mostly we only query the database
every 5 minute, cause of that.

Actually we also have a workaround to support Safari by trying to put stuff in
LocalStorage that tells the other Tab that it recently got a new token and so
on.

------
mattbroekhuis
So is this like oauth2 refresh token?

------
kiliancs
In the long run it would be better to find a standard way of doing this so
that browsers implement it without the need for a worker initiated from JS.
Static pages could benefit from safe long lived sessions as well.

------
Kequc
I've explored this in the past. Wouldn't it be possible to simply set two 1yr
cookies one at the mid-expiry point of the second. Then re-set the first when
it expires and vice versa?

~~~
sp332
But if the user resets their password, it should log out all the user's
sessions. But you have to wait for the cookies to time out before they are re-
authenticated. (Or make a check on every request to see if the password has
been changed, which is just a pain.)

~~~
bryanlarsen
You don't check on every request to see if the password has changed, you check
to see that the session is valid on every request. You should be doing that
anyways.

Then all you have to add is a way for password changes to invalidate the
session.

~~~
azdle
The thing is that the way that a session is usually "validated" these days is
to just store a userid in some serialized format then encrypt that and send it
off as a cookie that expires in a relatively short amount of time (and
hopefully put the expire time in the encrypted message too). Then the server
just has to try to decrypt the cookie and if it results in a valid userid then
the session is valid. This way you don't cause an extra database request for
every user request.

I'm not saying it's good or secure, but it's the way I often see it
done/suggested to be done.

------
projectramo
I just hope that that other tabs cannot see the cookie within a tab. Or if
there was some other way of isolating identity.

My concern is privacy.

~~~
sp332
It's just a cookie. It works like every other cookie.

~~~
projectramo
Yeah, but I mean before they implement this scheme, I hope they modify the
browser (or someone comes up with one), so that you can pick which group of
cookies are accessible within different tabs.

With apps, I know that this app doesn't know my identity from that app unless
I explicitly give it permissions.

~~~
sp332
Firefox is starting a project on this, it's still in research stages though.
[https://blog.mozilla.org/tanvi/2016/06/16/contextual-
identit...](https://blog.mozilla.org/tanvi/2016/06/16/contextual-identities-
on-the-web/) In the meantime, you can use different user profiles in Chrome or
Firefox, but they work per-window not per-tab.

~~~
projectramo
Great news. Thanks. Didn't realize that Chrome and Firefox do that on a per-
window basis. I browse everything in incognito mode.

