Skip to content

Commit

Permalink
Merge pull request #1543 from aesopwolf/master
Browse files Browse the repository at this point in the history
Initial support for oauth_body_hash on json payloads
  • Loading branch information
simov committed Apr 28, 2015
2 parents a11878a + e2fa5e9 commit d79ce97
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 4 deletions.
4 changes: 4 additions & 0 deletions README.md
Expand Up @@ -435,6 +435,10 @@ section of the oauth1 spec:
options object.
* `transport_method` defaults to `'header'`
To use [Request Body Hash](https://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html) you can either
* Manually generate the body hash and pass it as a string `body_hash: '...'`
* Automatically generate the body hash by passing `body_hash: true`
[back to top](#table-of-contents)
Expand Down
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()
})

0 comments on commit d79ce97

Please sign in to comment.