JsonWebTokenError: jwt must be a string

Issue

I’m trying to authenticate on the Backend so that only the right user can get the correct data.

App.js

const express = require('express');
const app = express();
const {mongoose} = require('./db/mongoose');
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken')

//load Middleware
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

//CORS Middleware
app.use(function(req, res, next) {
req.header("Content-Type: application/x-www-form-urlencoded");
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", " GET, POST, OPTIONS, PUT, PATCH, DELETE")
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, x-access-token, x-refresh-token");

res.header(
    'Access-Control-Expose-Headers',
    'x-access-token, x-refresh-token'
);

next();
})

To fulfil my goals I create the authenticate method

//aunthenticate middleware
let authenticate = (res, req, next) => {
let token = res.header('x-access-token');

jwt.verify(token, User.getJWTSecret(), (err, decoded) => {
    if (err) {
        res.status(401).send(err);
        console.log(err)
    } else {
        req.user_id = decoded._id;
        next();
    }
})
}

I had to get in the user Model

const { User } = require('./db/models/users.model');

The point is every user should have a record of its own dispatch. Hence

app.get('/dispatch', authenticate, (req, res) => {
    Dispatch.find({
      _userId: req.user_id
    }).then((dispatch) => {
      res.send(dispatch);
    }).catch((e) => {
      res.send(e);
    })
})

All the hints we have are in the

Users.model.js

const mongoose = require("mongoose");
const _ = require("lodash");
const jwt = require("jsonwebtoken");
const bcrypt = require("bcryptjs");
const crypto = require("crypto")
const jwtSecret = "XXXXXXXXXXX";
const UserSchema = new mongoose.Schema({
email: {
    type: String,
    required: true,
    minlength: 1,
    trim: true,
    unique: true
},
password: {
    type: String, 
    required: true,
    minlength: 8
},
sessions: [{
    token: {
        type: String,
        required: true
    },
    expiresAt: {
        type: Number,
        required: true
    }
}]
});
//Model Methods
UserSchema.statics.getJWTSecret = () => {
  
  return jwtSecret;
}

const User = mongoose.model('User', UserSchema);

module.exports = { User };

When I run the get dispatch method is postman the error on my terminal is
jsonwebtokenError: jwt must be a string

Solution

As the error suggests, your problem stands on how you set your token, as the value you are providing doesn’t seem to be of string type.

Now I can’t see where you set your token with the code you shared, but to fix the issue you will just need to make sure you pass a stringified value.

I’d suggest you force it by using toString:

jwt.sign(jwtValue.toString(), jwtSecret, { expiresIn: '1800s' });

Or you can stringify if you want to store objects:

jwt.sign(JSON.stringify(jwtValue), jwtSecret, { expiresIn: '1800s' });

Answered By – ale917k

Answer Checked By – Mildred Charles (AngularFixing Admin)

Leave a Reply

Your email address will not be published.