back
▲ 5 points

Ask HN: How authentication works at HN?

by abhas9·10y ago·2 comments·view on hn ↗
Whenever I upvote a story, HN sends a request of type: `vote?id=12390292&how=up&auth=XXX` `XXX` is different for each story in the page.

I checked the cookies using dev tools. There is a cookie called user whose value is <myusername>&[YYYY]

Here `YYYY` is a different token. Can anyone explain what is going on with all these tokens and why are they all different?

PS: Inspired by http://blog.watchandcode.com/2016/03/17/the-single-piece-of-javascript-on-hacker-news/

2 comments
For a voting URL, you want some value that the server can calculate based on info it has, and that's sufficiently large to not be brute-forceable, and sufficiently unpredictable to not be enumerable. They are 'capability URLs' [1] like a private Google Docs link, or a 'click here to reset your password' token. So 'auth' parameter in the URL is likely the output of a deterministic function of the user and a server-side secret, and possibly a time factor; you can accomplish this with an HMAC.

HOTP [2] and TOTP [3] are two concrete schemes that use this method and truncate to a human-friendly size at the end to use it as part of a challenge-response, but you don't want to truncate this here because then the range of values would be brute-forceable. So it's likely just the output of a LARGE-HMAC(secret-key, MixingFunction(user, timewindow)). Or, if time isn't present, then LARGE-HMAC(secret-key, user).

Since the voting URLs are server-generated, the Cookie value must be unrelated. Logging in with a web browser, copying the cookie, and mimicking the same cookies with curl, I'm logged in with curl, but changing either my username or my token I'm not logged in. The opaque value in the cookie is consistent with what you'd expect from a Session ID, which is not surprising. I'm speculating, but the addition of the username may serve as a countermeasure against session guessing attacks (like, being able to quickly distinguish a tampered Session ID from a good one, like these other apps try to [4][5]), or may simply be an implementation detail.

[1] https://www.w3.org/TR/capability-urls/

[2] https://en.wikipedia.org/wiki/HMAC-based_One-time_Password_A...

[3] https://en.wikipedia.org/wiki/Time-based_One-time_Password_A...

[4] http://stackoverflow.com/questions/18751565/detecting-rails-...

[5] https://github.com/expressjs/session/issues/176

After more testing, I was incorrect about the voting URLs being capability URLs, because you need to be logged-in to vote. True capability URLs don't this, because merely having the URL entitles you to all the access.

This makes the 'auth' parameter in the voting link a CSRF token [1]. A different site wouldn't be aware of the token, but might be aware of the rest of the URL (Post ID, vote direction). By requiring a large, unguessable token to also be provided along with a vote, a third-party site cannot naively issue CSRF to vote on a particular story on a user's behalf.

[1] https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(...