What is the best way to transfer the JWT token from the server to the client using an HTTP header?

I have been searching for an answer on how to pass the JWT Token from the client to the server securely, but I am not satisfied with the explanations I found. Everyone talks about the most secure way to transfer the JWT token using HTTP headers instead of cookies. But I am still confused - which specific header should I use to send the client's JWT token?

Let's say a user is already registered in my database and has submitted their login credentials to the server. After retrieving the credentials, I generated a JWT based on that information. Now, I am working with Express - can someone guide me on how to send this JWT to the client using a header?

I am implementing this using Express


       app.post("/login", async (inReq, inRes) => {
    
      //Loading the user's database
        usersDB.loadDatabase((err)=>{
            if (err) {console.log("Error while loading database: usersDB")};
        });
       
      // Starting our login logic here
      
      //Fetching the user's data
      const { username, password } = inReq.body;
    
      //Validating user input in some way.
        if(username.length < 4 || password.length < 8)
          return inRes.status(400).send('Bad data');
      
      //then attempting to...
      try {
        //Checking if the user exists in our database
        const foundUser = await findUser(usersDB,{"username":username});
    
        //Comparing the passwords (the one from DB and the one sent by the client)
        if (foundUser && (await bcrypt.compare(password, foundUser.password))) {
        
          //Creating a token if everything checks out
          const token = await  jwt.sign(
            { user_id: foundUser._id, username },
            process.env.TOKEN_KEY,
            {
              expiresIn: "40s",
            },
            function(err, intoken) {
              if(err) {
                  console.log(err);
                  return inRes.status(500).json({current_view: 'error', data: err});
              }
                 
            });

Now what?

  • WHAT DO I DO WITH THE TOKEN????
  • WHICH HEADER SHOULD I USE? And How?
    
          //sending a response to the user (successful login)
          return inRes.status(200).json(current_view: 'home', data: user);
        }
        //Sending an error message if the user is not valid
        return inRes.status(401).json(current_view: 'login', data: 'wrong-credentials');
      } 
      //Catching and logging any errors
      catch (err) {
        console.log(err);
      }
      // Finishing our register logic
    });

Answer №1

I'm currently facing a similar situation where there is no clear consensus on how to transmit the JWT to the client. I came across some guidelines that suggest different methods, which you can find in this link:

https://github.com/dwyl/hapi-auth-jwt2/issues/82#issuecomment-129873082

According to these guidelines, placing the JWT token in the Authorization header offers flexibility for sending an actual response in a web application. For REST-only App/API, you have the option to send the JWT as either the response body or a cookie. The key aspect is how the client stores and sends back the JWT to the Server, typically through the Authorization header (or Cookie or URL Token if preferred) 👍

In terms of existing implementations, I haven't come across any examples where the server sends an Authorisation header to the client, but there is nothing indicating that this approach is incorrect according to the specifications. Refer to:

During my experiments with Express, I have been exploring sending the JWT via the Authorization header:

inRes.set('Authorization', `Bearer ${myJWT}`);

Remember to do this before setting the inRes.status.

On the client side, the process appears more straightforward. Most sources advise against storing the JWT in localStorage due to the lack of an expiration property. While cookies offer slightly better options with expiration settings, they also provide the advantage of being sent back to the server with future requests. Alternatively, sessionStorage could be considered as it has a definite expiration period, lasting only until the browser is closed.

You may want to explore the suggested method linked below (although the examples are Java-specific, the explanation is general) for storing the JWT on the client side:

https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/JSON_Web_Token_for_Java_Cheat_Sheet.md#token-storage-on-client-side

Answer №2

Thank you so much, Scopique, for your response. I completely agree that finding a solution to this issue may not be simple and straightforward. It's interesting to hear that you also encountered a similar problem on GitHub - small world! In my opinion, given the importance of web security, any RFC standard should prioritize a secure approach in its description.

As I am currently focused on backend development, I haven't spent much time considering how to securely store tokens. However, I did create a basic diagram as a starting point. (Please note that this is not necessarily considered the best practice, but it works for now) https://i.sstatic.net/8MEeF.png

I hope taking this initial step isn't too risky. It's all part of the learning process!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Each time a user uploads an image, my website crashes due to issues with the webpack bundle build

My website was running smoothly for a couple of weeks, allowing users to upload images without any issues. However, recently, every time an image is uploaded, the entire website crashes. The log displays the following message after some images are uploaded ...

Creating a MySQL table that includes long string data types

Recently, I was working on creating an online forum and encountered a problem with the writing function. The form consists of a title and content section, which usually functions properly. However, when I enter a slightly longer text in the content field, ...

Express updates the body during a curl request

After successfully creating my first Node JS form, I decided to recreate it using Express. However, I am facing challenges with handling the body in Express compared to Node JS. I can see the headers and body data, but I don't understand why Express i ...

Setting the height of columns in a Bootstrap panel to 100%

Is there a way to achieve 100% height for all three columns even without content? Check out this JSFiddle: <div class="row"> <div class="col-md-12"> <div class="shadow panel panel-default"> <div class="blue white-bord ...

Next.js lacks proper Tree Shaking implementation for MUI

After setting up a react app with next.js, I noticed that the bundle size for the client significantly increased when importing MUI components. Specifically, there was a large module called @mui/base added to the bundle, even though I am only using three M ...

TypeScript does not verify keys within array objects

I am dealing with an issue where my TypeScript does not flag errors when I break an object in an array. The column object is being used for a Knex query. type Test = { id: string; startDate: string; percentDebitCard: number, } const column = { ...

Develop a responsive shopping cart using PHP and JavaScript

I am in the process of developing an ePos system that allows users to add items to their basket by simply clicking on them, and then calculates the total price without needing to refresh the entire page. I initially attempted to use $_SESSION and store th ...

Avoiding leaps through the use of dynamic pictures?

Currently, I am implementing the picture element along with srcset to download the same image but in varying resolutions depending on the screen size of the device. The image has a style of max-width: 100%, causing it to shift the content below when downl ...

What could be the reason for Sequelize to completely replace the record when updating in a put request?

I've been attempting to implement an "edit" feature within my project, but I've hit a roadblock in the process. Here's a snippet of the put request code: export const updateEvent = (event, id) => (dispatch, getState) => { request ...

Executing a class function within the ajax success method

I am attempting to set a variable inside the success callback of an AJAX call. I understand that in order to assign the value, I need to use a callback function. However, I want that function to be within the class. Is it feasible to implement something li ...

Tips for assigning a personalized value to an MUI Switch when it is in the off position

I am currently utilizing the MUI Switch component to create an On-Off button. I have manually set the value as "on" and it is functioning correctly when the switch is in the true state. However, there doesn't seem to be an option to change the default ...

Tips on saving an audio file to a Node server using blob or FormData

I am currently working on a project where I have a MedaRecroder stream recorded in audio/webm format. The stream is sent to a Node server, and while the file appears in the response under req.files, there seem to be encoding errors when playing it back. M ...

Using conditional statements like 'if' and 'else' in JavaScript can

Can someone help me with solving my problem using if-else statements in Javascript? I need to filter names by gender and save them as keys - woman / man in local storage. Any assistance would be greatly appreciated. I am struggling to figure out how to im ...

What is the best way to utilize JSON.stringify for substituting all keys and values?

In my current project, I am exploring how to leverage the replacer function argument within JSON.Stringify in JavaScript to alter the word case (toUpper / toLower case). The challenge I am facing is that my JSON data is not simply key:value pairs; some val ...

Creating a jQuery AJAX form that allows users to upload an image, submit the form, and store the entered values in a MySQL database

I am struggling with an HTML form that I am trying to submit using jQuery's $.ajax(); The form needs to: 1. Upload an image to a directory with error checks 2. Save the image path to a MySQL database 3. Insert two other form values (input and select) ...

A guide to monitoring and managing errors in the react-admin dataProvider

Rollbar has been successfully integrated into my react-admin app to track uncaught errors. However, I've noticed that errors thrown by the dataProvider are not being sent to Rollbar. It seems like errors from the dataProvider are internally handled w ...

The JSON reviver function is still not returning anything even when explicitly using the return

function _quotedText(data, config) { var pathKeys=config.customKey; console.log(pathKeys); //prints os_platform var inAuth_data=(JSON.parse(JSON.parse(JSON.parse(data["event.fields.custom_fields.inauth_device_data"])), (key, value) =& ...

Comparing nestableSortable with the Nestable JavaScript library

I am in the process of developing a navigation menu editor that consists of multiple nested, sortable forms. My goal is to submit all the form data in one comprehensive JSON data blob. After researching, I have narrowed down my options to two libraries: n ...

Checking for the presence of a specific function in a file using unit testing

I am curious if there is a possible way to utilize mocha and chai in order to test for the presence of a specific piece of code, such as a function like this: myfunction(arg1) { ...... } If the code has been implemented, then the test should return t ...

Convert string IDs from a JSON object to numerical IDs in JavaScript

My goal is to convert the IDs in a JSON object received from PHP into numeric keys using JavaScript. The initial structure of my JSON object looks like this: let foo = {"66":"test","65":"footest"}; What I aim for is to transform it into this format: let f ...