How to solve JsonWebTokenError "invalid signature" after assigning some infos to the generated token?

66.1k views Asked by At

Have a problem when trying to verify the token (it was working fine before i added some data to it before generating it) .. but now it does not seem to be working !

This is how i generate the token when user send a POST request (login)

require('dotenv')
const jwt       = require('jsonwebtoken');
const bcrypt    = require('bcryptjs')
const Role      = require('../models/Role');
const Section   = require('../models/Section');
const User      = require('../models/User');

// Login !
router.post('/', async (req, res) => {

    let sections_fetched = [];


    // Validate data 
        
    // Check username
    const user = await User.findOne({username: req.body.username });
    if(!user) return res.status(400).send('Wrong user login credentials !');

    // Check password
    const is_pass_valid = await bcrypt.compare(req.body.password , user.password);
    if (!is_pass_valid) return res.status(400).send('Wrong user login credentials !');


    // Get role Object:
    const _role = await Role.findOne({_id:user.role , is_deleted:false});
    if (!_role) res.json("Failed fetching role !");


    // loop through sections   
    for (let index = 0; index < _role.sections.length; index++) {

        const tmpRole = await Section.find({_id: _role.sections[index], is_deleted:false});
        sections_fetched.push({access:tmpRole[0].access , name:tmpRole[0].name});
    }


    // create jwt token
    const token = jwt.sign({username:user.username, role:{name:_role.name, sections:sections_fetched}}, 'secret', {expiresIn : '24h'}, process.env.JWT_TOKEN_SECRET);
    res.json({token:token});

});

this is my JWT verification middleare :

require('dotenv')
const jwt = require('jsonwebtoken');

module.exports = function (req, res, next) {

    const token = req.header('auth-token');

    if (!token) return res.status(401).send('Access Denied !');
    console.log(process.env.JWT_TOKEN_SECRET);
    console.log(token);

    try 
    {
        
        const verified = jwt.verify(token, process.env.JWT_TOKEN_SECRET);
        req.user = verified;  
        next();

    } 
    catch (error) 
    {
        res.status(400).send('Invalid token !');
    }
}

and this is a simple example of listing users (using the JWT verification middleware ! ) :

const verifyToken = require('../middlewares/verifyToken'); // my jwt middleware to verify !

// Listing All users
router.get('/', verifyToken, async (req, res) => 
{
    try 
    { 
        const users = await User.find({is_deleted:false});
        res.json(users);
    }
    catch (error) 
    {
        console.log("err ->\n"+error);
        res.json({message: error});
    } 
});

6

There are 6 answers

1
r7r On BEST ANSWER

what is 'secret in the below line? seems you are adding a secret key twice, replace the hardcoded word 'secret' with token from env

const token = jwt.sign({username:user.username, role:{name:_role.name, sections:sections_fetched}}, 'secret', {expiresIn : '24h'}, process.env.JWT_TOKEN_SECRET);
0
jaitn On

Hlo this error occur when secretkey does't match with the key thats provided during when you verifing token you can check you token on jwt website thats help you to get error main reason

1
Mohammad Yaser Ahmadi On

send a bearer token and your middleware should like this

require('dotenv')
const jwt = require('jsonwebtoken');

module.exports = (req, res, next) => {
  try {
    const token = req.headers.authorization.split(' ')[1]; // Authorization: 'Bearer TOKEN'
    if (!token) {
      throw new Error('Authentication failed!');
    }
    const verified = jwt.verify(token, process.env.JWT_TOKEN_SECRET);
    req.user = verified;  
    next();
  } catch (err) {
    res.status(400).send('Invalid token !');
  }
};

enter image description here

0
Devorein On

Please make sure then when generating the token you pass a valid algorithm. I stored the algorithm in an environment variable but used none which is not a valid algorithm. Thus even though the token got created, I couldn't verify it using the same secret. Spent hours trying to fix this. I hope this was helpful :D

sign(payload, JWT_SECRET, {
    algorithm: JWT_ALGORITHM,
    expiresIn: '1d'
});
0
HARIHARAN On

You described that you have changed the contents.

A signature represents the integrity of the contents, to ensure the content that was signed has not been modified, and you are modifying the contents making the signature invalid. This error you have is accurate for what you have done.

You must create a new signature when the signed contents are changed.

For Sign:

jwt.sign(
  {
    username:user.username,
    role:{
      name: _role.name,
      sections: sections_fetched
    }
  }, 'secret', {
    expiresIn : '24h'
  }, process.env.JWT_TOKEN_SECRET,
  function(err,res) {
    if (err) {
      callback(res);
    } else {
      callback(res);
    }
  }
);

To Verify:

jwt.verify(req,'SecretKey', function (err, res) {
  if (err) {
    callback(res);
  } else {
    callback(res);
  }
});
0
AMMAR YASIR On

In general, it's logicall there is no other way check and make sure of you jwt.sign() the secret key they must be same in the jwt.verify()

  var token = jwt.sign({ foo: "bar" }, "secret_key");

  const token = req.header("token");
  var decoded = jwt.verify(token, "secret_key");

  console.log(decoded.foo); // bar