I am making a web application using nodejs and angular cli I'm using JWT to authenticate my login function . But when I process it threw this error
Error: Expected "payload" to be a plain object. at validate (D:\Mean_Projects\meanauthapp\node_modules\jsonwebtoken\sign.js:34:11) at validatePayload (D:\Mean_Projects\meanauthapp\node_modules\jsonwebtoken\sign.js:56:10) at Object.module.exports [as sign] (D:\Mean_Projects\meanauthapp\node_modules\jsonwebtoken\sign.js:108:7) at User.comparePassword (D:\Mean_Projects\meanauthapp\routes\users.js:86:27) at bcrypt.compare (D:\Mean_Projects\meanauthapp\models\user.js:53:9) at D:\Mean_Projects\meanauthapp\node_modules\bcryptjs\dist\bcrypt.js:297:21 at D:\Mean_Projects\meanauthapp\node_modules\bcryptjs\dist\bcrypt.js:1353:21 at Immediate.next [as _onImmediate] (D:\Mean_Projects\meanauthapp\node_modules\bcryptjs\dist\bcrypt.js:1233:21) at runCallback (timers.js:785:20) at tryOnImmediate (timers.js:747:5) at processImmediate [as _immediateCallback] (timers.js:718:5)
Here my passport code
const JwtStrategy= require('passport-jwt').Strategy; const ExtractJwt=require('passport-jwt').ExtractJwt; const User= require('../models/user'); const config=require('../config/database'); module.exports=function(passport){ let opts={}; opts.jwtFromRequest=ExtractJwt.fromAuthHeader(); opts.secretOrKey=config.secret; opts.issuer = 'accounts.examplesoft.com'; opts.audience = 'yoursite.net'; passport.use(new JwtStrategy(opts,(jwt_payload,done)=>{ console.log(jwt_payload); User.getUserById(jwt_payload._doc._id,(err,user)=>{ if(err){ return done(err,false); } if(user){ return done(null,user); } else{ return done(null,false); } }); })); }
My code for authenticate and get profile
// Authenticate router.post('/authenticate', (req, res, next) => { const username = req.body.username; const password = req.body.password; User.getUserByUsername(username, (err, user) => { if(err) throw err; if(!user){ return res.json({success: false, msg: 'User not found'}); } User.comparePassword(password, user.password, (err, isMatch) => { if(err) throw err; if(isMatch){ const token = jwt.sign(user, config.secret, { expiresIn: 604800 // 1 week }); res.json({ success: true, token: 'JWT '+token, user: { id: user._id, name: user.name, username: user.username, email: user.email } }); } else { return res.json({success: false, msg: 'Wrong password'}); } }); }); }); // Profile router.get('/profile', passport.authenticate('jwt', {session:false}), (req, res, next) => { res.json({user: req.user}); });
Payload. The second part of the token is the payload, which contains the claims. Claims are statements about an entity (typically, the user) and additional data. There are three types of claims: registered, public, and private claims.
This error occurs if the JSON Web Token (JWT) specified in the <Source> element of the Decode JWT policy is malformed, invalid or otherwise not decodable. A properly structured JWT should contain a header, payload and signature in the following format: header.
jwt.verify(token, secretOrPublicKey, [options, callback]) (Synchronous) If a callback is not supplied, function acts synchronously. Returns the payload decoded if the signature is valid and optional expiration, audience, or issuer are valid. If not, it will throw the error.
It fails at the line
const token = jwt.sign(user, config.secret, {
With error "Expected "payload" to be a plain object"
Your user
object is initialized here:
User.getUserByUsername(username, (err, user)
Which I assume is mongoosejs
object, which contains many methods and is not "serializable". You could handle this by passing a plain object, by either using .lean()
from mongoose
or plain toJSON
method:
const token = jwt.sign(user.toJSON(), config.secret, { expiresIn: 604800 // 1 week });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With