2

I was intrigued by the discussion of this SO question as well as the accompanying blog post. I'm trying to better understand the mechanics of the two systems, and one of the questions I came up with is how much worse is it to have a token stolen vs. a session ID?

Here's what I understand so far, and please do correct me if I'm wrong:

A session ID is an opaque reference to actual session data stored on the server. It is safe insofar as it is random enough to not be guessed easily, and the data is safe because it is not directly accessible by or beholden to the front-end. The session ID is stored in a cookie to simplify authenticated requests.

An authentication token is a plaintext segment of JSON user data with a cryptographic signature that verifies the data's integrity. It is tamper-proof because of the signature, so no one can simply come up with their own token. The data it grants access to is safe on the server, except of course what is present in the token (which even then can be encrypted if need be). The token is also often stored in a cookie to simplify authenticated requests.

So here is what I do not understand. The way I see it currently, it seems just as likely that a token be stolen as a session ID, e.g. anyone breaking past my SSL and viewing my token would be able to view a session ID as well. Either event gives the attacker complete access to my account and all associated authorization. So in terms of the event likelihood and the resulting damage, is an authentication token really any worse than a session ID, as the article claims?

The one thing I could see potentially being worse for tokens is if the signing secret were somehow found out, in which case the attacker can do anything with anyone's account, rather than just mine. However I almost want to relegate this to the reasonable unlikelihood of someone first breaking RSA, in which case they can get past SSL, and then what good is a session ID anyway?

6
  • It depends. An authentication token like a JWT can contain a session ID as well, so it adds an additional layer of security. Especially if you follow best practices, don't store sensitive data in it, encrypt it (not only sign it), and use a strong encryption. Oct 23, 2019 at 22:15
  • I wouldn't call a JWT an authentication token. It's a signed message that often contains identification. A third party would then authenticate the origin server by verifying the signature and, based on their trust of the origin, might trust the identification of the token's bearer... but you're not authenticating the bearer in this; you're just identifying them (which is often good enough to give them authorization).
    – Ghedipunk
    Oct 23, 2019 at 22:20
  • And a session ID is also just that: An identification. Its security comes from being short lived and random, is often given out after authentication, and the ID is often the basis for authorization as well. (Web best practices say to change the session ID's nonce any time the authentication changes; such as when logging in or out.)
    – Ghedipunk
    Oct 23, 2019 at 22:23
  • @Ghedipunk JWTs can have multiple applications. In practice it is not more and not less than a way to transmit a JSON object. It can be used as an access token or authentication token - for example in stateless applications. It can also be used for ID tokens. Oct 23, 2019 at 23:58
  • So is a session ID any safer than a token, if the latter so happens to be used in an authentication/authorization context?
    – Bondolin
    Oct 24, 2019 at 13:00

1 Answer 1

3

I'm the author of the blog post you referenced, as well as the answer to the SO question you linked. Here are the answers you are looking for.

A session ID is an opaque reference to actual session data stored on the server. It is safe insofar as it is random enough to not be guessed easily, and the data is safe because it is not directly accessible by or beholden to the front-end. The session ID is stored in a cookie to simplify authenticated requests.

Kinda. When a session ID is stored in an httpOnly cookie, the cookie itself is cryptographically signed (and can also be encrypted). JavaScript code can never access an httpOnly cookie (the httpOnly flag makes it impossible for JS code to view the cookie).

An authentication token is a plaintext segment of JSON user data with a cryptographic signature that verifies the data's integrity. It is tamper-proof because of the signature, so no one can simply come up with their own token. The data it grants access to is safe on the server, except of course what is present in the token (which even then can be encrypted if need be). The token is also often stored in a cookie to simplify authenticated requests.

Kinda correct, again. Most tokens are stored in HTML5 LocalStorage (in JavaScript) because they are simply too large to fit inside of an httpOnly cookie. Cookies have a maximum data storage size of 4kb. If your token is larger than 4kb (which most are, since people use them to carry user information), then you must store them elsewhere. And the simplest way to store them outside of cookies is... you guessed it, LocalStorage!

Unfortunately, this has serious side effects.

So here is what I do not understand. The way I see it currently, it seems just as likely that a token be stolen as a session ID, e.g. anyone breaking past my SSL and viewing my token would be able to view a session ID as well. Either event gives the attacker complete access to my account and all associated authorization. So in terms of the event likelihood and the resulting damage, is an authentication token really any worse than a session ID, as the article claims?

The likelihood of someone stealing a token from LocalStorage is far higher than that of a secure httpOnly cookie being stolen. And it's also substantially easier for a stolen token to cause mayhem because:

  • A stolen token can be used by an attacker to impersonate the user from anywhere (the attacker's network, proxies, etc.)
  • If an attacker is able to inject JS code onto your website, this won't allow them to access cookies, however, so that means the attacker would only be able to run JS code to 'impersonate' a user while the user is still on the website. Because once the user closes the tab in their browser, the JS code the attacker was running will no longer run.

There are vastly different abuse scenarios here.

The one thing I could see potentially being worse for tokens is if the signing secret were somehow found out, in which case the attacker can do anything with anyone's account, rather than just mine. However I almost want to relegate this to the reasonable unlikelihood of someone first breaking RSA, in which case they can get past SSL, and then what good is a session ID anyway?

You're right that if an attacker can figure out the signing key, then they can tamper with an existing token (or create their own fake ones). But, this is highly unlikely because signing keys must be kept server-side. If you accidentally leak your signing key, for example, that's essentially the same thing as sharing your sever password with someone: obviously you're going to have a bad time.

The main difference here is in how the abuse can unfold. The article I linked to above is another post I wrote which details this in much more explicit ways. Hope this helps!

3
  • JWTs in practice typically are much smaller than 4kb. Never store sensitive information in local storage (I've listed the reasons for that in this answer: security.stackexchange.com/a/211282/148430). The safest option to store them is in the cookies with the proper cookie-flags set, together with a proper CSRF-protection. Oct 26, 2019 at 8:53
  • I'm the author of the post you link to in your research =)
    – rdegges
    Oct 27, 2019 at 17:17
  • That's awesome, then I don't need to tell you! My point is that you don't have to store a token in local storage, and you shouldn't. Therefore that's not an argument against using them. Oct 28, 2019 at 0:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .