JsonWebTokenError: jwt malformed in Express as soon as the user logs in, but if I refresh it works perfectly fine

huangapple go评论67阅读模式
英文:

JsonWebTokenError: jwt malformed in Express as soon as the user logs in, but if I refresh it works perfectly fine

问题

I am creating a React application and the backend using node.js.
I am listing all the steps, starting when the user putting the credentials and how the token is null when it gets verified.
But when I refresh the page the token is valid.

First Step(If users' credentials are correct in the frontend):

if (res.status === 200) {
localStorage.setItem("token", res.data.accessToken)
console.log(res.data)
dispatch(login(res.data.user))
navigate("/admin")
}

Second step (The token is stored in local storage and is valid because I checked on JWT.io)

JsonWebTokenError: jwt malformed in Express as soon as the user logs in, but if I refresh it works perfectly fine

This is the axios instance that I use to fetch

export default axios.create({
baseURL: ${process.env.REACT_APP_API_URL},
headers: {
token: ${localStorage.getItem("token")}, //I assume this may go null; but when I refresh, it loads perfectly fine
},

Third step (The routes on the backend, there is a middleware "admin_auth" that checks the token of the user and verifies it)

router.get("/", admin_auth, GET_ALL_CATEGORIES);

Fourth Step (where the token becomes null as soon as the user signs in)

const admin_auth = (req, res, next) => {
const token = req.headers["token"];
console.log(token) // NULL WHERE USER HAS JUST LOGGED IN; BUT WHEN THE USER REFRESHES, THE TOKEN IS VALID
if (token) {
console.log(token + " TOKEN ");
jwt.verify(token, process.env.SECRET_KEY, (err, user) => {
...//more code

英文:

I am creating a React application and the backend using node.js.
I am listing all the steps, starting when the user puting the credentials and how the token is null when it gets verified.
But when I refresh the page the token is valid.

First Step(If users credentials are correct in the frontend):

if (res.status === 200) {
            localStorage.setItem("token", res.data.accessToken)
            console.log(res.data)
            dispatch(login(res.data.user))
            navigate("/admin")
 }

Second step (The token is stored on localstorage, and is valid because I checked on JWT.io)

JsonWebTokenError: jwt malformed in Express as soon as the user logs in, but if I refresh it works perfectly fine

This is the axios instance that I use to fetch

   export default axios.create({
      baseURL: `${process.env.REACT_APP_API_URL}`,
      headers: {
        token: `${localStorage.getItem("token")}`, //I assume this my go null; but when I refresh it loads perfectly fine
      },

Third step (The routes on the backend, there is a middleware "admin_auth", that checks token of the user and verifies it)

router.get("/", admin_auth, GET_ALL_CATEGORIES);

Fourth Step (where token comes null as soon as the user sign in)

const admin_auth = (req, res, next) => {
  const token = req.headers["token"];
  console.log(token) // NULL WHERE USER HAVE JUST LOGGED IN; BUT WHEN THE USER REFRESH THE TOKEN IS VALID
  if (token) {
    console.log(token + " TOKEN ");
    jwt.verify(token, process.env.SECRET_KEY, (err, user) => {
      ...//more code

答案1

得分: 1

Here is the translated content:

所以基本上这里发生的情况是,当这段代码第一次运行时,token 没有保存在本地存储中。这就是为什么它会得到空值。

export default axios.create({
      baseURL: `${process.env.REACT_APP_API_URL}`,
      headers: {
        token: `${localStorage.getItem("token")}`, //我假设这里可能会变成null;但当我刷新页面时,它加载得很好
      },

为什么在刷新后它会运行

因为它在第一次成功保存在本地存储中,现在当上面的代码运行时,它获取到了token并正常运行。

解决方案

像这样更新你的 axios 文件:

import axios from 'axios';

const instanceAxios = axios.create({
  baseURL: `${process.env.REACT_APP_API_URL}`,
  headers: {
    token: `${localStorage.getItem("token")}`,
  }
});

// 更新axios实例中的token
export const setAuthToken = (token) => {
  if (token) {
    console.log('[axios] 确认新token更新 ===>', token);
    instanceAxios.defaults.headers.common['token'] = `${token}`;
  } else {
    delete instanceAxios.defaults.headers.common['token'];
  }
};

export default instanceAxios;

现在,当用户成功登录时,通过调用 setAuthToken 函数来更新你的token,同时在使用之前导入它:

if (res.status === 200) {
  localStorage.setItem("token", res.data.accessToken);
  setAuthToken(res.data.accessToken); // 调用这个函数
  console.log(res.data);
  dispatch(login(res.data.user));
  navigate("/admin");
}
英文:

So basically what's happening here is that when this code runs for the first time token is not saved in local storage. That's why it's getting null.

export default axios.create({
      baseURL: `${process.env.REACT_APP_API_URL}`,
      headers: {
        token: `${localStorage.getItem("token")}`, //I assume this my go null; but when I refresh it loads perfectly fine
      },

Why it's running after the refresh:

Because it got successfully saved in the local storage the first time and now when the above code runs it gets the token and runs fine.

Solution:

Update your axios file like this:

import axios from 'axios';

const instanceAxios = axios.create({
  baseURL: `${process.env.REACT_APP_API_URL}`,
  headers: {
    token: `${localStorage.getItem("token")}`,
  }
});



// update your token in axios instance
export const setAuthToken = (token) => {
  if (token ) {
    console.log('[axios] confirm new token update  ===>', token);
    instanceAxios.defaults.headers.common['token'] = `${token}`;
    
  } else {
    delete instanceAxios.defaults.headers.common['token'];
   
  }
};

export default instanceAxios;

Now when the user successfully login update your token by calling setAuthToken function also import it before use:

if (res.status === 200) {
  localStorage.setItem("token", res.data.accessToken)
  setAuthToken(res.data.accessToken);// CALLING THIS FUNCTION
  console.log(res.data)
  dispatch(login(res.data.user))
  navigate("/admin")
}

答案2

得分: 0

Your axios instance may need to be updated/re-created after a token is received from the server. Initially, when the axios instance is created, the token is not yet set in local storage and the value of token in the header will be null.

After the token is received from the server, you set the token key-value pair in local storage, but the axios instance you are using is still using the original value of the token key-value pair it loaded when the axios instance was instantiated.

When you reload the page, the axios instance is re-instantiated, and reads the correct value of token from local storage, which is why it works after the page is refreshed.

As a result, you will likely need to re-create your axios instance or modify the headers of your existing axios instance after the token has been received from the server and put into local storage.

英文:

Your axios instance may need to be updated/re-created after a token is received from the server. Initially, when the axios instance is created, the token is not yet set in local storage and the value of token in the header will be null.

After the token is received from the server, you set the token key-value pair in local storage, but the axios instance you are using is still using the original value of the token key-value pair it loaded when the axios instance was instantiated.

When you reload the page, the axios instance is re-instantiated, and reads the correct value of token from local storage, which is why it works after the page is refreshed.

As a result, you will likely need to re-create your axios instance or modify the headers of your existing axios instance after the token has been received from the server and put into local storage.

答案3

得分: 0

你没有正确使用redux。你正在从localStorage中访问令牌,这不是高效的方法。你可以使用react-persist来自动管理本地存储,无需手动设置localStorage。

或者在导航之前首先验证令牌是否已存储,然后尝试以下代码。

import axios from 'axios';

export default function setAuthToken(token) {
  axios.defaults.headers.common['Authorization'] = '';
  delete axios.defaults.headers.common['Authorization'];

  if (token) {
    axios.defaults.headers.common['Authorization'] = `${token}`;
  }
}

始终在初始化时清除现有的令牌,然后建立已收到的令牌。

英文:

You are not using the redux in proper way. You are accessing the token from localStorage and it's not efficient way. You can use react-persist which help you to automatically manage local storage, you don't have to set localStorage manually.

Or else first verify before navigating that token has been stored or not and then try below code.

import axios from 'axios';

export default function setAuthToken(token) {
  axios.defaults.headers.common['Authorization'] = '';
  delete axios.defaults.headers.common['Authorization'];

  if (token) {
    axios.defaults.headers.common['Authorization'] = `${token}`;
  }
}

Always clean the existing token at initialization, then establish the received one.

huangapple
  • 本文由 发表于 2023年1月4日 02:58:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/74997610.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定