diff --git a/node_modules/hawk/.npmignore b/node_modules/hawk/.npmignore index 70febc05e4f36..96ed0910bcb69 100644 --- a/node_modules/hawk/.npmignore +++ b/node_modules/hawk/.npmignore @@ -1,20 +1,20 @@ -.idea -*.iml -npm-debug.log -dump.rdb -node_modules -components -build -results.tap -results.xml -npm-shrinkwrap.json -config.json -.DS_Store -*/.DS_Store -*/*/.DS_Store -._* -*/._* -*/*/._* -coverage.* -lib-cov - +.idea +*.iml +npm-debug.log +dump.rdb +node_modules +components +build +results.tap +results.xml +npm-shrinkwrap.json +config.json +.DS_Store +*/.DS_Store +*/*/.DS_Store +._* +*/._* +*/*/._* +coverage.* +lib-cov + diff --git a/node_modules/hawk/.travis.yml b/node_modules/hawk/.travis.yml index 047f7e3d5e1e3..40ca59eeebdd3 100755 --- a/node_modules/hawk/.travis.yml +++ b/node_modules/hawk/.travis.yml @@ -1,5 +1,5 @@ -language: node_js - -node_js: - - 0.10 - +language: node_js + +node_js: + - 0.10 + diff --git a/node_modules/hawk/Makefile b/node_modules/hawk/Makefile deleted file mode 100755 index b102d5ab800b6..0000000000000 --- a/node_modules/hawk/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -test: - @node node_modules/lab/bin/lab -a code -test-cov: - @node node_modules/lab/bin/lab -a code -t 100 -test-cov-html: - @node node_modules/lab/bin/lab -a code -r html -o coverage.html - -.PHONY: test test-cov test-cov-html diff --git a/node_modules/hawk/README.md b/node_modules/hawk/README.md index 0bcd2879012bd..4aff23f3a3f7c 100755 --- a/node_modules/hawk/README.md +++ b/node_modules/hawk/README.md @@ -3,10 +3,9 @@ **Hawk** is an HTTP authentication scheme using a message authentication code (MAC) algorithm to provide partial HTTP request cryptographic verification. For more complex use cases such as access delegation, see [Oz](https://github.com/hueniverse/oz). -Current version: **2.3** +Current version: **3.x** -Note: 2.x is the same exact protocol as 1.1. The version increment reflects a change in the internal error format -used by the module and used by the node API. +Note: 3.x and 2.x are the same exact protocol as 1.1. The version increments reflect changes in the node API. [![Build Status](https://secure.travis-ci.org/hueniverse/hawk.png)](http://travis-ci.org/hueniverse/hawk) diff --git a/node_modules/hawk/example/usage.js b/node_modules/hawk/example/usage.js index 8c063f6cf969a..13b860b4c5ad8 100755 --- a/node_modules/hawk/example/usage.js +++ b/node_modules/hawk/example/usage.js @@ -10,7 +10,7 @@ var Hawk = require('../lib'); var internals = { credentials: { dh37fgj492je: { - id: 'dh37fgj492je', // Required by Hawk.client.header + id: 'dh37fgj492je', // Required by Hawk.client.header key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', algorithm: 'sha256', user: 'Steve' diff --git a/node_modules/hawk/index.js b/node_modules/hawk/index.js deleted file mode 100755 index 4cc88b35877b9..0000000000000 --- a/node_modules/hawk/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./lib'); \ No newline at end of file diff --git a/node_modules/hawk/lib/browser.js b/node_modules/hawk/lib/browser.js index 3307fa243ad75..7ccacf613bbea 100755 --- a/node_modules/hawk/lib/browser.js +++ b/node_modules/hawk/lib/browser.js @@ -238,18 +238,18 @@ hawk.client = { // Parse HTTP WWW-Authenticate header - var attributes = hawk.utils.parseAuthorizationHeader(wwwAuthenticate, ['ts', 'tsm', 'error']); - if (!attributes) { + var wwwAttributes = hawk.utils.parseAuthorizationHeader(wwwAuthenticate, ['ts', 'tsm', 'error']); + if (!wwwAttributes) { return false; } - if (attributes.ts) { - var tsm = hawk.crypto.calculateTsMac(attributes.ts, credentials); - if (tsm !== attributes.tsm) { + if (wwwAttributes.ts) { + var tsm = hawk.crypto.calculateTsMac(wwwAttributes.ts, credentials); + if (tsm !== wwwAttributes.tsm) { return false; } - hawk.utils.setNtpOffset(attributes.ts - Math.floor((new Date()).getTime() / 1000)); // Keep offset at 1 second precision + hawk.utils.setNtpOffset(wwwAttributes.ts - Math.floor((new Date()).getTime() / 1000)); // Keep offset at 1 second precision } } @@ -617,6 +617,7 @@ hawk.utils = { // $lab:coverage:off$ +/* eslint-disable */ // Based on: Crypto-JS v3.1.2 // Copyright (c) 2009-2013, Jeff Mott. All rights reserved. @@ -638,4 +639,5 @@ if (typeof module !== 'undefined' && module.exports) { module.exports = hawk; } +/* eslint-enable */ // $lab:coverage:on$ diff --git a/node_modules/hawk/lib/client.js b/node_modules/hawk/lib/client.js index 7fdd48412aa76..b3e8649e3a621 100755 --- a/node_modules/hawk/lib/client.js +++ b/node_modules/hawk/lib/client.js @@ -153,16 +153,16 @@ exports.authenticate = function (res, credentials, artifacts, options) { // Parse HTTP WWW-Authenticate header - var attributes = Utils.parseAuthorizationHeader(res.headers['www-authenticate'], ['ts', 'tsm', 'error']); - if (attributes instanceof Error) { + var wwwAttributes = Utils.parseAuthorizationHeader(res.headers['www-authenticate'], ['ts', 'tsm', 'error']); + if (wwwAttributes instanceof Error) { return false; } // Validate server timestamp (not used to update clock since it is done via the SNPT client) - if (attributes.ts) { - var tsm = Crypto.calculateTsMac(attributes.ts, credentials); - if (tsm !== attributes.tsm) { + if (wwwAttributes.ts) { + var tsm = Crypto.calculateTsMac(wwwAttributes.ts, credentials); + if (tsm !== wwwAttributes.tsm) { return false; } } diff --git a/node_modules/hawk/lib/server.js b/node_modules/hawk/lib/server.js index a803930311d4d..a325d56a55dc6 100755 --- a/node_modules/hawk/lib/server.js +++ b/node_modules/hawk/lib/server.js @@ -16,7 +16,7 @@ var internals = {}; /* req: node's HTTP request object or an object as follows: - + var request = { method: 'GET', url: '/resource/4?a=1&b=2', @@ -24,21 +24,21 @@ var internals = {}; port: 8080, authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data", mac="6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE="' }; - + credentialsFunc: required function to lookup the set of Hawk credentials based on the provided credentials id. The credentials include the MAC key, MAC algorithm, and other attributes (such as username) needed by the application. This function is the equivalent of verifying the username and password in Basic authentication. - + var credentialsFunc = function (id, callback) { - + // Lookup credentials in database db.lookup(id, function (err, item) { - + if (err || !item) { return callback(err); } - + var credentials = { // Required key: item.key, @@ -46,27 +46,27 @@ var internals = {}; // Application specific user: item.user }; - + return callback(null, credentials); }); }; - + options: { hostHeaderName: optional header field name, used to override the default 'Host' header when used behind a cache of a proxy. Apache2 changes the value of the 'Host' header while preserving the original (which is what the module must verify) in the 'x-forwarded-host' header field. Only used when passed a node Http.ServerRequest object. - - nonceFunc: optional nonce validation function. The function signature is function(nonce, ts, callback) + + nonceFunc: optional nonce validation function. The function signature is function(key, nonce, ts, callback) where 'callback' must be called using the signature function(err). - + timestampSkewSec: optional number of seconds of permitted clock skew for incoming timestamps. Defaults to 60 seconds. Provides a +/- skew which means actual allowed window is double the number of seconds. - + localtimeOffsetMsec: optional local clock time offset express in a number of milliseconds (positive or negative). Defaults to 0. - + payload: optional payload for validation. The client calculates the hash value and includes it via the 'hash' header attribute. The server always ensures the value provided has been included in the request MAC. When this option is provided, it validates the hash value itself. Validation is done by calculating @@ -85,10 +85,10 @@ var internals = {}; exports.authenticate = function (req, credentialsFunc, options, callback) { callback = Hoek.nextTick(callback); - + // Default options - options.nonceFunc = options.nonceFunc || function (nonce, ts, nonceCallback) { return nonceCallback(); }; // No validation + options.nonceFunc = options.nonceFunc || internals.nonceFunc; options.timestampSkewSec = options.timestampSkewSec || 60; // 60 seconds // Application time @@ -182,7 +182,7 @@ exports.authenticate = function (req, credentialsFunc, options, callback) { // Check nonce - options.nonceFunc(attributes.nonce, attributes.ts, function (err) { + options.nonceFunc(credentials.key, attributes.nonce, attributes.ts, function (err) { if (err) { return callback(Boom.unauthorized('Invalid nonce', 'Hawk'), credentials, artifacts); @@ -325,7 +325,7 @@ exports.authenticateBewit = function (req, credentialsFunc, options, callback) { // Extract bewit - // 1 2 3 4 + // 1 2 3 4 var resource = request.url.match(/^(\/.*)([\?&])bewit\=([^&$]*)(?:&(.+))?$/); if (!resource) { return callback(Boom.unauthorized(null, 'Hawk')); @@ -445,10 +445,10 @@ exports.authenticateBewit = function (req, credentialsFunc, options, callback) { exports.authenticateMessage = function (host, port, message, authorization, credentialsFunc, options, callback) { callback = Hoek.nextTick(callback); - + // Default options - options.nonceFunc = options.nonceFunc || function (nonce, ts, nonceCallback) { return nonceCallback(); }; // No validation + options.nonceFunc = options.nonceFunc || internals.nonceFunc; options.timestampSkewSec = options.timestampSkewSec || 60; // 60 seconds // Application time @@ -456,14 +456,14 @@ exports.authenticateMessage = function (host, port, message, authorization, cred var now = Utils.now(options.localtimeOffsetMsec); // Measure now before any other processing // Validate authorization - + if (!authorization.id || !authorization.ts || !authorization.nonce || !authorization.hash || !authorization.mac) { - - return callback(Boom.badRequest('Invalid authorization')) + + return callback(Boom.badRequest('Invalid authorization')); } // Fetch Hawk credentials @@ -514,7 +514,7 @@ exports.authenticateMessage = function (host, port, message, authorization, cred // Check nonce - options.nonceFunc(authorization.nonce, authorization.ts, function (err) { + options.nonceFunc(credentials.key, authorization.nonce, authorization.ts, function (err) { if (err) { return callback(Boom.unauthorized('Invalid nonce', 'Hawk'), credentials); @@ -532,3 +532,9 @@ exports.authenticateMessage = function (host, port, message, authorization, cred }); }); }; + + +internals.nonceFunc = function (key, nonce, ts, nonceCallback) { + + return nonceCallback(); // No validation +}; diff --git a/node_modules/hawk/lib/utils.js b/node_modules/hawk/lib/utils.js index de74606f33468..8d2719abc6821 100755 --- a/node_modules/hawk/lib/utils.js +++ b/node_modules/hawk/lib/utils.js @@ -60,7 +60,7 @@ exports.parseRequest = function (req, options) { if (!req.headers) { return req; } - + // Obtain host and port information if (!options.host || !options.port) { @@ -157,8 +157,8 @@ exports.parseAuthorizationHeader = function (header, keys) { }; -exports.unauthorized = function (message) { +exports.unauthorized = function (message, attributes) { - return Boom.unauthorized(message, 'Hawk'); + return Boom.unauthorized(message, 'Hawk', attributes); }; diff --git a/node_modules/hawk/package.json b/node_modules/hawk/package.json index d542c3e6db728..81abc2e1c658c 100644 --- a/node_modules/hawk/package.json +++ b/node_modules/hawk/package.json @@ -1,35 +1,36 @@ { "_args": [ [ - "hawk@~2.3.0", + "hawk@~3.1.0", "/Users/rebecca/code/npm/node_modules/request" ] ], - "_from": "hawk@>=2.3.0 <2.4.0", - "_id": "hawk@2.3.1", + "_from": "hawk@>=3.1.0 <3.2.0", + "_id": "hawk@3.1.0", "_inCache": true, "_location": "/hawk", + "_nodeVersion": "0.10.38", "_npmUser": { - "email": "eran@hueniverse.com", + "email": "eran@hammer.io", "name": "hueniverse" }, - "_npmVersion": "1.4.28", + "_npmVersion": "2.10.0", "_phantomChildren": {}, "_requested": { "name": "hawk", - "raw": "hawk@~2.3.0", - "rawSpec": "~2.3.0", + "raw": "hawk@~3.1.0", + "rawSpec": "~3.1.0", "scope": null, - "spec": ">=2.3.0 <2.4.0", + "spec": ">=3.1.0 <3.2.0", "type": "range" }, "_requiredBy": [ "/request" ], - "_resolved": "https://registry.npmjs.org/hawk/-/hawk-2.3.1.tgz", - "_shasum": "1e731ce39447fa1d0f6d707f7bceebec0fd1ec1f", + "_resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.0.tgz", + "_shasum": "8a13ae19977ec607602f3f0b9fd676f18c384e44", "_shrinkwrap": null, - "_spec": "hawk@~2.3.0", + "_spec": "hawk@~3.1.0", "_where": "/Users/rebecca/code/npm/node_modules/request", "author": { "email": "eran@hammer.io", @@ -42,7 +43,7 @@ }, "contributors": [], "dependencies": { - "boom": "2.x.x", + "boom": "^2.8.x", "cryptiles": "2.x.x", "hoek": "2.x.x", "sntp": "1.x.x" @@ -54,27 +55,22 @@ }, "directories": {}, "dist": { - "shasum": "1e731ce39447fa1d0f6d707f7bceebec0fd1ec1f", - "tarball": "http://registry.npmjs.org/hawk/-/hawk-2.3.1.tgz" + "shasum": "8a13ae19977ec607602f3f0b9fd676f18c384e44", + "tarball": "http://registry.npmjs.org/hawk/-/hawk-3.1.0.tgz" }, "engines": { - "node": ">=0.8.0" + "node": ">=0.10.32" }, - "gitHead": "492632da51ecedd5f59ce96f081860ad24ce6532", - "homepage": "https://github.com/hueniverse/hawk", + "gitHead": "fdb9d05e383d5237631eaddc4f51422e54fa8b52", + "homepage": "https://github.com/hueniverse/hawk#readme", "keywords": [ "authentication", "hawk", "http", "scheme" ], - "licenses": [ - { - "type": "BSD", - "url": "http://github.com/hueniverse/hawk/raw/master/LICENSE" - } - ], - "main": "index", + "license": "BSD-3-Clause", + "main": "lib/index.js", "maintainers": [ { "name": "hueniverse", @@ -85,10 +81,11 @@ "optionalDependencies": {}, "repository": { "type": "git", - "url": "git://github.com/hueniverse/hawk" + "url": "git://github.com/hueniverse/hawk.git" }, "scripts": { - "test": "make test-cov" + "test": "lab -a code -t 100 -L", + "test-cov-html": "lab -a code -r html -o coverage.html" }, - "version": "2.3.1" + "version": "3.1.0" } diff --git a/node_modules/hawk/test/browser.js b/node_modules/hawk/test/browser.js index a45241389c594..49dc4cadd1660 100755 --- a/node_modules/hawk/test/browser.js +++ b/node_modules/hawk/test/browser.js @@ -82,7 +82,7 @@ describe('Browser', function () { }); }); - describe('#bewit', function () { + describe('bewit()', function () { it('returns a valid bewit value', function (done) { @@ -516,7 +516,7 @@ describe('Browser', function () { var localStorage = new Browser.internals.LocalStorage(); - Browser.utils.setStorage(localStorage) + Browser.utils.setStorage(localStorage); Browser.utils.setNtpOffset(60 * 60 * 1000); var header = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data' }); @@ -741,7 +741,7 @@ describe('Browser', function () { describe('client', function () { - describe('#header', function () { + describe('header()', function () { it('returns a valid authorization header (sha1)', function (done) { @@ -950,7 +950,7 @@ describe('Browser', function () { }); }); - describe('#authenticate', function () { + describe('authenticate()', function () { it('skips tsm validation when missing ts', function (done) { @@ -1119,7 +1119,7 @@ describe('Browser', function () { }); }); - describe('#message', function () { + describe('message()', function () { it('generates an authorization then successfully parse it', function (done) { @@ -1270,7 +1270,7 @@ describe('Browser', function () { }); }); - describe('#authenticateTimestamp', function (done) { + describe('authenticateTimestamp()', function (done) { it('validates a timestamp', function (done) { @@ -1342,7 +1342,7 @@ describe('Browser', function () { describe('utils', function () { - describe('#setStorage', function () { + describe('setStorage()', function () { it('sets storage for the first time', function (done) { @@ -1358,21 +1358,29 @@ describe('Browser', function () { }); }); - describe('#setNtpOffset', function (done) { + describe('setNtpOffset()', function (done) { - it('catches localStorage errors', function (done) { + it('catches localStorage errors', { parallel: false }, function (done) { var orig = Browser.utils.storage.setItem; - var error = console.error; + var consoleOrig = console.error; var count = 0; - console.error = function () { if (count++ === 2) { console.error = error; } }; + console.error = function () { + + if (count++ === 2) { + + console.error = consoleOrig; + } + }; + Browser.utils.storage.setItem = function () { Browser.utils.storage.setItem = orig; - throw new Error() + throw new Error(); }; expect(function () { + Browser.utils.setNtpOffset(100); }).not.to.throw(); @@ -1380,7 +1388,7 @@ describe('Browser', function () { }); }); - describe('#parseAuthorizationHeader', function (done) { + describe('parseAuthorizationHeader()', function (done) { it('returns null on missing header', function (done) { @@ -1419,7 +1427,7 @@ describe('Browser', function () { }); }); - describe('#parseUri', function () { + describe('parseUri()', function () { it('returns empty port when unknown scheme', function (done) { @@ -1436,18 +1444,16 @@ describe('Browser', function () { }); }); - var str = "https://www.google.ca/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=url"; - var base64str = "aHR0cHM6Ly93d3cuZ29vZ2xlLmNhL3dlYmhwP3NvdXJjZWlkPWNocm9tZS1pbnN0YW50Jmlvbj0xJmVzcHY9MiZpZT1VVEYtOCNxPXVybA"; + var str = 'https://www.google.ca/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=url'; + var base64str = 'aHR0cHM6Ly93d3cuZ29vZ2xlLmNhL3dlYmhwP3NvdXJjZWlkPWNocm9tZS1pbnN0YW50Jmlvbj0xJmVzcHY9MiZpZT1VVEYtOCNxPXVybA'; - describe('#base64urlEncode', function () { + describe('base64urlEncode()', function () { it('should base64 URL-safe decode a string', function (done) { expect(Browser.utils.base64urlEncode(str)).to.equal(base64str); done(); }); - }); - }); }); diff --git a/node_modules/hawk/test/client.js b/node_modules/hawk/test/client.js index 5983897b215b1..d6be231ae8fd1 100755 --- a/node_modules/hawk/test/client.js +++ b/node_modules/hawk/test/client.js @@ -19,425 +19,422 @@ var it = lab.test; var expect = Code.expect; -describe('Hawk', function () { +describe('Client', function () { - describe('client', function () { + describe('header()', function () { - describe('#header', function () { + it('returns a valid authorization header (sha1)', function (done) { - it('returns a valid authorization header (sha1)', function (done) { - - var credentials = { - id: '123456', - key: '2983d45yun89q', - algorithm: 'sha1' - }; + var credentials = { + id: '123456', + key: '2983d45yun89q', + algorithm: 'sha1' + }; - var header = Hawk.client.header('http://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about' }).field; - expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="bsvY3IfUllw6V5rvk4tStEvpBhE=", ext="Bazinga!", mac="qbf1ZPG/r/e06F4ht+T77LXi5vw="'); - done(); - }); + var header = Hawk.client.header('http://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about' }).field; + expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="bsvY3IfUllw6V5rvk4tStEvpBhE=", ext="Bazinga!", mac="qbf1ZPG/r/e06F4ht+T77LXi5vw="'); + done(); + }); + + it('returns a valid authorization header (sha256)', function (done) { + + var credentials = { + id: '123456', + key: '2983d45yun89q', + algorithm: 'sha256' + }; + + var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }).field; + expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", ext="Bazinga!", mac="q1CwFoSHzPZSkbIvl0oYlD+91rBUEvFk763nMjMndj8="'); + done(); + }); + + it('returns a valid authorization header (no ext)', function (done) { + + var credentials = { + id: '123456', + key: '2983d45yun89q', + algorithm: 'sha256' + }; + + var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }).field; + expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="'); + done(); + }); + + it('returns a valid authorization header (null ext)', function (done) { + + var credentials = { + id: '123456', + key: '2983d45yun89q', + algorithm: 'sha256' + }; + + var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain', ext: null }).field; + expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="'); + done(); + }); + + it('returns a valid authorization header (empty payload)', function (done) { + + var credentials = { + id: '123456', + key: '2983d45yun89q', + algorithm: 'sha256' + }; + + var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: '', contentType: 'text/plain' }).field; + expect(header).to.equal('Hawk id=\"123456\", ts=\"1353809207\", nonce=\"Ygvqdz\", hash=\"q/t+NNAkQZNlq/aAD6PlexImwQTxwgT2MahfTa9XRLA=\", mac=\"U5k16YEzn3UnBHKeBzsDXn067Gu3R4YaY6xOt9PYRZM=\"'); + done(); + }); + + it('returns a valid authorization header (pre hashed payload)', function (done) { + + var credentials = { + id: '123456', + key: '2983d45yun89q', + algorithm: 'sha256' + }; + + var options = { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }; + options.hash = Hawk.crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType); + var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', options).field; + expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="'); + done(); + }); + + it('errors on missing uri', function (done) { + + var header = Hawk.client.header('', 'POST'); + expect(header.field).to.equal(''); + expect(header.err).to.equal('Invalid argument type'); + done(); + }); + + it('errors on invalid uri', function (done) { + + var header = Hawk.client.header(4, 'POST'); + expect(header.field).to.equal(''); + expect(header.err).to.equal('Invalid argument type'); + done(); + }); + + it('errors on missing method', function (done) { + + var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', ''); + expect(header.field).to.equal(''); + expect(header.err).to.equal('Invalid argument type'); + done(); + }); + + it('errors on invalid method', function (done) { + + var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 5); + expect(header.field).to.equal(''); + expect(header.err).to.equal('Invalid argument type'); + done(); + }); + + it('errors on missing options', function (done) { + + var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST'); + expect(header.field).to.equal(''); + expect(header.err).to.equal('Invalid argument type'); + done(); + }); + + it('errors on invalid credentials (id)', function (done) { + + var credentials = { + key: '2983d45yun89q', + algorithm: 'sha256' + }; + + var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207 }); + expect(header.field).to.equal(''); + expect(header.err).to.equal('Invalid credential object'); + done(); + }); + + it('errors on missing credentials', function (done) { + + var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { ext: 'Bazinga!', timestamp: 1353809207 }); + expect(header.field).to.equal(''); + expect(header.err).to.equal('Invalid credential object'); + done(); + }); + + it('errors on invalid credentials', function (done) { + + var credentials = { + id: '123456', + algorithm: 'sha256' + }; + + var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207 }); + expect(header.field).to.equal(''); + expect(header.err).to.equal('Invalid credential object'); + done(); + }); + + it('errors on invalid algorithm', function (done) { + + var credentials = { + id: '123456', + key: '2983d45yun89q', + algorithm: 'hmac-sha-0' + }; + + var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, payload: 'something, anything!', ext: 'Bazinga!', timestamp: 1353809207 }); + expect(header.field).to.equal(''); + expect(header.err).to.equal('Unknown algorithm'); + done(); + }); + }); + + describe('authenticate()', function () { + + it('returns false on invalid header', function (done) { + + var res = { + headers: { + 'server-authorization': 'Hawk mac="abc", bad="xyz"' + } + }; + + expect(Hawk.client.authenticate(res, {})).to.equal(false); + done(); + }); + + it('returns false on invalid mac', function (done) { + + var res = { + headers: { + 'content-type': 'text/plain', + 'server-authorization': 'Hawk mac="_IJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"' + } + }; + + var artifacts = { + method: 'POST', + host: 'example.com', + port: '8080', + resource: '/resource/4?filter=a', + ts: '1362336900', + nonce: 'eb5S_L', + hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=', + ext: 'some-app-data', + app: undefined, + dlg: undefined, + mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=', + id: '123456' + }; + + var credentials = { + id: '123456', + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: 'sha256', + user: 'steve' + }; + + expect(Hawk.client.authenticate(res, credentials, artifacts)).to.equal(false); + done(); + }); + + it('returns true on ignoring hash', function (done) { + + var res = { + headers: { + 'content-type': 'text/plain', + 'server-authorization': 'Hawk mac="XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"' + } + }; + + var artifacts = { + method: 'POST', + host: 'example.com', + port: '8080', + resource: '/resource/4?filter=a', + ts: '1362336900', + nonce: 'eb5S_L', + hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=', + ext: 'some-app-data', + app: undefined, + dlg: undefined, + mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=', + id: '123456' + }; + + var credentials = { + id: '123456', + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: 'sha256', + user: 'steve' + }; + + expect(Hawk.client.authenticate(res, credentials, artifacts)).to.equal(true); + done(); + }); + + it('fails on invalid WWW-Authenticate header format', function (done) { + + var header = 'Hawk ts="1362346425875", tsm="PhwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", x="Stale timestamp"'; + expect(Hawk.client.authenticate({ headers: { 'www-authenticate': header } }, {})).to.equal(false); + done(); + }); - it('returns a valid authorization header (sha256)', function (done) { + it('fails on invalid WWW-Authenticate header format', function (done) { - var credentials = { - id: '123456', - key: '2983d45yun89q', - algorithm: 'sha256' - }; + var credentials = { + id: '123456', + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: 'sha256', + user: 'steve' + }; - var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }).field; - expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", ext="Bazinga!", mac="q1CwFoSHzPZSkbIvl0oYlD+91rBUEvFk763nMjMndj8="'); - done(); - }); - - it('returns a valid authorization header (no ext)', function (done) { + var header = 'Hawk ts="1362346425875", tsm="hwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", error="Stale timestamp"'; + expect(Hawk.client.authenticate({ headers: { 'www-authenticate': header } }, credentials)).to.equal(false); + done(); + }); + + it('skips tsm validation when missing ts', function (done) { + + var header = 'Hawk error="Stale timestamp"'; + expect(Hawk.client.authenticate({ headers: { 'www-authenticate': header } }, {})).to.equal(true); + done(); + }); + }); + + describe('message()', function () { + + it('generates authorization', function (done) { - var credentials = { - id: '123456', - key: '2983d45yun89q', - algorithm: 'sha256' - }; - - var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }).field; - expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="'); - done(); - }); - - it('returns a valid authorization header (null ext)', function (done) { + var credentials = { + id: '123456', + key: '2983d45yun89q', + algorithm: 'sha1' + }; - var credentials = { - id: '123456', - key: '2983d45yun89q', - algorithm: 'sha256' - }; - - var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain', ext: null }).field; - expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="'); - done(); - }); - - it('returns a valid authorization header (empty payload)', function (done) { - - var credentials = { - id: '123456', - key: '2983d45yun89q', - algorithm: 'sha256' - }; - - var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: '', contentType: 'text/plain' }).field; - expect(header).to.equal('Hawk id=\"123456\", ts=\"1353809207\", nonce=\"Ygvqdz\", hash=\"q/t+NNAkQZNlq/aAD6PlexImwQTxwgT2MahfTa9XRLA=\", mac=\"U5k16YEzn3UnBHKeBzsDXn067Gu3R4YaY6xOt9PYRZM=\"'); - done(); - }); - - it('returns a valid authorization header (pre hashed payload)', function (done) { - - var credentials = { - id: '123456', - key: '2983d45yun89q', - algorithm: 'sha256' - }; - - var options = { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }; - options.hash = Hawk.crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType); - var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', options).field; - expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="'); - done(); - }); - - it('errors on missing uri', function (done) { - - var header = Hawk.client.header('', 'POST'); - expect(header.field).to.equal(''); - expect(header.err).to.equal('Invalid argument type'); - done(); - }); - - it('errors on invalid uri', function (done) { - - var header = Hawk.client.header(4, 'POST'); - expect(header.field).to.equal(''); - expect(header.err).to.equal('Invalid argument type'); - done(); - }); - - it('errors on missing method', function (done) { - - var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', ''); - expect(header.field).to.equal(''); - expect(header.err).to.equal('Invalid argument type'); - done(); - }); - - it('errors on invalid method', function (done) { - - var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 5); - expect(header.field).to.equal(''); - expect(header.err).to.equal('Invalid argument type'); - done(); - }); - - it('errors on missing options', function (done) { - - var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST'); - expect(header.field).to.equal(''); - expect(header.err).to.equal('Invalid argument type'); - done(); - }); - - it('errors on invalid credentials (id)', function (done) { - - var credentials = { - key: '2983d45yun89q', - algorithm: 'sha256' - }; - - var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207 }); - expect(header.field).to.equal(''); - expect(header.err).to.equal('Invalid credential object'); - done(); - }); - - it('errors on missing credentials', function (done) { - - var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { ext: 'Bazinga!', timestamp: 1353809207 }); - expect(header.field).to.equal(''); - expect(header.err).to.equal('Invalid credential object'); - done(); - }); - - it('errors on invalid credentials', function (done) { - - var credentials = { - id: '123456', - algorithm: 'sha256' - }; - - var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207 }); - expect(header.field).to.equal(''); - expect(header.err).to.equal('Invalid credential object'); - done(); - }); - - it('errors on invalid algorithm', function (done) { - - var credentials = { - id: '123456', - key: '2983d45yun89q', - algorithm: 'hmac-sha-0' - }; - - var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, payload: 'something, anything!', ext: 'Bazinga!', timestamp: 1353809207 }); - expect(header.field).to.equal(''); - expect(header.err).to.equal('Unknown algorithm'); - done(); - }); + var auth = Hawk.client.message('example.com', 80, 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' }); + expect(auth).to.exist(); + expect(auth.ts).to.equal(1353809207); + expect(auth.nonce).to.equal('abc123'); + done(); }); - describe('#authenticate', function () { - - it('returns false on invalid header', function (done) { - - var res = { - headers: { - 'server-authorization': 'Hawk mac="abc", bad="xyz"' - } - }; - - expect(Hawk.client.authenticate(res, {})).to.equal(false); - done(); - }); - - it('returns false on invalid mac', function (done) { - - var res = { - headers: { - 'content-type': 'text/plain', - 'server-authorization': 'Hawk mac="_IJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"' - } - }; - - var artifacts = { - method: 'POST', - host: 'example.com', - port: '8080', - resource: '/resource/4?filter=a', - ts: '1362336900', - nonce: 'eb5S_L', - hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=', - ext: 'some-app-data', - app: undefined, - dlg: undefined, - mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=', - id: '123456' - }; - - var credentials = { - id: '123456', - key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', - algorithm: 'sha256', - user: 'steve' - }; - - expect(Hawk.client.authenticate(res, credentials, artifacts)).to.equal(false); - done(); - }); - - it('returns true on ignoring hash', function (done) { - - var res = { - headers: { - 'content-type': 'text/plain', - 'server-authorization': 'Hawk mac="XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"' - } - }; - - var artifacts = { - method: 'POST', - host: 'example.com', - port: '8080', - resource: '/resource/4?filter=a', - ts: '1362336900', - nonce: 'eb5S_L', - hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=', - ext: 'some-app-data', - app: undefined, - dlg: undefined, - mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=', - id: '123456' - }; - - var credentials = { - id: '123456', - key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', - algorithm: 'sha256', - user: 'steve' - }; - - expect(Hawk.client.authenticate(res, credentials, artifacts)).to.equal(true); - done(); - }); - - it('fails on invalid WWW-Authenticate header format', function (done) { - - var header = 'Hawk ts="1362346425875", tsm="PhwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", x="Stale timestamp"'; - expect(Hawk.client.authenticate({ headers: { 'www-authenticate': header } }, {})).to.equal(false); - done(); - }); - - it('fails on invalid WWW-Authenticate header format', function (done) { - - var credentials = { - id: '123456', - key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', - algorithm: 'sha256', - user: 'steve' - }; - - var header = 'Hawk ts="1362346425875", tsm="hwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", error="Stale timestamp"'; - expect(Hawk.client.authenticate({ headers: { 'www-authenticate': header } }, credentials)).to.equal(false); - done(); - }); - - it('skips tsm validation when missing ts', function (done) { - - var header = 'Hawk error="Stale timestamp"'; - expect(Hawk.client.authenticate({ headers: { 'www-authenticate': header } }, {})).to.equal(true); - done(); - }); + it('errors on invalid host', function (done) { + + var credentials = { + id: '123456', + key: '2983d45yun89q', + algorithm: 'sha1' + }; + + var auth = Hawk.client.message(5, 80, 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' }); + expect(auth).to.not.exist(); + done(); + }); + + it('errors on invalid port', function (done) { + + var credentials = { + id: '123456', + key: '2983d45yun89q', + algorithm: 'sha1' + }; + + var auth = Hawk.client.message('example.com', '80', 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' }); + expect(auth).to.not.exist(); + done(); }); - describe('#message', function () { - - it('generates authorization', function (done) { - - var credentials = { - id: '123456', - key: '2983d45yun89q', - algorithm: 'sha1' - }; + it('errors on missing host', function (done) { + + var credentials = { + id: '123456', + key: '2983d45yun89q', + algorithm: 'sha1' + }; + + var auth = Hawk.client.message('example.com', 0, 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' }); + expect(auth).to.not.exist(); + done(); + }); + + it('errors on null message', function (done) { + + var credentials = { + id: '123456', + key: '2983d45yun89q', + algorithm: 'sha1' + }; + + var auth = Hawk.client.message('example.com', 80, null, { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' }); + expect(auth).to.not.exist(); + done(); + }); + + it('errors on missing message', function (done) { + + var credentials = { + id: '123456', + key: '2983d45yun89q', + algorithm: 'sha1' + }; + + var auth = Hawk.client.message('example.com', 80, undefined, { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' }); + expect(auth).to.not.exist(); + done(); + }); + + it('errors on invalid message', function (done) { + + var credentials = { + id: '123456', + key: '2983d45yun89q', + algorithm: 'sha1' + }; + + var auth = Hawk.client.message('example.com', 80, 5, { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' }); + expect(auth).to.not.exist(); + done(); + }); + + it('errors on missing options', function (done) { + + var credentials = { + id: '123456', + key: '2983d45yun89q', + algorithm: 'sha1' + }; + + var auth = Hawk.client.message('example.com', 80, 'I am the boodyman'); + expect(auth).to.not.exist(); + done(); + }); + + it('errors on invalid credentials (id)', function (done) { + + var credentials = { + key: '2983d45yun89q', + algorithm: 'sha1' + }; + + var auth = Hawk.client.message('example.com', 80, 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' }); + expect(auth).to.not.exist(); + done(); + }); + + it('errors on invalid credentials (key)', function (done) { + + var credentials = { + id: '123456', + algorithm: 'sha1' + }; - var auth = Hawk.client.message('example.com', 80, 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' }); - expect(auth).to.exist(); - expect(auth.ts).to.equal(1353809207); - expect(auth.nonce).to.equal('abc123'); - done(); - }); - - it('errors on invalid host', function (done) { - - var credentials = { - id: '123456', - key: '2983d45yun89q', - algorithm: 'sha1' - }; - - var auth = Hawk.client.message(5, 80, 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' }); - expect(auth).to.not.exist(); - done(); - }); - - it('errors on invalid port', function (done) { - - var credentials = { - id: '123456', - key: '2983d45yun89q', - algorithm: 'sha1' - }; - - var auth = Hawk.client.message('example.com', '80', 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' }); - expect(auth).to.not.exist(); - done(); - }); - - it('errors on missing host', function (done) { - - var credentials = { - id: '123456', - key: '2983d45yun89q', - algorithm: 'sha1' - }; - - var auth = Hawk.client.message('example.com', 0, 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' }); - expect(auth).to.not.exist(); - done(); - }); - - it('errors on null message', function (done) { - - var credentials = { - id: '123456', - key: '2983d45yun89q', - algorithm: 'sha1' - }; - - var auth = Hawk.client.message('example.com', 80, null, { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' }); - expect(auth).to.not.exist(); - done(); - }); - - it('errors on missing message', function (done) { - - var credentials = { - id: '123456', - key: '2983d45yun89q', - algorithm: 'sha1' - }; - - var auth = Hawk.client.message('example.com', 80, undefined, { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' }); - expect(auth).to.not.exist(); - done(); - }); - - it('errors on invalid message', function (done) { - - var credentials = { - id: '123456', - key: '2983d45yun89q', - algorithm: 'sha1' - }; - - var auth = Hawk.client.message('example.com', 80, 5, { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' }); - expect(auth).to.not.exist(); - done(); - }); - - it('errors on missing options', function (done) { - - var credentials = { - id: '123456', - key: '2983d45yun89q', - algorithm: 'sha1' - }; - - var auth = Hawk.client.message('example.com', 80, 'I am the boodyman'); - expect(auth).to.not.exist(); - done(); - }); - - it('errors on invalid credentials (id)', function (done) { - - var credentials = { - key: '2983d45yun89q', - algorithm: 'sha1' - }; - - var auth = Hawk.client.message('example.com', 80, 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' }); - expect(auth).to.not.exist(); - done(); - }); - - it('errors on invalid credentials (key)', function (done) { - - var credentials = { - id: '123456', - algorithm: 'sha1' - }; - - var auth = Hawk.client.message('example.com', 80, 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' }); - expect(auth).to.not.exist(); - done(); - }); + var auth = Hawk.client.message('example.com', 80, 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' }); + expect(auth).to.not.exist(); + done(); }); }); }); diff --git a/node_modules/hawk/test/crypto.js b/node_modules/hawk/test/crypto.js index f2d3d45801cb8..1131628bfb00a 100755 --- a/node_modules/hawk/test/crypto.js +++ b/node_modules/hawk/test/crypto.js @@ -18,69 +18,53 @@ var it = lab.test; var expect = Code.expect; -describe('Hawk', function () { - - describe('Crypto', function () { - - describe('#generateNormalizedString', function () { - - it('should return a valid normalized string', function (done) { - - expect(Hawk.crypto.generateNormalizedString('header', { - credentials: { - key: 'dasdfasdf', - algorithm: 'sha256' - }, - ts: 1357747017, - nonce: 'k3k4j5', - method: 'GET', - resource: '/resource/something', - host: 'example.com', - port: 8080 - })).to.equal('hawk.1.header\n1357747017\nk3k4j5\nGET\n/resource/something\nexample.com\n8080\n\n\n'); - - done(); - }); - - it('should return a valid normalized string (ext)', function (done) { - - expect(Hawk.crypto.generateNormalizedString('header', { - credentials: { - key: 'dasdfasdf', - algorithm: 'sha256' - }, - ts: 1357747017, - nonce: 'k3k4j5', - method: 'GET', - resource: '/resource/something', - host: 'example.com', - port: 8080, - ext: 'this is some app data' - })).to.equal('hawk.1.header\n1357747017\nk3k4j5\nGET\n/resource/something\nexample.com\n8080\n\nthis is some app data\n'); - - done(); - }); - - it('should return a valid normalized string (payload + ext)', function (done) { - - expect(Hawk.crypto.generateNormalizedString('header', { - credentials: { - key: 'dasdfasdf', - algorithm: 'sha256' - }, - ts: 1357747017, - nonce: 'k3k4j5', - method: 'GET', - resource: '/resource/something', - host: 'example.com', - port: 8080, - hash: 'U4MKKSmiVxk37JCCrAVIjV/OhB3y+NdwoCr6RShbVkE=', - ext: 'this is some app data' - })).to.equal('hawk.1.header\n1357747017\nk3k4j5\nGET\n/resource/something\nexample.com\n8080\nU4MKKSmiVxk37JCCrAVIjV/OhB3y+NdwoCr6RShbVkE=\nthis is some app data\n'); - - done(); - }); +describe('Crypto', function () { + + describe('generateNormalizedString()', function () { + + it('should return a valid normalized string', function (done) { + + expect(Hawk.crypto.generateNormalizedString('header', { + ts: 1357747017, + nonce: 'k3k4j5', + method: 'GET', + resource: '/resource/something', + host: 'example.com', + port: 8080 + })).to.equal('hawk.1.header\n1357747017\nk3k4j5\nGET\n/resource/something\nexample.com\n8080\n\n\n'); + + done(); + }); + + it('should return a valid normalized string (ext)', function (done) { + + expect(Hawk.crypto.generateNormalizedString('header', { + ts: 1357747017, + nonce: 'k3k4j5', + method: 'GET', + resource: '/resource/something', + host: 'example.com', + port: 8080, + ext: 'this is some app data' + })).to.equal('hawk.1.header\n1357747017\nk3k4j5\nGET\n/resource/something\nexample.com\n8080\n\nthis is some app data\n'); + + done(); + }); + + it('should return a valid normalized string (payload + ext)', function (done) { + + expect(Hawk.crypto.generateNormalizedString('header', { + ts: 1357747017, + nonce: 'k3k4j5', + method: 'GET', + resource: '/resource/something', + host: 'example.com', + port: 8080, + hash: 'U4MKKSmiVxk37JCCrAVIjV/OhB3y+NdwoCr6RShbVkE=', + ext: 'this is some app data' + })).to.equal('hawk.1.header\n1357747017\nk3k4j5\nGET\n/resource/something\nexample.com\n8080\nU4MKKSmiVxk37JCCrAVIjV/OhB3y+NdwoCr6RShbVkE=\nthis is some app data\n'); + + done(); }); }); }); - diff --git a/node_modules/hawk/test/message.js b/node_modules/hawk/test/message.js deleted file mode 100755 index b0494cc456157..0000000000000 --- a/node_modules/hawk/test/message.js +++ /dev/null @@ -1,261 +0,0 @@ -// Load modules - -var Url = require('url'); -var Code = require('code'); -var Hawk = require('../lib'); -var Hoek = require('hoek'); -var Lab = require('lab'); - - -// Declare internals - -var internals = {}; - - -// Test shortcuts - -var lab = exports.lab = Lab.script(); -var describe = lab.experiment; -var it = lab.test; -var expect = Code.expect; - - -describe('Hawk', function () { - - var credentialsFunc = function (id, callback) { - - var credentials = { - id: id, - key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', - algorithm: (id === '1' ? 'sha1' : 'sha256'), - user: 'steve' - }; - - return callback(null, credentials); - }; - - it('should generate an authorization then successfully parse it', function (done) { - - credentialsFunc('123456', function (err, credentials) { - - var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); - expect(auth).to.exist(); - - Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials) { - - expect(err).to.not.exist(); - expect(credentials.user).to.equal('steve'); - done(); - }); - }); - }); - - it('should fail authorization on mismatching host', function (done) { - - credentialsFunc('123456', function (err, credentials) { - - var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); - expect(auth).to.exist(); - - Hawk.server.authenticateMessage('example1.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials) { - - expect(err).to.exist(); - expect(err.message).to.equal('Bad mac'); - done(); - }); - }); - }); - - it('should fail authorization on stale timestamp', function (done) { - - credentialsFunc('123456', function (err, credentials) { - - var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); - expect(auth).to.exist(); - - Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, { localtimeOffsetMsec: 100000 }, function (err, credentials) { - - expect(err).to.exist(); - expect(err.message).to.equal('Stale timestamp'); - done(); - }); - }); - }); - - it('overrides timestampSkewSec', function (done) { - - credentialsFunc('123456', function (err, credentials) { - - var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials, localtimeOffsetMsec: 100000 }); - expect(auth).to.exist(); - - Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, { timestampSkewSec: 500 }, function (err, credentials) { - - expect(err).to.not.exist(); - done(); - }); - }); - }); - - it('should fail authorization on invalid authorization', function (done) { - - credentialsFunc('123456', function (err, credentials) { - - var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); - expect(auth).to.exist(); - delete auth.id; - - Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials) { - - expect(err).to.exist(); - expect(err.message).to.equal('Invalid authorization'); - done(); - }); - }); - }); - - it('should fail authorization on bad hash', function (done) { - - credentialsFunc('123456', function (err, credentials) { - - var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); - expect(auth).to.exist(); - - Hawk.server.authenticateMessage('example.com', 8080, 'some message1', auth, credentialsFunc, {}, function (err, credentials) { - - expect(err).to.exist(); - expect(err.message).to.equal('Bad message hash'); - done(); - }); - }); - }); - - it('should fail authorization on nonce error', function (done) { - - credentialsFunc('123456', function (err, credentials) { - - var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); - expect(auth).to.exist(); - - Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, { nonceFunc: function (nonce, ts, callback) { callback (new Error('kaboom')); } }, function (err, credentials) { - - expect(err).to.exist(); - expect(err.message).to.equal('Invalid nonce'); - done(); - }); - }); - }); - - it('should fail authorization on credentials error', function (done) { - - credentialsFunc('123456', function (err, credentials) { - - var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); - expect(auth).to.exist(); - - var errFunc = function (id, callback) { - - callback(new Error('kablooey')); - }; - - Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials) { - - expect(err).to.exist(); - expect(err.message).to.equal('kablooey'); - done(); - }); - }); - }); - - it('should fail authorization on missing credentials', function (done) { - - credentialsFunc('123456', function (err, credentials) { - - var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); - expect(auth).to.exist(); - - var errFunc = function (id, callback) { - - callback(); - }; - - Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials) { - - expect(err).to.exist(); - expect(err.message).to.equal('Unknown credentials'); - done(); - }); - }); - }); - - it('should fail authorization on invalid credentials', function (done) { - - credentialsFunc('123456', function (err, credentials) { - - var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); - expect(auth).to.exist(); - - var errFunc = function (id, callback) { - - callback(null, {}); - }; - - Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials) { - - expect(err).to.exist(); - expect(err.message).to.equal('Invalid credentials'); - done(); - }); - }); - }); - - it('should fail authorization on invalid credentials algorithm', function (done) { - - credentialsFunc('123456', function (err, credentials) { - - var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); - expect(auth).to.exist(); - - var errFunc = function (id, callback) { - - callback(null, { key: '123', algorithm: '456' }); - }; - - Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials) { - - expect(err).to.exist(); - expect(err.message).to.equal('Unknown algorithm'); - done(); - }); - }); - }); - - it('should fail on missing host', function (done) { - - credentialsFunc('123456', function (err, credentials) { - - var auth = Hawk.client.message(null, 8080, 'some message', { credentials: credentials }); - expect(auth).to.not.exist(); - done(); - }); - }); - - it('should fail on missing credentials', function (done) { - - var auth = Hawk.client.message('example.com', 8080, 'some message', {}); - expect(auth).to.not.exist(); - done(); - }); - - it('should fail on invalid algorithm', function (done) { - - credentialsFunc('123456', function (err, credentials) { - - var creds = Hoek.clone(credentials); - creds.algorithm = 'blah'; - var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: creds }); - expect(auth).to.not.exist(); - done(); - }); - }); -}); diff --git a/node_modules/hawk/test/readme.js b/node_modules/hawk/test/readme.js index 60af19983294e..a466264667ee6 100755 --- a/node_modules/hawk/test/readme.js +++ b/node_modules/hawk/test/readme.js @@ -19,79 +19,76 @@ var it = lab.test; var expect = Code.expect; -describe('Hawk', function () { +describe('README', function () { - describe('README', function () { + describe('core', function () { - describe('core', function () { + var credentials = { + id: 'dh37fgj492je', + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: 'sha256' + }; - var credentials = { - id: 'dh37fgj492je', - key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', - algorithm: 'sha256' - }; + var options = { + credentials: credentials, + timestamp: 1353832234, + nonce: 'j4h3g2', + ext: 'some-app-ext-data' + }; - var options = { - credentials: credentials, - timestamp: 1353832234, - nonce: 'j4h3g2', - ext: 'some-app-ext-data' - }; + it('should generate a header protocol example', function (done) { - it('should generate a header protocol example', function (done) { + var header = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'GET', options).field; - var header = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'GET', options).field; + expect(header).to.equal('Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data", mac="6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE="'); + done(); + }); - expect(header).to.equal('Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data", mac="6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE="'); - done(); - }); + it('should generate a normalized string protocol example', function (done) { - it('should generate a normalized string protocol example', function (done) { - - var normalized = Hawk.crypto.generateNormalizedString('header', { - credentials: credentials, - ts: options.timestamp, - nonce: options.nonce, - method: 'GET', - resource: '/resource?a=1&b=2', - host: 'example.com', - port: 8000, - ext: options.ext - }); - - expect(normalized).to.equal('hawk.1.header\n1353832234\nj4h3g2\nGET\n/resource?a=1&b=2\nexample.com\n8000\n\nsome-app-ext-data\n'); - done(); + var normalized = Hawk.crypto.generateNormalizedString('header', { + credentials: credentials, + ts: options.timestamp, + nonce: options.nonce, + method: 'GET', + resource: '/resource?a=1&b=2', + host: 'example.com', + port: 8000, + ext: options.ext }); - var payloadOptions = Hoek.clone(options); - payloadOptions.payload = 'Thank you for flying Hawk'; - payloadOptions.contentType = 'text/plain'; + expect(normalized).to.equal('hawk.1.header\n1353832234\nj4h3g2\nGET\n/resource?a=1&b=2\nexample.com\n8000\n\nsome-app-ext-data\n'); + done(); + }); - it('should generate a header protocol example (with payload)', function (done) { + var payloadOptions = Hoek.clone(options); + payloadOptions.payload = 'Thank you for flying Hawk'; + payloadOptions.contentType = 'text/plain'; - var header = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'POST', payloadOptions).field; + it('should generate a header protocol example (with payload)', function (done) { - expect(header).to.equal('Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", hash="Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=", ext="some-app-ext-data", mac="aSe1DERmZuRl3pI36/9BdZmnErTw3sNzOOAUlfeKjVw="'); - done(); - }); + var header = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'POST', payloadOptions).field; - it('should generate a normalized string protocol example (with payload)', function (done) { - - var normalized = Hawk.crypto.generateNormalizedString('header', { - credentials: credentials, - ts: options.timestamp, - nonce: options.nonce, - method: 'POST', - resource: '/resource?a=1&b=2', - host: 'example.com', - port: 8000, - hash: Hawk.crypto.calculatePayloadHash(payloadOptions.payload, credentials.algorithm, payloadOptions.contentType), - ext: options.ext - }); - - expect(normalized).to.equal('hawk.1.header\n1353832234\nj4h3g2\nPOST\n/resource?a=1&b=2\nexample.com\n8000\nYi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=\nsome-app-ext-data\n'); - done(); + expect(header).to.equal('Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", hash="Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=", ext="some-app-ext-data", mac="aSe1DERmZuRl3pI36/9BdZmnErTw3sNzOOAUlfeKjVw="'); + done(); + }); + + it('should generate a normalized string protocol example (with payload)', function (done) { + + var normalized = Hawk.crypto.generateNormalizedString('header', { + credentials: credentials, + ts: options.timestamp, + nonce: options.nonce, + method: 'POST', + resource: '/resource?a=1&b=2', + host: 'example.com', + port: 8000, + hash: Hawk.crypto.calculatePayloadHash(payloadOptions.payload, credentials.algorithm, payloadOptions.contentType), + ext: options.ext }); + + expect(normalized).to.equal('hawk.1.header\n1353832234\nj4h3g2\nPOST\n/resource?a=1&b=2\nexample.com\n8000\nYi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=\nsome-app-ext-data\n'); + done(); }); }); }); diff --git a/node_modules/hawk/test/server.js b/node_modules/hawk/test/server.js index 00d7d085fe3d4..b95b7cd023324 100755 --- a/node_modules/hawk/test/server.js +++ b/node_modules/hawk/test/server.js @@ -3,6 +3,7 @@ var Url = require('url'); var Code = require('code'); var Hawk = require('../lib'); +var Hoek = require('hoek'); var Lab = require('lab'); @@ -19,967 +20,1295 @@ var it = lab.test; var expect = Code.expect; -describe('Hawk', function () { +describe('Server', function () { - describe('server', function () { + var credentialsFunc = function (id, callback) { - var credentialsFunc = function (id, callback) { + var credentials = { + id: id, + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: (id === '1' ? 'sha1' : 'sha256'), + user: 'steve' + }; - var credentials = { - id: id, - key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', - algorithm: (id === '1' ? 'sha1' : 'sha256'), - user: 'steve' + return callback(null, credentials); + }; + + describe('authenticate()', function () { + + it('parses a valid authentication header (sha1)', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk id="1", ts="1353788437", nonce="k3j4h2", mac="zy79QQ5/EYFmQqutVnYb73gAc/U=", ext="hello"' }; - return callback(null, credentials); - }; + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { - describe('#authenticate', function () { + expect(err).to.not.exist(); + expect(credentials.user).to.equal('steve'); + done(); + }); + }); + + it('parses a valid authentication header (sha256)', function (done) { + + var req = { + method: 'GET', + url: '/resource/1?b=1&a=2', + host: 'example.com', + port: 8000, + authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", mac="m8r1rHbXN6NgO+KIIhjO7sFRyd78RNGVUwehe8Cp2dU=", ext="some-app-data"' + }; + + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353832234000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + + expect(err).to.not.exist(); + expect(credentials.user).to.equal('steve'); + done(); + }); + }); - it('parses a valid authentication header (sha1)', function (done) { + it('parses a valid authentication header (host override)', function (done) { - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, + var req = { + method: 'GET', + url: '/resource/4?filter=a', + headers: { + host: 'example1.com:8080', authorization: 'Hawk id="1", ts="1353788437", nonce="k3j4h2", mac="zy79QQ5/EYFmQqutVnYb73gAc/U=", ext="hello"' - }; + } + }; - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + Hawk.server.authenticate(req, credentialsFunc, { host: 'example.com', localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { - expect(err).to.not.exist(); - expect(credentials.user).to.equal('steve'); - done(); - }); + expect(err).to.not.exist(); + expect(credentials.user).to.equal('steve'); + done(); }); + }); - it('parses a valid authentication header (sha256)', function (done) { + it('parses a valid authentication header (host port override)', function (done) { - var req = { - method: 'GET', - url: '/resource/1?b=1&a=2', - host: 'example.com', - port: 8000, - authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", mac="m8r1rHbXN6NgO+KIIhjO7sFRyd78RNGVUwehe8Cp2dU=", ext="some-app-data"' - }; + var req = { + method: 'GET', + url: '/resource/4?filter=a', + headers: { + host: 'example1.com:80', + authorization: 'Hawk id="1", ts="1353788437", nonce="k3j4h2", mac="zy79QQ5/EYFmQqutVnYb73gAc/U=", ext="hello"' + } + }; - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353832234000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + Hawk.server.authenticate(req, credentialsFunc, { host: 'example.com', port: 8080, localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { - expect(err).to.not.exist(); - expect(credentials.user).to.equal('steve'); - done(); - }); + expect(err).to.not.exist(); + expect(credentials.user).to.equal('steve'); + done(); }); + }); - it('parses a valid authentication header (host override)', function (done) { + it('parses a valid authentication header (POST with payload)', function (done) { - var req = { - method: 'GET', - url: '/resource/4?filter=a', + var req = { + method: 'POST', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk id="123456", ts="1357926341", nonce="1AwuJD", hash="qAiXIVv+yjDATneWxZP2YCTa9aHRgQdnH9b3Wc+o3dg=", ext="some-app-data", mac="UeYcj5UoTVaAWXNvJfLVia7kU3VabxCqrccXP8sUGC4="' + }; + + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1357926341000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + + expect(err).to.not.exist(); + expect(credentials.user).to.equal('steve'); + done(); + }); + }); + + it('errors on missing hash', function (done) { + + var req = { + method: 'GET', + url: '/resource/1?b=1&a=2', + host: 'example.com', + port: 8000, + authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", mac="m8r1rHbXN6NgO+KIIhjO7sFRyd78RNGVUwehe8Cp2dU=", ext="some-app-data"' + }; + + Hawk.server.authenticate(req, credentialsFunc, { payload: 'body', localtimeOffsetMsec: 1353832234000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Missing required payload hash'); + done(); + }); + }); + + it('errors on a stale timestamp', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk id="123456", ts="1362337299", nonce="UzmxSs", ext="some-app-data", mac="wnNUxchvvryMH2RxckTdZ/gY3ijzvccx4keVvELC61w="' + }; + + Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Stale timestamp'); + var header = err.output.headers['WWW-Authenticate']; + var ts = header.match(/^Hawk ts\=\"(\d+)\"\, tsm\=\"([^\"]+)\"\, error=\"Stale timestamp\"$/); + var now = Hawk.utils.now(); + expect(parseInt(ts[1], 10) * 1000).to.be.within(now - 1000, now + 1000); + + var res = { headers: { - host: 'example1.com:8080', - authorization: 'Hawk id="1", ts="1353788437", nonce="k3j4h2", mac="zy79QQ5/EYFmQqutVnYb73gAc/U=", ext="hello"' + 'www-authenticate': header } }; - Hawk.server.authenticate(req, credentialsFunc, { host: 'example.com', localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + expect(Hawk.client.authenticate(res, credentials, artifacts)).to.equal(true); + done(); + }); + }); - expect(err).to.not.exist(); - expect(credentials.user).to.equal('steve'); + it('errors on a replay', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="bXx7a7p1h9QYQNZ8x7QhvDQym8ACgab4m3lVSFn4DBw=", ext="hello"' + }; + + var memoryCache = {}; + var options = { + localtimeOffsetMsec: 1353788437000 - Hawk.utils.now(), + nonceFunc: function (key, nonce, ts, callback) { + + if (memoryCache[key + nonce]) { + return callback(new Error()); + } + + memoryCache[key + nonce] = true; + return callback(); + } + }; + + Hawk.server.authenticate(req, credentialsFunc, options, function (err, credentials, artifacts) { + + expect(err).to.not.exist(); + expect(credentials.user).to.equal('steve'); + + Hawk.server.authenticate(req, credentialsFunc, options, function (err, credentials, artifacts) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Invalid nonce'); done(); }); }); + }); - it('parses a valid authentication header (host port override)', function (done) { + it('does not error on nonce collision if keys differ', function (done) { - var req = { - method: 'GET', - url: '/resource/4?filter=a', - headers: { - host: 'example1.com:80', - authorization: 'Hawk id="1", ts="1353788437", nonce="k3j4h2", mac="zy79QQ5/EYFmQqutVnYb73gAc/U=", ext="hello"' + var reqSteve = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="bXx7a7p1h9QYQNZ8x7QhvDQym8ACgab4m3lVSFn4DBw=", ext="hello"' + }; + + var reqBob = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk id="456", ts="1353788437", nonce="k3j4h2", mac="LXfmTnRzrLd9TD7yfH+4se46Bx6AHyhpM94hLCiNia4=", ext="hello"' + }; + + var credentialsFunc = function (id, callback) { + + var credentials = { + '123': { + id: id, + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: (id === '1' ? 'sha1' : 'sha256'), + user: 'steve' + }, + '456': { + id: id, + key: 'xrunpaw3489ruxnpa98w4rxnwerxhqb98rpaxn39848', + algorithm: (id === '1' ? 'sha1' : 'sha256'), + user: 'bob' } }; - Hawk.server.authenticate(req, credentialsFunc, { host: 'example.com', port: 8080, localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + return callback(null, credentials[id]); + }; + + var memoryCache = {}; + var options = { + localtimeOffsetMsec: 1353788437000 - Hawk.utils.now(), + nonceFunc: function (key, nonce, ts, callback) { + + if (memoryCache[key + nonce]) { + return callback(new Error()); + } + + memoryCache[key + nonce] = true; + return callback(); + } + }; + + Hawk.server.authenticate(reqSteve, credentialsFunc, options, function (err, credentials, artifacts) { + + expect(err).to.not.exist(); + expect(credentials.user).to.equal('steve'); + + Hawk.server.authenticate(reqBob, credentialsFunc, options, function (err, credentials, artifacts) { expect(err).to.not.exist(); - expect(credentials.user).to.equal('steve'); + expect(credentials.user).to.equal('bob'); done(); }); }); + }); - it('parses a valid authentication header (POST with payload)', function (done) { + it('errors on an invalid authentication header: wrong scheme', function (done) { - var req = { - method: 'POST', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: 'Hawk id="123456", ts="1357926341", nonce="1AwuJD", hash="qAiXIVv+yjDATneWxZP2YCTa9aHRgQdnH9b3Wc+o3dg=", ext="some-app-data", mac="UeYcj5UoTVaAWXNvJfLVia7kU3VabxCqrccXP8sUGC4="' - }; + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Basic asdasdasdasd' + }; - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1357926341000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { - expect(err).to.not.exist(); - expect(credentials.user).to.equal('steve'); - done(); - }); + expect(err).to.exist(); + expect(err.output.payload.message).to.not.exist(); + done(); }); + }); - it('errors on missing hash', function (done) { + it('errors on an invalid authentication header: no scheme', function (done) { - var req = { - method: 'GET', - url: '/resource/1?b=1&a=2', - host: 'example.com', - port: 8000, - authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", mac="m8r1rHbXN6NgO+KIIhjO7sFRyd78RNGVUwehe8Cp2dU=", ext="some-app-data"' - }; + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: '!@#' + }; - Hawk.server.authenticate(req, credentialsFunc, { payload: 'body', localtimeOffsetMsec: 1353832234000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Missing required payload hash'); - done(); - }); + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Invalid header syntax'); + done(); + }); + }); + + it('errors on an missing authorization header', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080 + }; + + Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) { + + expect(err).to.exist(); + expect(err.isMissing).to.equal(true); + done(); }); + }); - it('errors on a stale timestamp', function (done) { + it('errors on an missing host header', function (done) { - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: 'Hawk id="123456", ts="1362337299", nonce="UzmxSs", ext="some-app-data", mac="wnNUxchvvryMH2RxckTdZ/gY3ijzvccx4keVvELC61w="' - }; + var req = { + method: 'GET', + url: '/resource/4?filter=a', + headers: { + authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' + } + }; - Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) { + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Stale timestamp'); - var header = err.output.headers['WWW-Authenticate']; - var ts = header.match(/^Hawk ts\=\"(\d+)\"\, tsm\=\"([^\"]+)\"\, error=\"Stale timestamp\"$/); - var now = Hawk.utils.now(); - expect(parseInt(ts[1], 10) * 1000).to.be.within(now - 1000, now + 1000); - - var res = { - headers: { - 'www-authenticate': header - } - }; - - expect(Hawk.client.authenticate(res, credentials, artifacts)).to.equal(true); - done(); - }); + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Invalid Host header'); + done(); + }); + }); + + it('errors on an missing authorization attribute (id)', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' + }; + + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Missing attributes'); + done(); + }); + }); + + it('errors on an missing authorization attribute (ts)', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk id="123", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' + }; + + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Missing attributes'); + done(); + }); + }); + + it('errors on an missing authorization attribute (nonce)', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk id="123", ts="1353788437", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' + }; + + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Missing attributes'); + done(); + }); + }); + + it('errors on an missing authorization attribute (mac)', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", ext="hello"' + }; + + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Missing attributes'); + done(); + }); + }); + + it('errors on an unknown authorization attribute', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", x="3", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' + }; + + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Unknown attribute: x'); + done(); + }); + }); + + it('errors on an bad authorization header format', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk id="123\\", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' + }; + + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Bad header format'); + done(); + }); + }); + + it('errors on an bad authorization attribute value', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk id="\t", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' + }; + + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Bad attribute value: id'); + done(); + }); + }); + + it('errors on an empty authorization attribute value', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk id="", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' + }; + + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Bad attribute value: id'); + done(); + }); + }); + + it('errors on duplicated authorization attribute key', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk id="123", id="456", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' + }; + + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Duplicate attribute: id'); + done(); + }); + }); + + it('errors on an invalid authorization header format', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk' + }; + + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Invalid header syntax'); + done(); }); + }); + + it('errors on an bad host header (missing host)', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?filter=a', + headers: { + host: ':8080', + authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' + } + }; + + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Invalid Host header'); + done(); + }); + }); + + it('errors on an bad host header (pad port)', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?filter=a', + headers: { + host: 'example.com:something', + authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' + } + }; + + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Invalid Host header'); + done(); + }); + }); - it('errors on a replay', function (done) { + it('errors on credentialsFunc error', function (done) { - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="bXx7a7p1h9QYQNZ8x7QhvDQym8ACgab4m3lVSFn4DBw=", ext="hello"' + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' + }; + + var credentialsFunc = function (id, callback) { + + return callback(new Error('Unknown user')); + }; + + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + + expect(err).to.exist(); + expect(err.message).to.equal('Unknown user'); + done(); + }); + }); + + it('errors on credentialsFunc error (with credentials)', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' + }; + + var credentialsFunc = function (id, callback) { + + return callback(new Error('Unknown user'), { some: 'value' }); + }; + + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + + expect(err).to.exist(); + expect(err.message).to.equal('Unknown user'); + expect(credentials.some).to.equal('value'); + done(); + }); + }); + + it('errors on missing credentials', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' + }; + + var credentialsFunc = function (id, callback) { + + return callback(null, null); + }; + + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Unknown credentials'); + done(); + }); + }); + + it('errors on invalid credentials (id)', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' + }; + + var credentialsFunc = function (id, callback) { + + var credentials = { + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + user: 'steve' }; - var memoryCache = {}; - var options = { - localtimeOffsetMsec: 1353788437000 - Hawk.utils.now(), - nonceFunc: function (nonce, ts, callback) { + return callback(null, credentials); + }; - if (memoryCache[nonce]) { - return callback(new Error()); - } + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { - memoryCache[nonce] = true; - return callback(); - } + expect(err).to.exist(); + expect(err.message).to.equal('Invalid credentials'); + expect(err.output.payload.message).to.equal('An internal server error occurred'); + done(); + }); + }); + + it('errors on invalid credentials (key)', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' + }; + + var credentialsFunc = function (id, callback) { + + var credentials = { + id: '23434d3q4d5345d', + user: 'steve' }; - Hawk.server.authenticate(req, credentialsFunc, options, function (err, credentials, artifacts) { + return callback(null, credentials); + }; - expect(err).to.not.exist(); - expect(credentials.user).to.equal('steve'); + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { - Hawk.server.authenticate(req, credentialsFunc, options, function (err, credentials, artifacts) { + expect(err).to.exist(); + expect(err.message).to.equal('Invalid credentials'); + expect(err.output.payload.message).to.equal('An internal server error occurred'); + done(); + }); + }); - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Invalid nonce'); - done(); - }); - }); + it('errors on unknown credentials algorithm', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' + }; + + var credentialsFunc = function (id, callback) { + + var credentials = { + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: 'hmac-sha-0', + user: 'steve' + }; + + return callback(null, credentials); + }; + + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + + expect(err).to.exist(); + expect(err.message).to.equal('Unknown algorithm'); + expect(err.output.payload.message).to.equal('An internal server error occurred'); + done(); }); + }); + + it('errors on unknown bad mac', function (done) { - it('errors on an invalid authentication header: wrong scheme', function (done) { + var req = { + method: 'GET', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080, + authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcU4jlr7T/wuKe3dKijvTvSos=", ext="hello"' + }; + + var credentialsFunc = function (id, callback) { - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: 'Basic asdasdasdasd' + var credentials = { + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: 'sha256', + user: 'steve' }; - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + return callback(null, credentials); + }; - expect(err).to.exist(); - expect(err.output.payload.message).to.not.exist(); - done(); - }); + Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Bad mac'); + done(); }); + }); + }); + + describe('header()', function () { - it('errors on an invalid authentication header: no scheme', function (done) { + it('generates header', function (done) { + + var credentials = { + id: '123456', + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: 'sha256', + user: 'steve' + }; + + var artifacts = { + method: 'POST', + host: 'example.com', + port: '8080', + resource: '/resource/4?filter=a', + ts: '1398546787', + nonce: 'xUwusx', + hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=', + ext: 'some-app-data', + mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=', + id: '123456' + }; + + var header = Hawk.server.header(credentials, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' }); + expect(header).to.equal('Hawk mac=\"n14wVJK4cOxAytPUMc5bPezQzuJGl5n7MYXhFQgEKsE=\", hash=\"f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=\", ext=\"response-specific\"'); + done(); + }); + + it('generates header (empty payload)', function (done) { + + var credentials = { + id: '123456', + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: 'sha256', + user: 'steve' + }; + + var artifacts = { + method: 'POST', + host: 'example.com', + port: '8080', + resource: '/resource/4?filter=a', + ts: '1398546787', + nonce: 'xUwusx', + hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=', + ext: 'some-app-data', + mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=', + id: '123456' + }; + + var header = Hawk.server.header(credentials, artifacts, { payload: '', contentType: 'text/plain', ext: 'response-specific' }); + expect(header).to.equal('Hawk mac=\"i8/kUBDx0QF+PpCtW860kkV/fa9dbwEoe/FpGUXowf0=\", hash=\"q/t+NNAkQZNlq/aAD6PlexImwQTxwgT2MahfTa9XRLA=\", ext=\"response-specific\"'); + done(); + }); + + it('generates header (pre calculated hash)', function (done) { + + var credentials = { + id: '123456', + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: 'sha256', + user: 'steve' + }; + + var artifacts = { + method: 'POST', + host: 'example.com', + port: '8080', + resource: '/resource/4?filter=a', + ts: '1398546787', + nonce: 'xUwusx', + hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=', + ext: 'some-app-data', + mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=', + id: '123456' + }; + + var options = { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' }; + options.hash = Hawk.crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType); + var header = Hawk.server.header(credentials, artifacts, options); + expect(header).to.equal('Hawk mac=\"n14wVJK4cOxAytPUMc5bPezQzuJGl5n7MYXhFQgEKsE=\", hash=\"f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=\", ext=\"response-specific\"'); + done(); + }); + + it('generates header (null ext)', function (done) { + + var credentials = { + id: '123456', + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: 'sha256', + user: 'steve' + }; + + var artifacts = { + method: 'POST', + host: 'example.com', + port: '8080', + resource: '/resource/4?filter=a', + ts: '1398546787', + nonce: 'xUwusx', + hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=', + mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=', + id: '123456' + }; + + var header = Hawk.server.header(credentials, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: null }); + expect(header).to.equal('Hawk mac=\"6PrybJTJs20jsgBw5eilXpcytD8kUbaIKNYXL+6g0ns=\", hash=\"f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=\"'); + done(); + }); + + it('errors on missing artifacts', function (done) { + + var credentials = { + id: '123456', + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: 'sha256', + user: 'steve' + }; + + var header = Hawk.server.header(credentials, null, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' }); + expect(header).to.equal(''); + done(); + }); - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: '!@#' - }; + it('errors on invalid artifacts', function (done) { - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + var credentials = { + id: '123456', + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: 'sha256', + user: 'steve' + }; - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Invalid header syntax'); - done(); - }); - }); + var header = Hawk.server.header(credentials, 5, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' }); + expect(header).to.equal(''); + done(); + }); - it('errors on an missing authorization header', function (done) { + it('errors on missing credentials', function (done) { + + var artifacts = { + method: 'POST', + host: 'example.com', + port: '8080', + resource: '/resource/4?filter=a', + ts: '1398546787', + nonce: 'xUwusx', + hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=', + ext: 'some-app-data', + mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=', + id: '123456' + }; - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080 - }; + var header = Hawk.server.header(null, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' }); + expect(header).to.equal(''); + done(); + }); - Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) { + it('errors on invalid credentials (key)', function (done) { - expect(err).to.exist(); - expect(err.isMissing).to.equal(true); - done(); - }); - }); + var credentials = { + id: '123456', + algorithm: 'sha256', + user: 'steve' + }; - it('errors on an missing host header', function (done) { + var artifacts = { + method: 'POST', + host: 'example.com', + port: '8080', + resource: '/resource/4?filter=a', + ts: '1398546787', + nonce: 'xUwusx', + hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=', + ext: 'some-app-data', + mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=', + id: '123456' + }; - var req = { - method: 'GET', - url: '/resource/4?filter=a', - headers: { - authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' - } - }; + var header = Hawk.server.header(credentials, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' }); + expect(header).to.equal(''); + done(); + }); - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + it('errors on invalid algorithm', function (done) { - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Invalid Host header'); - done(); - }); - }); + var credentials = { + id: '123456', + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: 'x', + user: 'steve' + }; - it('errors on an missing authorization attribute (id)', function (done) { + var artifacts = { + method: 'POST', + host: 'example.com', + port: '8080', + resource: '/resource/4?filter=a', + ts: '1398546787', + nonce: 'xUwusx', + hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=', + ext: 'some-app-data', + mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=', + id: '123456' + }; - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: 'Hawk ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' - }; + var header = Hawk.server.header(credentials, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' }); + expect(header).to.equal(''); + done(); + }); + }); - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + describe('authenticateMessage()', function () { - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Missing attributes'); - done(); - }); - }); + it('errors on invalid authorization (ts)', function (done) { - it('errors on an missing authorization attribute (ts)', function (done) { + credentialsFunc('123456', function (err, credentials) { - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: 'Hawk id="123", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' - }; + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + delete auth.ts; - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials) { expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Missing attributes'); + expect(err.message).to.equal('Invalid authorization'); done(); }); }); + }); - it('errors on an missing authorization attribute (nonce)', function (done) { + it('errors on invalid authorization (nonce)', function (done) { - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: 'Hawk id="123", ts="1353788437", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' - }; + credentialsFunc('123456', function (err, credentials) { - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + delete auth.nonce; + + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials) { expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Missing attributes'); + expect(err.message).to.equal('Invalid authorization'); done(); }); }); + }); - it('errors on an missing authorization attribute (mac)', function (done) { + it('errors on invalid authorization (hash)', function (done) { - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", ext="hello"' - }; + credentialsFunc('123456', function (err, credentials) { + + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + delete auth.hash; - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials) { expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Missing attributes'); + expect(err.message).to.equal('Invalid authorization'); done(); }); }); + }); - it('errors on an unknown authorization attribute', function (done) { - - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", x="3", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' - }; - - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + it('errors with credentials', function (done) { - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Unknown attribute: x'); - done(); - }); - }); + credentialsFunc('123456', function (err, credentials) { - it('errors on an bad authorization header format', function (done) { + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: 'Hawk id="123\\", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' - }; + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, function (id, callback) { - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + callback(new Error('something'), { some: 'value' }); + }, {}, function (err, credentials) { expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Bad header format'); + expect(err.message).to.equal('something'); + expect(credentials.some).to.equal('value'); done(); }); }); + }); - it('errors on an bad authorization attribute value', function (done) { + it('errors on nonce collision', function (done) { - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: 'Hawk id="\t", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' - }; + credentialsFunc('123456', function (err, credentials) { - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, { + nonceFunc: function (key, nonce, ts, nonceCallback) { + + nonceCallback(true); + } + }, function (err, credentials) { expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Bad attribute value: id'); + expect(err.message).to.equal('Invalid nonce'); done(); }); }); + }); - it('errors on an empty authorization attribute value', function (done) { + var credentialsFunc = function (id, callback) { - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: 'Hawk id="", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' - }; + var credentials = { + id: id, + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: (id === '1' ? 'sha1' : 'sha256'), + user: 'steve' + }; - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + return callback(null, credentials); + }; - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Bad attribute value: id'); - done(); - }); - }); + it('should generate an authorization then successfully parse it', function (done) { - it('errors on duplicated authorization attribute key', function (done) { + credentialsFunc('123456', function (err, credentials) { - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: 'Hawk id="123", id="456", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' - }; + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + expect(auth).to.exist(); - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials) { - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Duplicate attribute: id'); + expect(err).to.not.exist(); + expect(credentials.user).to.equal('steve'); done(); }); }); + }); - it('errors on an invalid authorization header format', function (done) { + it('should fail authorization on mismatching host', function (done) { - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: 'Hawk' - }; + credentialsFunc('123456', function (err, credentials) { + + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + expect(auth).to.exist(); - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + Hawk.server.authenticateMessage('example1.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials) { expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Invalid header syntax'); + expect(err.message).to.equal('Bad mac'); done(); }); }); + }); - it('errors on an bad host header (missing host)', function (done) { + it('should fail authorization on stale timestamp', function (done) { - var req = { - method: 'GET', - url: '/resource/4?filter=a', - headers: { - host: ':8080', - authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' - } - }; + credentialsFunc('123456', function (err, credentials) { - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + expect(auth).to.exist(); + + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, { localtimeOffsetMsec: 100000 }, function (err, credentials) { expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Invalid Host header'); + expect(err.message).to.equal('Stale timestamp'); done(); }); }); + }); - it('errors on an bad host header (pad port)', function (done) { + it('overrides timestampSkewSec', function (done) { - var req = { - method: 'GET', - url: '/resource/4?filter=a', - headers: { - host: 'example.com:something', - authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' - } - }; + credentialsFunc('123456', function (err, credentials) { - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials, localtimeOffsetMsec: 100000 }); + expect(auth).to.exist(); - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Invalid Host header'); + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, { timestampSkewSec: 500 }, function (err, credentials) { + + expect(err).to.not.exist(); done(); }); }); + }); - it('errors on credentialsFunc error', function (done) { - - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' - }; + it('should fail authorization on invalid authorization', function (done) { - var credentialsFunc = function (id, callback) { + credentialsFunc('123456', function (err, credentials) { - return callback(new Error('Unknown user')); - }; + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + expect(auth).to.exist(); + delete auth.id; - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials) { expect(err).to.exist(); - expect(err.message).to.equal('Unknown user'); + expect(err.message).to.equal('Invalid authorization'); done(); }); }); + }); - it('errors on credentialsFunc error (with credentials)', function (done) { - - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' - }; + it('should fail authorization on bad hash', function (done) { - var credentialsFunc = function (id, callback) { + credentialsFunc('123456', function (err, credentials) { - return callback(new Error('Unknown user'), { some: 'value' }); - }; + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + expect(auth).to.exist(); - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + Hawk.server.authenticateMessage('example.com', 8080, 'some message1', auth, credentialsFunc, {}, function (err, credentials) { expect(err).to.exist(); - expect(err.message).to.equal('Unknown user'); - expect(credentials.some).to.equal('value'); + expect(err.message).to.equal('Bad message hash'); done(); }); }); + }); - it('errors on missing credentials', function (done) { + it('should fail authorization on nonce error', function (done) { - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' - }; + credentialsFunc('123456', function (err, credentials) { - var credentialsFunc = function (id, callback) { + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + expect(auth).to.exist(); - return callback(null, null); - }; + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, { + nonceFunc: function (key, nonce, ts, callback) { - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + callback(new Error('kaboom')); + } + }, function (err, credentials) { expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Unknown credentials'); + expect(err.message).to.equal('Invalid nonce'); done(); }); }); + }); - it('errors on invalid credentials (id)', function (done) { + it('should fail authorization on credentials error', function (done) { - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' - }; + credentialsFunc('123456', function (err, credentials) { - var credentialsFunc = function (id, callback) { + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + expect(auth).to.exist(); - var credentials = { - key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', - user: 'steve' - }; + var errFunc = function (id, callback) { - return callback(null, credentials); + callback(new Error('kablooey')); }; - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials) { expect(err).to.exist(); - expect(err.message).to.equal('Invalid credentials'); - expect(err.output.payload.message).to.equal('An internal server error occurred'); + expect(err.message).to.equal('kablooey'); done(); }); }); + }); - it('errors on invalid credentials (key)', function (done) { + it('should fail authorization on missing credentials', function (done) { - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' - }; + credentialsFunc('123456', function (err, credentials) { - var credentialsFunc = function (id, callback) { + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + expect(auth).to.exist(); - var credentials = { - id: '23434d3q4d5345d', - user: 'steve' - }; + var errFunc = function (id, callback) { - return callback(null, credentials); + callback(); }; - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials) { expect(err).to.exist(); - expect(err.message).to.equal('Invalid credentials'); - expect(err.output.payload.message).to.equal('An internal server error occurred'); + expect(err.message).to.equal('Unknown credentials'); done(); }); }); + }); - it('errors on unknown credentials algorithm', function (done) { + it('should fail authorization on invalid credentials', function (done) { - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"' - }; + credentialsFunc('123456', function (err, credentials) { - var credentialsFunc = function (id, callback) { + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + expect(auth).to.exist(); - var credentials = { - key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', - algorithm: 'hmac-sha-0', - user: 'steve' - }; + var errFunc = function (id, callback) { - return callback(null, credentials); + callback(null, {}); }; - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials) { expect(err).to.exist(); - expect(err.message).to.equal('Unknown algorithm'); - expect(err.output.payload.message).to.equal('An internal server error occurred'); + expect(err.message).to.equal('Invalid credentials'); done(); }); }); + }); - it('errors on unknown bad mac', function (done) { + it('should fail authorization on invalid credentials algorithm', function (done) { - var req = { - method: 'GET', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080, - authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcU4jlr7T/wuKe3dKijvTvSos=", ext="hello"' - }; + credentialsFunc('123456', function (err, credentials) { - var credentialsFunc = function (id, callback) { + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + expect(auth).to.exist(); - var credentials = { - key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', - algorithm: 'sha256', - user: 'steve' - }; + var errFunc = function (id, callback) { - return callback(null, credentials); + callback(null, { key: '123', algorithm: '456' }); }; - Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) { + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials) { expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Bad mac'); + expect(err.message).to.equal('Unknown algorithm'); done(); }); }); }); - describe('#header', function () { - - it('generates header', function (done) { - - var credentials = { - id: '123456', - key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', - algorithm: 'sha256', - user: 'steve' - }; - - var artifacts = { - method: 'POST', - host: 'example.com', - port: '8080', - resource: '/resource/4?filter=a', - ts: '1398546787', - nonce: 'xUwusx', - hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=', - ext: 'some-app-data', - mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=', - id: '123456' - }; - - var header = Hawk.server.header(credentials, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' }); - expect(header).to.equal('Hawk mac=\"n14wVJK4cOxAytPUMc5bPezQzuJGl5n7MYXhFQgEKsE=\", hash=\"f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=\", ext=\"response-specific\"'); - done(); - }); - - it('generates header (empty payload)', function (done) { - - var credentials = { - id: '123456', - key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', - algorithm: 'sha256', - user: 'steve' - }; - - var artifacts = { - method: 'POST', - host: 'example.com', - port: '8080', - resource: '/resource/4?filter=a', - ts: '1398546787', - nonce: 'xUwusx', - hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=', - ext: 'some-app-data', - mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=', - id: '123456' - }; - - var header = Hawk.server.header(credentials, artifacts, { payload: '', contentType: 'text/plain', ext: 'response-specific' }); - expect(header).to.equal('Hawk mac=\"i8/kUBDx0QF+PpCtW860kkV/fa9dbwEoe/FpGUXowf0=\", hash=\"q/t+NNAkQZNlq/aAD6PlexImwQTxwgT2MahfTa9XRLA=\", ext=\"response-specific\"'); - done(); - }); - - it('generates header (pre calculated hash)', function (done) { - - var credentials = { - id: '123456', - key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', - algorithm: 'sha256', - user: 'steve' - }; - - var artifacts = { - method: 'POST', - host: 'example.com', - port: '8080', - resource: '/resource/4?filter=a', - ts: '1398546787', - nonce: 'xUwusx', - hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=', - ext: 'some-app-data', - mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=', - id: '123456' - }; - - var options = { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' }; - options.hash = Hawk.crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType); - var header = Hawk.server.header(credentials, artifacts, options); - expect(header).to.equal('Hawk mac=\"n14wVJK4cOxAytPUMc5bPezQzuJGl5n7MYXhFQgEKsE=\", hash=\"f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=\", ext=\"response-specific\"'); - done(); - }); - - it('generates header (null ext)', function (done) { - - var credentials = { - id: '123456', - key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', - algorithm: 'sha256', - user: 'steve' - }; - - var artifacts = { - method: 'POST', - host: 'example.com', - port: '8080', - resource: '/resource/4?filter=a', - ts: '1398546787', - nonce: 'xUwusx', - hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=', - mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=', - id: '123456' - }; - - var header = Hawk.server.header(credentials, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: null }); - expect(header).to.equal('Hawk mac=\"6PrybJTJs20jsgBw5eilXpcytD8kUbaIKNYXL+6g0ns=\", hash=\"f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=\"'); - done(); - }); - - it('errors on missing artifacts', function (done) { - - var credentials = { - id: '123456', - key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', - algorithm: 'sha256', - user: 'steve' - }; - - var header = Hawk.server.header(credentials, null, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' }); - expect(header).to.equal(''); - done(); - }); - - it('errors on invalid artifacts', function (done) { - - var credentials = { - id: '123456', - key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', - algorithm: 'sha256', - user: 'steve' - }; - - var header = Hawk.server.header(credentials, 5, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' }); - expect(header).to.equal(''); - done(); - }); - - it('errors on missing credentials', function (done) { - - var artifacts = { - method: 'POST', - host: 'example.com', - port: '8080', - resource: '/resource/4?filter=a', - ts: '1398546787', - nonce: 'xUwusx', - hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=', - ext: 'some-app-data', - mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=', - id: '123456' - }; - - var header = Hawk.server.header(null, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' }); - expect(header).to.equal(''); - done(); - }); - - it('errors on invalid credentials (key)', function (done) { - - var credentials = { - id: '123456', - algorithm: 'sha256', - user: 'steve' - }; - - var artifacts = { - method: 'POST', - host: 'example.com', - port: '8080', - resource: '/resource/4?filter=a', - ts: '1398546787', - nonce: 'xUwusx', - hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=', - ext: 'some-app-data', - mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=', - id: '123456' - }; - - var header = Hawk.server.header(credentials, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' }); - expect(header).to.equal(''); - done(); - }); - - it('errors on invalid algorithm', function (done) { - - var credentials = { - id: '123456', - key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', - algorithm: 'x', - user: 'steve' - }; + it('should fail on missing host', function (done) { - var artifacts = { - method: 'POST', - host: 'example.com', - port: '8080', - resource: '/resource/4?filter=a', - ts: '1398546787', - nonce: 'xUwusx', - hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=', - ext: 'some-app-data', - mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=', - id: '123456' - }; + credentialsFunc('123456', function (err, credentials) { - var header = Hawk.server.header(credentials, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' }); - expect(header).to.equal(''); + var auth = Hawk.client.message(null, 8080, 'some message', { credentials: credentials }); + expect(auth).to.not.exist(); done(); }); }); - describe('#authenticateMessage', function () { - - it('errors on invalid authorization (ts)', function (done) { - - credentialsFunc('123456', function (err, credentials) { - - var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); - delete auth.ts; - - Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials) { - - expect(err).to.exist(); - expect(err.message).to.equal('Invalid authorization'); - done(); - }); - }); - }); - - it('errors on invalid authorization (nonce)', function (done) { - - credentialsFunc('123456', function (err, credentials) { - - var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); - delete auth.nonce; - - Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials) { - - expect(err).to.exist(); - expect(err.message).to.equal('Invalid authorization'); - done(); - }); - }); - }); - - it('errors on invalid authorization (hash)', function (done) { - - credentialsFunc('123456', function (err, credentials) { - - var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); - delete auth.hash; - - Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials) { - - expect(err).to.exist(); - expect(err.message).to.equal('Invalid authorization'); - done(); - }); - }); - }); - - it('errors with credentials', function (done) { + it('should fail on missing credentials', function (done) { - credentialsFunc('123456', function (err, credentials) { + var auth = Hawk.client.message('example.com', 8080, 'some message', {}); + expect(auth).to.not.exist(); + done(); + }); - var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + it('should fail on invalid algorithm', function (done) { - Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, function (id, callback) { callback(new Error('something'), { some: 'value' }); }, {}, function (err, credentials) { + credentialsFunc('123456', function (err, credentials) { - expect(err).to.exist(); - expect(err.message).to.equal('something'); - expect(credentials.some).to.equal('value'); - done(); - }); - }); + var creds = Hoek.clone(credentials); + creds.algorithm = 'blah'; + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: creds }); + expect(auth).to.not.exist(); + done(); }); }); + }); - describe('#authenticatePayloadHash', function () { + describe('authenticatePayloadHash()', function () { - it('checks payload hash', function (done) { + it('checks payload hash', function (done) { - expect(Hawk.server.authenticatePayloadHash('abcdefg', { hash: 'abcdefg' })).to.equal(true); - expect(Hawk.server.authenticatePayloadHash('1234567', { hash: 'abcdefg' })).to.equal(false); - done(); - }); + expect(Hawk.server.authenticatePayloadHash('abcdefg', { hash: 'abcdefg' })).to.equal(true); + expect(Hawk.server.authenticatePayloadHash('1234567', { hash: 'abcdefg' })).to.equal(false); + done(); }); }); }); + diff --git a/node_modules/hawk/test/uri.js b/node_modules/hawk/test/uri.js index e64b0095b2f0b..1b623c09126c3 100755 --- a/node_modules/hawk/test/uri.js +++ b/node_modules/hawk/test/uri.js @@ -21,77 +21,33 @@ var it = lab.test; var expect = Code.expect; -describe('Hawk', function () { +describe('Uri', function () { - describe('Uri', function () { + var credentialsFunc = function (id, callback) { - var credentialsFunc = function (id, callback) { - - var credentials = { - id: id, - key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', - algorithm: 'sha256', - user: 'steve' - }; - - return callback(null, credentials); + var credentials = { + id: id, + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: 'sha256', + user: 'steve' }; - it('should generate a bewit then successfully authenticate it', function (done) { - - var req = { - method: 'GET', - url: '/resource/4?a=1&b=2', - host: 'example.com', - port: 80 - }; - - credentialsFunc('123456', function (err, credentials) { - - var bewit = Hawk.uri.getBewit('http://example.com/resource/4?a=1&b=2', { credentials: credentials, ttlSec: 60 * 60 * 24 * 365 * 100, ext: 'some-app-data' }); - req.url += '&bewit=' + bewit; - - Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { - - expect(err).to.not.exist(); - expect(credentials.user).to.equal('steve'); - expect(attributes.ext).to.equal('some-app-data'); - done(); - }); - }); - }); - - it('should generate a bewit then successfully authenticate it (no ext)', function (done) { - - var req = { - method: 'GET', - url: '/resource/4?a=1&b=2', - host: 'example.com', - port: 80 - }; + return callback(null, credentials); + }; - credentialsFunc('123456', function (err, credentials) { + it('should generate a bewit then successfully authenticate it', function (done) { - var bewit = Hawk.uri.getBewit('http://example.com/resource/4?a=1&b=2', { credentials: credentials, ttlSec: 60 * 60 * 24 * 365 * 100 }); - req.url += '&bewit=' + bewit; - - Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { - - expect(err).to.not.exist(); - expect(credentials.user).to.equal('steve'); - done(); - }); - }); - }); + var req = { + method: 'GET', + url: '/resource/4?a=1&b=2', + host: 'example.com', + port: 80 + }; - it('should successfully authenticate a request (last param)', function (done) { + credentialsFunc('123456', function (err, credentials) { - var req = { - method: 'GET', - url: '/resource/4?a=1&b=2&bewit=MTIzNDU2XDQ1MTE0ODQ2MjFcMzFjMmNkbUJFd1NJRVZDOVkva1NFb2c3d3YrdEVNWjZ3RXNmOGNHU2FXQT1cc29tZS1hcHAtZGF0YQ', - host: 'example.com', - port: 8080 - }; + var bewit = Hawk.uri.getBewit('http://example.com/resource/4?a=1&b=2', { credentials: credentials, ttlSec: 60 * 60 * 24 * 365 * 100, ext: 'some-app-data' }); + req.url += '&bewit=' + bewit; Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { @@ -101,342 +57,401 @@ describe('Hawk', function () { done(); }); }); + }); - it('should successfully authenticate a request (first param)', function (done) { + it('should generate a bewit then successfully authenticate it (no ext)', function (done) { - var req = { - method: 'GET', - url: '/resource/4?bewit=MTIzNDU2XDQ1MTE0ODQ2MjFcMzFjMmNkbUJFd1NJRVZDOVkva1NFb2c3d3YrdEVNWjZ3RXNmOGNHU2FXQT1cc29tZS1hcHAtZGF0YQ&a=1&b=2', - host: 'example.com', - port: 8080 - }; + var req = { + method: 'GET', + url: '/resource/4?a=1&b=2', + host: 'example.com', + port: 80 + }; + + credentialsFunc('123456', function (err, credentials) { + + var bewit = Hawk.uri.getBewit('http://example.com/resource/4?a=1&b=2', { credentials: credentials, ttlSec: 60 * 60 * 24 * 365 * 100 }); + req.url += '&bewit=' + bewit; Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { expect(err).to.not.exist(); expect(credentials.user).to.equal('steve'); - expect(attributes.ext).to.equal('some-app-data'); done(); }); }); + }); - it('should successfully authenticate a request (only param)', function (done) { + it('should successfully authenticate a request (last param)', function (done) { - var req = { - method: 'GET', - url: '/resource/4?bewit=MTIzNDU2XDQ1MTE0ODQ2NDFcZm1CdkNWT3MvcElOTUUxSTIwbWhrejQ3UnBwTmo4Y1VrSHpQd3Q5OXJ1cz1cc29tZS1hcHAtZGF0YQ', - host: 'example.com', - port: 8080 - }; + var req = { + method: 'GET', + url: '/resource/4?a=1&b=2&bewit=MTIzNDU2XDQ1MTE0ODQ2MjFcMzFjMmNkbUJFd1NJRVZDOVkva1NFb2c3d3YrdEVNWjZ3RXNmOGNHU2FXQT1cc29tZS1hcHAtZGF0YQ', + host: 'example.com', + port: 8080 + }; - Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { + Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { - expect(err).to.not.exist(); - expect(credentials.user).to.equal('steve'); - expect(attributes.ext).to.equal('some-app-data'); - done(); - }); + expect(err).to.not.exist(); + expect(credentials.user).to.equal('steve'); + expect(attributes.ext).to.equal('some-app-data'); + done(); }); + }); - it('should fail on multiple authentication', function (done) { + it('should successfully authenticate a request (first param)', function (done) { - var req = { - method: 'GET', - url: '/resource/4?bewit=MTIzNDU2XDQ1MTE0ODQ2NDFcZm1CdkNWT3MvcElOTUUxSTIwbWhrejQ3UnBwTmo4Y1VrSHpQd3Q5OXJ1cz1cc29tZS1hcHAtZGF0YQ', - host: 'example.com', - port: 8080, - authorization: 'Basic asdasdasdasd' - }; + var req = { + method: 'GET', + url: '/resource/4?bewit=MTIzNDU2XDQ1MTE0ODQ2MjFcMzFjMmNkbUJFd1NJRVZDOVkva1NFb2c3d3YrdEVNWjZ3RXNmOGNHU2FXQT1cc29tZS1hcHAtZGF0YQ&a=1&b=2', + host: 'example.com', + port: 8080 + }; - Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { + Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Multiple authentications'); - done(); - }); + expect(err).to.not.exist(); + expect(credentials.user).to.equal('steve'); + expect(attributes.ext).to.equal('some-app-data'); + done(); }); + }); - it('should fail on method other than GET', function (done) { + it('should successfully authenticate a request (only param)', function (done) { - credentialsFunc('123456', function (err, credentials) { + var req = { + method: 'GET', + url: '/resource/4?bewit=MTIzNDU2XDQ1MTE0ODQ2NDFcZm1CdkNWT3MvcElOTUUxSTIwbWhrejQ3UnBwTmo4Y1VrSHpQd3Q5OXJ1cz1cc29tZS1hcHAtZGF0YQ', + host: 'example.com', + port: 8080 + }; - var req = { - method: 'POST', - url: '/resource/4?filter=a', - host: 'example.com', - port: 8080 - }; + Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { - var exp = Math.floor(Hawk.utils.now() / 1000) + 60; - var ext = 'some-app-data'; - var mac = Hawk.crypto.calculateMac('bewit', credentials, { - timestamp: exp, - nonce: '', - method: req.method, - resource: req.url, - host: req.host, - port: req.port, - ext: ext - }); + expect(err).to.not.exist(); + expect(credentials.user).to.equal('steve'); + expect(attributes.ext).to.equal('some-app-data'); + done(); + }); + }); - var bewit = credentials.id + '\\' + exp + '\\' + mac + '\\' + ext; + it('should fail on multiple authentication', function (done) { - req.url += '&bewit=' + Hoek.base64urlEncode(bewit); + var req = { + method: 'GET', + url: '/resource/4?bewit=MTIzNDU2XDQ1MTE0ODQ2NDFcZm1CdkNWT3MvcElOTUUxSTIwbWhrejQ3UnBwTmo4Y1VrSHpQd3Q5OXJ1cz1cc29tZS1hcHAtZGF0YQ', + host: 'example.com', + port: 8080, + authorization: 'Basic asdasdasdasd' + }; - Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { + Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Invalid method'); - done(); - }); - }); + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Multiple authentications'); + done(); }); + }); + + it('should fail on method other than GET', function (done) { - it('should fail on invalid host header', function (done) { + credentialsFunc('123456', function (err, credentials) { var req = { - method: 'GET', - url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ', - headers: { - host: 'example.com:something' - } + method: 'POST', + url: '/resource/4?filter=a', + host: 'example.com', + port: 8080 }; + var exp = Math.floor(Hawk.utils.now() / 1000) + 60; + var ext = 'some-app-data'; + var mac = Hawk.crypto.calculateMac('bewit', credentials, { + timestamp: exp, + nonce: '', + method: req.method, + resource: req.url, + host: req.host, + port: req.port, + ext: ext + }); + + var bewit = credentials.id + '\\' + exp + '\\' + mac + '\\' + ext; + + req.url += '&bewit=' + Hoek.base64urlEncode(bewit); + Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Invalid Host header'); + expect(err.output.payload.message).to.equal('Invalid method'); done(); }); }); + }); - it('should fail on empty bewit', function (done) { + it('should fail on invalid host header', function (done) { - var req = { - method: 'GET', - url: '/resource/4?bewit=', - host: 'example.com', - port: 8080 - }; + var req = { + method: 'GET', + url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ', + headers: { + host: 'example.com:something' + } + }; - Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { + Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Empty bewit'); - expect(err.isMissing).to.not.exist(); - done(); - }); + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Invalid Host header'); + done(); }); + }); - it('should fail on invalid bewit', function (done) { + it('should fail on empty bewit', function (done) { - var req = { - method: 'GET', - url: '/resource/4?bewit=*', - host: 'example.com', - port: 8080 - }; + var req = { + method: 'GET', + url: '/resource/4?bewit=', + host: 'example.com', + port: 8080 + }; - Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { + Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Invalid bewit encoding'); - expect(err.isMissing).to.not.exist(); - done(); - }); + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Empty bewit'); + expect(err.isMissing).to.not.exist(); + done(); }); + }); - it('should fail on missing bewit', function (done) { + it('should fail on invalid bewit', function (done) { - var req = { - method: 'GET', - url: '/resource/4', - host: 'example.com', - port: 8080 - }; + var req = { + method: 'GET', + url: '/resource/4?bewit=*', + host: 'example.com', + port: 8080 + }; - Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { + Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { - expect(err).to.exist(); - expect(err.output.payload.message).to.not.exist(); - expect(err.isMissing).to.equal(true); - done(); - }); + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Invalid bewit encoding'); + expect(err.isMissing).to.not.exist(); + done(); }); + }); - it('should fail on invalid bewit structure', function (done) { + it('should fail on missing bewit', function (done) { - var req = { - method: 'GET', - url: '/resource/4?bewit=abc', - host: 'example.com', - port: 8080 - }; + var req = { + method: 'GET', + url: '/resource/4', + host: 'example.com', + port: 8080 + }; - Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { + Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Invalid bewit structure'); - done(); - }); + expect(err).to.exist(); + expect(err.output.payload.message).to.not.exist(); + expect(err.isMissing).to.equal(true); + done(); }); + }); - it('should fail on empty bewit attribute', function (done) { + it('should fail on invalid bewit structure', function (done) { - var req = { - method: 'GET', - url: '/resource/4?bewit=YVxcY1xk', - host: 'example.com', - port: 8080 - }; + var req = { + method: 'GET', + url: '/resource/4?bewit=abc', + host: 'example.com', + port: 8080 + }; - Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { + Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Missing bewit attributes'); - done(); - }); + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Invalid bewit structure'); + done(); }); + }); - it('should fail on missing bewit id attribute', function (done) { + it('should fail on empty bewit attribute', function (done) { - var req = { - method: 'GET', - url: '/resource/4?bewit=XDQ1NTIxNDc2MjJcK0JFbFhQMXhuWjcvd1Nrbm1ldGhlZm5vUTNHVjZNSlFVRHk4NWpTZVJ4VT1cc29tZS1hcHAtZGF0YQ', - host: 'example.com', - port: 8080 - }; + var req = { + method: 'GET', + url: '/resource/4?bewit=YVxcY1xk', + host: 'example.com', + port: 8080 + }; - Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { + Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Missing bewit attributes'); - done(); - }); + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Missing bewit attributes'); + done(); }); - - it('should fail on expired access', function (done) { + }); - var req = { - method: 'GET', - url: '/resource/4?a=1&b=2&bewit=MTIzNDU2XDEzNTY0MTg1ODNcWk1wZlMwWU5KNHV0WHpOMmRucTRydEk3NXNXTjFjeWVITTcrL0tNZFdVQT1cc29tZS1hcHAtZGF0YQ', - host: 'example.com', - port: 8080 - }; + it('should fail on missing bewit id attribute', function (done) { - Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { + var req = { + method: 'GET', + url: '/resource/4?bewit=XDQ1NTIxNDc2MjJcK0JFbFhQMXhuWjcvd1Nrbm1ldGhlZm5vUTNHVjZNSlFVRHk4NWpTZVJ4VT1cc29tZS1hcHAtZGF0YQ', + host: 'example.com', + port: 8080 + }; - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Access expired'); - done(); - }); + Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Missing bewit attributes'); + done(); }); + }); - it('should fail on credentials function error', function (done) { + it('should fail on expired access', function (done) { - var req = { - method: 'GET', - url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ', - host: 'example.com', - port: 8080 - }; + var req = { + method: 'GET', + url: '/resource/4?a=1&b=2&bewit=MTIzNDU2XDEzNTY0MTg1ODNcWk1wZlMwWU5KNHV0WHpOMmRucTRydEk3NXNXTjFjeWVITTcrL0tNZFdVQT1cc29tZS1hcHAtZGF0YQ', + host: 'example.com', + port: 8080 + }; - Hawk.uri.authenticate(req, function (id, callback) { callback(Hawk.error.badRequest('Boom')); }, {}, function (err, credentials, attributes) { + Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Boom'); - done(); - }); + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Access expired'); + done(); }); + }); - it('should fail on credentials function error with credentials', function (done) { + it('should fail on credentials function error', function (done) { - var req = { - method: 'GET', - url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ', - host: 'example.com', - port: 8080 - }; + var req = { + method: 'GET', + url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ', + host: 'example.com', + port: 8080 + }; - Hawk.uri.authenticate(req, function (id, callback) { callback(Hawk.error.badRequest('Boom'), { some: 'value' }); }, {}, function (err, credentials, attributes) { + Hawk.uri.authenticate(req, function (id, callback) { - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Boom'); - expect(credentials.some).to.equal('value'); - done(); - }); + callback(Hawk.error.badRequest('Boom')); + }, {}, function (err, credentials, attributes) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Boom'); + done(); }); + }); - it('should fail on null credentials function response', function (done) { + it('should fail on credentials function error with credentials', function (done) { - var req = { - method: 'GET', - url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ', - host: 'example.com', - port: 8080 - }; + var req = { + method: 'GET', + url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ', + host: 'example.com', + port: 8080 + }; - Hawk.uri.authenticate(req, function (id, callback) { callback(null, null); }, {}, function (err, credentials, attributes) { + Hawk.uri.authenticate(req, function (id, callback) { - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Unknown credentials'); - done(); - }); + callback(Hawk.error.badRequest('Boom'), { some: 'value' }); + }, {}, function (err, credentials, attributes) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Boom'); + expect(credentials.some).to.equal('value'); + done(); }); + }); - it('should fail on invalid credentials function response', function (done) { + it('should fail on null credentials function response', function (done) { - var req = { - method: 'GET', - url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ', - host: 'example.com', - port: 8080 - }; + var req = { + method: 'GET', + url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ', + host: 'example.com', + port: 8080 + }; - Hawk.uri.authenticate(req, function (id, callback) { callback(null, {}); }, {}, function (err, credentials, attributes) { + Hawk.uri.authenticate(req, function (id, callback) { - expect(err).to.exist(); - expect(err.message).to.equal('Invalid credentials'); - done(); - }); + callback(null, null); + }, {}, function (err, credentials, attributes) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Unknown credentials'); + done(); }); + }); - it('should fail on invalid credentials function response (unknown algorithm)', function (done) { + it('should fail on invalid credentials function response', function (done) { - var req = { - method: 'GET', - url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ', - host: 'example.com', - port: 8080 - }; + var req = { + method: 'GET', + url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ', + host: 'example.com', + port: 8080 + }; - Hawk.uri.authenticate(req, function (id, callback) { callback(null, { key: 'xxx', algorithm: 'xxx' }); }, {}, function (err, credentials, attributes) { + Hawk.uri.authenticate(req, function (id, callback) { - expect(err).to.exist(); - expect(err.message).to.equal('Unknown algorithm'); - done(); - }); + callback(null, {}); + }, {}, function (err, credentials, attributes) { + + expect(err).to.exist(); + expect(err.message).to.equal('Invalid credentials'); + done(); }); + }); - it('should fail on expired access', function (done) { + it('should fail on invalid credentials function response (unknown algorithm)', function (done) { - var req = { - method: 'GET', - url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ', - host: 'example.com', - port: 8080 - }; + var req = { + method: 'GET', + url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ', + host: 'example.com', + port: 8080 + }; - Hawk.uri.authenticate(req, function (id, callback) { callback(null, { key: 'xxx', algorithm: 'sha256' }); }, {}, function (err, credentials, attributes) { + Hawk.uri.authenticate(req, function (id, callback) { - expect(err).to.exist(); - expect(err.output.payload.message).to.equal('Bad mac'); - done(); - }); + callback(null, { key: 'xxx', algorithm: 'xxx' }); + }, {}, function (err, credentials, attributes) { + + expect(err).to.exist(); + expect(err.message).to.equal('Unknown algorithm'); + done(); + }); + }); + + it('should fail on expired access', function (done) { + + var req = { + method: 'GET', + url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ', + host: 'example.com', + port: 8080 + }; + + Hawk.uri.authenticate(req, function (id, callback) { + + callback(null, { key: 'xxx', algorithm: 'sha256' }); + }, {}, function (err, credentials, attributes) { + + expect(err).to.exist(); + expect(err.output.payload.message).to.equal('Bad mac'); + done(); }); }); - describe('#getBewit', function () { + describe('getBewit()', function () { it('returns a valid bewit value', function (done) { @@ -586,5 +601,249 @@ describe('Hawk', function () { done(); }); }); + describe('authenticateMessage()', function () { + + var credentialsFunc = function (id, callback) { + + var credentials = { + id: id, + key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', + algorithm: (id === '1' ? 'sha1' : 'sha256'), + user: 'steve' + }; + + return callback(null, credentials); + }; + + it('should generate an authorization then successfully parse it', function (done) { + + credentialsFunc('123456', function (err, credentials) { + + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + expect(auth).to.exist(); + + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials) { + + expect(err).to.not.exist(); + expect(credentials.user).to.equal('steve'); + done(); + }); + }); + }); + + it('should fail authorization on mismatching host', function (done) { + + credentialsFunc('123456', function (err, credentials) { + + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + expect(auth).to.exist(); + + Hawk.server.authenticateMessage('example1.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials) { + + expect(err).to.exist(); + expect(err.message).to.equal('Bad mac'); + done(); + }); + }); + }); + + it('should fail authorization on stale timestamp', function (done) { + + credentialsFunc('123456', function (err, credentials) { + + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + expect(auth).to.exist(); + + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, { localtimeOffsetMsec: 100000 }, function (err, credentials) { + + expect(err).to.exist(); + expect(err.message).to.equal('Stale timestamp'); + done(); + }); + }); + }); + + it('overrides timestampSkewSec', function (done) { + + credentialsFunc('123456', function (err, credentials) { + + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials, localtimeOffsetMsec: 100000 }); + expect(auth).to.exist(); + + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, { timestampSkewSec: 500 }, function (err, credentials) { + + expect(err).to.not.exist(); + done(); + }); + }); + }); + + it('should fail authorization on invalid authorization', function (done) { + + credentialsFunc('123456', function (err, credentials) { + + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + expect(auth).to.exist(); + delete auth.id; + + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials) { + + expect(err).to.exist(); + expect(err.message).to.equal('Invalid authorization'); + done(); + }); + }); + }); + + it('should fail authorization on bad hash', function (done) { + + credentialsFunc('123456', function (err, credentials) { + + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + expect(auth).to.exist(); + + Hawk.server.authenticateMessage('example.com', 8080, 'some message1', auth, credentialsFunc, {}, function (err, credentials) { + + expect(err).to.exist(); + expect(err.message).to.equal('Bad message hash'); + done(); + }); + }); + }); + + it('should fail authorization on nonce error', function (done) { + + credentialsFunc('123456', function (err, credentials) { + + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + expect(auth).to.exist(); + + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, { + nonceFunc: function (key, nonce, ts, callback) { + + callback(new Error('kaboom')); + } + }, function (err, credentials) { + + expect(err).to.exist(); + expect(err.message).to.equal('Invalid nonce'); + done(); + }); + }); + }); + + it('should fail authorization on credentials error', function (done) { + + credentialsFunc('123456', function (err, credentials) { + + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + expect(auth).to.exist(); + + var errFunc = function (id, callback) { + + callback(new Error('kablooey')); + }; + + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials) { + + expect(err).to.exist(); + expect(err.message).to.equal('kablooey'); + done(); + }); + }); + }); + + it('should fail authorization on missing credentials', function (done) { + + credentialsFunc('123456', function (err, credentials) { + + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + expect(auth).to.exist(); + + var errFunc = function (id, callback) { + + callback(); + }; + + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials) { + + expect(err).to.exist(); + expect(err.message).to.equal('Unknown credentials'); + done(); + }); + }); + }); + + it('should fail authorization on invalid credentials', function (done) { + + credentialsFunc('123456', function (err, credentials) { + + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + expect(auth).to.exist(); + + var errFunc = function (id, callback) { + + callback(null, {}); + }; + + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials) { + + expect(err).to.exist(); + expect(err.message).to.equal('Invalid credentials'); + done(); + }); + }); + }); + + it('should fail authorization on invalid credentials algorithm', function (done) { + + credentialsFunc('123456', function (err, credentials) { + + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials }); + expect(auth).to.exist(); + + var errFunc = function (id, callback) { + + callback(null, { key: '123', algorithm: '456' }); + }; + + Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials) { + + expect(err).to.exist(); + expect(err.message).to.equal('Unknown algorithm'); + done(); + }); + }); + }); + + it('should fail on missing host', function (done) { + + credentialsFunc('123456', function (err, credentials) { + + var auth = Hawk.client.message(null, 8080, 'some message', { credentials: credentials }); + expect(auth).to.not.exist(); + done(); + }); + }); + + it('should fail on missing credentials', function (done) { + + var auth = Hawk.client.message('example.com', 8080, 'some message', {}); + expect(auth).to.not.exist(); + done(); + }); + + it('should fail on invalid algorithm', function (done) { + + credentialsFunc('123456', function (err, credentials) { + + var creds = Hoek.clone(credentials); + creds.algorithm = 'blah'; + var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: creds }); + expect(auth).to.not.exist(); + done(); + }); + }); + }); }); diff --git a/node_modules/hawk/test/utils.js b/node_modules/hawk/test/utils.js index 9ccda8be374cb..1bfef65f8cf5c 100755 --- a/node_modules/hawk/test/utils.js +++ b/node_modules/hawk/test/utils.js @@ -19,102 +19,103 @@ var it = lab.test; var expect = Code.expect; -describe('Hawk', function () { - - describe('Utils', function () { - - describe('#parseHost', function () { - - it('returns port 80 for non tls node request', function (done) { - - var req = { - method: 'POST', - url: '/resource/4?filter=a', - headers: { - host: 'example.com', - 'content-type': 'text/plain;x=y' - } - }; - - expect(Hawk.utils.parseHost(req, 'Host').port).to.equal(80); - done(); - }); - - it('returns port 443 for non tls node request', function (done) { - - var req = { - method: 'POST', - url: '/resource/4?filter=a', - headers: { - host: 'example.com', - 'content-type': 'text/plain;x=y' - }, - connection: { - encrypted: true - } - }; - - expect(Hawk.utils.parseHost(req, 'Host').port).to.equal(443); - done(); - }); - - it('returns port 443 for non tls node request (IPv6)', function (done) { - - var req = { - method: 'POST', - url: '/resource/4?filter=a', - headers: { - host: '[123:123:123]', - 'content-type': 'text/plain;x=y' - }, - connection: { - encrypted: true - } - }; - - expect(Hawk.utils.parseHost(req, 'Host').port).to.equal(443); - done(); - }); - - it('parses IPv6 headers', function (done) { - - var req = { - method: 'POST', - url: '/resource/4?filter=a', - headers: { - host: '[123:123:123]:8000', - 'content-type': 'text/plain;x=y' - }, - connection: { - encrypted: true - } - }; - - var host = Hawk.utils.parseHost(req, 'Host'); - expect(host.port).to.equal('8000'); - expect(host.name).to.equal('[123:123:123]'); - done(); - }); +describe('Utils', function () { + + describe('parseHost()', function () { + + it('returns port 80 for non tls node request', function (done) { + + var req = { + method: 'POST', + url: '/resource/4?filter=a', + headers: { + host: 'example.com', + 'content-type': 'text/plain;x=y' + } + }; + + expect(Hawk.utils.parseHost(req, 'Host').port).to.equal(80); + done(); }); - describe('#version', function () { + it('returns port 443 for non tls node request', function (done) { + + var req = { + method: 'POST', + url: '/resource/4?filter=a', + headers: { + host: 'example.com', + 'content-type': 'text/plain;x=y' + }, + connection: { + encrypted: true + } + }; + + expect(Hawk.utils.parseHost(req, 'Host').port).to.equal(443); + done(); + }); - it('returns the correct package version number', function (done) { + it('returns port 443 for non tls node request (IPv6)', function (done) { + + var req = { + method: 'POST', + url: '/resource/4?filter=a', + headers: { + host: '[123:123:123]', + 'content-type': 'text/plain;x=y' + }, + connection: { + encrypted: true + } + }; + + expect(Hawk.utils.parseHost(req, 'Host').port).to.equal(443); + done(); + }); - expect(Hawk.utils.version()).to.equal(Package.version); - done(); - }); + it('parses IPv6 headers', function (done) { + + var req = { + method: 'POST', + url: '/resource/4?filter=a', + headers: { + host: '[123:123:123]:8000', + 'content-type': 'text/plain;x=y' + }, + connection: { + encrypted: true + } + }; + + var host = Hawk.utils.parseHost(req, 'Host'); + expect(host.port).to.equal('8000'); + expect(host.name).to.equal('[123:123:123]'); + done(); }); + }); - describe('#unauthorized', function () { + describe('version()', function () { - it('returns a hawk 401', function (done) { + it('returns the correct package version number', function (done) { - expect(Hawk.utils.unauthorized('kaboom').output.headers['WWW-Authenticate']).to.equal('Hawk error="kaboom"'); - done(); - }); + expect(Hawk.utils.version()).to.equal(Package.version); + done(); }); }); -}); + describe('unauthorized()', function () { + it('returns a hawk 401', function (done) { + + expect(Hawk.utils.unauthorized('kaboom').output.headers['WWW-Authenticate']).to.equal('Hawk error="kaboom"'); + done(); + }); + + it('supports attributes', function (done) { + + expect(Hawk.utils.unauthorized('kaboom', { a: 'b' }).output.headers['WWW-Authenticate']).to.equal('Hawk a="b", error="kaboom"'); + done(); + }); + }); +});