
Ask HN: How authentication works at HN? - abhas9
Whenever I upvote a story, HN sends a request of type: `vote?id=12390292&amp;how=up&amp;auth=XXX`
`XXX` is different for each story in the page.<p>I checked the cookies using dev tools. There is a cookie called user whose value is &lt;myusername&gt;&amp;[YYYY]<p>Here `YYYY` is a different token. Can anyone explain what is going on with all these tokens and why are they all different?<p>PS: Inspired by http:&#x2F;&#x2F;blog.watchandcode.com&#x2F;2016&#x2F;03&#x2F;17&#x2F;the-single-piece-of-javascript-on-hacker-news&#x2F;
======
niftich
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/](https://www.w3.org/TR/capability-
urls/)

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

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

[4] [http://stackoverflow.com/questions/18751565/detecting-
rails-...](http://stackoverflow.com/questions/18751565/detecting-
rails-4-session-cookie-tampering)

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

~~~
niftich
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_(...](https://www.owasp.org/index.php/Cross-
Site_Request_Forgery_\(CSRF\)_Prevention_Cheat_Sheet#Synchronizer_.28CSRF.29_Tokens)

