Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JWT decode returns null

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~
like image 294
Zack Avatar asked Mar 26 '16 15:03

Zack


People also ask

Can you decrypt a JWT?

By design, anyone can decode a JWT and read the contents of the header and payload sections. But we need access to the secret key used to create the signature to verify a token's integrity.

What JWT verify returns?

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.

How do you inspect a JWT token?

To visually inspect a JWT, visit JWT.io or use the JWT Debugger Chrome Extension). The JWT token signature is generated using a signing algorithm.


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);
like image 170
lokanath Avatar answered Oct 01 '22 13:10

lokanath


I believe the issue is that when using jwt.decode while also having a secret key you will need to pass in an option to the decode call with complete set to true:

From the jwt docs:

// get the decoded payload ignoring signature, no secretOrPrivateKey needed
var decoded = jwt.decode(token);

// get the decoded payload and header
var decoded = jwt.decode(token, {complete: true});
console.log(decoded.header);
console.log(decoded.payload)

https://github.com/auth0/node-jsonwebtoken

Apparently it might be best to use jwt.verify here:

Warning: This will not verify whether the signature is valid. You should 
not use this for untrusted messages. You most likely want to use jwt.verify instead.
like image 41
omarjmh Avatar answered Oct 01 '22 14:10

omarjmh


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))
like image 31
KennyJacobson Avatar answered Oct 01 '22 14:10

KennyJacobson