Node-jsonwebtoken: Payload has lot more data after jwt.sign in version 5.5.4, works fine in 5.5.0

Created on 5 Jan 2016  路  13Comments  路  Source: auth0/node-jsonwebtoken

Hello Team,

Recently our app broke due the mismatch in the decoded object for jwt.verify(), this is my payload for signing the token,

{ local: 
   { mobile_verified: false,
     verify_token: '5VqK0',
     mobile: '****',
     email: '[email protected]' },
  facebook: {},
  google: {},
  ownership: [],
  createdAt: Tue Jan 05 2016 13:11:53 GMT+0000 (UTC),
  __v: 0,
  _id: 568bc1196972145a37089f12 }

In 5.5.4, the payload I got back after decoding is,

{ '$__': 
   { strictMode: true,
     getters: {},
     wasPopulated: false,
     activePaths: { paths: [Object], states: [Object], stateNames: [Object] },
     emitter: 
      { domain: null,
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: 0 } },
  isNew: false,
  _doc: 
   { local: 
      { mobile_verified: false,
        verify_token: '5VqK0',
        mobile: '9886699975',
        email: '[email protected]' },
     facebook: {},
     google: {},
     ownership: [],
     createdAt: '2016-01-05T13:11:53.364Z',
     __v: 0,
     _id: '568bc1196972145a37089f12' },
  _pres: { '$__original_save': [ null, null ] },
  _posts: { '$__original_save': [] },
  iat: 1452001249,
  exp: 1452087649 }

This should be fixed.

Most helpful comment

Let me explain what's going on.

mongoose has a class claled Document that overrides the toJSON method as explained here: http://mongoosejs.com/docs/api.html#document_Document-toJSON

In 5.5.0 we where adding exp, iat, etc to the object you pass and then calling JSON.stringify of that thing. This cause an issue for some users using mongoose as well since the toJSON method of mongoose didn't add the properties that this library added, so the resulting token didn't have expiration. Another user has this very same problem but not with mongoose, but with a "sealed" object.

I fixed this issue yesterday and now I am cloning the properties of the payload when you sign the token. So exp is added to the token even if is a object overriding toJSON or a sealed object.

I think this is the right behavior and the library was broken before that patch. I think you should generate tokens using toObject() now http://mongoosejs.com/docs/api.html#document_Document-toObject

jwt.sign(doc.toObject(), secret)

All 13 comments

Thanks for reporting this issue and I am sorry to have broken your use case.

These extra properties are definitely not from us, the payload you send to the sign method might have these properties and must be doing some weird things with serialization. Is this a mongoose object or something like that? I am asking this because of the _id and because some users have reported problems with this library.

Yes it's a user object I get from mongoose after saving the user. But, 5.5.0 it's works as expected bec, I get the same payload back after decoding.

Thanks for looking into this.

Let me explain what's going on.

mongoose has a class claled Document that overrides the toJSON method as explained here: http://mongoosejs.com/docs/api.html#document_Document-toJSON

In 5.5.0 we where adding exp, iat, etc to the object you pass and then calling JSON.stringify of that thing. This cause an issue for some users using mongoose as well since the toJSON method of mongoose didn't add the properties that this library added, so the resulting token didn't have expiration. Another user has this very same problem but not with mongoose, but with a "sealed" object.

I fixed this issue yesterday and now I am cloning the properties of the payload when you sign the token. So exp is added to the token even if is a object overriding toJSON or a sealed object.

I think this is the right behavior and the library was broken before that patch. I think you should generate tokens using toObject() now http://mongoosejs.com/docs/api.html#document_Document-toObject

jwt.sign(doc.toObject(), secret)

Thanks a lot for the explanation. I learned something new today :) It makes perfect sense. I will give it a shot tomorrow and update this issue. If everything checks out we can close this one.

Had this exact same issue and toObject seemed to do the trick for me. Thanks for the explanation @jfromaniello!

For me .toObject() also didn't work, here is my code,

if (!user) {
         UserCtrl.createUser(req, res).then(function(user){
           var token = jwt.sign(user.toObject(), 'alliswell_jwt', {
             expiresIn: 86400 // expires in 24 hours
           });

           // return the information including token as JSON
           res.json({
             success: true,
             message: 'Enjoy your token!',
             token: token,
             user: user
           });

         });
      }

After decoding this I am getting this,

{ '$__':
   { strictMode: true,
     getters: {},
     wasPopulated: false,
     activePaths: { paths: [Object], states: [Object], stateNames: [Object] },
     emitter:
      { domain: null,
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: 0 } },
  isNew: false,
  _doc:
   { local:
      { email: '[email protected]',
        password: '$2a$08$Eu1YroIekr3oidBe.zGoauuuB0Xl7oQnhz1TLTDzUblOW0xS5.lJW' },
     facebook: {},
     google: {},
     ownership: [ [Object] ],
     createdAt: '2015-12-26T09:56:56.278Z',
     status: 3000,
     __v: 0,
     _id: '567e64689678d9881b73e27c' },
  _pres: { '$__original_save': [ null, null ] },
  _posts: { '$__original_save': [] },
  iat: 1452691232,
  exp: 1452777632 }

@arindam89 put a console.dir(user.toObject()) before signing the token and show me the output

My bad, it works perfectly fine. Thanks @jfromaniello , I am closing this now.

@arindam89 no problem, I am really glad to help!

Sorry to all you guys for the troubles we caused

@jfromaniello I posted to a newly-opened issue that covers this same thing. The introduction of this problem came from using the xtend package. In lines 56-59 of index.js you use xtend(payload), which seems to be adding all of the meta properties that mongoose is adding. I changed it to xtend(payload._doc) and that made it work again.

Out of curiosity, what is the reason behind the addition of the xtend package in version 5.5.2? I wanted to submit a PR to fix this, but what I changed above might be completely undermining the whole reason behind adding it...

Hi guys, i had this problem and now it's working perfectly.. Thank you @jfromaniello.

Could a warning be added to the README example so people know to use .toObject() when using this with Mongoose objects.

@jfromaniello solution .toObject() work perfectly! Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ehartford picture ehartford  路  3Comments

p-brighenti picture p-brighenti  路  4Comments

salali picture salali  路  5Comments

shea256 picture shea256  路  3Comments

cope picture cope  路  4Comments