最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to turn callback function with Promise - Stack Overflow

programmeradmin6浏览0评论

I'm using Bluebird promises and trying to get below function with Promisify working:

var jwt = require('jsonwebtoken');

function _test_encode() {
    var cert = fs.readFileSync('public.pub'); 
    return jwt.verify(token, cert, function(err, decoded) {
        console.log(decoded);
    });
}

I tried below:

var jwt = require('jsonwebtoken');
var Promise = require('bluebird');
var jwtVerifyAsync = Promise.promisify(jwt.verify);

function _test_encode() {
    var cert = fs.readFileSync('public.pub');  // get public key
    return jwtVerifyAsync(token, cert).then(function(decoded) {
        console.log(decoded);
    });
}

But I'm getting:

Possibly unhandled TypeError: Object #<Object> has no method 'decode'

Is there something I'm missing here that I need to get it working? I just want to get _test_encode function to return result of the promise and use it in my other functions.

Verify function is below:

module.exports.verify = function(jwtString, secretOrPublicKey, options, callback) {
  if ((typeof options === 'function') && !callback) {
    callback = options;
    options = {};
  }

  if (!options) options = {};

  var done;

  if (callback) {
    done = function() {
      var args = Array.prototype.slice.call(arguments, 0);
      return process.nextTick(function() {
        callback.apply(null, args);
      });
    };
  } else {
    done = function(err, data) {
      if (err) throw err;
      return data;
    };
  }

  if (!jwtString){
    return done(new JsonWebTokenError('jwt must be provided'));
  }

  var parts = jwtString.split('.');

  if (parts.length !== 3){
    return done(new JsonWebTokenError('jwt malformed'));
  }

  if (parts[2].trim() === '' && secretOrPublicKey){
    return done(new JsonWebTokenError('jwt signature is required'));
  }

  var valid;

  try {
    valid = jws.verify(jwtString, secretOrPublicKey);
  } catch (e) {
    return done(e);
  }

  if (!valid)
    return done(new JsonWebTokenError('invalid signature'));

  var payload;

  try {
   payload = this.decode(jwtString);
  } catch(err) {
    return done(err);
  }

  if (typeof payload.exp !== 'undefined') {
    if (typeof payload.exp !== 'number') {
      return done(new JsonWebTokenError('invalid exp value'));
    }
    if (Math.floor(Date.now() / 1000) >= payload.exp)
      return done(new TokenExpiredError('jwt expired', new Date(payload.exp * 1000)));
  }

  if (options.audience) {
    var audiences = Array.isArray(options.audience)? options.audience : [options.audience];
    var target = Array.isArray(payload.aud) ? payload.aud : [payload.aud];

    var match = target.some(function(aud) { return audiences.indexOf(aud) != -1; });

    if (!match)
      return done(new JsonWebTokenError('jwt audience invalid. expected: ' + payload.aud));
  }

  if (options.issuer) {
    if (payload.iss !== options.issuer)
      return done(new JsonWebTokenError('jwt issuer invalid. expected: ' + payload.iss));
  }

  return done(null, payload);
};

I'm using Bluebird promises and trying to get below function with Promisify working:

var jwt = require('jsonwebtoken');

function _test_encode() {
    var cert = fs.readFileSync('public.pub'); 
    return jwt.verify(token, cert, function(err, decoded) {
        console.log(decoded);
    });
}

I tried below:

var jwt = require('jsonwebtoken');
var Promise = require('bluebird');
var jwtVerifyAsync = Promise.promisify(jwt.verify);

function _test_encode() {
    var cert = fs.readFileSync('public.pub');  // get public key
    return jwtVerifyAsync(token, cert).then(function(decoded) {
        console.log(decoded);
    });
}

But I'm getting:

Possibly unhandled TypeError: Object #<Object> has no method 'decode'

Is there something I'm missing here that I need to get it working? I just want to get _test_encode function to return result of the promise and use it in my other functions.

Verify function is below:

module.exports.verify = function(jwtString, secretOrPublicKey, options, callback) {
  if ((typeof options === 'function') && !callback) {
    callback = options;
    options = {};
  }

  if (!options) options = {};

  var done;

  if (callback) {
    done = function() {
      var args = Array.prototype.slice.call(arguments, 0);
      return process.nextTick(function() {
        callback.apply(null, args);
      });
    };
  } else {
    done = function(err, data) {
      if (err) throw err;
      return data;
    };
  }

  if (!jwtString){
    return done(new JsonWebTokenError('jwt must be provided'));
  }

  var parts = jwtString.split('.');

  if (parts.length !== 3){
    return done(new JsonWebTokenError('jwt malformed'));
  }

  if (parts[2].trim() === '' && secretOrPublicKey){
    return done(new JsonWebTokenError('jwt signature is required'));
  }

  var valid;

  try {
    valid = jws.verify(jwtString, secretOrPublicKey);
  } catch (e) {
    return done(e);
  }

  if (!valid)
    return done(new JsonWebTokenError('invalid signature'));

  var payload;

  try {
   payload = this.decode(jwtString);
  } catch(err) {
    return done(err);
  }

  if (typeof payload.exp !== 'undefined') {
    if (typeof payload.exp !== 'number') {
      return done(new JsonWebTokenError('invalid exp value'));
    }
    if (Math.floor(Date.now() / 1000) >= payload.exp)
      return done(new TokenExpiredError('jwt expired', new Date(payload.exp * 1000)));
  }

  if (options.audience) {
    var audiences = Array.isArray(options.audience)? options.audience : [options.audience];
    var target = Array.isArray(payload.aud) ? payload.aud : [payload.aud];

    var match = target.some(function(aud) { return audiences.indexOf(aud) != -1; });

    if (!match)
      return done(new JsonWebTokenError('jwt audience invalid. expected: ' + payload.aud));
  }

  if (options.issuer) {
    if (payload.iss !== options.issuer)
      return done(new JsonWebTokenError('jwt issuer invalid. expected: ' + payload.iss));
  }

  return done(null, payload);
};
Share Improve this question edited Feb 25, 2015 at 16:29 Passionate Engineer asked Feb 25, 2015 at 16:21 Passionate EngineerPassionate Engineer 10.4k26 gold badges102 silver badges173 bronze badges 3
  • It sounds like jwt.verify doesn't receive the right arguments. It throws an exception which you don't catch. – Felix Kling Commented Feb 25, 2015 at 16:28
  • @FelixKling I've just updated with jwt.verify functioin – Passionate Engineer Commented Feb 25, 2015 at 16:29
  • Possible duplicate of cannot denodeify methods – Bergi Commented Feb 25, 2015 at 16:39
Add a ment  | 

3 Answers 3

Reset to default 2

It's trying to call this.decode, but you've stripped away the context by promisifying it, so this isn't jwt like it expects. You can keep context through promisification by passing it as a second argument:

var jwtVerifyAsync = Promise.promisify(jwt.verify, jwt);

This is an older post, but for anyone reading this now, be aware of which version of Bluebird you are using.

As of v3.0, the second argument passed into the promisify method is an options object. See here.

This code should now be:

var jwtVerifyAsync = Promise.promisify(jwt.verify, {context: jwt})

I just used jwt.verify(token, secret) without promisify. It worked just fine. I suppose with latest version of JWT you don't need to promisify.

发布评论

评论列表(0)

  1. 暂无评论