Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

initial support for oauth_body_hash on json payloads #1543

Merged
merged 8 commits into from Apr 28, 2015
17 changes: 17 additions & 0 deletions lib/oauth.js
Expand Up @@ -4,6 +4,7 @@ var qs = require('qs')
, caseless = require('caseless')
, uuid = require('node-uuid')
, oauth = require('oauth-sign')
, crypto = require('crypto')


function OAuth (request) {
Expand Down Expand Up @@ -57,6 +58,18 @@ OAuth.prototype.buildParams = function (_oauth, uri, method, query, form, qsLib)
return oa
}

OAuth.prototype.buildBodyHash = function(_oauth, body) {
if (['HMAC-SHA1', 'RSA-SHA1'].indexOf(_oauth.signature_method || 'HMAC-SHA1') < 0) {
throw new Error('oauth: ' + _oauth.signature_method + ' signature_method not supported with body_hash signing.')
}

var shasum = crypto.createHash('sha1')
shasum.update(body || '')
var sha1 = shasum.digest('hex')

return new Buffer(sha1).toString('base64')
}

OAuth.prototype.concatParams = function (oa, sep, wrap) {
wrap = wrap || ''

Expand Down Expand Up @@ -102,6 +115,10 @@ OAuth.prototype.onRequest = function (_oauth) {
'and content-type \'' + formContentType + '\'')
}

if (!form && typeof _oauth.body_hash === 'boolean') {
_oauth.body_hash = this.buildBodyHash(_oauth, this.request.body.toString())
}

var oa = this.buildParams(_oauth, uri, method, query, form, qsLib)

switch (transport) {
Expand Down
8 changes: 4 additions & 4 deletions request.js
Expand Up @@ -542,10 +542,6 @@ Request.prototype.init = function (options) {
}

// Auth must happen last in case signing is dependent on other headers
if (options.oauth) {
self.oauth(options.oauth)
}

if (options.aws) {
self.aws(options.aws)
}
Expand Down Expand Up @@ -630,6 +626,10 @@ Request.prototype.init = function (options) {
}
}

if (options.oauth) {
self.oauth(options.oauth)
}

var protocol = self.proxy && !self.tunnel ? self.proxy.protocol : self.uri.protocol
, defaultModules = {'http:':http, 'https:':https}
, httpModules = self.httpModules || {}
Expand Down
63 changes: 63 additions & 0 deletions tests/test-oauth.js
Expand Up @@ -6,6 +6,7 @@ var oauth = require('oauth-sign')
, path = require('path')
, request = require('../index')
, tape = require('tape')
, crypto = require('crypto')

function getSignature(r) {
var sign
Expand Down Expand Up @@ -527,3 +528,65 @@ tape('body transport_method with prexisting body params', function(t) {
t.end()
})
})

tape('body_hash manual built', function(t) {
function buildBodyHash (body) {
var shasum = crypto.createHash('sha1')
shasum.update(body || '')
var sha1 = shasum.digest('hex')
return new Buffer(sha1).toString('base64')
}

var json = {foo: 'bar'}
var r = request.post(
{ url: 'http://example.com'
, oauth:
{ consumer_secret: 'consumer_secret'
, body_hash: buildBodyHash(JSON.stringify(json))
}
, json: json
})

process.nextTick(function() {
var body_hash = r.headers.Authorization.replace(/.*oauth_body_hash="([^"]+)".*/, '$1')
t.equal('YTVlNzQ0ZDAxNjQ1NDBkMzNiMWQ3ZWE2MTZjMjhmMmZhOTdlNzU0YQ%3D%3D', body_hash)
r.abort()
t.end()
})
})

tape('body_hash automatic built', function(t) {
var r = request.post(
{ url: 'http://example.com'
, oauth:
{ consumer_secret: 'consumer_secret'
, body_hash: true
}
, json: {foo: 'bar'}
})

process.nextTick(function() {
var body_hash = r.headers.Authorization.replace(/.*oauth_body_hash="([^"]+)".*/, '$1')
t.equal('YTVlNzQ0ZDAxNjQ1NDBkMzNiMWQ3ZWE2MTZjMjhmMmZhOTdlNzU0YQ%3D%3D', body_hash)
r.abort()
t.end()
})
})

tape('body_hash PLAINTEXT signature_method', function(t) {
t.throws(function() {
request.post(
{ url: 'http://example.com'
, oauth:
{ consumer_secret: 'consumer_secret'
, body_hash: true
, signature_method: 'PLAINTEXT'
}
, json: {foo: 'bar'}
}, function () {
t.fail('body_hash is not allowed with PLAINTEXT signature_method')
t.end()
})
}, /oauth: PLAINTEXT signature_method not supported with body_hash signing/)
t.end()
})