All files apiAuth.js

80.95% Statements 34/42
75.51% Branches 37/49
80% Functions 4/5
97.14% Lines 34/35
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 641x 1x 1x 1x   3x 3x     3x 3x 1x 1x   3x                   3x     3x 3x 3x 3x     3x 3x 3x 3x   3x 3x             3x 3x 3x     3x 3x 3x 3x 3x 3x 3x 3x       1x  
var crypto = require('crypto')
var url = require('url')
var HMAC_ALG = 'sha256'
var apiAuth = {
  buildMessage: function(secret, timestamp, reqOpts) {
    var urlInfo = url.parse(reqOpts.path, true)
    var sortedParams = Object.keys(urlInfo.query).sort(function(a, b) {
      return a.localeCompare(b)
    })
    var sortedParts = []
    for (var i = 0; i < sortedParams.length; i++) {
      var paramName = sortedParams[i]
      sortedParts.push(paramName + '=' + urlInfo.query[paramName])
    }
    var parts = [
      reqOpts.method.toUpperCase(),
      reqOpts.host || '',
      reqOpts.contentType || '',
      reqOpts.contentMD5 || '',
      urlInfo.pathname,
      sortedParts.join('&') || '',
      timestamp,
      secret
    ]
    return parts.join('\n')
  },
  buildHmacSig: function(secret, timestamp, reqOpts) {
    var message = apiAuth.buildMessage(secret, timestamp, reqOpts)
    var hmac = crypto.createHmac(HMAC_ALG, new Buffer(secret))
    hmac.update(message)
    return hmac.digest('base64')
  },
  signRequest: function(key, secret, requestOpts, opts) {
    opts = opts || {}
    var urlInfo = url.parse(requestOpts.url)
    requestOpts.headers = requestOpts.headers || {}
    var dateVal = requestOpts.headers.Date || opts.date || new Date().toUTCString()
    // ensure the date header exists
    requestOpts.headers.Date = dateVal
    var reqOpts = {
      method: requestOpts.method || 'GET',
      path: urlInfo.path,
      host: opts.host || urlInfo.host,
      contentType: apiAuth.determineContentType(requestOpts, opts),
      contentMD5: opts.contentMD5 || (requestOpts.headers && requestOpts.headers['Content-MD5'] ? requestOpts.headers['Content-MD5'] : null),
    }
    var signature = apiAuth.buildHmacSig(secret, dateVal, reqOpts)
    requestOpts.headers.Authorization = 'HMACAuth ' + key + ':' + signature
    return requestOpts
  },
  determineContentType: function(requestOpts, opts) {
    Iif (opts && opts.contentType) return opts.contentType
    Iif (requestOpts.form) return 'application/x-www-form-urlencoded'
    Iif (requestOpts.formData) return 'multipart/form-data'
    Iif (requestOpts.json && requestOpts.body) return 'application/json'
    Iif (requestOpts.json && typeof requestOpts.json === 'object') return 'application/json'
    Iif (requestOpts.body && typeof requestOpts.body === 'string') return 'text/plain'
    Iif (requestOpts.body && Buffer.isBuffer(requestOpts.body)) return 'application/octet-stream'
    return null
  }
}
 
module.exports = apiAuth