JWT decode returns null

Viewed 14644

I'm new to Node.js, reading Node.js Essentials by Fabian Cook. When trying the code in authentication with JWT, I got an NULL from jwt.decode( token ), but the token can be parsed by the Debugger on jwt.io. What's wrong with the code?

var Passport = require( 'passport' );
var LocalStrategy = require( 'passport-local' ).Strategy;
var Express = require( 'express' );
var BodyParser = require( 'body-parser' );
var jwt = require( 'jsonwebtoken' );
var Crypto = require ( 'crypto' );

var users = {
  zack: {
    username: 'zack',
    password: '1234',
    id: 1,
  },
  node: {
    username: 'node',
    password: '5678',
    id: 2,
  },
}

var localStrategy = new LocalStrategy({
      usernameField: 'username',
      passwordField: 'password',
    },
    function(username, password, done) {
      user = users[ username ];

      if ( user == null ) {
        return done( null, false, { message: 'Invalid user' } );
      };

      if ( user.password !== password ) {
        return done( null, false, { message: 'Invalid password' } );
      };

      done( null, user );
    }
  )

Passport.use( 'local', localStrategy );

var app = Express();
app.use( BodyParser.urlencoded( { extended: false } ) );
app.use( BodyParser.json() );
app.use( Passport.initialize() );

var generateToken = function( req, res ) {
  var payload = {
    id: user.id,
    username: user.username
  }
  var secret = user.secret || Crypto.randomBytes( 128 ).toString( 'base64' );
  var token = jwt.sign( payload, secret );
  user.secret = secret;
  return token;
};

var generateTokenHandler = function ( req, res ) {
  var user = req.user;
  var token = generateToken( user );
  res.send( token );
};

app.post(
  '/login',
  Passport.authenticate( 'local', { session: false } ),
  generateTokenHandler
);

var BearerStrategy = require( 'passport-http-bearer' ).Strategy;

var verifyToken = function( token, done ) {
  var payload = jwt.decode(token);
  if ( payload == null ){
    return done( null, false );
  }
  console.log(payload);
  var user = users[ payload.username ];
  if ( user == null ||
       user.id !== payload.id ||
       user.username !== payload.username ) {
    return done( null, false );
  }
  jwt.verify( token, user.secret, function ( error, decoded ) {
    if ( error || decoded == null ) {
      return done( error, false );
    }
    return done( null, user );
  })
}
var bearerStrategy = new BearerStrategy( verifyToken )


Passport.use( 'bearer', bearerStrategy );


app.get(
  '/userinfo',
  Passport.authenticate( 'bearer', { session: false } ),
  function ( req, res ) {
    var user = request.user;
    res.send( {
      id: user.id,
      username: user.username
    });
  }
);

app.listen( 3000, function() {
  console.log( 'Listening on 3000' );
});

Here is a token I got from the code F.Y.I.

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJ6YWNrIiwiaWF0IjoxNDU5MDAzMTYxfQ.rhqOX0ICRvivNCwwLNsu5KizNPLQTKPVEqfCuxtII90~
3 Answers

If you are using this,

var decoded = jwt.decode(token, {complete: true}); 
or 
var payload = jwt.decode(token);

Check if the token is similar to this -> Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJ6YWNrIiwiaWF0IjoxNDU5MDAzMTYxfQ.rhqOX0ICRvivNCwwLNsu5KizNPLQTKPVEqfCuxtII90~

Then, before you pass the token token to the jwt.decode, we have to remove the Bearer from the token and then pass it. Bearer is an authorization type and needs to be removed. For example:

var newToken = token.substring(7, bearerString.length); // used to remove the Bearer string and space from the token so that it consists of only header,payload and signature.
var decoded = jwt.decode(newToken, { complete: true });
or 
var payload = jwt.decode(newToken);

I was having this problem too, ends up I needed to throw a JSON.parse() around the token...

var decoded = jwt.decode(JSON.parse(token))
Related