Token vs Session

JWT or Session Authorization?

First, why do you need authorization after you have been authenticated on a website by logging in using your username and password? Because HTTP is a stateless protocol, so the next request you (the client) make to that same website (server) (maybe clicking an internal link after logging in) the server has no idea who you are. To the server, all it sees is a request to access a protected resource it has from your IP address. It does not remember that you are logged in already, so it would either deny access or make you enter your login information yet again. Each HTTP request is treated as a fresh start, even after you login.

Remember, all stateless means in this case is that each HTTP request is treated as independent, it has no knowledge of previous HTTP requests. Since HTTP is stateless, there needed to be a way for the client to remain logged in and not have to enter their username and password for authorization and authentication every single HTTP request.

HTTP

The HTTP does have a header you can use for the this, the “Authorization” header. HTTP does not remember what you put into this header, the client must do that each time a request is sent. You can also create your own header and put whatever you want inside it, in this case it would be your authorization method.

So the client and server had to come up with a way to keep track of who was authenticated already and keep them authorized on the server. The main way of doing this is having the server send sosuccesfullyhe client after the client successfully logs in (authentication), and have the client send the item back along with each HTTP request to the server. The server could just look at the item from the client, and verify that it was the item it sent to the client, allowing access (authentication) if so. All this would take place under the hood, the client sitting at their laptop browsing the web would have no clue any of it was happening behind the scenes after they logged in.

Token types, advantages

Simple Web Tokens, SWT
Security Assertion Markup Language Tokens, SAML
JSON Web Tokens, JWT

JWT’s do have some big advantages over other authorization method such as session ID’s stored on the server. Let use say there is a big company, and they offer two different services online. Maybe booking flights, and booking cruise ships. Each services is pretty extensive, and requires separate servers. The user does not know this, however, and when the visit the company website they login to book a cruise. After booking the cruise, they want to book a flight to the cruise departure port. So they navigate on the same website to the flight booking section, where they are asked to login AGAIN.

Why? Because the company is using session ID’s, when they logged in to book the cruise ship, the cruise ship booking server created and stored the session ID on the server and sent it back to the user. Now every time the user sent a request that had to do with cruise ships, the cruise ship booking server would check the session ID sent by the client against the session ID it had stored, and allow the user to continue. When the user switched to book a flight, it sent the session ID to the flight booking server. The flight booking server checked the session ID sent by the client, and it matches nothing it has saved. Because only the cruise ship booking server created and saved the session ID, the flight booking server has no knowledge of it. So the user is denied, and has to login yet again.

Now, you could create ANOTHER server and use it as a database to store session ID’s. But that would mean more traffic between your server and the database server each time a user requested a resources. Also a possible weak point, needing more than one database in case it went down.

Token storage security

JWT’s (and other token based authorization) avoid this problem by storing the token with the client, and not on the server. So another server could accept the JWT from a client, use the same secret key your other server had, and use it’s HASH algorithm to verify the signature of the JWT. All this means is that if you control two servers, both servers would only need to be set up with the same secret key for the same JWT to work on both.

Where to store the JWT? Client side, you have the following options with the browser:

  1. Web Storage API
    This has two items:

    • localStorage
    • sessionStorage
  2. Cookies
  3. IndexedDB API
  4. Cache API
  5. in-memory??

localStorage can be attacked with XSS, localStorage can be accessed by JavaScript running on the same domain. This means if you have a third party JS file running it could access the token in local storage and do whatever it wanted with it. <script src="https://randomjslibray.com/stealtoken.js"></script>Having a script tag linking to a 3rd party leaves you vulnerable.

sessionStorage has the same issue, XSS, and also does not persist through tab and window closes. This would prompt the user to login again if they had to restarted the browser or it crashed.

Cookies: When using cookies, with a JWT for example, the server will send the JWT inside a Cookie HTTP header instead of the HTTP body or some other HTTP header. Set-Cookie: <cookie-name>=<cookie-value>is how the server sets and sends a cookie the client. Below the server sets and sends cookies to client.

HTTP/2.0 200 OK
Content-Type: text/html
Set-Cookie: water=water
Set-Cookie: air=house

The client would receive these cookies, store them, and return them to the server with each HTTP request it sent.

GET /sample_page.html HTTP/2.0
Host: www.firefox.org
Cookie: water=water; air=house

For more on Cookies, check out my post on them here!

IndexedDB API: Newer, but currently used by 97% of people online according to caniuse.com There is currently not much information on using this to store tokens,

in-memory: This one is a bit vague, basically it is the application itself storing the token. In React, this would be the component state. A page refresh would, however, remove this data.

Which is best??

Apparently the Web Storage API (localStorage, sessionStorage) has fallen out of favor and most people recommend cookies. Of course, I found lots of people saying the exact opposite. Apparently any random fool can write a blog post and I have no way of telling who is legit! From reading, Cookies are generally considered more secure than localStorage/sessionStorage.

Security

Session ID’s are stored on both the server and client. Tokens are only stored with the client. If either a session ID or token is stolen it is bad news. The attacker could use your session/token and send a request to the server, and be authorized without having to enter in a username and password. So your account could be used for nefarious purposes without the attacker ever having stolen your authentication credentials.

A stolen session/token can be worse than having your username and password stolen in some cases. For example, what if you have implemented 2FA via SMS after a client enters a valid username and password? The user would get a text on their phone, and have to enter the code from in into the browser in order to be authenticated. Once authenticated, the client/user is sent a session/token created by the server which the client will send back to the server with each additional HTTP request for authorization. If an attacker steals a session/token it means they now don’t need your username or password, and since 2FA via SMS was already used, that is also bypassed by stealing the session/token.

Protect this!

So, session/tokens should be treated as sensitive data and sent over a secure protocol, such as HTTPS.

REST API’s

A REST API is, by definition, stateless. This mean that the server does not store any state about the current client request. With a session based authorization system, the server would store the session and check it against the client request. This makes it not stateless, and thus it would not be a REST API.

Token based authorization is stored client side, the server and it’s API don’t keep track of who is currently logged in. So tokens are popular with REST API’s.