authenticator.js 1.58 KB
/**
 * Created by lintry on 2017/5/19.
 */

const Authenticator = function (secret, options) {
  if (!(this instanceof Authenticator)) {
    return new Authenticator(secret, options)
  }

  const _ = require('lodash'),
    speakeasy = require('speakeasy'),
    qr = require('qr-image');

  options = options || {};

  this.secret = secret;

  const TOTP_OPTIONS = this.totp_options = {
    secret: this.secret,
    encoding: options.encoding || 'base32',
    step: options.step || 30,
    algorithm: options.algorithm || 'sha512'
  };


  /**
   * 验证token有效性
   * @param token
   */
  this.verify = function(token) {
    return speakeasy.totp.verify(_.merge({}, TOTP_OPTIONS, {token: token}));
  };

  /**
   * 在options.window的范围内验证token的有效性
   * @param token
   * @param window
   */
  this.verifyDelta = function(token, window) {
    return speakeasy.totp.verifyDelta(_.merge({}, TOTP_OPTIONS, {token: token, window: window}));
  };

  /**
   * 获取QR显示值
   * @param title
   * @param issuer
   * @return {string}
   */
  this.getOtpAuth = function (title, issuer) {
    return speakeasy.otpauthURL(_.merge({}, TOTP_OPTIONS, {label: title, issuer: issuer}));
  };

  /**
   * 生成svg的QR图片内容
   * @param title
   * @param issuer
   * @return {*}
   */
  this.getQR = function(title, issuer) {
    return qr.imageSync(this.getOtpAuth(title, issuer), { type: 'svg' });
  };

  /**
   * 生成新的token
   * @return {String}
   */
  this.totp = function () {
    return speakeasy.totp(_.merge({}, TOTP_OPTIONS));
  };

  return this;
};

module.exports = Authenticator;