13

What is the most secure way to store transfer and store a JWT token, or any authentication token in general?

Someone told me it's secure to send the authentication token as a cookie, but I don't understand how this would provide any additional security over just using a plain session ID cookie for authentication, as the browser would include that cookie for all outgoing requests anyway. Have I misunderstood something?

What makes a lot more sense to me, is if the token would be stored in a response header or body, then extracted in the client side programmatically and manually added to each request. There would be no way to intercept the token over HTTPS connection and CSRF attacks are rendered impossible (I would use CSRF token anyway). Of course the authentication token could still be accessed by XSS attack, but isn't the cookie also prone to this attack?

I don't understand how token in a cookie provides ANY additional security over authentication based on simple session ID cookie? Am I missing some information?

3 Answers 3

12

By putting the token in the cookie and setting that cookie HttpOnly, you can prevent access to the cookie by malicious client side script (ie, XSS) - there is no access to an HttpOnly cookie from JavaScript, the browser will protect it and handle sending the cookie only to the right origin.

https://www.owasp.org/index.php/HttpOnly

2
  • 2
    That will make CSRF attack a possibility, and it doesn't really matter that much in case of XSS either, since you can still make requests with the cookies. Commented Jun 14, 2018 at 12:20
  • The comment about CSRF + XSS isn't quite right. CSRF can be reliably prevented by best practices (check out OWASP recs), but XSS cannot: you pretty much always have some exposure from supply-chain poisoning. Yes, an HttpOnly cookie will be included with requests that an XSS attacker sends to your application, impersonating the user. But using an HttpOnly cookie and a correct CORS configuration, an XSS attacker can't exfiltrate the credentials. If you keep sensitive information in a place where JS can access it: in localStorage or even in memory, XSS can exfiltrate the credentials. Commented Jan 30 at 0:27
3

Ok, let's start by understanding what's JWT (quoted from their website):

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

JWT.IO allows you to decode, verify and generate JWT.

The goal of JWT isn't to hide data, but to prove your identity to the server. Anyone can decode the token, but they can't create fake tokens because that requires the secret key. The server will throw an exception when attempting to decode a fake token, since no one knows your private key (I hope!).

Usually, the token is sent in the Authorization header, which looks something like this:

Authorization: Bearer <the token>

And then you have many libraries which will parse the header and extract the needed information for you, depending on your language.

3
  • Actually the tokens are generated by the server, when a login request is received from the client. Then the server sends the token together with the response to the login request. Therefore, the client does need to store it, in order to add it to subsequent requests.
    – Ioanna
    Commented Apr 8, 2019 at 3:04
  • 3
    Well obviously... Otherwise how will it be sent in the authorization header?
    – Tom
    Commented Apr 8, 2019 at 16:50
  • @Tom lol .......
    – ADP
    Commented Dec 22, 2020 at 4:03
1

Because cookie headers can be exposed, you set a short expiry date for your session id or access token. And this means bad UX as user has to login frequently. This can be solved using refresh tokens are long lived and used for silent authentication where basically new access tokens are issued as long as the refresh token is valid or user logs out. Coming to your question, the vulnerability of cookies being compromised still exists though and Refresh Tokens can be. The answer for this is Rotating Refresh Tokens.

Refresh token rotation guarantees that every time an application exchanges a refresh token to get a new access token, a new refresh token is also returned. Therefore, you no longer have a long-lived refresh token that could provide illegitimate access to resources if it ever becomes compromised. The threat of illegitimate access is reduced as refresh tokens are continually exchanged and invalidated. https://auth0.com/blog/refresh-tokens-what-are-they-and-when-to-use-them/#Refresh-Token-Rotation

The database stores all the Refresh Tokens including the invalidated ones so that in the case an adversary gains access to one of the invalidated Refresh Token and queries the server we know that the invalidated refresh token has been exposed and we invalidate the Refresh Token that was issued the latest and therefore requiring the user to login again.

The only way for the adversary to win is to gain access to the latest issued Refresh Token and query the server within its expiry date. If successful the adversary would have control until the legitimate user tries accessing the server with their invalidated Refresh Token thereby prompting us that their has been a malicious attack.

You must log in to answer this question.

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