ephDev
ephDev

Reputation: 65

JsonWebTokenError: jwt must be a string

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

Upvotes: 5

Views: 14621

Answers (3)

hà huy hùng
hà huy hùng

Reputation: 11

const token = authHeader.split(' ')[1];

Upvotes: 1

Vinay _Sharma
Vinay _Sharma

Reputation: 1

When you take out your token from the cookies that full object is giving you you need to take the token from the cookies. This error came to me also if you want you can use this method because yours and my code are a bit different you need to take only token from the header and not the whole object and your jwt_secret also be string

Upvotes: 0

ale917k
ale917k

Reputation: 1768

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' });

Upvotes: 4

Related Questions