Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
81146 views
1
// Load modules
2
3
var Url = require('url');
4
var Code = require('code');
5
var Hawk = require('../lib');
6
var Lab = require('lab');
7
8
9
// Declare internals
10
11
var internals = {};
12
13
14
// Test shortcuts
15
16
var lab = exports.lab = Lab.script();
17
var describe = lab.experiment;
18
var it = lab.test;
19
var expect = Code.expect;
20
21
22
describe('Hawk', function () {
23
24
describe('client', function () {
25
26
describe('#header', function () {
27
28
it('returns a valid authorization header (sha1)', function (done) {
29
30
var credentials = {
31
id: '123456',
32
key: '2983d45yun89q',
33
algorithm: 'sha1'
34
};
35
36
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;
37
expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="bsvY3IfUllw6V5rvk4tStEvpBhE=", ext="Bazinga!", mac="qbf1ZPG/r/e06F4ht+T77LXi5vw="');
38
done();
39
});
40
41
it('returns a valid authorization header (sha256)', function (done) {
42
43
var credentials = {
44
id: '123456',
45
key: '2983d45yun89q',
46
algorithm: 'sha256'
47
};
48
49
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;
50
expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", ext="Bazinga!", mac="q1CwFoSHzPZSkbIvl0oYlD+91rBUEvFk763nMjMndj8="');
51
done();
52
});
53
54
it('returns a valid authorization header (no ext)', function (done) {
55
56
var credentials = {
57
id: '123456',
58
key: '2983d45yun89q',
59
algorithm: 'sha256'
60
};
61
62
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;
63
expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="');
64
done();
65
});
66
67
it('returns a valid authorization header (null ext)', function (done) {
68
69
var credentials = {
70
id: '123456',
71
key: '2983d45yun89q',
72
algorithm: 'sha256'
73
};
74
75
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;
76
expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="');
77
done();
78
});
79
80
it('returns a valid authorization header (empty payload)', function (done) {
81
82
var credentials = {
83
id: '123456',
84
key: '2983d45yun89q',
85
algorithm: 'sha256'
86
};
87
88
var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: '', contentType: 'text/plain' }).field;
89
expect(header).to.equal('Hawk id=\"123456\", ts=\"1353809207\", nonce=\"Ygvqdz\", hash=\"q/t+NNAkQZNlq/aAD6PlexImwQTxwgT2MahfTa9XRLA=\", mac=\"U5k16YEzn3UnBHKeBzsDXn067Gu3R4YaY6xOt9PYRZM=\"');
90
done();
91
});
92
93
it('returns a valid authorization header (pre hashed payload)', function (done) {
94
95
var credentials = {
96
id: '123456',
97
key: '2983d45yun89q',
98
algorithm: 'sha256'
99
};
100
101
var options = { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' };
102
options.hash = Hawk.crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType);
103
var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', options).field;
104
expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="');
105
done();
106
});
107
108
it('errors on missing uri', function (done) {
109
110
var header = Hawk.client.header('', 'POST');
111
expect(header.field).to.equal('');
112
expect(header.err).to.equal('Invalid argument type');
113
done();
114
});
115
116
it('errors on invalid uri', function (done) {
117
118
var header = Hawk.client.header(4, 'POST');
119
expect(header.field).to.equal('');
120
expect(header.err).to.equal('Invalid argument type');
121
done();
122
});
123
124
it('errors on missing method', function (done) {
125
126
var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', '');
127
expect(header.field).to.equal('');
128
expect(header.err).to.equal('Invalid argument type');
129
done();
130
});
131
132
it('errors on invalid method', function (done) {
133
134
var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 5);
135
expect(header.field).to.equal('');
136
expect(header.err).to.equal('Invalid argument type');
137
done();
138
});
139
140
it('errors on missing options', function (done) {
141
142
var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST');
143
expect(header.field).to.equal('');
144
expect(header.err).to.equal('Invalid argument type');
145
done();
146
});
147
148
it('errors on invalid credentials (id)', function (done) {
149
150
var credentials = {
151
key: '2983d45yun89q',
152
algorithm: 'sha256'
153
};
154
155
var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207 });
156
expect(header.field).to.equal('');
157
expect(header.err).to.equal('Invalid credential object');
158
done();
159
});
160
161
it('errors on missing credentials', function (done) {
162
163
var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { ext: 'Bazinga!', timestamp: 1353809207 });
164
expect(header.field).to.equal('');
165
expect(header.err).to.equal('Invalid credential object');
166
done();
167
});
168
169
it('errors on invalid credentials', function (done) {
170
171
var credentials = {
172
id: '123456',
173
algorithm: 'sha256'
174
};
175
176
var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207 });
177
expect(header.field).to.equal('');
178
expect(header.err).to.equal('Invalid credential object');
179
done();
180
});
181
182
it('errors on invalid algorithm', function (done) {
183
184
var credentials = {
185
id: '123456',
186
key: '2983d45yun89q',
187
algorithm: 'hmac-sha-0'
188
};
189
190
var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, payload: 'something, anything!', ext: 'Bazinga!', timestamp: 1353809207 });
191
expect(header.field).to.equal('');
192
expect(header.err).to.equal('Unknown algorithm');
193
done();
194
});
195
});
196
197
describe('#authenticate', function () {
198
199
it('returns false on invalid header', function (done) {
200
201
var res = {
202
headers: {
203
'server-authorization': 'Hawk mac="abc", bad="xyz"'
204
}
205
};
206
207
expect(Hawk.client.authenticate(res, {})).to.equal(false);
208
done();
209
});
210
211
it('returns false on invalid mac', function (done) {
212
213
var res = {
214
headers: {
215
'content-type': 'text/plain',
216
'server-authorization': 'Hawk mac="_IJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"'
217
}
218
};
219
220
var artifacts = {
221
method: 'POST',
222
host: 'example.com',
223
port: '8080',
224
resource: '/resource/4?filter=a',
225
ts: '1362336900',
226
nonce: 'eb5S_L',
227
hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
228
ext: 'some-app-data',
229
app: undefined,
230
dlg: undefined,
231
mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=',
232
id: '123456'
233
};
234
235
var credentials = {
236
id: '123456',
237
key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
238
algorithm: 'sha256',
239
user: 'steve'
240
};
241
242
expect(Hawk.client.authenticate(res, credentials, artifacts)).to.equal(false);
243
done();
244
});
245
246
it('returns true on ignoring hash', function (done) {
247
248
var res = {
249
headers: {
250
'content-type': 'text/plain',
251
'server-authorization': 'Hawk mac="XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"'
252
}
253
};
254
255
var artifacts = {
256
method: 'POST',
257
host: 'example.com',
258
port: '8080',
259
resource: '/resource/4?filter=a',
260
ts: '1362336900',
261
nonce: 'eb5S_L',
262
hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
263
ext: 'some-app-data',
264
app: undefined,
265
dlg: undefined,
266
mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=',
267
id: '123456'
268
};
269
270
var credentials = {
271
id: '123456',
272
key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
273
algorithm: 'sha256',
274
user: 'steve'
275
};
276
277
expect(Hawk.client.authenticate(res, credentials, artifacts)).to.equal(true);
278
done();
279
});
280
281
it('fails on invalid WWW-Authenticate header format', function (done) {
282
283
var header = 'Hawk ts="1362346425875", tsm="PhwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", x="Stale timestamp"';
284
expect(Hawk.client.authenticate({ headers: { 'www-authenticate': header } }, {})).to.equal(false);
285
done();
286
});
287
288
it('fails on invalid WWW-Authenticate header format', function (done) {
289
290
var credentials = {
291
id: '123456',
292
key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
293
algorithm: 'sha256',
294
user: 'steve'
295
};
296
297
var header = 'Hawk ts="1362346425875", tsm="hwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", error="Stale timestamp"';
298
expect(Hawk.client.authenticate({ headers: { 'www-authenticate': header } }, credentials)).to.equal(false);
299
done();
300
});
301
302
it('skips tsm validation when missing ts', function (done) {
303
304
var header = 'Hawk error="Stale timestamp"';
305
expect(Hawk.client.authenticate({ headers: { 'www-authenticate': header } }, {})).to.equal(true);
306
done();
307
});
308
});
309
310
describe('#message', function () {
311
312
it('generates authorization', function (done) {
313
314
var credentials = {
315
id: '123456',
316
key: '2983d45yun89q',
317
algorithm: 'sha1'
318
};
319
320
var auth = Hawk.client.message('example.com', 80, 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' });
321
expect(auth).to.exist();
322
expect(auth.ts).to.equal(1353809207);
323
expect(auth.nonce).to.equal('abc123');
324
done();
325
});
326
327
it('errors on invalid host', function (done) {
328
329
var credentials = {
330
id: '123456',
331
key: '2983d45yun89q',
332
algorithm: 'sha1'
333
};
334
335
var auth = Hawk.client.message(5, 80, 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' });
336
expect(auth).to.not.exist();
337
done();
338
});
339
340
it('errors on invalid port', function (done) {
341
342
var credentials = {
343
id: '123456',
344
key: '2983d45yun89q',
345
algorithm: 'sha1'
346
};
347
348
var auth = Hawk.client.message('example.com', '80', 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' });
349
expect(auth).to.not.exist();
350
done();
351
});
352
353
it('errors on missing host', function (done) {
354
355
var credentials = {
356
id: '123456',
357
key: '2983d45yun89q',
358
algorithm: 'sha1'
359
};
360
361
var auth = Hawk.client.message('example.com', 0, 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' });
362
expect(auth).to.not.exist();
363
done();
364
});
365
366
it('errors on null message', function (done) {
367
368
var credentials = {
369
id: '123456',
370
key: '2983d45yun89q',
371
algorithm: 'sha1'
372
};
373
374
var auth = Hawk.client.message('example.com', 80, null, { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' });
375
expect(auth).to.not.exist();
376
done();
377
});
378
379
it('errors on missing message', function (done) {
380
381
var credentials = {
382
id: '123456',
383
key: '2983d45yun89q',
384
algorithm: 'sha1'
385
};
386
387
var auth = Hawk.client.message('example.com', 80, undefined, { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' });
388
expect(auth).to.not.exist();
389
done();
390
});
391
392
it('errors on invalid message', function (done) {
393
394
var credentials = {
395
id: '123456',
396
key: '2983d45yun89q',
397
algorithm: 'sha1'
398
};
399
400
var auth = Hawk.client.message('example.com', 80, 5, { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' });
401
expect(auth).to.not.exist();
402
done();
403
});
404
405
it('errors on missing options', function (done) {
406
407
var credentials = {
408
id: '123456',
409
key: '2983d45yun89q',
410
algorithm: 'sha1'
411
};
412
413
var auth = Hawk.client.message('example.com', 80, 'I am the boodyman');
414
expect(auth).to.not.exist();
415
done();
416
});
417
418
it('errors on invalid credentials (id)', function (done) {
419
420
var credentials = {
421
key: '2983d45yun89q',
422
algorithm: 'sha1'
423
};
424
425
var auth = Hawk.client.message('example.com', 80, 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' });
426
expect(auth).to.not.exist();
427
done();
428
});
429
430
it('errors on invalid credentials (key)', function (done) {
431
432
var credentials = {
433
id: '123456',
434
algorithm: 'sha1'
435
};
436
437
var auth = Hawk.client.message('example.com', 80, 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' });
438
expect(auth).to.not.exist();
439
done();
440
});
441
});
442
});
443
});
444
445