6 ms·
As someone who's a little behind the times here, can someone explain the distinction between a session ID and a token? I'm referring to this passage: > Session
by wk_end 4y ago
As someone who's a little behind the times here, can someone explain the distinction between a session ID and a token? I'm referring to this passage:
> Sessions were built on top of cookies. The server kept context about the user's "session" [...] and indexed it with a random session ID. The session ID was sent as a cookie and for each subsequent request, server looked up the session state.
> Then came mobile apps and single-page JavaScript apps, and plain cookies and sessions started being inadequate. Developers started using tokens, where a token was an unguessable random string that behaved like an identity card. Possession of it proved your (client's) identity (bearer token).
Both a session ID and a token are random strings clients send with requests to indicate who they are. Why were sessions inadequate, and how do tokens solve this problem?
- tyingq 4y agoI think they are trying to point out that a "session ID" is typically a key into session data stored on the server side, where the token is usually not just a key, but all the session data stored client side. With signing and other mitigations intended to keep that from being dangerous. >Why were sessions inadequate I suspect there are more reasons, but one is likely CORS and the tendency for the auth infra to be separate from the app infra.
- WA 4y agoSession ID: Server has a list of valid sessions. Compares your session ID to its own list. Have session token? Access granted. JWT: Server doesn't keep a list. Someone comes with a JWT, which is signed by the server. Server grants access purely on the fact that there is a signed token. JWTs are useful if you don't want to sync the server-side list of valid session ids (many microservices for example).
- deleted 4y ago[deleted]
- 0x457 4y agoThat's not entirely true. Session cookie doesn't have to be opaque and can be signed and encrypted. That's how RoR been using it for long time. Realistically, you only need to make sure that an unexpired and verified session hasn't been revoked. Opaque sessions are smaller, though.
- adolph 4y ago> Both a session ID and a token are random strings clients send with requests to indicate who they are. Why were sessions inadequate, and how do tokens solve this problem? JWT tokens are not random strings. They contain claims about the bearer that are cryptographically signed to prevent the bearer from altering them. https://jwt.io/introduction https://jwt.io/introduction
- stefs 4y agoyes, but they ask about the difference between session ids and bearer tokens (NOT jwt).
- ehutch79 4y agoThere's nothing actually wrong with session ids in a cookie. It's that JWT was the new hotness and a buzzword. Now there's a lot of cargo culting around them. JWTs are a signed claim that your service can trust, and use for authorization after just verifying the signature. A session id, you need to take the id and look up your session in some mechanism on your backend. JWTs are great for different services saying 'yes, this connection is actually this person, trust them.' Inter-server communication, oauth, etc, are good examples. Session ids only work for the issuing service. Django sessions, php sessions, etc, are good examples. One of the biggest problems with JWTs is that a lot of people are ONLY storing a user_id, or a session_id in them. On the server the decode the token and proceed with the standard session_id workflow, still hitting the db. Invalidation is another thing. You still end up hitting the database, and if the JWT is only ever used by your own service, why bother? Then there's people just shooting themselves in the foot and not actually signing them and just trusting them without any crypto signatures.
- xtracto 4y ago>Then there's people just shooting themselves in the foot and not actually signing them and just trusting them without any crypto signatures. You would be surprised, a very short time ago I saw a (pretty large/common) web FinTech service provider that included the private key to verify the signature encoded within the JWT. It was SHOUTING to be hacked. I don't understad how people can be so irresponsible.
- Salgat 4y agoYou mean the public key? The private key is what's used to sign tokens, the public key is used to verify the signature and can be freely shared. Or maybe you mean they used a symmetric key and shared that?
- ehutch79 4y agoI'm pretty sure he meant they were putting the private key in the jwt. People do some dumb stuff. And the dunning kruger effect is all too real.
- jmartrican 4y agoThe token refers to an API token or an OAuth token. These tokens are what backend systems require to allow a user to access data. The problem is that these tokens should not be used by your JS code (they should never make it to the browser for security reasons). So how exactly does a user access their data if the front-end code running on their browser does not know the token? That's where sessions come in. The webapp hosting the front-end JS code (for example Node.js or Java-Spring) creates a session whenever a request is made. When the user logs in, their token (which the server retrieves though whatever authentication method is being used) is stored in the webapp as session data. That is to say, for each session, the webapp can store information about that session.... e.g. the token. The token is then used by the webapp to access the user's data via the API calls to the backend. The backend, will then use the token to verify the user has access to the requested data (or the requested resources).
- ilovetux 4y agoThe way I see it is that session ids are handed out by the server as you login and revoked when you log out, so while it would be advisable for this session ids to be truly random there is no guarantee that this is the case. In truth I have seen sessions stored with an autoincrement id meaning that if you were to get a session id you could, in theory, just use the number before yours and highjack someone else's session. A bearer token, in my experience, is a cryptographically generated random key (presumably unguessable) which the user can create, use and revoke at will.
- stefs 4y agoif someone is dumb enough to use guessable session ids (instead of, e.g. uuids), then they'd be also dumb enough to use guessable bearer tokens.
- noisem4ker 4y agoTo prevent guessing, the session ID must be cryptographically signed (and possibly encrypted) by the server, with the signature appended to it. Upon receiving it back from the client, the server needs to check it wasn't tampered with. This guarantees an attacker may not simply generate random session IDs until someone else's is found and their session is hijacked, because they wouldn't know how to fake the signature.
- slowmovintarget 4y agoIf you have a "true microservices architecture" as the article comments, you have a time budget for every request from the front end, through the graph of calls on the back-end. Let's imagine a call-graph budget of 300ms. Every hop after the request lands on the back end takes a bite of that. Let's imagine a straight stack of calls three deep with no branching. Front-end makes a RESTful API call to Service A. Service A calls B, B calls C, and C queries a database. Diving down to the bottom, the database call + networking will take 50ms (it's a big query), service C spends 5ms filtering, and another 10ms reorganizing the data into its response format and returns. 65ms eaten. Service B deserializes (3ms) and acts on the data (10ms), then serializes the response (2ms). 80ms eaten. Service A gets this back and chews on it for a bit to put it into shape for the front end. There's also a layer of proxies and caches the request and response goes through, so another 20 ms here. 100ms! Great! We're under budget (because we're not counting network latency back to the UI)! Now imagine, that for every one of these hops, we add a 10ms call to a session service, and processing time (hopefully tiny) to review, and error handling. We've also only covered happy path, we've not considered call retries, branching calls to resolve additional data, each with a +10ms check for that session. Now that time budget is starting to chafe. Validation of signed tokens with claims eliminates that 10ms tax on every call, and it is a big deal. How do I know? I work on a system with hundreds of microservices. We use JWTs for back-end authentication. Thank goodness the article clears us to use JWTs. :)
- BigJono 4y agoThink you misread, they were asking about the difference between a session ID in a cookie, and a bearer token. Not a session ID and a JWT. With a bearer token each microservice still needs to call out to an auth service to validate the token, right?
- slowmovintarget 4y agoFunny thing about the terminology, JWT is just one kind of bearer token. The phrase bearer token in the first place simply means that if you have the token, assume you are who you say you are. (It's also shorthand for passing in the authorization HTTP request header with type "Bearer: ") If you have an opaque token, then yes, you save nothing and still require a call to a central service.
- stefs 4y agonote: most other answers compare sessions to JWTs, not the bearer token. i'm guessing you're asking about sessions vs. bearer tokens, not sessions vs. JWT. ---- i've been wondering the same thing. the only explanation i have are life times and explicitness. sessions are usually based on the browser session, i.e. cookies without an explicit expiration date are invalidated if the browser is closed. also, session cookies are always sent on any request (simplification) to the matching hosts. this means you have to re-login to get a fresh session every time you reopen the browser (unless you set an expiration date for the session cookie i guess). i guess bearer tokens have a very long life time independent from the browser session and the user can invalidate them manually through some settings option. moreover, the token is added to the relevant backend calls manually (instead of automatically by the browser). i'm not sure though how a bearer token would prevent CSRF. imo it's roughly the same as a session with a long expiration time.
- jdmichal 4y ago> i'm not sure though how a bearer token would prevent CSRF. imo it's roughly the same as a session with a long expiration time. You said it yourself. Bearer tokens have to be added manually, while cookies are automatic. So simply issuing a request to a backend will not include the bearer token, and you (as the attacker) have no way of actually gaining that token from your cross-site context.
- stefs 4y agoas far as i understand, that's not necessarily the case; a malicious CSRF triggers a completely valid request by tricking the user to open an url while logged in. imo the principle works for both sessions and token based auth as long as the token based auth frontend application exposes an url that triggers the action. ok, now that i think about it: providing an url that triggers the (malicious) action is a necessity for session based auth but only a possibility in token based auth.
- dwaite 4y agoXSRF is of the class of confused deputy problems; the site expects that the browser will only let the end-user that was authorized perform actions, but the reality is that the browser on its own has no concept of user choice or consent for web content. The hypermedia aspect means that content by third parties can by default initiate actions, which would override the first-party presentation by the site for user consent. So XSRF protections make it so that third party content cannot successfully initiate those actions. Prime examples are: - SameSite cookies, where the initial request from another domain will not have cookies presented. - The local content adding session-related parameters unknown to third parties, such as an OAuth access token in a header or a session cookie repeated as a form parameter. These protect against the third party being able to initiate actions and pick up any background implicit authorizations being provided by the browser, such as session cookies or HTTP Basic authorization headers.
- 9dev 4y agoI think the easiest explanation is this: Session IDs are bound to cookies from a given origin. Thus, every request needs to include the original cookie, and have the same origin, to transport authentication data. But cookies cannot be accessed from JavaScript, only be sent implicitly if these things are true. This made it difficult to work with separate hosts (www.my.app vs. api.my.app). In contrast, Bearer tokens are explicit: JavaScript code can use and attach them to requests as appropriate, thus allowing for more control. The also are a little easier to work with (no reason to keep a cookie jar, stateless stuff works). JWTs in turn aren't simply random strings anymore -- they contain some claims about the bearer, which are cryptographically signed, so whoever receives the token can be sure the claims haven't been tampered with. This allows for very powerful, interconnected services -- but most people use them to pass a session ID around, so... here we are :)
- qabqabaca 4y ago> This made it difficult to work with separate hosts (www.my.app vs. api.my.app). This is still possible with session cookies if you use wildcard origin cookies i.e. *.my.app
- GoToRO 4y agoSession IDs were short, so it was easy to randomly guess them. You would get access to some random account. Also randomly generating them would result in colisions if you had a lot of traffic.
- AndrewStephens 4y agoIf your session Ids were short enough to be guessed then you were doing it wrong. The simplest thing to do is just use a unique GUID as a session id but a sufficiently large random number would do just as well.
- GoToRO 4y agoAt first they were short, and you could get one to see the format and then just try to enumerate some random numbers around that value. Without rate limit for the requests, it worked.
- bradstewart 4y agoIt's a question of cookies vs HTTP headers. Cookies are hard to use with CORS (when using backend-as-a-service stuff like Firebase, in particular) and/or mobile apps. There's really no difference between a random session id and a random token. But people typically think "session id == cookie" and "token == header". More secure session cookies are also HTTP-only, which means JavaScript code can't access them. Which can be a security feature in a lot of cases, but makes SPAs harder.
- 0x457 4y agoI think it came from misunderstanding a lot of things by people making SPAs... Session cookie is invisible to JavaScript, so handling unauthenticated state is a bit weird. Bearer token is visible to JavaScript, so SPA can make some assumption about authentication status. However, it still must handle 401s because token could have been revoked or expired (JWT solves the expired problem). You also could encode some metadata like username and email and instead of having a single round-trip to fetch it once, now you will be sending kilobytes of cookies with every request. CORS is a black magic to them. How to properly set cookie is also back magic - who would know that you can set cookie in way that would include subdomains, so it will be sent to www.acme.org AND to api.acme.org. It was also weird to set a session cookie on outgoing requests when service a talks to service b.
- LoganDark 4y agoSessions are a unique identifier that index into some server-stored data, which requires the server to store that data. Tokens include the data itself (along with a signature that verifies it's actually from the server). For example, Discord bot tokens include the user ID of the bot they're associated with. So do user tokens. With sessions, you have to keep track of every client that may be used to access an account. With tokens, those clients self-identify. You have to store less. Some services unify multiple clients into one session but this is uncommon in my experience.