简体   繁体   中英

How to store token in http header

I am currently working on an application (React frontend, node.js server and api) and am using JWT. I am having a hard time wrapping my head around the process of storing and sending the token using HTTP "Authorization" header.

Tutorials online seem to do a great job of showing me how to send this token once it is stored somewhere, but how does it actually get stored there in the first place is where my confusion arises.

I have two ways of thinking of approaching this:

  1. The token is generated on login, then returned to the frontend, then stored in localstorage. Then, when a request is made, the HTTP "Authorization" header is set by pulling the token from local storage.

  2. The token is generated on login, then returned to the frontend. It is somehow stored already in the "Authorization" HTTP header (Does this even make sense?). Then when a request is made, the header is already set.

  3. Do option 1 but use a cookie (or session-cookie?) (don't know how to do this approach).

I would like to know:

A. Which of the 3 (if any) is the right approach

B. If approach 2 is the correct way, how do you actually STORE this header once you get the token?

C. If NOT approach 2, where is the preferred place to store this token (localstorage, cookie, etc.)?

I have tried approach 1, it works but seems unsafe and not best practice. I have NOT tried approach 2, because I have no idea how to do it, and couldn't find anything online. I have NOT tried approach 3, but I assume it could work in a similar fashion to 1?

First, your instincts are right; you should not use local storage for a secure token because local storage persists even when the browser is completely closed.

The most straightforward way to store your token is to just keep it in memory. A global variable in Javascript, or even attaching it to window , works fine. Then with every XHR call you insert Bearer [Token] into the Authorization header yourself. There are a bajillion npm packages to help with XHR requests but virtually all of them should let you insert this header. If you haven't already you should write a single wrapper function to encapsulate all your API calls and insert the token at this point.

The drawback with this is that the token won't persist across different pages on the same domain or across browser tabs, nor will it work with non-XHR requests like img src="https://secure_api_route_that_returns_an_image.jpg" , as there's no way to programmatically inject custom headers in those cases. I don't know if any of that is a problem for you. Usually with React SPAs you aren't going to be bouncing around truly different "pages" on the same domain, but you may well want to be securely sourcing images with what are technically API routes, or keeping the session alive across browser tabs; I'm not sure what your requirements are.

Anyway if you do need any of that functionality, you have to use a "session cookie". (Technically you could use session storage if you only need to preserve the token across page navigation but it doesn't work across tabs, so I find it to be pretty useless over just storing in-memory). This just means a cookie with no expiration date, which is automatically purged when all browser tabs have been closed. You must enforce earlier expiration on the backend rather than through the cookie header.

I use .NET backends rather than Node, so I can't give you specific code, but basically you need to return this header in a successful login API response:

 set-cookie: myCookie={jwt}; Path=/; Secure; HttpOnly; SameSite=Strict;

Don't omit Secure , HttpOnly or SameSite=Strict except possibly in development, as otherwise you'll be open to common vulnerabilities. (This is one of the disadvantages of the cookie approach; it's easier to implement wrongly and open up a vulnerability). This assumes your frontend and backend are hosted on the same domain. It becomes a little more complicated if not (CORS, etc.) but it can be done in that case too with a little more work.

On the authentication side, you will just need to look for this cookie in every API other than login. If everything is working right the browser will automatically send something like this with every request to your domain, on any tab, for as long as any browser tab remains open:

 cookie: myCookie={jwt}

Again not a Node.js guy but I'm reasonably sure most any library that can verify a token via the Authorization header will support cookie authentication too; you'll need to check the documentation or please post a new question if you can't figure it out.

On the frontend side, besides the cross-tab support, the browser takes care of saving the cookie and sending it when it should, so it's conceptually close to what you're looking for in option 2.

So as with most things there's no single right way (though there is definitely one wrong way - localstorage). For what it's worth, a few years ago I surveyed several commercial sites to see how they handled this, and I found most used the session cookie. This included US banks and financial institutions, which have to follow some of the strictest security standards that exist. While cookies sometimes get a bad rap, when used correctly they are still industry standard for secure authentication. But storing the token in plain old Javascript memory is fine if you don't want to deal with cookies or need the features cookies give you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM