UNPKG

dynatrace-cordova-outsystems-plugin

Version:

This plugin gives you the ability to use the Dynatrace instrumentation in your hybrid application (Cordova, Ionic, ..). It uses the Mobile Agent, the JavaScript Agent and the Javascript Bridge. The Mobile Agent will give you all device specific values con

1,216 lines (923 loc) 60.6 kB
// Load modules var Url = require('url'); var Code = require('code'); var Hawk = require('../lib'); var Hoek = require('hoek'); var Lab = require('lab'); var Browser = require('../lib/browser'); // 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('Browser', 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 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, credentials1) { var bewit = Browser.client.bewit('http://example.com/resource/4?a=1&b=2', { credentials: credentials1, ttlSec: 60 * 60 * 24 * 365 * 100, ext: 'some-app-data' }); req.url += '&bewit=' + bewit; Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials2, attributes) { expect(err).to.not.exist(); expect(credentials2.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 }; credentialsFunc('123456', function (err, credentials1) { var bewit = Browser.client.bewit('http://example.com/resource/4?a=1&b=2', { credentials: credentials1, ttlSec: 60 * 60 * 24 * 365 * 100 }); req.url += '&bewit=' + bewit; Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials2, attributes) { expect(err).to.not.exist(); expect(credentials2.user).to.equal('steve'); done(); }); }); }); describe('bewit()', function () { it('returns a valid bewit value', function (done) { var credentials = { id: '123456', key: '2983d45yun89q', algorithm: 'sha256' }; var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' }); expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdca3NjeHdOUjJ0SnBQMVQxekRMTlBiQjVVaUtJVTl0T1NKWFRVZEc3WDloOD1ceGFuZHlhbmR6'); done(); }); it('returns a valid bewit value (explicit HTTP port)', function (done) { var credentials = { id: '123456', key: '2983d45yun89q', algorithm: 'sha256' }; var bewit = Browser.client.bewit('http://example.com:8080/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' }); expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdcaFpiSjNQMmNLRW80a3kwQzhqa1pBa1J5Q1p1ZWc0V1NOYnhWN3ZxM3hIVT1ceGFuZHlhbmR6'); done(); }); it('returns a valid bewit value (explicit HTTPS port)', function (done) { var credentials = { id: '123456', key: '2983d45yun89q', algorithm: 'sha256' }; var bewit = Browser.client.bewit('https://example.com:8043/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' }); expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdcL2t4UjhwK0xSaTdvQTRnUXc3cWlxa3BiVHRKYkR4OEtRMC9HRUwvVytTUT1ceGFuZHlhbmR6'); done(); }); it('returns a valid bewit value (null ext)', function (done) { var credentials = { id: '123456', key: '2983d45yun89q', algorithm: 'sha256' }; var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: null }); expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdcSUdZbUxnSXFMckNlOEN4dktQczRKbFdJQStValdKSm91d2dBUmlWaENBZz1c'); done(); }); it('errors on invalid options', function (done) { var credentials = { id: '123456', key: '2983d45yun89q', algorithm: 'sha256' }; var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow', 4); expect(bewit).to.equal(''); done(); }); it('errors on missing uri', function (done) { var credentials = { id: '123456', key: '2983d45yun89q', algorithm: 'sha256' }; var bewit = Browser.client.bewit('', { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' }); expect(bewit).to.equal(''); done(); }); it('errors on invalid uri', function (done) { var credentials = { id: '123456', key: '2983d45yun89q', algorithm: 'sha256' }; var bewit = Browser.client.bewit(5, { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' }); expect(bewit).to.equal(''); done(); }); it('errors on invalid credentials (id)', function (done) { var credentials = { key: '2983d45yun89q', algorithm: 'sha256' }; var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 3000, ext: 'xandyandz' }); expect(bewit).to.equal(''); done(); }); it('errors on missing credentials', function (done) { var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow', { ttlSec: 3000, ext: 'xandyandz' }); expect(bewit).to.equal(''); done(); }); it('errors on invalid credentials (key)', function (done) { var credentials = { id: '123456', algorithm: 'sha256' }; var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 3000, ext: 'xandyandz' }); expect(bewit).to.equal(''); done(); }); it('errors on invalid algorithm', function (done) { var credentials = { id: '123456', key: '2983d45yun89q', algorithm: 'hmac-sha-0' }; var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, ext: 'xandyandz' }); expect(bewit).to.equal(''); done(); }); it('errors on missing options', function (done) { var credentials = { id: '123456', key: '2983d45yun89q', algorithm: 'hmac-sha-0' }; var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow'); expect(bewit).to.equal(''); done(); }); }); it('generates a header then successfully parse it (configuration)', function (done) { var req = { method: 'GET', url: '/resource/4?filter=a', host: 'example.com', port: 8080 }; credentialsFunc('123456', function (err, credentials1) { req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data' }).field; expect(req.authorization).to.exist(); Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) { expect(err).to.not.exist(); expect(credentials2.user).to.equal('steve'); expect(artifacts.ext).to.equal('some-app-data'); done(); }); }); }); it('generates a header then successfully parse it (node request)', function (done) { var req = { method: 'POST', url: '/resource/4?filter=a', headers: { host: 'example.com:8080', 'content-type': 'text/plain;x=y' } }; var payload = 'some not so random text'; credentialsFunc('123456', function (err, credentials1) { var reqHeader = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] }); req.headers.authorization = reqHeader.field; Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) { expect(err).to.not.exist(); expect(credentials2.user).to.equal('steve'); expect(artifacts.ext).to.equal('some-app-data'); expect(Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.equal(true); var res = { headers: { 'content-type': 'text/plain' }, getResponseHeader: function (header) { return res.headers[header.toLowerCase()]; } }; res.headers['server-authorization'] = Hawk.server.header(credentials2, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' }); expect(res.headers['server-authorization']).to.exist(); expect(Browser.client.authenticate(res, credentials2, artifacts, { payload: 'some reply' })).to.equal(true); done(); }); }); }); it('generates a header then successfully parse it (browserify)', function (done) { var req = { method: 'POST', url: '/resource/4?filter=a', headers: { host: 'example.com:8080', 'content-type': 'text/plain;x=y' } }; var payload = 'some not so random text'; credentialsFunc('123456', function (err, credentials1) { var reqHeader = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] }); req.headers.authorization = reqHeader.field; Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) { expect(err).to.not.exist(); expect(credentials2.user).to.equal('steve'); expect(artifacts.ext).to.equal('some-app-data'); expect(Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.equal(true); var res = { headers: { 'content-type': 'text/plain' }, getHeader: function (header) { return res.headers[header.toLowerCase()]; } }; res.headers['server-authorization'] = Hawk.server.header(credentials2, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' }); expect(res.headers['server-authorization']).to.exist(); expect(Browser.client.authenticate(res, credentials2, artifacts, { payload: 'some reply' })).to.equal(true); done(); }); }); }); it('generates a header then successfully parse it (time offset)', function (done) { var req = { method: 'GET', url: '/resource/4?filter=a', host: 'example.com', port: 8080 }; credentialsFunc('123456', function (err, credentials1) { req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', localtimeOffsetMsec: 100000 }).field; expect(req.authorization).to.exist(); Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 100000 }, function (err, credentials2, artifacts) { expect(err).to.not.exist(); expect(credentials2.user).to.equal('steve'); expect(artifacts.ext).to.equal('some-app-data'); done(); }); }); }); it('generates a header then successfully parse it (no server header options)', function (done) { var req = { method: 'POST', url: '/resource/4?filter=a', headers: { host: 'example.com:8080', 'content-type': 'text/plain;x=y' } }; var payload = 'some not so random text'; credentialsFunc('123456', function (err, credentials1) { var reqHeader = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] }); req.headers.authorization = reqHeader.field; Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) { expect(err).to.not.exist(); expect(credentials2.user).to.equal('steve'); expect(artifacts.ext).to.equal('some-app-data'); expect(Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.equal(true); var res = { headers: { 'content-type': 'text/plain' }, getResponseHeader: function (header) { return res.headers[header.toLowerCase()]; } }; res.headers['server-authorization'] = Hawk.server.header(credentials2, artifacts); expect(res.headers['server-authorization']).to.exist(); expect(Browser.client.authenticate(res, credentials2, artifacts)).to.equal(true); done(); }); }); }); it('generates a header then successfully parse it (no server header)', function (done) { var req = { method: 'POST', url: '/resource/4?filter=a', headers: { host: 'example.com:8080', 'content-type': 'text/plain;x=y' } }; var payload = 'some not so random text'; credentialsFunc('123456', function (err, credentials1) { var reqHeader = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] }); req.headers.authorization = reqHeader.field; Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) { expect(err).to.not.exist(); expect(credentials2.user).to.equal('steve'); expect(artifacts.ext).to.equal('some-app-data'); expect(Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.equal(true); var res = { headers: { 'content-type': 'text/plain' }, getResponseHeader: function (header) { return res.headers[header.toLowerCase()]; } }; expect(Browser.client.authenticate(res, credentials2, artifacts)).to.equal(true); done(); }); }); }); it('generates a header with stale ts and successfully authenticate on second call', function (done) { var req = { method: 'GET', url: '/resource/4?filter=a', host: 'example.com', port: 8080 }; credentialsFunc('123456', function (err, credentials1) { Browser.utils.setNtpOffset(60 * 60 * 1000); var header = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data' }); req.authorization = header.field; expect(req.authorization).to.exist(); Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts2) { expect(err).to.exist(); expect(err.message).to.equal('Stale timestamp'); var res = { headers: { 'www-authenticate': err.output.headers['WWW-Authenticate'] }, getResponseHeader: function (lookup) { return res.headers[lookup.toLowerCase()]; } }; expect(Browser.utils.getNtpOffset()).to.equal(60 * 60 * 1000); expect(Browser.client.authenticate(res, credentials2, header.artifacts)).to.equal(true); expect(Browser.utils.getNtpOffset()).to.equal(0); req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials2, ext: 'some-app-data' }).field; expect(req.authorization).to.exist(); Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials3, artifacts3) { expect(err).to.not.exist(); expect(credentials3.user).to.equal('steve'); expect(artifacts3.ext).to.equal('some-app-data'); done(); }); }); }); }); it('generates a header with stale ts and successfully authenticate on second call (manual localStorage)', function (done) { var req = { method: 'GET', url: '/resource/4?filter=a', host: 'example.com', port: 8080 }; credentialsFunc('123456', function (err, credentials1) { var localStorage = new Browser.internals.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: credentials1, ext: 'some-app-data' }); req.authorization = header.field; expect(req.authorization).to.exist(); Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts2) { expect(err).to.exist(); expect(err.message).to.equal('Stale timestamp'); var res = { headers: { 'www-authenticate': err.output.headers['WWW-Authenticate'] }, getResponseHeader: function (lookup) { return res.headers[lookup.toLowerCase()]; } }; expect(parseInt(localStorage.getItem('hawk_ntp_offset'))).to.equal(60 * 60 * 1000); expect(Browser.utils.getNtpOffset()).to.equal(60 * 60 * 1000); expect(Browser.client.authenticate(res, credentials2, header.artifacts)).to.equal(true); expect(Browser.utils.getNtpOffset()).to.equal(0); expect(parseInt(localStorage.getItem('hawk_ntp_offset'))).to.equal(0); req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials2, ext: 'some-app-data' }).field; expect(req.authorization).to.exist(); Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials3, artifacts3) { expect(err).to.not.exist(); expect(credentials3.user).to.equal('steve'); expect(artifacts3.ext).to.equal('some-app-data'); done(); }); }); }); }); it('generates a header then fails to parse it (missing server header hash)', function (done) { var req = { method: 'POST', url: '/resource/4?filter=a', headers: { host: 'example.com:8080', 'content-type': 'text/plain;x=y' } }; var payload = 'some not so random text'; credentialsFunc('123456', function (err, credentials1) { var reqHeader = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] }); req.headers.authorization = reqHeader.field; Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) { expect(err).to.not.exist(); expect(credentials2.user).to.equal('steve'); expect(artifacts.ext).to.equal('some-app-data'); expect(Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.equal(true); var res = { headers: { 'content-type': 'text/plain' }, getResponseHeader: function (header) { return res.headers[header.toLowerCase()]; } }; res.headers['server-authorization'] = Hawk.server.header(credentials2, artifacts); expect(res.headers['server-authorization']).to.exist(); expect(Browser.client.authenticate(res, credentials2, artifacts, { payload: 'some reply' })).to.equal(false); done(); }); }); }); it('generates a header then successfully parse it (with hash)', function (done) { var req = { method: 'GET', url: '/resource/4?filter=a', host: 'example.com', port: 8080 }; credentialsFunc('123456', function (err, credentials1) { req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, payload: 'hola!', ext: 'some-app-data' }).field; Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) { expect(err).to.not.exist(); expect(credentials2.user).to.equal('steve'); expect(artifacts.ext).to.equal('some-app-data'); done(); }); }); }); it('generates a header then successfully parse it then validate payload', function (done) { var req = { method: 'GET', url: '/resource/4?filter=a', host: 'example.com', port: 8080 }; credentialsFunc('123456', function (err, credentials1) { req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, payload: 'hola!', ext: 'some-app-data' }).field; Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) { expect(err).to.not.exist(); expect(credentials2.user).to.equal('steve'); expect(artifacts.ext).to.equal('some-app-data'); expect(Hawk.server.authenticatePayload('hola!', credentials2, artifacts)).to.be.true(); expect(Hawk.server.authenticatePayload('hello!', credentials2, artifacts)).to.be.false(); done(); }); }); }); it('generates a header then successfully parse it (app)', function (done) { var req = { method: 'GET', url: '/resource/4?filter=a', host: 'example.com', port: 8080 }; credentialsFunc('123456', function (err, credentials1) { req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', app: 'asd23ased' }).field; Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) { expect(err).to.not.exist(); expect(credentials2.user).to.equal('steve'); expect(artifacts.ext).to.equal('some-app-data'); expect(artifacts.app).to.equal('asd23ased'); done(); }); }); }); it('generates a header then successfully parse it (app, dlg)', function (done) { var req = { method: 'GET', url: '/resource/4?filter=a', host: 'example.com', port: 8080 }; credentialsFunc('123456', function (err, credentials1) { req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', app: 'asd23ased', dlg: '23434szr3q4d' }).field; Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) { expect(err).to.not.exist(); expect(credentials2.user).to.equal('steve'); expect(artifacts.ext).to.equal('some-app-data'); expect(artifacts.app).to.equal('asd23ased'); expect(artifacts.dlg).to.equal('23434szr3q4d'); done(); }); }); }); it('generates a header then fail authentication due to bad hash', function (done) { var req = { method: 'GET', url: '/resource/4?filter=a', host: 'example.com', port: 8080 }; credentialsFunc('123456', function (err, credentials1) { req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, payload: 'hola!', ext: 'some-app-data' }).field; Hawk.server.authenticate(req, credentialsFunc, { payload: 'byebye!' }, function (err, credentials2, artifacts) { expect(err).to.exist(); expect(err.output.payload.message).to.equal('Bad payload hash'); done(); }); }); }); it('generates a header for one resource then fail to authenticate another', function (done) { var req = { method: 'GET', url: '/resource/4?filter=a', host: 'example.com', port: 8080 }; credentialsFunc('123456', function (err, credentials1) { req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data' }).field; req.url = '/something/else'; Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) { expect(err).to.exist(); expect(credentials2).to.exist(); done(); }); }); }); describe('client', function () { describe('header()', function () { it('returns a valid authorization header (sha1)', function (done) { var credentials = { id: '123456', key: '2983d45yun89q', algorithm: 'sha1' }; var header = Browser.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 = Browser.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 (empty payload)', function (done) { var credentials = { id: '123456', key: '2983d45yun89q', algorithm: 'sha1' }; var header = Browser.client.header('http://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: '' }).field; expect(header).to.equal('Hawk id=\"123456\", ts=\"1353809207\", nonce=\"Ygvqdz\", hash=\"404ghL7K+hfyhByKKejFBRGgTjU=\", ext=\"Bazinga!\", mac=\"Bh1sj1DOfFRWOdi3ww52nLCJdBE=\"'); done(); }); it('returns a valid authorization header (no ext)', function (done) { var credentials = { id: '123456', key: '2983d45yun89q', algorithm: 'sha256' }; var header = Browser.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 = Browser.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 (uri object)', function (done) { var credentials = { id: '123456', key: '2983d45yun89q', algorithm: 'sha256' }; var uri = Browser.utils.parseUri('https://example.net/somewhere/over/the/rainbow'); var header = Browser.client.header(uri, '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('errors on missing options', function (done) { var header = Browser.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 empty uri', function (done) { var credentials = { id: '123456', key: '2983d45yun89q', algorithm: 'sha256' }; var header = Browser.client.header('', 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }); expect(header.field).to.equal(''); expect(header.err).to.equal('Invalid argument type'); done(); }); it('errors on invalid uri', function (done) { var credentials = { id: '123456', key: '2983d45yun89q', algorithm: 'sha256' }; var header = Browser.client.header(4, 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }); expect(header.field).to.equal(''); expect(header.err).to.equal('Invalid argument type'); done(); }); it('errors on missing method', function (done) { var credentials = { id: '123456', key: '2983d45yun89q', algorithm: 'sha256' }; var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', '', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }); expect(header.field).to.equal(''); expect(header.err).to.equal('Invalid argument type'); done(); }); it('errors on invalid method', function (done) { var credentials = { id: '123456', key: '2983d45yun89q', algorithm: 'sha256' }; var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 5, { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }); expect(header.field).to.equal(''); expect(header.err).to.equal('Invalid argument type'); done(); }); it('errors on missing credentials', function (done) { var header = Browser.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 credentials object'); done(); }); it('errors on invalid credentials (id)', function (done) { var credentials = { key: '2983d45yun89q', algorithm: 'sha256' }; var header = Browser.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 credentials object'); done(); }); it('errors on invalid credentials (key)', function (done) { var credentials = { id: '123456', algorithm: 'sha256' }; var header = Browser.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 credentials object'); done(); }); it('errors on invalid algorithm', function (done) { var credentials = { id: '123456', key: '2983d45yun89q', algorithm: 'hmac-sha-0' }; var header = Browser.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(); }); it('uses a pre-calculated payload hash', function (done) { var credentials = { id: '123456', key: '2983d45yun89q', algorithm: 'sha256' }; var options = { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }; options.hash = Browser.crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType); var header = Browser.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=", ext="Bazinga!", mac="q1CwFoSHzPZSkbIvl0oYlD+91rBUEvFk763nMjMndj8="'); done(); }); }); describe('authenticate()', function () { it('skips tsm validation when missing ts', function (done) { var res = { headers: { 'www-authenticate': 'Hawk error="Stale timestamp"' }, getResponseHeader: function (header) { return res.headers[header.toLowerCase()]; } }; var credentials = { id: '123456', key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', algorithm: 'sha256', user: 'steve' }; var artifacts = { ts: 1402135580, nonce: 'iBRB6t', method: 'GET', resource: '/resource/4?filter=a', host: 'example.com', port: '8080', ext: 'some-app-data' }; expect(Browser.client.authenticate(res, credentials, artifacts)).to.equal(true); done(); }); it('returns false on invalid header', function (done) { var res = { headers: { 'server-authorization': 'Hawk mac="abc", bad="xyz"' }, getResponseHeader: function (header) { return res.headers[header.toLowerCase()]; } }; expect(Browser.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"' }, getResponseHeader: function (header) { return res.headers[header.toLowerCase()]; } }; 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(Browser.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"' }, getResponseHeader: function (header) { return res.headers[header.toLowerCase()]; } }; 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(Browser.client.authenticate(res, credentials, artifacts)).to.equal(true); done(); }); it('errors on invalid WWW-Authenticate header format', function (done) { var res = { headers: { 'www-authenticate': 'Hawk ts="1362346425875", tsm="PhwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", x="Stale timestamp"' }, getResponseHeader: function (header) { return res.headers[header.toLowerCase()]; } }; expect(Browser.client.authenticate(res, {})).to.equal(false); done(); }); it('errors on invalid WWW-Authenticate header format', function (done) { var credentials = { id: '123456', key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', algorithm: 'sha256', user: 'steve' }; var res = { headers: { 'www-authenticate': 'Hawk ts="1362346425875", tsm="hwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", error="Stale timestamp"' }, getResponseHeader: function (header) { return res.headers[header.toLowerCase()]; } }; expect(Browser.client.authenticate(res, credentials)).to.equal(false); done(); }); }); describe('message()', function () { it('generates an authorization then successfully parse it', function (done) { credentialsFunc('123456', function (err, credentials1) { var auth = Browser.client.message('example.com', 8080, 'some message', { credentials: credentials1 }); expect(auth).to.exist(); Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials2) { expect(err).to.not.exist(); expect(credentials2.user).to.equal('steve'); done(); }); }); }); it('generates an authorization using custom nonce/timestamp', function (done) { credentialsFunc('123456', function (err, credentials) { var auth = Browser.client.message('example.com', 8080, 'some message', { credentials: credentials, nonce: 'abc123', timestamp: 1398536270957 }); expect(auth).to.exist(); expect(auth.nonce).to.equal('abc123'); expect(auth.ts).to.equal(1398536270957); done(); }); }); it('errors on missing host', function (done) { credentialsFunc('123456', function (err, credentials) { var auth = Browser.client.message(null, 8080, 'some message', { credentials: credentials }); expect(auth).to.not.exist(); done(); }); }); it('errors on invalid host', function (done) { credentialsFunc('123456', function (err, credentials) { var auth = Browser.client.message(5, 8080, 'some message', { credentials: credentials }); expect(auth).to.not.exist(); done(); }); }); it('errors on missing port', function (done) { credentialsFunc('123456', function (err, credentials) { var auth = Browser.client.message('example.com', 0, 'some message', { credentials: credentials }); expect(auth).to.not.exist(); done(); }); }); it('errors on invalid port', function (done) { credentialsFunc('123456', function (err, credentials) { var auth = Browser.client.message('example.com', 'a', 'some message', { credentials: credentials }); expect(auth).to.not.exist(); done(); }); }); it('errors on missing message', function (done) { credentialsFunc('123456', function (err, credentials) { var auth = Browser.client.message('example.com', 8080, undefined, { credentials: credentials }); expect(auth).to.not.exist(); done(); }); }); it('errors on null message', function (done) { credentialsFunc('123456', function (err, credentials) { var auth = Browser.client.message('example.com', 8080, null, { credentials: credentials }); expect(auth).to.not.exist(); done(); }); }); it('errors on invalid message', function (done) { credentialsFunc('123456', function (err, credentials) { var auth = Brows