fsevents 1.0.7 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of fsevents might be problematic. Click here for more details.

Files changed (322) hide show
  1. package/node_modules/ansi/History.md +7 -0
  2. package/node_modules/ansi/LICENSE +24 -0
  3. package/node_modules/ansi/lib/ansi.js +2 -2
  4. package/node_modules/ansi/package.json +15 -10
  5. package/node_modules/ansi-regex/package.json +1 -0
  6. package/node_modules/ansi-styles/package.json +1 -0
  7. package/node_modules/are-we-there-yet/.npmignore +2 -0
  8. package/node_modules/are-we-there-yet/index.js +20 -18
  9. package/node_modules/are-we-there-yet/package.json +15 -13
  10. package/node_modules/asn1/package.json +3 -1
  11. package/node_modules/assert-plus/README.md +50 -21
  12. package/node_modules/assert-plus/assert.js +168 -207
  13. package/node_modules/assert-plus/package.json +55 -15
  14. package/node_modules/async/README.md +86 -4
  15. package/node_modules/async/dist/async.js +4 -3
  16. package/node_modules/async/dist/async.min.js +1 -1
  17. package/node_modules/async/lib/async.js +4 -3
  18. package/node_modules/async/package.json +10 -10
  19. package/node_modules/aws-sign2/package.json +1 -0
  20. package/node_modules/aws4/.npmignore +3 -0
  21. package/node_modules/aws4/.tern-port +1 -0
  22. package/node_modules/{tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match → aws4}/.travis.yml +2 -0
  23. package/node_modules/{tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/LICENSE.md → aws4/LICENSE} +1 -3
  24. package/node_modules/aws4/README.md +510 -0
  25. package/node_modules/aws4/aws4.js +313 -0
  26. package/node_modules/aws4/example.js +372 -0
  27. package/node_modules/aws4/node_modules/lru-cache/.npmignore +1 -0
  28. package/node_modules/aws4/node_modules/lru-cache/.travis.yml +8 -0
  29. package/node_modules/aws4/node_modules/lru-cache/CONTRIBUTORS +14 -0
  30. package/node_modules/aws4/node_modules/lru-cache/README.md +137 -0
  31. package/node_modules/aws4/node_modules/lru-cache/lib/lru-cache.js +334 -0
  32. package/node_modules/aws4/node_modules/lru-cache/package.json +66 -0
  33. package/node_modules/aws4/node_modules/lru-cache/test/basic.js +396 -0
  34. package/node_modules/aws4/node_modules/lru-cache/test/foreach.js +120 -0
  35. package/node_modules/aws4/node_modules/lru-cache/test/memory-leak.js +51 -0
  36. package/node_modules/aws4/node_modules/lru-cache/test/serialize.js +216 -0
  37. package/node_modules/aws4/package.json +113 -0
  38. package/node_modules/bl/.travis.yml +5 -6
  39. package/node_modules/bl/bl.js +5 -0
  40. package/node_modules/bl/package.json +16 -13
  41. package/node_modules/bl/test/test.js +554 -6
  42. package/node_modules/block-stream/package.json +1 -0
  43. package/node_modules/boom/package.json +1 -0
  44. package/node_modules/caseless/package.json +1 -0
  45. package/node_modules/chalk/package.json +1 -0
  46. package/node_modules/combined-stream/package.json +1 -0
  47. package/node_modules/commander/package.json +1 -0
  48. package/node_modules/core-util-is/package.json +2 -2
  49. package/node_modules/cryptiles/package.json +1 -0
  50. package/node_modules/dashdash/README.md +70 -7
  51. package/node_modules/dashdash/etc/dashdash.bash_completion.in +388 -0
  52. package/node_modules/dashdash/lib/dashdash.js +202 -2
  53. package/node_modules/dashdash/package.json +12 -9
  54. package/node_modules/debug/.jshintrc +3 -0
  55. package/node_modules/debug/.npmignore +6 -0
  56. package/node_modules/debug/History.md +195 -0
  57. package/node_modules/debug/Makefile +36 -0
  58. package/node_modules/debug/Readme.md +86 -13
  59. package/node_modules/debug/bower.json +28 -0
  60. package/node_modules/debug/browser.js +168 -0
  61. package/node_modules/debug/component.json +19 -0
  62. package/node_modules/debug/debug.js +132 -72
  63. package/node_modules/debug/node.js +209 -0
  64. package/node_modules/debug/package.json +32 -22
  65. package/node_modules/deep-extend/README.md +51 -50
  66. package/node_modules/deep-extend/package.json +14 -16
  67. package/node_modules/delayed-stream/package.json +1 -0
  68. package/node_modules/delegates/History.md +6 -0
  69. package/node_modules/delegates/License +20 -0
  70. package/node_modules/delegates/package.json +17 -13
  71. package/node_modules/ecc-jsbn/package.json +3 -1
  72. package/node_modules/escape-string-regexp/package.json +2 -2
  73. package/node_modules/extend/package.json +1 -0
  74. package/node_modules/extsprintf/package.json +4 -2
  75. package/node_modules/forever-agent/package.json +1 -0
  76. package/node_modules/form-data/package.json +1 -0
  77. package/node_modules/fstream/package.json +1 -0
  78. package/node_modules/fstream-ignore/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/package.json +1 -0
  79. package/node_modules/fstream-ignore/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/package.json +1 -0
  80. package/node_modules/fstream-ignore/node_modules/minimatch/node_modules/brace-expansion/package.json +1 -0
  81. package/node_modules/fstream-ignore/node_modules/minimatch/package.json +1 -0
  82. package/node_modules/fstream-ignore/package.json +3 -1
  83. package/node_modules/gauge/package.json +14 -12
  84. package/node_modules/gauge/progress-bar.js +4 -5
  85. package/node_modules/gauge/test/progress-bar.js +1 -1
  86. package/node_modules/generate-function/package.json +1 -0
  87. package/node_modules/generate-object-property/package.json +1 -0
  88. package/node_modules/graceful-fs/README.md +17 -0
  89. package/node_modules/graceful-fs/graceful-fs.js +2 -0
  90. package/node_modules/graceful-fs/package.json +16 -11
  91. package/node_modules/graceful-readlink/package.json +1 -0
  92. package/node_modules/har-validator/README.md +45 -122
  93. package/node_modules/har-validator/package.json +16 -16
  94. package/node_modules/has-ansi/package.json +1 -0
  95. package/node_modules/has-unicode/README.md +6 -3
  96. package/node_modules/has-unicode/index.js +7 -3
  97. package/node_modules/has-unicode/package.json +15 -13
  98. package/node_modules/has-unicode/test/index.js +1 -1
  99. package/node_modules/hawk/README.md +634 -634
  100. package/node_modules/hawk/bower.json +24 -24
  101. package/node_modules/hawk/component.json +18 -18
  102. package/node_modules/hawk/dist/client.js +343 -340
  103. package/node_modules/hawk/example/usage.js +78 -78
  104. package/node_modules/hawk/lib/browser.js +637 -637
  105. package/node_modules/hawk/lib/client.js +369 -369
  106. package/node_modules/hawk/lib/crypto.js +126 -126
  107. package/node_modules/hawk/lib/index.js +15 -15
  108. package/node_modules/hawk/lib/server.js +548 -540
  109. package/node_modules/hawk/lib/utils.js +184 -164
  110. package/node_modules/hawk/package.json +9 -8
  111. package/node_modules/hawk/test/browser.js +1492 -1492
  112. package/node_modules/hawk/test/client.js +440 -440
  113. package/node_modules/hawk/test/crypto.js +70 -70
  114. package/node_modules/hawk/test/index.js +378 -378
  115. package/node_modules/hawk/test/readme.js +95 -95
  116. package/node_modules/hawk/test/server.js +1329 -1302
  117. package/node_modules/hawk/test/uri.js +838 -838
  118. package/node_modules/hawk/test/utils.js +149 -121
  119. package/node_modules/hoek/package.json +1 -0
  120. package/node_modules/http-signature/CHANGES.md +7 -0
  121. package/node_modules/http-signature/http_signing.md +71 -3
  122. package/node_modules/http-signature/lib/signer.js +5 -0
  123. package/node_modules/http-signature/package.json +13 -11
  124. package/node_modules/ini/package.json +3 -1
  125. package/node_modules/is-my-json-valid/formats.js +1 -1
  126. package/node_modules/is-my-json-valid/package.json +11 -10
  127. package/node_modules/is-property/package.json +1 -0
  128. package/node_modules/is-typedarray/package.json +3 -1
  129. package/node_modules/isarray/package.json +2 -2
  130. package/node_modules/isstream/package.json +1 -0
  131. package/node_modules/jodid25519/package.json +3 -1
  132. package/node_modules/jsbn/package.json +3 -1
  133. package/node_modules/json-schema/package.json +2 -1
  134. package/node_modules/json-stringify-safe/package.json +1 -0
  135. package/node_modules/jsonpointer/package.json +1 -0
  136. package/node_modules/jsprim/package.json +3 -1
  137. package/node_modules/lodash._basetostring/package.json +4 -4
  138. package/node_modules/lodash._createpadding/package.json +3 -2
  139. package/node_modules/lodash._root/LICENSE +22 -0
  140. package/node_modules/lodash._root/README.md +18 -0
  141. package/node_modules/lodash._root/index.js +53 -0
  142. package/node_modules/lodash._root/package.json +77 -0
  143. package/node_modules/lodash.pad/LICENSE +2 -2
  144. package/node_modules/lodash.pad/README.md +4 -6
  145. package/node_modules/lodash.pad/index.js +347 -15
  146. package/node_modules/lodash.pad/package.json +20 -34
  147. package/node_modules/lodash.padleft/package.json +3 -1
  148. package/node_modules/lodash.padright/package.json +3 -1
  149. package/node_modules/lodash.repeat/LICENSE +2 -2
  150. package/node_modules/lodash.repeat/README.md +4 -6
  151. package/node_modules/lodash.repeat/index.js +262 -11
  152. package/node_modules/lodash.repeat/package.json +21 -34
  153. package/node_modules/mime-db/package.json +2 -2
  154. package/node_modules/mime-types/package.json +2 -2
  155. package/node_modules/ms/.npmignore +5 -0
  156. package/node_modules/{deep-extend → ms}/LICENSE +2 -2
  157. package/node_modules/ms/README.md +35 -0
  158. package/node_modules/ms/index.js +125 -0
  159. package/node_modules/ms/package.json +56 -0
  160. package/node_modules/node-pre-gyp/CHANGELOG.md +8 -0
  161. package/node_modules/node-pre-gyp/LICENSE +27 -0
  162. package/node_modules/node-pre-gyp/lib/util/abi_crosswalk.json +36 -0
  163. package/node_modules/node-pre-gyp/package.json +23 -22
  164. package/node_modules/node-uuid/package.json +1 -0
  165. package/node_modules/npmlog/package.json +18 -16
  166. package/node_modules/oauth-sign/index.js +2 -0
  167. package/node_modules/oauth-sign/package.json +10 -9
  168. package/node_modules/once/README.md +18 -0
  169. package/node_modules/once/once.js +8 -6
  170. package/node_modules/once/package.json +20 -12
  171. package/node_modules/pinkie/index.js +3 -3
  172. package/node_modules/pinkie/package.json +10 -9
  173. package/node_modules/pinkie/readme.md +1 -1
  174. package/node_modules/pinkie-promise/package.json +1 -0
  175. package/node_modules/process-nextick-args/package.json +2 -2
  176. package/node_modules/qs/.eslintrc +17 -0
  177. package/node_modules/qs/.travis.yml +66 -5
  178. package/node_modules/qs/CHANGELOG.md +86 -75
  179. package/node_modules/qs/README.md +85 -81
  180. package/node_modules/qs/bower.json +1 -1
  181. package/node_modules/qs/component.json +1 -1
  182. package/node_modules/qs/dist/qs.js +108 -177
  183. package/node_modules/qs/lib/index.js +1 -7
  184. package/node_modules/qs/lib/parse.js +26 -49
  185. package/node_modules/qs/lib/stringify.js +22 -46
  186. package/node_modules/qs/lib/utils.js +45 -73
  187. package/node_modules/qs/package.json +51 -28
  188. package/node_modules/qs/test/index.js +5 -0
  189. package/node_modules/qs/test/parse.js +236 -321
  190. package/node_modules/qs/test/stringify.js +139 -197
  191. package/node_modules/qs/test/utils.js +6 -25
  192. package/node_modules/rc/node_modules/minimist/package.json +1 -0
  193. package/node_modules/rc/package.json +1 -0
  194. package/node_modules/readable-stream/package.json +1 -0
  195. package/node_modules/request/CHANGELOG.md +16 -1
  196. package/node_modules/request/README.md +1 -1
  197. package/node_modules/request/lib/har.js +3 -2
  198. package/node_modules/request/lib/multipart.js +3 -0
  199. package/node_modules/request/lib/tunnel.js +0 -2
  200. package/node_modules/request/package.json +20 -17
  201. package/node_modules/request/request.js +50 -26
  202. package/node_modules/rimraf/README.md +1 -1
  203. package/node_modules/rimraf/node_modules/glob/README.md +2 -2
  204. package/node_modules/rimraf/node_modules/glob/glob.js +14 -1
  205. package/node_modules/rimraf/node_modules/glob/node_modules/inflight/node_modules/wrappy/package.json +1 -0
  206. package/node_modules/rimraf/node_modules/glob/node_modules/inflight/package.json +1 -0
  207. package/node_modules/rimraf/node_modules/glob/node_modules/inherits/package.json +2 -1
  208. package/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/package.json +1 -0
  209. package/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/package.json +1 -0
  210. package/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/package.json +1 -0
  211. package/node_modules/rimraf/node_modules/glob/node_modules/minimatch/package.json +1 -0
  212. package/node_modules/rimraf/node_modules/glob/node_modules/once/node_modules/wrappy/package.json +1 -0
  213. package/node_modules/rimraf/node_modules/glob/node_modules/once/package.json +1 -0
  214. package/node_modules/rimraf/node_modules/glob/node_modules/path-is-absolute/package.json +1 -0
  215. package/node_modules/rimraf/node_modules/glob/package.json +11 -11
  216. package/node_modules/rimraf/package.json +13 -12
  217. package/node_modules/semver/package.json +3 -1
  218. package/node_modules/sntp/package.json +1 -0
  219. package/node_modules/sshpk/.npmignore +1 -0
  220. package/node_modules/sshpk/bin/sshpk-sign +176 -0
  221. package/node_modules/sshpk/bin/sshpk-verify +166 -0
  222. package/node_modules/sshpk/lib/ed-compat.js +2 -0
  223. package/node_modules/sshpk/lib/key.js +6 -0
  224. package/node_modules/sshpk/man/man1/sshpk-conv.1 +135 -0
  225. package/node_modules/sshpk/man/man1/sshpk-sign.1 +81 -0
  226. package/node_modules/sshpk/man/man1/sshpk-verify.1 +68 -0
  227. package/node_modules/sshpk/package.json +18 -9
  228. package/node_modules/string_decoder/package.json +2 -2
  229. package/node_modules/stringstream/package.json +1 -0
  230. package/node_modules/strip-ansi/package.json +1 -0
  231. package/node_modules/strip-json-comments/package.json +1 -0
  232. package/node_modules/supports-color/package.json +1 -0
  233. package/node_modules/tar/package.json +1 -0
  234. package/node_modules/tar-pack/README.md +2 -2
  235. package/node_modules/tar-pack/package.json +25 -26
  236. package/node_modules/tough-cookie/package.json +1 -0
  237. package/node_modules/tunnel-agent/package.json +1 -0
  238. package/node_modules/tweetnacl/README.md +1 -1
  239. package/node_modules/tweetnacl/package.json +13 -11
  240. package/node_modules/uid-number/package.json +14 -13
  241. package/node_modules/uid-number/uid-number.js +9 -4
  242. package/node_modules/util-deprecate/package.json +2 -2
  243. package/node_modules/verror/package.json +1 -0
  244. package/node_modules/{tar-pack/node_modules/rimraf/node_modules/glob/node_modules/once/node_modules/wrappy → wrappy}/package.json +3 -2
  245. package/node_modules/xtend/package.json +1 -0
  246. package/package.json +2 -2
  247. package/node_modules/are-we-there-yet/README.md~ +0 -183
  248. package/node_modules/bl/test/basic-test.js +0 -541
  249. package/node_modules/bl/test/sauce.js +0 -38
  250. package/node_modules/debug/index.js +0 -5
  251. package/node_modules/debug/lib/debug.js +0 -147
  252. package/node_modules/deep-extend/test/index.spec.js +0 -220
  253. package/node_modules/deep-extend/test/mocha.opts +0 -1
  254. package/node_modules/gauge/README.md~ +0 -161
  255. package/node_modules/has-unicode/README.md~ +0 -4
  256. package/node_modules/once/LICENSE +0 -27
  257. package/node_modules/once/test/once.js +0 -18
  258. package/node_modules/sshpk/node_modules/assert-plus/README.md +0 -155
  259. package/node_modules/sshpk/node_modules/assert-plus/assert.js +0 -206
  260. package/node_modules/sshpk/node_modules/assert-plus/package.json +0 -88
  261. package/node_modules/tar-pack/node_modules/rimraf/README.md +0 -43
  262. package/node_modules/tar-pack/node_modules/rimraf/bin.js +0 -40
  263. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/README.md +0 -359
  264. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/common.js +0 -226
  265. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/glob.js +0 -752
  266. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/inflight/.eslintrc +0 -17
  267. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/inflight/README.md +0 -37
  268. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/inflight/inflight.js +0 -44
  269. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/inflight/node_modules/wrappy/package.json +0 -58
  270. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/inflight/package.json +0 -67
  271. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/inflight/test.js +0 -97
  272. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/inherits/LICENSE +0 -16
  273. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/inherits/README.md +0 -42
  274. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/inherits/inherits.js +0 -1
  275. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/inherits/inherits_browser.js +0 -23
  276. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/inherits/package.json +0 -58
  277. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/inherits/test.js +0 -25
  278. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/README.md +0 -216
  279. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/minimatch.js +0 -912
  280. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/.npmignore +0 -3
  281. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/README.md +0 -122
  282. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/example.js +0 -8
  283. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/index.js +0 -191
  284. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/.npmignore +0 -2
  285. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/Makefile +0 -6
  286. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/README.md +0 -89
  287. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/example.js +0 -5
  288. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/index.js +0 -50
  289. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/package.json +0 -79
  290. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/test/balanced.js +0 -84
  291. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/.travis.yml +0 -4
  292. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/LICENSE +0 -18
  293. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/README.markdown +0 -62
  294. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/example/map.js +0 -6
  295. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/index.js +0 -13
  296. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/package.json +0 -90
  297. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/test/map.js +0 -39
  298. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/package.json +0 -81
  299. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/minimatch/package.json +0 -66
  300. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/once/README.md +0 -51
  301. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/once/node_modules/wrappy/LICENSE +0 -15
  302. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/once/node_modules/wrappy/README.md +0 -36
  303. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/once/node_modules/wrappy/test/basic.js +0 -51
  304. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/once/node_modules/wrappy/wrappy.js +0 -33
  305. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/once/once.js +0 -21
  306. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/once/package.json +0 -70
  307. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/path-is-absolute/index.js +0 -20
  308. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/path-is-absolute/package.json +0 -78
  309. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/node_modules/path-is-absolute/readme.md +0 -51
  310. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/package.json +0 -79
  311. package/node_modules/tar-pack/node_modules/rimraf/node_modules/glob/sync.js +0 -460
  312. package/node_modules/tar-pack/node_modules/rimraf/package.json +0 -69
  313. package/node_modules/tar-pack/node_modules/rimraf/rimraf.js +0 -333
  314. package/node_modules/uid-number/LICENCE +0 -25
  315. /package/node_modules/{sshpk/node_modules/assert-plus → assert-plus}/AUTHORS +0 -0
  316. /package/node_modules/{sshpk/node_modules/assert-plus → assert-plus}/CHANGES.md +0 -0
  317. /package/node_modules/{tar-pack/node_modules/rimraf → aws4/node_modules/lru-cache}/LICENSE +0 -0
  318. /package/node_modules/{tar-pack/node_modules/rimraf/node_modules/glob/node_modules/inflight → uid-number}/LICENSE +0 -0
  319. /package/node_modules/{tar-pack/node_modules/rimraf/node_modules/glob/node_modules/inflight/node_modules/wrappy → wrappy}/LICENSE +0 -0
  320. /package/node_modules/{tar-pack/node_modules/rimraf/node_modules/glob/node_modules/inflight/node_modules/wrappy → wrappy}/README.md +0 -0
  321. /package/node_modules/{tar-pack/node_modules/rimraf/node_modules/glob/node_modules/inflight/node_modules/wrappy → wrappy}/test/basic.js +0 -0
  322. /package/node_modules/{tar-pack/node_modules/rimraf/node_modules/glob/node_modules/inflight/node_modules/wrappy → wrappy}/wrappy.js +0 -0
@@ -1,1492 +1,1492 @@
1
- // Load modules
2
-
3
- var Url = require('url');
4
- var Code = require('code');
5
- var Hawk = require('../lib');
6
- var Hoek = require('hoek');
7
- var Lab = require('lab');
8
- var Browser = require('../lib/browser');
9
-
10
-
11
- // Declare internals
12
-
13
- var internals = {};
14
-
15
-
16
- // Test shortcuts
17
-
18
- var lab = exports.lab = Lab.script();
19
- var describe = lab.experiment;
20
- var it = lab.test;
21
- var expect = Code.expect;
22
-
23
-
24
- describe('Browser', function () {
25
-
26
- var credentialsFunc = function (id, callback) {
27
-
28
- var credentials = {
29
- id: id,
30
- key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
31
- algorithm: (id === '1' ? 'sha1' : 'sha256'),
32
- user: 'steve'
33
- };
34
-
35
- return callback(null, credentials);
36
- };
37
-
38
- it('should generate a bewit then successfully authenticate it', function (done) {
39
-
40
- var req = {
41
- method: 'GET',
42
- url: '/resource/4?a=1&b=2',
43
- host: 'example.com',
44
- port: 80
45
- };
46
-
47
- credentialsFunc('123456', function (err, credentials1) {
48
-
49
- 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' });
50
- req.url += '&bewit=' + bewit;
51
-
52
- Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials2, attributes) {
53
-
54
- expect(err).to.not.exist();
55
- expect(credentials2.user).to.equal('steve');
56
- expect(attributes.ext).to.equal('some-app-data');
57
- done();
58
- });
59
- });
60
- });
61
-
62
- it('should generate a bewit then successfully authenticate it (no ext)', function (done) {
63
-
64
- var req = {
65
- method: 'GET',
66
- url: '/resource/4?a=1&b=2',
67
- host: 'example.com',
68
- port: 80
69
- };
70
-
71
- credentialsFunc('123456', function (err, credentials1) {
72
-
73
- var bewit = Browser.client.bewit('http://example.com/resource/4?a=1&b=2', { credentials: credentials1, ttlSec: 60 * 60 * 24 * 365 * 100 });
74
- req.url += '&bewit=' + bewit;
75
-
76
- Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials2, attributes) {
77
-
78
- expect(err).to.not.exist();
79
- expect(credentials2.user).to.equal('steve');
80
- done();
81
- });
82
- });
83
- });
84
-
85
- describe('bewit()', function () {
86
-
87
- it('returns a valid bewit value', function (done) {
88
-
89
- var credentials = {
90
- id: '123456',
91
- key: '2983d45yun89q',
92
- algorithm: 'sha256'
93
- };
94
-
95
- var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' });
96
- expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdca3NjeHdOUjJ0SnBQMVQxekRMTlBiQjVVaUtJVTl0T1NKWFRVZEc3WDloOD1ceGFuZHlhbmR6');
97
- done();
98
- });
99
-
100
- it('returns a valid bewit value (explicit HTTP port)', function (done) {
101
-
102
- var credentials = {
103
- id: '123456',
104
- key: '2983d45yun89q',
105
- algorithm: 'sha256'
106
- };
107
-
108
- var bewit = Browser.client.bewit('http://example.com:8080/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' });
109
- expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdcaFpiSjNQMmNLRW80a3kwQzhqa1pBa1J5Q1p1ZWc0V1NOYnhWN3ZxM3hIVT1ceGFuZHlhbmR6');
110
- done();
111
- });
112
-
113
- it('returns a valid bewit value (explicit HTTPS port)', function (done) {
114
-
115
- var credentials = {
116
- id: '123456',
117
- key: '2983d45yun89q',
118
- algorithm: 'sha256'
119
- };
120
-
121
- var bewit = Browser.client.bewit('https://example.com:8043/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' });
122
- expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdcL2t4UjhwK0xSaTdvQTRnUXc3cWlxa3BiVHRKYkR4OEtRMC9HRUwvVytTUT1ceGFuZHlhbmR6');
123
- done();
124
- });
125
-
126
- it('returns a valid bewit value (null ext)', function (done) {
127
-
128
- var credentials = {
129
- id: '123456',
130
- key: '2983d45yun89q',
131
- algorithm: 'sha256'
132
- };
133
-
134
- var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: null });
135
- expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdcSUdZbUxnSXFMckNlOEN4dktQczRKbFdJQStValdKSm91d2dBUmlWaENBZz1c');
136
- done();
137
- });
138
-
139
- it('errors on invalid options', function (done) {
140
-
141
- var credentials = {
142
- id: '123456',
143
- key: '2983d45yun89q',
144
- algorithm: 'sha256'
145
- };
146
-
147
- var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow', 4);
148
- expect(bewit).to.equal('');
149
- done();
150
- });
151
-
152
- it('errors on missing uri', function (done) {
153
-
154
- var credentials = {
155
- id: '123456',
156
- key: '2983d45yun89q',
157
- algorithm: 'sha256'
158
- };
159
-
160
- var bewit = Browser.client.bewit('', { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' });
161
- expect(bewit).to.equal('');
162
- done();
163
- });
164
-
165
- it('errors on invalid uri', function (done) {
166
-
167
- var credentials = {
168
- id: '123456',
169
- key: '2983d45yun89q',
170
- algorithm: 'sha256'
171
- };
172
-
173
- var bewit = Browser.client.bewit(5, { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' });
174
- expect(bewit).to.equal('');
175
- done();
176
- });
177
-
178
- it('errors on invalid credentials (id)', function (done) {
179
-
180
- var credentials = {
181
- key: '2983d45yun89q',
182
- algorithm: 'sha256'
183
- };
184
-
185
- var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 3000, ext: 'xandyandz' });
186
- expect(bewit).to.equal('');
187
- done();
188
- });
189
-
190
- it('errors on missing credentials', function (done) {
191
-
192
- var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow', { ttlSec: 3000, ext: 'xandyandz' });
193
- expect(bewit).to.equal('');
194
- done();
195
- });
196
-
197
- it('errors on invalid credentials (key)', function (done) {
198
-
199
- var credentials = {
200
- id: '123456',
201
- algorithm: 'sha256'
202
- };
203
-
204
- var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 3000, ext: 'xandyandz' });
205
- expect(bewit).to.equal('');
206
- done();
207
- });
208
-
209
- it('errors on invalid algorithm', function (done) {
210
-
211
- var credentials = {
212
- id: '123456',
213
- key: '2983d45yun89q',
214
- algorithm: 'hmac-sha-0'
215
- };
216
-
217
- var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, ext: 'xandyandz' });
218
- expect(bewit).to.equal('');
219
- done();
220
- });
221
-
222
- it('errors on missing options', function (done) {
223
-
224
- var credentials = {
225
- id: '123456',
226
- key: '2983d45yun89q',
227
- algorithm: 'hmac-sha-0'
228
- };
229
-
230
- var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow');
231
- expect(bewit).to.equal('');
232
- done();
233
- });
234
- });
235
-
236
- it('generates a header then successfully parse it (configuration)', function (done) {
237
-
238
- var req = {
239
- method: 'GET',
240
- url: '/resource/4?filter=a',
241
- host: 'example.com',
242
- port: 8080
243
- };
244
-
245
- credentialsFunc('123456', function (err, credentials1) {
246
-
247
- req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data' }).field;
248
- expect(req.authorization).to.exist();
249
-
250
- Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
251
-
252
- expect(err).to.not.exist();
253
- expect(credentials2.user).to.equal('steve');
254
- expect(artifacts.ext).to.equal('some-app-data');
255
- done();
256
- });
257
- });
258
- });
259
-
260
- it('generates a header then successfully parse it (node request)', function (done) {
261
-
262
- var req = {
263
- method: 'POST',
264
- url: '/resource/4?filter=a',
265
- headers: {
266
- host: 'example.com:8080',
267
- 'content-type': 'text/plain;x=y'
268
- }
269
- };
270
-
271
- var payload = 'some not so random text';
272
-
273
- credentialsFunc('123456', function (err, credentials1) {
274
-
275
- 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'] });
276
- req.headers.authorization = reqHeader.field;
277
-
278
- Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
279
-
280
- expect(err).to.not.exist();
281
- expect(credentials2.user).to.equal('steve');
282
- expect(artifacts.ext).to.equal('some-app-data');
283
- expect(Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.equal(true);
284
-
285
- var res = {
286
- headers: {
287
- 'content-type': 'text/plain'
288
- },
289
- getResponseHeader: function (header) {
290
-
291
- return res.headers[header.toLowerCase()];
292
- }
293
- };
294
-
295
- res.headers['server-authorization'] = Hawk.server.header(credentials2, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' });
296
- expect(res.headers['server-authorization']).to.exist();
297
-
298
- expect(Browser.client.authenticate(res, credentials2, artifacts, { payload: 'some reply' })).to.equal(true);
299
- done();
300
- });
301
- });
302
- });
303
-
304
- it('generates a header then successfully parse it (browserify)', function (done) {
305
-
306
- var req = {
307
- method: 'POST',
308
- url: '/resource/4?filter=a',
309
- headers: {
310
- host: 'example.com:8080',
311
- 'content-type': 'text/plain;x=y'
312
- }
313
- };
314
-
315
- var payload = 'some not so random text';
316
-
317
- credentialsFunc('123456', function (err, credentials1) {
318
-
319
- 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'] });
320
- req.headers.authorization = reqHeader.field;
321
-
322
- Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
323
-
324
- expect(err).to.not.exist();
325
- expect(credentials2.user).to.equal('steve');
326
- expect(artifacts.ext).to.equal('some-app-data');
327
- expect(Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.equal(true);
328
-
329
- var res = {
330
- headers: {
331
- 'content-type': 'text/plain'
332
- },
333
- getHeader: function (header) {
334
-
335
- return res.headers[header.toLowerCase()];
336
- }
337
- };
338
-
339
- res.headers['server-authorization'] = Hawk.server.header(credentials2, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' });
340
- expect(res.headers['server-authorization']).to.exist();
341
-
342
- expect(Browser.client.authenticate(res, credentials2, artifacts, { payload: 'some reply' })).to.equal(true);
343
- done();
344
- });
345
- });
346
- });
347
-
348
- it('generates a header then successfully parse it (time offset)', function (done) {
349
-
350
- var req = {
351
- method: 'GET',
352
- url: '/resource/4?filter=a',
353
- host: 'example.com',
354
- port: 8080
355
- };
356
-
357
- credentialsFunc('123456', function (err, credentials1) {
358
-
359
- req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', localtimeOffsetMsec: 100000 }).field;
360
- expect(req.authorization).to.exist();
361
-
362
- Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 100000 }, function (err, credentials2, artifacts) {
363
-
364
- expect(err).to.not.exist();
365
- expect(credentials2.user).to.equal('steve');
366
- expect(artifacts.ext).to.equal('some-app-data');
367
- done();
368
- });
369
- });
370
- });
371
-
372
- it('generates a header then successfully parse it (no server header options)', function (done) {
373
-
374
- var req = {
375
- method: 'POST',
376
- url: '/resource/4?filter=a',
377
- headers: {
378
- host: 'example.com:8080',
379
- 'content-type': 'text/plain;x=y'
380
- }
381
- };
382
-
383
- var payload = 'some not so random text';
384
-
385
- credentialsFunc('123456', function (err, credentials1) {
386
-
387
- 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'] });
388
- req.headers.authorization = reqHeader.field;
389
-
390
- Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
391
-
392
- expect(err).to.not.exist();
393
- expect(credentials2.user).to.equal('steve');
394
- expect(artifacts.ext).to.equal('some-app-data');
395
- expect(Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.equal(true);
396
-
397
- var res = {
398
- headers: {
399
- 'content-type': 'text/plain'
400
- },
401
- getResponseHeader: function (header) {
402
-
403
- return res.headers[header.toLowerCase()];
404
- }
405
- };
406
-
407
- res.headers['server-authorization'] = Hawk.server.header(credentials2, artifacts);
408
- expect(res.headers['server-authorization']).to.exist();
409
-
410
- expect(Browser.client.authenticate(res, credentials2, artifacts)).to.equal(true);
411
- done();
412
- });
413
- });
414
- });
415
-
416
- it('generates a header then successfully parse it (no server header)', function (done) {
417
-
418
- var req = {
419
- method: 'POST',
420
- url: '/resource/4?filter=a',
421
- headers: {
422
- host: 'example.com:8080',
423
- 'content-type': 'text/plain;x=y'
424
- }
425
- };
426
-
427
- var payload = 'some not so random text';
428
-
429
- credentialsFunc('123456', function (err, credentials1) {
430
-
431
- 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'] });
432
- req.headers.authorization = reqHeader.field;
433
-
434
- Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
435
-
436
- expect(err).to.not.exist();
437
- expect(credentials2.user).to.equal('steve');
438
- expect(artifacts.ext).to.equal('some-app-data');
439
- expect(Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.equal(true);
440
-
441
- var res = {
442
- headers: {
443
- 'content-type': 'text/plain'
444
- },
445
- getResponseHeader: function (header) {
446
-
447
- return res.headers[header.toLowerCase()];
448
- }
449
- };
450
-
451
- expect(Browser.client.authenticate(res, credentials2, artifacts)).to.equal(true);
452
- done();
453
- });
454
- });
455
- });
456
-
457
- it('generates a header with stale ts and successfully authenticate on second call', function (done) {
458
-
459
- var req = {
460
- method: 'GET',
461
- url: '/resource/4?filter=a',
462
- host: 'example.com',
463
- port: 8080
464
- };
465
-
466
- credentialsFunc('123456', function (err, credentials1) {
467
-
468
- Browser.utils.setNtpOffset(60 * 60 * 1000);
469
- var header = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data' });
470
- req.authorization = header.field;
471
- expect(req.authorization).to.exist();
472
-
473
- Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts2) {
474
-
475
- expect(err).to.exist();
476
- expect(err.message).to.equal('Stale timestamp');
477
-
478
- var res = {
479
- headers: {
480
- 'www-authenticate': err.output.headers['WWW-Authenticate']
481
- },
482
- getResponseHeader: function (lookup) {
483
-
484
- return res.headers[lookup.toLowerCase()];
485
- }
486
- };
487
-
488
- expect(Browser.utils.getNtpOffset()).to.equal(60 * 60 * 1000);
489
- expect(Browser.client.authenticate(res, credentials2, header.artifacts)).to.equal(true);
490
- expect(Browser.utils.getNtpOffset()).to.equal(0);
491
-
492
- req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials2, ext: 'some-app-data' }).field;
493
- expect(req.authorization).to.exist();
494
-
495
- Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials3, artifacts3) {
496
-
497
- expect(err).to.not.exist();
498
- expect(credentials3.user).to.equal('steve');
499
- expect(artifacts3.ext).to.equal('some-app-data');
500
- done();
501
- });
502
- });
503
- });
504
- });
505
-
506
- it('generates a header with stale ts and successfully authenticate on second call (manual localStorage)', function (done) {
507
-
508
- var req = {
509
- method: 'GET',
510
- url: '/resource/4?filter=a',
511
- host: 'example.com',
512
- port: 8080
513
- };
514
-
515
- credentialsFunc('123456', function (err, credentials1) {
516
-
517
- var localStorage = new Browser.internals.LocalStorage();
518
-
519
- Browser.utils.setStorage(localStorage);
520
-
521
- Browser.utils.setNtpOffset(60 * 60 * 1000);
522
- var header = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data' });
523
- req.authorization = header.field;
524
- expect(req.authorization).to.exist();
525
-
526
- Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts2) {
527
-
528
- expect(err).to.exist();
529
- expect(err.message).to.equal('Stale timestamp');
530
-
531
- var res = {
532
- headers: {
533
- 'www-authenticate': err.output.headers['WWW-Authenticate']
534
- },
535
- getResponseHeader: function (lookup) {
536
-
537
- return res.headers[lookup.toLowerCase()];
538
- }
539
- };
540
-
541
- expect(parseInt(localStorage.getItem('hawk_ntp_offset'))).to.equal(60 * 60 * 1000);
542
- expect(Browser.utils.getNtpOffset()).to.equal(60 * 60 * 1000);
543
- expect(Browser.client.authenticate(res, credentials2, header.artifacts)).to.equal(true);
544
- expect(Browser.utils.getNtpOffset()).to.equal(0);
545
- expect(parseInt(localStorage.getItem('hawk_ntp_offset'))).to.equal(0);
546
-
547
- req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials2, ext: 'some-app-data' }).field;
548
- expect(req.authorization).to.exist();
549
-
550
- Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials3, artifacts3) {
551
-
552
- expect(err).to.not.exist();
553
- expect(credentials3.user).to.equal('steve');
554
- expect(artifacts3.ext).to.equal('some-app-data');
555
- done();
556
- });
557
- });
558
- });
559
- });
560
-
561
- it('generates a header then fails to parse it (missing server header hash)', function (done) {
562
-
563
- var req = {
564
- method: 'POST',
565
- url: '/resource/4?filter=a',
566
- headers: {
567
- host: 'example.com:8080',
568
- 'content-type': 'text/plain;x=y'
569
- }
570
- };
571
-
572
- var payload = 'some not so random text';
573
-
574
- credentialsFunc('123456', function (err, credentials1) {
575
-
576
- 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'] });
577
- req.headers.authorization = reqHeader.field;
578
-
579
- Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
580
-
581
- expect(err).to.not.exist();
582
- expect(credentials2.user).to.equal('steve');
583
- expect(artifacts.ext).to.equal('some-app-data');
584
- expect(Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.equal(true);
585
-
586
- var res = {
587
- headers: {
588
- 'content-type': 'text/plain'
589
- },
590
- getResponseHeader: function (header) {
591
-
592
- return res.headers[header.toLowerCase()];
593
- }
594
- };
595
-
596
- res.headers['server-authorization'] = Hawk.server.header(credentials2, artifacts);
597
- expect(res.headers['server-authorization']).to.exist();
598
-
599
- expect(Browser.client.authenticate(res, credentials2, artifacts, { payload: 'some reply' })).to.equal(false);
600
- done();
601
- });
602
- });
603
- });
604
-
605
- it('generates a header then successfully parse it (with hash)', function (done) {
606
-
607
- var req = {
608
- method: 'GET',
609
- url: '/resource/4?filter=a',
610
- host: 'example.com',
611
- port: 8080
612
- };
613
-
614
- credentialsFunc('123456', function (err, credentials1) {
615
-
616
- req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, payload: 'hola!', ext: 'some-app-data' }).field;
617
- Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
618
-
619
- expect(err).to.not.exist();
620
- expect(credentials2.user).to.equal('steve');
621
- expect(artifacts.ext).to.equal('some-app-data');
622
- done();
623
- });
624
- });
625
- });
626
-
627
- it('generates a header then successfully parse it then validate payload', function (done) {
628
-
629
- var req = {
630
- method: 'GET',
631
- url: '/resource/4?filter=a',
632
- host: 'example.com',
633
- port: 8080
634
- };
635
-
636
- credentialsFunc('123456', function (err, credentials1) {
637
-
638
- req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, payload: 'hola!', ext: 'some-app-data' }).field;
639
- Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
640
-
641
- expect(err).to.not.exist();
642
- expect(credentials2.user).to.equal('steve');
643
- expect(artifacts.ext).to.equal('some-app-data');
644
- expect(Hawk.server.authenticatePayload('hola!', credentials2, artifacts)).to.be.true();
645
- expect(Hawk.server.authenticatePayload('hello!', credentials2, artifacts)).to.be.false();
646
- done();
647
- });
648
- });
649
- });
650
-
651
- it('generates a header then successfully parse it (app)', function (done) {
652
-
653
- var req = {
654
- method: 'GET',
655
- url: '/resource/4?filter=a',
656
- host: 'example.com',
657
- port: 8080
658
- };
659
-
660
- credentialsFunc('123456', function (err, credentials1) {
661
-
662
- req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', app: 'asd23ased' }).field;
663
- Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
664
-
665
- expect(err).to.not.exist();
666
- expect(credentials2.user).to.equal('steve');
667
- expect(artifacts.ext).to.equal('some-app-data');
668
- expect(artifacts.app).to.equal('asd23ased');
669
- done();
670
- });
671
- });
672
- });
673
-
674
- it('generates a header then successfully parse it (app, dlg)', function (done) {
675
-
676
- var req = {
677
- method: 'GET',
678
- url: '/resource/4?filter=a',
679
- host: 'example.com',
680
- port: 8080
681
- };
682
-
683
- credentialsFunc('123456', function (err, credentials1) {
684
-
685
- 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;
686
- Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
687
-
688
- expect(err).to.not.exist();
689
- expect(credentials2.user).to.equal('steve');
690
- expect(artifacts.ext).to.equal('some-app-data');
691
- expect(artifacts.app).to.equal('asd23ased');
692
- expect(artifacts.dlg).to.equal('23434szr3q4d');
693
- done();
694
- });
695
- });
696
- });
697
-
698
- it('generates a header then fail authentication due to bad hash', function (done) {
699
-
700
- var req = {
701
- method: 'GET',
702
- url: '/resource/4?filter=a',
703
- host: 'example.com',
704
- port: 8080
705
- };
706
-
707
- credentialsFunc('123456', function (err, credentials1) {
708
-
709
- req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, payload: 'hola!', ext: 'some-app-data' }).field;
710
- Hawk.server.authenticate(req, credentialsFunc, { payload: 'byebye!' }, function (err, credentials2, artifacts) {
711
-
712
- expect(err).to.exist();
713
- expect(err.output.payload.message).to.equal('Bad payload hash');
714
- done();
715
- });
716
- });
717
- });
718
-
719
- it('generates a header for one resource then fail to authenticate another', function (done) {
720
-
721
- var req = {
722
- method: 'GET',
723
- url: '/resource/4?filter=a',
724
- host: 'example.com',
725
- port: 8080
726
- };
727
-
728
- credentialsFunc('123456', function (err, credentials1) {
729
-
730
- req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data' }).field;
731
- req.url = '/something/else';
732
-
733
- Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
734
-
735
- expect(err).to.exist();
736
- expect(credentials2).to.exist();
737
- done();
738
- });
739
- });
740
- });
741
-
742
- describe('client', function () {
743
-
744
- describe('header()', function () {
745
-
746
- it('returns a valid authorization header (sha1)', function (done) {
747
-
748
- var credentials = {
749
- id: '123456',
750
- key: '2983d45yun89q',
751
- algorithm: 'sha1'
752
- };
753
-
754
- 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;
755
- expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="bsvY3IfUllw6V5rvk4tStEvpBhE=", ext="Bazinga!", mac="qbf1ZPG/r/e06F4ht+T77LXi5vw="');
756
- done();
757
- });
758
-
759
- it('returns a valid authorization header (sha256)', function (done) {
760
-
761
- var credentials = {
762
- id: '123456',
763
- key: '2983d45yun89q',
764
- algorithm: 'sha256'
765
- };
766
-
767
- 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;
768
- expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", ext="Bazinga!", mac="q1CwFoSHzPZSkbIvl0oYlD+91rBUEvFk763nMjMndj8="');
769
- done();
770
- });
771
-
772
- it('returns a valid authorization header (empty payload)', function (done) {
773
-
774
- var credentials = {
775
- id: '123456',
776
- key: '2983d45yun89q',
777
- algorithm: 'sha1'
778
- };
779
-
780
- var header = Browser.client.header('http://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: '' }).field;
781
- expect(header).to.equal('Hawk id=\"123456\", ts=\"1353809207\", nonce=\"Ygvqdz\", hash=\"404ghL7K+hfyhByKKejFBRGgTjU=\", ext=\"Bazinga!\", mac=\"Bh1sj1DOfFRWOdi3ww52nLCJdBE=\"');
782
- done();
783
- });
784
-
785
- it('returns a valid authorization header (no ext)', function (done) {
786
-
787
- var credentials = {
788
- id: '123456',
789
- key: '2983d45yun89q',
790
- algorithm: 'sha256'
791
- };
792
-
793
- 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;
794
- expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="');
795
- done();
796
- });
797
-
798
- it('returns a valid authorization header (null ext)', function (done) {
799
-
800
- var credentials = {
801
- id: '123456',
802
- key: '2983d45yun89q',
803
- algorithm: 'sha256'
804
- };
805
-
806
- 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;
807
- expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="');
808
- done();
809
- });
810
-
811
- it('returns a valid authorization header (uri object)', function (done) {
812
-
813
- var credentials = {
814
- id: '123456',
815
- key: '2983d45yun89q',
816
- algorithm: 'sha256'
817
- };
818
-
819
- var uri = Browser.utils.parseUri('https://example.net/somewhere/over/the/rainbow');
820
- var header = Browser.client.header(uri, 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }).field;
821
- expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="');
822
- done();
823
- });
824
-
825
- it('errors on missing options', function (done) {
826
-
827
- var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST');
828
- expect(header.field).to.equal('');
829
- expect(header.err).to.equal('Invalid argument type');
830
- done();
831
- });
832
-
833
- it('errors on empty uri', function (done) {
834
-
835
- var credentials = {
836
- id: '123456',
837
- key: '2983d45yun89q',
838
- algorithm: 'sha256'
839
- };
840
-
841
- var header = Browser.client.header('', 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' });
842
- expect(header.field).to.equal('');
843
- expect(header.err).to.equal('Invalid argument type');
844
- done();
845
- });
846
-
847
- it('errors on invalid uri', function (done) {
848
-
849
- var credentials = {
850
- id: '123456',
851
- key: '2983d45yun89q',
852
- algorithm: 'sha256'
853
- };
854
-
855
- var header = Browser.client.header(4, 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' });
856
- expect(header.field).to.equal('');
857
- expect(header.err).to.equal('Invalid argument type');
858
- done();
859
- });
860
-
861
- it('errors on missing method', function (done) {
862
-
863
- var credentials = {
864
- id: '123456',
865
- key: '2983d45yun89q',
866
- algorithm: 'sha256'
867
- };
868
-
869
- 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' });
870
- expect(header.field).to.equal('');
871
- expect(header.err).to.equal('Invalid argument type');
872
- done();
873
- });
874
-
875
- it('errors on invalid method', function (done) {
876
-
877
- var credentials = {
878
- id: '123456',
879
- key: '2983d45yun89q',
880
- algorithm: 'sha256'
881
- };
882
-
883
- 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' });
884
- expect(header.field).to.equal('');
885
- expect(header.err).to.equal('Invalid argument type');
886
- done();
887
- });
888
-
889
- it('errors on missing credentials', function (done) {
890
-
891
- var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { ext: 'Bazinga!', timestamp: 1353809207 });
892
- expect(header.field).to.equal('');
893
- expect(header.err).to.equal('Invalid credentials object');
894
- done();
895
- });
896
-
897
- it('errors on invalid credentials (id)', function (done) {
898
-
899
- var credentials = {
900
- key: '2983d45yun89q',
901
- algorithm: 'sha256'
902
- };
903
-
904
- var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207 });
905
- expect(header.field).to.equal('');
906
- expect(header.err).to.equal('Invalid credentials object');
907
- done();
908
- });
909
-
910
- it('errors on invalid credentials (key)', function (done) {
911
-
912
- var credentials = {
913
- id: '123456',
914
- algorithm: 'sha256'
915
- };
916
-
917
- var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207 });
918
- expect(header.field).to.equal('');
919
- expect(header.err).to.equal('Invalid credentials object');
920
- done();
921
- });
922
-
923
- it('errors on invalid algorithm', function (done) {
924
-
925
- var credentials = {
926
- id: '123456',
927
- key: '2983d45yun89q',
928
- algorithm: 'hmac-sha-0'
929
- };
930
-
931
- var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, payload: 'something, anything!', ext: 'Bazinga!', timestamp: 1353809207 });
932
- expect(header.field).to.equal('');
933
- expect(header.err).to.equal('Unknown algorithm');
934
- done();
935
- });
936
-
937
- it('uses a pre-calculated payload hash', function (done) {
938
-
939
- var credentials = {
940
- id: '123456',
941
- key: '2983d45yun89q',
942
- algorithm: 'sha256'
943
- };
944
-
945
- var options = { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' };
946
- options.hash = Browser.crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType);
947
- var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', options).field;
948
- expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", ext="Bazinga!", mac="q1CwFoSHzPZSkbIvl0oYlD+91rBUEvFk763nMjMndj8="');
949
- done();
950
- });
951
- });
952
-
953
- describe('authenticate()', function () {
954
-
955
- it('skips tsm validation when missing ts', function (done) {
956
-
957
- var res = {
958
- headers: {
959
- 'www-authenticate': 'Hawk error="Stale timestamp"'
960
- },
961
- getResponseHeader: function (header) {
962
-
963
- return res.headers[header.toLowerCase()];
964
- }
965
- };
966
-
967
- var credentials = {
968
- id: '123456',
969
- key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
970
- algorithm: 'sha256',
971
- user: 'steve'
972
- };
973
-
974
- var artifacts = {
975
- ts: 1402135580,
976
- nonce: 'iBRB6t',
977
- method: 'GET',
978
- resource: '/resource/4?filter=a',
979
- host: 'example.com',
980
- port: '8080',
981
- ext: 'some-app-data'
982
- };
983
-
984
- expect(Browser.client.authenticate(res, credentials, artifacts)).to.equal(true);
985
- done();
986
- });
987
-
988
- it('returns false on invalid header', function (done) {
989
-
990
- var res = {
991
- headers: {
992
- 'server-authorization': 'Hawk mac="abc", bad="xyz"'
993
- },
994
- getResponseHeader: function (header) {
995
-
996
- return res.headers[header.toLowerCase()];
997
- }
998
- };
999
-
1000
- expect(Browser.client.authenticate(res, {})).to.equal(false);
1001
- done();
1002
- });
1003
-
1004
- it('returns false on invalid mac', function (done) {
1005
-
1006
- var res = {
1007
- headers: {
1008
- 'content-type': 'text/plain',
1009
- 'server-authorization': 'Hawk mac="_IJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"'
1010
- },
1011
- getResponseHeader: function (header) {
1012
-
1013
- return res.headers[header.toLowerCase()];
1014
- }
1015
- };
1016
-
1017
- var artifacts = {
1018
- method: 'POST',
1019
- host: 'example.com',
1020
- port: '8080',
1021
- resource: '/resource/4?filter=a',
1022
- ts: '1362336900',
1023
- nonce: 'eb5S_L',
1024
- hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
1025
- ext: 'some-app-data',
1026
- app: undefined,
1027
- dlg: undefined,
1028
- mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=',
1029
- id: '123456'
1030
- };
1031
-
1032
- var credentials = {
1033
- id: '123456',
1034
- key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
1035
- algorithm: 'sha256',
1036
- user: 'steve'
1037
- };
1038
-
1039
- expect(Browser.client.authenticate(res, credentials, artifacts)).to.equal(false);
1040
- done();
1041
- });
1042
-
1043
- it('returns true on ignoring hash', function (done) {
1044
-
1045
- var res = {
1046
- headers: {
1047
- 'content-type': 'text/plain',
1048
- 'server-authorization': 'Hawk mac="XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"'
1049
- },
1050
- getResponseHeader: function (header) {
1051
-
1052
- return res.headers[header.toLowerCase()];
1053
- }
1054
- };
1055
-
1056
- var artifacts = {
1057
- method: 'POST',
1058
- host: 'example.com',
1059
- port: '8080',
1060
- resource: '/resource/4?filter=a',
1061
- ts: '1362336900',
1062
- nonce: 'eb5S_L',
1063
- hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
1064
- ext: 'some-app-data',
1065
- app: undefined,
1066
- dlg: undefined,
1067
- mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=',
1068
- id: '123456'
1069
- };
1070
-
1071
- var credentials = {
1072
- id: '123456',
1073
- key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
1074
- algorithm: 'sha256',
1075
- user: 'steve'
1076
- };
1077
-
1078
- expect(Browser.client.authenticate(res, credentials, artifacts)).to.equal(true);
1079
- done();
1080
- });
1081
-
1082
- it('errors on invalid WWW-Authenticate header format', function (done) {
1083
-
1084
- var res = {
1085
- headers: {
1086
- 'www-authenticate': 'Hawk ts="1362346425875", tsm="PhwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", x="Stale timestamp"'
1087
- },
1088
- getResponseHeader: function (header) {
1089
-
1090
- return res.headers[header.toLowerCase()];
1091
- }
1092
- };
1093
-
1094
- expect(Browser.client.authenticate(res, {})).to.equal(false);
1095
- done();
1096
- });
1097
-
1098
- it('errors on invalid WWW-Authenticate header format', function (done) {
1099
-
1100
- var credentials = {
1101
- id: '123456',
1102
- key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
1103
- algorithm: 'sha256',
1104
- user: 'steve'
1105
- };
1106
-
1107
- var res = {
1108
- headers: {
1109
- 'www-authenticate': 'Hawk ts="1362346425875", tsm="hwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", error="Stale timestamp"'
1110
- },
1111
- getResponseHeader: function (header) {
1112
-
1113
- return res.headers[header.toLowerCase()];
1114
- }
1115
- };
1116
-
1117
- expect(Browser.client.authenticate(res, credentials)).to.equal(false);
1118
- done();
1119
- });
1120
- });
1121
-
1122
- describe('message()', function () {
1123
-
1124
- it('generates an authorization then successfully parse it', function (done) {
1125
-
1126
- credentialsFunc('123456', function (err, credentials1) {
1127
-
1128
- var auth = Browser.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
1129
- expect(auth).to.exist();
1130
-
1131
- Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials2) {
1132
-
1133
- expect(err).to.not.exist();
1134
- expect(credentials2.user).to.equal('steve');
1135
- done();
1136
- });
1137
- });
1138
- });
1139
-
1140
- it('generates an authorization using custom nonce/timestamp', function (done) {
1141
-
1142
- credentialsFunc('123456', function (err, credentials) {
1143
-
1144
- var auth = Browser.client.message('example.com', 8080, 'some message', { credentials: credentials, nonce: 'abc123', timestamp: 1398536270957 });
1145
- expect(auth).to.exist();
1146
- expect(auth.nonce).to.equal('abc123');
1147
- expect(auth.ts).to.equal(1398536270957);
1148
- done();
1149
- });
1150
- });
1151
-
1152
- it('errors on missing host', function (done) {
1153
-
1154
- credentialsFunc('123456', function (err, credentials) {
1155
-
1156
- var auth = Browser.client.message(null, 8080, 'some message', { credentials: credentials });
1157
- expect(auth).to.not.exist();
1158
- done();
1159
- });
1160
- });
1161
-
1162
- it('errors on invalid host', function (done) {
1163
-
1164
- credentialsFunc('123456', function (err, credentials) {
1165
-
1166
- var auth = Browser.client.message(5, 8080, 'some message', { credentials: credentials });
1167
- expect(auth).to.not.exist();
1168
- done();
1169
- });
1170
- });
1171
-
1172
- it('errors on missing port', function (done) {
1173
-
1174
- credentialsFunc('123456', function (err, credentials) {
1175
-
1176
- var auth = Browser.client.message('example.com', 0, 'some message', { credentials: credentials });
1177
- expect(auth).to.not.exist();
1178
- done();
1179
- });
1180
- });
1181
-
1182
- it('errors on invalid port', function (done) {
1183
-
1184
- credentialsFunc('123456', function (err, credentials) {
1185
-
1186
- var auth = Browser.client.message('example.com', 'a', 'some message', { credentials: credentials });
1187
- expect(auth).to.not.exist();
1188
- done();
1189
- });
1190
- });
1191
-
1192
- it('errors on missing message', function (done) {
1193
-
1194
- credentialsFunc('123456', function (err, credentials) {
1195
-
1196
- var auth = Browser.client.message('example.com', 8080, undefined, { credentials: credentials });
1197
- expect(auth).to.not.exist();
1198
- done();
1199
- });
1200
- });
1201
-
1202
- it('errors on null message', function (done) {
1203
-
1204
- credentialsFunc('123456', function (err, credentials) {
1205
-
1206
- var auth = Browser.client.message('example.com', 8080, null, { credentials: credentials });
1207
- expect(auth).to.not.exist();
1208
- done();
1209
- });
1210
- });
1211
-
1212
- it('errors on invalid message', function (done) {
1213
-
1214
- credentialsFunc('123456', function (err, credentials) {
1215
-
1216
- var auth = Browser.client.message('example.com', 8080, 5, { credentials: credentials });
1217
- expect(auth).to.not.exist();
1218
- done();
1219
- });
1220
- });
1221
-
1222
- it('errors on missing credentials', function (done) {
1223
-
1224
- var auth = Browser.client.message('example.com', 8080, 'some message', {});
1225
- expect(auth).to.not.exist();
1226
- done();
1227
- });
1228
-
1229
- it('errors on missing options', function (done) {
1230
-
1231
- var auth = Browser.client.message('example.com', 8080, 'some message');
1232
- expect(auth).to.not.exist();
1233
- done();
1234
- });
1235
-
1236
- it('errors on invalid credentials (id)', function (done) {
1237
-
1238
- credentialsFunc('123456', function (err, credentials) {
1239
-
1240
- var creds = Hoek.clone(credentials);
1241
- delete creds.id;
1242
- var auth = Browser.client.message('example.com', 8080, 'some message', { credentials: creds });
1243
- expect(auth).to.not.exist();
1244
- done();
1245
- });
1246
- });
1247
-
1248
- it('errors on invalid credentials (key)', function (done) {
1249
-
1250
- credentialsFunc('123456', function (err, credentials) {
1251
-
1252
- var creds = Hoek.clone(credentials);
1253
- delete creds.key;
1254
- var auth = Browser.client.message('example.com', 8080, 'some message', { credentials: creds });
1255
- expect(auth).to.not.exist();
1256
- done();
1257
- });
1258
- });
1259
-
1260
- it('errors on invalid algorithm', function (done) {
1261
-
1262
- credentialsFunc('123456', function (err, credentials) {
1263
-
1264
- var creds = Hoek.clone(credentials);
1265
- creds.algorithm = 'blah';
1266
- var auth = Browser.client.message('example.com', 8080, 'some message', { credentials: creds });
1267
- expect(auth).to.not.exist();
1268
- done();
1269
- });
1270
- });
1271
- });
1272
-
1273
- describe('authenticateTimestamp()', function (done) {
1274
-
1275
- it('validates a timestamp', function (done) {
1276
-
1277
- credentialsFunc('123456', function (err, credentials) {
1278
-
1279
- var tsm = Hawk.crypto.timestampMessage(credentials);
1280
- expect(Browser.client.authenticateTimestamp(tsm, credentials)).to.equal(true);
1281
- done();
1282
- });
1283
- });
1284
-
1285
- it('validates a timestamp without updating local time', function (done) {
1286
-
1287
- credentialsFunc('123456', function (err, credentials) {
1288
-
1289
- var offset = Browser.utils.getNtpOffset();
1290
- var tsm = Hawk.crypto.timestampMessage(credentials, 10000);
1291
- expect(Browser.client.authenticateTimestamp(tsm, credentials, false)).to.equal(true);
1292
- expect(offset).to.equal(Browser.utils.getNtpOffset());
1293
- done();
1294
- });
1295
- });
1296
-
1297
- it('detects a bad timestamp', function (done) {
1298
-
1299
- credentialsFunc('123456', function (err, credentials) {
1300
-
1301
- var tsm = Hawk.crypto.timestampMessage(credentials);
1302
- tsm.ts = 4;
1303
- expect(Browser.client.authenticateTimestamp(tsm, credentials)).to.equal(false);
1304
- done();
1305
- });
1306
- });
1307
- });
1308
- });
1309
-
1310
- describe('internals', function () {
1311
-
1312
- describe('LocalStorage', function () {
1313
-
1314
- it('goes through the full lifecycle', function (done) {
1315
-
1316
- var storage = new Browser.internals.LocalStorage();
1317
- expect(storage.length).to.equal(0);
1318
- expect(storage.getItem('a')).to.equal(null);
1319
- storage.setItem('a', 5);
1320
- expect(storage.length).to.equal(1);
1321
- expect(storage.key()).to.equal('a');
1322
- expect(storage.key(0)).to.equal('a');
1323
- expect(storage.getItem('a')).to.equal('5');
1324
- storage.setItem('b', 'test');
1325
- expect(storage.key()).to.equal('a');
1326
- expect(storage.key(0)).to.equal('a');
1327
- expect(storage.key(1)).to.equal('b');
1328
- expect(storage.length).to.equal(2);
1329
- expect(storage.getItem('b')).to.equal('test');
1330
- storage.removeItem('a');
1331
- expect(storage.length).to.equal(1);
1332
- expect(storage.getItem('a')).to.equal(null);
1333
- expect(storage.getItem('b')).to.equal('test');
1334
- storage.clear();
1335
- expect(storage.length).to.equal(0);
1336
- expect(storage.getItem('a')).to.equal(null);
1337
- expect(storage.getItem('b')).to.equal(null);
1338
- done();
1339
- });
1340
- });
1341
- });
1342
-
1343
- describe('utils', function () {
1344
-
1345
- describe('setStorage()', function () {
1346
-
1347
- it('sets storage for the first time', function (done) {
1348
-
1349
- Browser.utils.storage = new Browser.internals.LocalStorage(); // Reset state
1350
-
1351
- expect(Browser.utils.storage.getItem('hawk_ntp_offset')).to.not.exist();
1352
- Browser.utils.storage.setItem('test', '1');
1353
- Browser.utils.setStorage(new Browser.internals.LocalStorage());
1354
- expect(Browser.utils.storage.getItem('test')).to.not.exist();
1355
- Browser.utils.storage.setItem('test', '2');
1356
- expect(Browser.utils.storage.getItem('test')).to.equal('2');
1357
- done();
1358
- });
1359
- });
1360
-
1361
- describe('setNtpOffset()', function (done) {
1362
-
1363
- it('catches localStorage errors', { parallel: false }, function (done) {
1364
-
1365
- var orig = Browser.utils.storage.setItem;
1366
- var consoleOrig = console.error;
1367
- var count = 0;
1368
- console.error = function () {
1369
-
1370
- if (count++ === 2) {
1371
-
1372
- console.error = consoleOrig;
1373
- }
1374
- };
1375
-
1376
- Browser.utils.storage.setItem = function () {
1377
-
1378
- Browser.utils.storage.setItem = orig;
1379
- throw new Error();
1380
- };
1381
-
1382
- expect(function () {
1383
-
1384
- Browser.utils.setNtpOffset(100);
1385
- }).not.to.throw();
1386
-
1387
- done();
1388
- });
1389
- });
1390
-
1391
- describe('parseAuthorizationHeader()', function (done) {
1392
-
1393
- it('returns null on missing header', function (done) {
1394
-
1395
- expect(Browser.utils.parseAuthorizationHeader()).to.equal(null);
1396
- done();
1397
- });
1398
-
1399
- it('returns null on bad header syntax (structure)', function (done) {
1400
-
1401
- expect(Browser.utils.parseAuthorizationHeader('Hawk')).to.equal(null);
1402
- done();
1403
- });
1404
-
1405
- it('returns null on bad header syntax (parts)', function (done) {
1406
-
1407
- expect(Browser.utils.parseAuthorizationHeader(' ')).to.equal(null);
1408
- done();
1409
- });
1410
-
1411
- it('returns null on bad scheme name', function (done) {
1412
-
1413
- expect(Browser.utils.parseAuthorizationHeader('Basic asdasd')).to.equal(null);
1414
- done();
1415
- });
1416
-
1417
- it('returns null on bad attribute value', function (done) {
1418
-
1419
- expect(Browser.utils.parseAuthorizationHeader('Hawk test="\t"', ['test'])).to.equal(null);
1420
- done();
1421
- });
1422
-
1423
- it('returns null on duplicated attribute', function (done) {
1424
-
1425
- expect(Browser.utils.parseAuthorizationHeader('Hawk test="a", test="b"', ['test'])).to.equal(null);
1426
- done();
1427
- });
1428
- });
1429
-
1430
- describe('parseUri()', function () {
1431
-
1432
- it('returns empty object on invalid', function (done) {
1433
-
1434
- var uri = Browser.utils.parseUri('ftp');
1435
- expect(uri).to.deep.equal({ host: '', port: '', resource: '' });
1436
- done();
1437
- });
1438
-
1439
- it('returns empty port when unknown scheme', function (done) {
1440
-
1441
- var uri = Browser.utils.parseUri('ftp://example.com');
1442
- expect(uri.port).to.equal('');
1443
- done();
1444
- });
1445
-
1446
- it('returns default port when missing', function (done) {
1447
-
1448
- var uri = Browser.utils.parseUri('http://example.com');
1449
- expect(uri.port).to.equal('80');
1450
- done();
1451
- });
1452
-
1453
- it('handles unusual characters correctly', function (done) {
1454
-
1455
- var parts = {
1456
- protocol: 'http+vnd.my-extension',
1457
- user: 'user!$&\'()*+,;=%40my-domain.com',
1458
- password: 'pass!$&\'()*+,;=%40:word',
1459
- hostname: 'foo-bar.com',
1460
- port: '99',
1461
- pathname: '/path/%40/!$&\'()*+,;=:@/',
1462
- query: 'query%40/!$&\'()*+,;=:@/?',
1463
- fragment: 'fragm%40/!$&\'()*+,;=:@/?'
1464
- };
1465
-
1466
- parts.userInfo = parts.user + ':' + parts.password;
1467
- parts.authority = parts.userInfo + '@' + parts.hostname + ':' + parts.port;
1468
- parts.relative = parts.pathname + '?' + parts.query;
1469
- parts.resource = parts.relative + '#' + parts.fragment;
1470
- parts.source = parts.protocol + '://' + parts.authority + parts.resource;
1471
-
1472
- var uri = Browser.utils.parseUri(parts.source);
1473
- expect(uri.host).to.equal('foo-bar.com');
1474
- expect(uri.port).to.equal('99');
1475
- expect(uri.resource).to.equal(parts.pathname + '?' + parts.query);
1476
- done();
1477
- });
1478
- });
1479
-
1480
- var str = 'https://www.google.ca/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=url';
1481
- var base64str = 'aHR0cHM6Ly93d3cuZ29vZ2xlLmNhL3dlYmhwP3NvdXJjZWlkPWNocm9tZS1pbnN0YW50Jmlvbj0xJmVzcHY9MiZpZT1VVEYtOCNxPXVybA';
1482
-
1483
- describe('base64urlEncode()', function () {
1484
-
1485
- it('should base64 URL-safe decode a string', function (done) {
1486
-
1487
- expect(Browser.utils.base64urlEncode(str)).to.equal(base64str);
1488
- done();
1489
- });
1490
- });
1491
- });
1492
- });
1
+ // Load modules
2
+
3
+ var Url = require('url');
4
+ var Code = require('code');
5
+ var Hawk = require('../lib');
6
+ var Hoek = require('hoek');
7
+ var Lab = require('lab');
8
+ var Browser = require('../lib/browser');
9
+
10
+
11
+ // Declare internals
12
+
13
+ var internals = {};
14
+
15
+
16
+ // Test shortcuts
17
+
18
+ var lab = exports.lab = Lab.script();
19
+ var describe = lab.experiment;
20
+ var it = lab.test;
21
+ var expect = Code.expect;
22
+
23
+
24
+ describe('Browser', function () {
25
+
26
+ var credentialsFunc = function (id, callback) {
27
+
28
+ var credentials = {
29
+ id: id,
30
+ key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
31
+ algorithm: (id === '1' ? 'sha1' : 'sha256'),
32
+ user: 'steve'
33
+ };
34
+
35
+ return callback(null, credentials);
36
+ };
37
+
38
+ it('should generate a bewit then successfully authenticate it', function (done) {
39
+
40
+ var req = {
41
+ method: 'GET',
42
+ url: '/resource/4?a=1&b=2',
43
+ host: 'example.com',
44
+ port: 80
45
+ };
46
+
47
+ credentialsFunc('123456', function (err, credentials1) {
48
+
49
+ 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' });
50
+ req.url += '&bewit=' + bewit;
51
+
52
+ Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials2, attributes) {
53
+
54
+ expect(err).to.not.exist();
55
+ expect(credentials2.user).to.equal('steve');
56
+ expect(attributes.ext).to.equal('some-app-data');
57
+ done();
58
+ });
59
+ });
60
+ });
61
+
62
+ it('should generate a bewit then successfully authenticate it (no ext)', function (done) {
63
+
64
+ var req = {
65
+ method: 'GET',
66
+ url: '/resource/4?a=1&b=2',
67
+ host: 'example.com',
68
+ port: 80
69
+ };
70
+
71
+ credentialsFunc('123456', function (err, credentials1) {
72
+
73
+ var bewit = Browser.client.bewit('http://example.com/resource/4?a=1&b=2', { credentials: credentials1, ttlSec: 60 * 60 * 24 * 365 * 100 });
74
+ req.url += '&bewit=' + bewit;
75
+
76
+ Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials2, attributes) {
77
+
78
+ expect(err).to.not.exist();
79
+ expect(credentials2.user).to.equal('steve');
80
+ done();
81
+ });
82
+ });
83
+ });
84
+
85
+ describe('bewit()', function () {
86
+
87
+ it('returns a valid bewit value', function (done) {
88
+
89
+ var credentials = {
90
+ id: '123456',
91
+ key: '2983d45yun89q',
92
+ algorithm: 'sha256'
93
+ };
94
+
95
+ var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' });
96
+ expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdca3NjeHdOUjJ0SnBQMVQxekRMTlBiQjVVaUtJVTl0T1NKWFRVZEc3WDloOD1ceGFuZHlhbmR6');
97
+ done();
98
+ });
99
+
100
+ it('returns a valid bewit value (explicit HTTP port)', function (done) {
101
+
102
+ var credentials = {
103
+ id: '123456',
104
+ key: '2983d45yun89q',
105
+ algorithm: 'sha256'
106
+ };
107
+
108
+ var bewit = Browser.client.bewit('http://example.com:8080/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' });
109
+ expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdcaFpiSjNQMmNLRW80a3kwQzhqa1pBa1J5Q1p1ZWc0V1NOYnhWN3ZxM3hIVT1ceGFuZHlhbmR6');
110
+ done();
111
+ });
112
+
113
+ it('returns a valid bewit value (explicit HTTPS port)', function (done) {
114
+
115
+ var credentials = {
116
+ id: '123456',
117
+ key: '2983d45yun89q',
118
+ algorithm: 'sha256'
119
+ };
120
+
121
+ var bewit = Browser.client.bewit('https://example.com:8043/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' });
122
+ expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdcL2t4UjhwK0xSaTdvQTRnUXc3cWlxa3BiVHRKYkR4OEtRMC9HRUwvVytTUT1ceGFuZHlhbmR6');
123
+ done();
124
+ });
125
+
126
+ it('returns a valid bewit value (null ext)', function (done) {
127
+
128
+ var credentials = {
129
+ id: '123456',
130
+ key: '2983d45yun89q',
131
+ algorithm: 'sha256'
132
+ };
133
+
134
+ var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: null });
135
+ expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdcSUdZbUxnSXFMckNlOEN4dktQczRKbFdJQStValdKSm91d2dBUmlWaENBZz1c');
136
+ done();
137
+ });
138
+
139
+ it('errors on invalid options', function (done) {
140
+
141
+ var credentials = {
142
+ id: '123456',
143
+ key: '2983d45yun89q',
144
+ algorithm: 'sha256'
145
+ };
146
+
147
+ var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow', 4);
148
+ expect(bewit).to.equal('');
149
+ done();
150
+ });
151
+
152
+ it('errors on missing uri', function (done) {
153
+
154
+ var credentials = {
155
+ id: '123456',
156
+ key: '2983d45yun89q',
157
+ algorithm: 'sha256'
158
+ };
159
+
160
+ var bewit = Browser.client.bewit('', { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' });
161
+ expect(bewit).to.equal('');
162
+ done();
163
+ });
164
+
165
+ it('errors on invalid uri', function (done) {
166
+
167
+ var credentials = {
168
+ id: '123456',
169
+ key: '2983d45yun89q',
170
+ algorithm: 'sha256'
171
+ };
172
+
173
+ var bewit = Browser.client.bewit(5, { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' });
174
+ expect(bewit).to.equal('');
175
+ done();
176
+ });
177
+
178
+ it('errors on invalid credentials (id)', function (done) {
179
+
180
+ var credentials = {
181
+ key: '2983d45yun89q',
182
+ algorithm: 'sha256'
183
+ };
184
+
185
+ var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 3000, ext: 'xandyandz' });
186
+ expect(bewit).to.equal('');
187
+ done();
188
+ });
189
+
190
+ it('errors on missing credentials', function (done) {
191
+
192
+ var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow', { ttlSec: 3000, ext: 'xandyandz' });
193
+ expect(bewit).to.equal('');
194
+ done();
195
+ });
196
+
197
+ it('errors on invalid credentials (key)', function (done) {
198
+
199
+ var credentials = {
200
+ id: '123456',
201
+ algorithm: 'sha256'
202
+ };
203
+
204
+ var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 3000, ext: 'xandyandz' });
205
+ expect(bewit).to.equal('');
206
+ done();
207
+ });
208
+
209
+ it('errors on invalid algorithm', function (done) {
210
+
211
+ var credentials = {
212
+ id: '123456',
213
+ key: '2983d45yun89q',
214
+ algorithm: 'hmac-sha-0'
215
+ };
216
+
217
+ var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, ext: 'xandyandz' });
218
+ expect(bewit).to.equal('');
219
+ done();
220
+ });
221
+
222
+ it('errors on missing options', function (done) {
223
+
224
+ var credentials = {
225
+ id: '123456',
226
+ key: '2983d45yun89q',
227
+ algorithm: 'hmac-sha-0'
228
+ };
229
+
230
+ var bewit = Browser.client.bewit('https://example.com/somewhere/over/the/rainbow');
231
+ expect(bewit).to.equal('');
232
+ done();
233
+ });
234
+ });
235
+
236
+ it('generates a header then successfully parse it (configuration)', function (done) {
237
+
238
+ var req = {
239
+ method: 'GET',
240
+ url: '/resource/4?filter=a',
241
+ host: 'example.com',
242
+ port: 8080
243
+ };
244
+
245
+ credentialsFunc('123456', function (err, credentials1) {
246
+
247
+ req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data' }).field;
248
+ expect(req.authorization).to.exist();
249
+
250
+ Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
251
+
252
+ expect(err).to.not.exist();
253
+ expect(credentials2.user).to.equal('steve');
254
+ expect(artifacts.ext).to.equal('some-app-data');
255
+ done();
256
+ });
257
+ });
258
+ });
259
+
260
+ it('generates a header then successfully parse it (node request)', function (done) {
261
+
262
+ var req = {
263
+ method: 'POST',
264
+ url: '/resource/4?filter=a',
265
+ headers: {
266
+ host: 'example.com:8080',
267
+ 'content-type': 'text/plain;x=y'
268
+ }
269
+ };
270
+
271
+ var payload = 'some not so random text';
272
+
273
+ credentialsFunc('123456', function (err, credentials1) {
274
+
275
+ 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'] });
276
+ req.headers.authorization = reqHeader.field;
277
+
278
+ Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
279
+
280
+ expect(err).to.not.exist();
281
+ expect(credentials2.user).to.equal('steve');
282
+ expect(artifacts.ext).to.equal('some-app-data');
283
+ expect(Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.equal(true);
284
+
285
+ var res = {
286
+ headers: {
287
+ 'content-type': 'text/plain'
288
+ },
289
+ getResponseHeader: function (header) {
290
+
291
+ return res.headers[header.toLowerCase()];
292
+ }
293
+ };
294
+
295
+ res.headers['server-authorization'] = Hawk.server.header(credentials2, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' });
296
+ expect(res.headers['server-authorization']).to.exist();
297
+
298
+ expect(Browser.client.authenticate(res, credentials2, artifacts, { payload: 'some reply' })).to.equal(true);
299
+ done();
300
+ });
301
+ });
302
+ });
303
+
304
+ it('generates a header then successfully parse it (browserify)', function (done) {
305
+
306
+ var req = {
307
+ method: 'POST',
308
+ url: '/resource/4?filter=a',
309
+ headers: {
310
+ host: 'example.com:8080',
311
+ 'content-type': 'text/plain;x=y'
312
+ }
313
+ };
314
+
315
+ var payload = 'some not so random text';
316
+
317
+ credentialsFunc('123456', function (err, credentials1) {
318
+
319
+ 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'] });
320
+ req.headers.authorization = reqHeader.field;
321
+
322
+ Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
323
+
324
+ expect(err).to.not.exist();
325
+ expect(credentials2.user).to.equal('steve');
326
+ expect(artifacts.ext).to.equal('some-app-data');
327
+ expect(Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.equal(true);
328
+
329
+ var res = {
330
+ headers: {
331
+ 'content-type': 'text/plain'
332
+ },
333
+ getHeader: function (header) {
334
+
335
+ return res.headers[header.toLowerCase()];
336
+ }
337
+ };
338
+
339
+ res.headers['server-authorization'] = Hawk.server.header(credentials2, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' });
340
+ expect(res.headers['server-authorization']).to.exist();
341
+
342
+ expect(Browser.client.authenticate(res, credentials2, artifacts, { payload: 'some reply' })).to.equal(true);
343
+ done();
344
+ });
345
+ });
346
+ });
347
+
348
+ it('generates a header then successfully parse it (time offset)', function (done) {
349
+
350
+ var req = {
351
+ method: 'GET',
352
+ url: '/resource/4?filter=a',
353
+ host: 'example.com',
354
+ port: 8080
355
+ };
356
+
357
+ credentialsFunc('123456', function (err, credentials1) {
358
+
359
+ req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', localtimeOffsetMsec: 100000 }).field;
360
+ expect(req.authorization).to.exist();
361
+
362
+ Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 100000 }, function (err, credentials2, artifacts) {
363
+
364
+ expect(err).to.not.exist();
365
+ expect(credentials2.user).to.equal('steve');
366
+ expect(artifacts.ext).to.equal('some-app-data');
367
+ done();
368
+ });
369
+ });
370
+ });
371
+
372
+ it('generates a header then successfully parse it (no server header options)', function (done) {
373
+
374
+ var req = {
375
+ method: 'POST',
376
+ url: '/resource/4?filter=a',
377
+ headers: {
378
+ host: 'example.com:8080',
379
+ 'content-type': 'text/plain;x=y'
380
+ }
381
+ };
382
+
383
+ var payload = 'some not so random text';
384
+
385
+ credentialsFunc('123456', function (err, credentials1) {
386
+
387
+ 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'] });
388
+ req.headers.authorization = reqHeader.field;
389
+
390
+ Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
391
+
392
+ expect(err).to.not.exist();
393
+ expect(credentials2.user).to.equal('steve');
394
+ expect(artifacts.ext).to.equal('some-app-data');
395
+ expect(Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.equal(true);
396
+
397
+ var res = {
398
+ headers: {
399
+ 'content-type': 'text/plain'
400
+ },
401
+ getResponseHeader: function (header) {
402
+
403
+ return res.headers[header.toLowerCase()];
404
+ }
405
+ };
406
+
407
+ res.headers['server-authorization'] = Hawk.server.header(credentials2, artifacts);
408
+ expect(res.headers['server-authorization']).to.exist();
409
+
410
+ expect(Browser.client.authenticate(res, credentials2, artifacts)).to.equal(true);
411
+ done();
412
+ });
413
+ });
414
+ });
415
+
416
+ it('generates a header then successfully parse it (no server header)', function (done) {
417
+
418
+ var req = {
419
+ method: 'POST',
420
+ url: '/resource/4?filter=a',
421
+ headers: {
422
+ host: 'example.com:8080',
423
+ 'content-type': 'text/plain;x=y'
424
+ }
425
+ };
426
+
427
+ var payload = 'some not so random text';
428
+
429
+ credentialsFunc('123456', function (err, credentials1) {
430
+
431
+ 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'] });
432
+ req.headers.authorization = reqHeader.field;
433
+
434
+ Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
435
+
436
+ expect(err).to.not.exist();
437
+ expect(credentials2.user).to.equal('steve');
438
+ expect(artifacts.ext).to.equal('some-app-data');
439
+ expect(Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.equal(true);
440
+
441
+ var res = {
442
+ headers: {
443
+ 'content-type': 'text/plain'
444
+ },
445
+ getResponseHeader: function (header) {
446
+
447
+ return res.headers[header.toLowerCase()];
448
+ }
449
+ };
450
+
451
+ expect(Browser.client.authenticate(res, credentials2, artifacts)).to.equal(true);
452
+ done();
453
+ });
454
+ });
455
+ });
456
+
457
+ it('generates a header with stale ts and successfully authenticate on second call', function (done) {
458
+
459
+ var req = {
460
+ method: 'GET',
461
+ url: '/resource/4?filter=a',
462
+ host: 'example.com',
463
+ port: 8080
464
+ };
465
+
466
+ credentialsFunc('123456', function (err, credentials1) {
467
+
468
+ Browser.utils.setNtpOffset(60 * 60 * 1000);
469
+ var header = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data' });
470
+ req.authorization = header.field;
471
+ expect(req.authorization).to.exist();
472
+
473
+ Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts2) {
474
+
475
+ expect(err).to.exist();
476
+ expect(err.message).to.equal('Stale timestamp');
477
+
478
+ var res = {
479
+ headers: {
480
+ 'www-authenticate': err.output.headers['WWW-Authenticate']
481
+ },
482
+ getResponseHeader: function (lookup) {
483
+
484
+ return res.headers[lookup.toLowerCase()];
485
+ }
486
+ };
487
+
488
+ expect(Browser.utils.getNtpOffset()).to.equal(60 * 60 * 1000);
489
+ expect(Browser.client.authenticate(res, credentials2, header.artifacts)).to.equal(true);
490
+ expect(Browser.utils.getNtpOffset()).to.equal(0);
491
+
492
+ req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials2, ext: 'some-app-data' }).field;
493
+ expect(req.authorization).to.exist();
494
+
495
+ Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials3, artifacts3) {
496
+
497
+ expect(err).to.not.exist();
498
+ expect(credentials3.user).to.equal('steve');
499
+ expect(artifacts3.ext).to.equal('some-app-data');
500
+ done();
501
+ });
502
+ });
503
+ });
504
+ });
505
+
506
+ it('generates a header with stale ts and successfully authenticate on second call (manual localStorage)', function (done) {
507
+
508
+ var req = {
509
+ method: 'GET',
510
+ url: '/resource/4?filter=a',
511
+ host: 'example.com',
512
+ port: 8080
513
+ };
514
+
515
+ credentialsFunc('123456', function (err, credentials1) {
516
+
517
+ var localStorage = new Browser.internals.LocalStorage();
518
+
519
+ Browser.utils.setStorage(localStorage);
520
+
521
+ Browser.utils.setNtpOffset(60 * 60 * 1000);
522
+ var header = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data' });
523
+ req.authorization = header.field;
524
+ expect(req.authorization).to.exist();
525
+
526
+ Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts2) {
527
+
528
+ expect(err).to.exist();
529
+ expect(err.message).to.equal('Stale timestamp');
530
+
531
+ var res = {
532
+ headers: {
533
+ 'www-authenticate': err.output.headers['WWW-Authenticate']
534
+ },
535
+ getResponseHeader: function (lookup) {
536
+
537
+ return res.headers[lookup.toLowerCase()];
538
+ }
539
+ };
540
+
541
+ expect(parseInt(localStorage.getItem('hawk_ntp_offset'))).to.equal(60 * 60 * 1000);
542
+ expect(Browser.utils.getNtpOffset()).to.equal(60 * 60 * 1000);
543
+ expect(Browser.client.authenticate(res, credentials2, header.artifacts)).to.equal(true);
544
+ expect(Browser.utils.getNtpOffset()).to.equal(0);
545
+ expect(parseInt(localStorage.getItem('hawk_ntp_offset'))).to.equal(0);
546
+
547
+ req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials2, ext: 'some-app-data' }).field;
548
+ expect(req.authorization).to.exist();
549
+
550
+ Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials3, artifacts3) {
551
+
552
+ expect(err).to.not.exist();
553
+ expect(credentials3.user).to.equal('steve');
554
+ expect(artifacts3.ext).to.equal('some-app-data');
555
+ done();
556
+ });
557
+ });
558
+ });
559
+ });
560
+
561
+ it('generates a header then fails to parse it (missing server header hash)', function (done) {
562
+
563
+ var req = {
564
+ method: 'POST',
565
+ url: '/resource/4?filter=a',
566
+ headers: {
567
+ host: 'example.com:8080',
568
+ 'content-type': 'text/plain;x=y'
569
+ }
570
+ };
571
+
572
+ var payload = 'some not so random text';
573
+
574
+ credentialsFunc('123456', function (err, credentials1) {
575
+
576
+ 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'] });
577
+ req.headers.authorization = reqHeader.field;
578
+
579
+ Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
580
+
581
+ expect(err).to.not.exist();
582
+ expect(credentials2.user).to.equal('steve');
583
+ expect(artifacts.ext).to.equal('some-app-data');
584
+ expect(Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.equal(true);
585
+
586
+ var res = {
587
+ headers: {
588
+ 'content-type': 'text/plain'
589
+ },
590
+ getResponseHeader: function (header) {
591
+
592
+ return res.headers[header.toLowerCase()];
593
+ }
594
+ };
595
+
596
+ res.headers['server-authorization'] = Hawk.server.header(credentials2, artifacts);
597
+ expect(res.headers['server-authorization']).to.exist();
598
+
599
+ expect(Browser.client.authenticate(res, credentials2, artifacts, { payload: 'some reply' })).to.equal(false);
600
+ done();
601
+ });
602
+ });
603
+ });
604
+
605
+ it('generates a header then successfully parse it (with hash)', function (done) {
606
+
607
+ var req = {
608
+ method: 'GET',
609
+ url: '/resource/4?filter=a',
610
+ host: 'example.com',
611
+ port: 8080
612
+ };
613
+
614
+ credentialsFunc('123456', function (err, credentials1) {
615
+
616
+ req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, payload: 'hola!', ext: 'some-app-data' }).field;
617
+ Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
618
+
619
+ expect(err).to.not.exist();
620
+ expect(credentials2.user).to.equal('steve');
621
+ expect(artifacts.ext).to.equal('some-app-data');
622
+ done();
623
+ });
624
+ });
625
+ });
626
+
627
+ it('generates a header then successfully parse it then validate payload', function (done) {
628
+
629
+ var req = {
630
+ method: 'GET',
631
+ url: '/resource/4?filter=a',
632
+ host: 'example.com',
633
+ port: 8080
634
+ };
635
+
636
+ credentialsFunc('123456', function (err, credentials1) {
637
+
638
+ req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, payload: 'hola!', ext: 'some-app-data' }).field;
639
+ Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
640
+
641
+ expect(err).to.not.exist();
642
+ expect(credentials2.user).to.equal('steve');
643
+ expect(artifacts.ext).to.equal('some-app-data');
644
+ expect(Hawk.server.authenticatePayload('hola!', credentials2, artifacts)).to.be.true();
645
+ expect(Hawk.server.authenticatePayload('hello!', credentials2, artifacts)).to.be.false();
646
+ done();
647
+ });
648
+ });
649
+ });
650
+
651
+ it('generates a header then successfully parse it (app)', function (done) {
652
+
653
+ var req = {
654
+ method: 'GET',
655
+ url: '/resource/4?filter=a',
656
+ host: 'example.com',
657
+ port: 8080
658
+ };
659
+
660
+ credentialsFunc('123456', function (err, credentials1) {
661
+
662
+ req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', app: 'asd23ased' }).field;
663
+ Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
664
+
665
+ expect(err).to.not.exist();
666
+ expect(credentials2.user).to.equal('steve');
667
+ expect(artifacts.ext).to.equal('some-app-data');
668
+ expect(artifacts.app).to.equal('asd23ased');
669
+ done();
670
+ });
671
+ });
672
+ });
673
+
674
+ it('generates a header then successfully parse it (app, dlg)', function (done) {
675
+
676
+ var req = {
677
+ method: 'GET',
678
+ url: '/resource/4?filter=a',
679
+ host: 'example.com',
680
+ port: 8080
681
+ };
682
+
683
+ credentialsFunc('123456', function (err, credentials1) {
684
+
685
+ 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;
686
+ Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
687
+
688
+ expect(err).to.not.exist();
689
+ expect(credentials2.user).to.equal('steve');
690
+ expect(artifacts.ext).to.equal('some-app-data');
691
+ expect(artifacts.app).to.equal('asd23ased');
692
+ expect(artifacts.dlg).to.equal('23434szr3q4d');
693
+ done();
694
+ });
695
+ });
696
+ });
697
+
698
+ it('generates a header then fail authentication due to bad hash', function (done) {
699
+
700
+ var req = {
701
+ method: 'GET',
702
+ url: '/resource/4?filter=a',
703
+ host: 'example.com',
704
+ port: 8080
705
+ };
706
+
707
+ credentialsFunc('123456', function (err, credentials1) {
708
+
709
+ req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, payload: 'hola!', ext: 'some-app-data' }).field;
710
+ Hawk.server.authenticate(req, credentialsFunc, { payload: 'byebye!' }, function (err, credentials2, artifacts) {
711
+
712
+ expect(err).to.exist();
713
+ expect(err.output.payload.message).to.equal('Bad payload hash');
714
+ done();
715
+ });
716
+ });
717
+ });
718
+
719
+ it('generates a header for one resource then fail to authenticate another', function (done) {
720
+
721
+ var req = {
722
+ method: 'GET',
723
+ url: '/resource/4?filter=a',
724
+ host: 'example.com',
725
+ port: 8080
726
+ };
727
+
728
+ credentialsFunc('123456', function (err, credentials1) {
729
+
730
+ req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data' }).field;
731
+ req.url = '/something/else';
732
+
733
+ Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
734
+
735
+ expect(err).to.exist();
736
+ expect(credentials2).to.exist();
737
+ done();
738
+ });
739
+ });
740
+ });
741
+
742
+ describe('client', function () {
743
+
744
+ describe('header()', function () {
745
+
746
+ it('returns a valid authorization header (sha1)', function (done) {
747
+
748
+ var credentials = {
749
+ id: '123456',
750
+ key: '2983d45yun89q',
751
+ algorithm: 'sha1'
752
+ };
753
+
754
+ 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;
755
+ expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="bsvY3IfUllw6V5rvk4tStEvpBhE=", ext="Bazinga!", mac="qbf1ZPG/r/e06F4ht+T77LXi5vw="');
756
+ done();
757
+ });
758
+
759
+ it('returns a valid authorization header (sha256)', function (done) {
760
+
761
+ var credentials = {
762
+ id: '123456',
763
+ key: '2983d45yun89q',
764
+ algorithm: 'sha256'
765
+ };
766
+
767
+ 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;
768
+ expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", ext="Bazinga!", mac="q1CwFoSHzPZSkbIvl0oYlD+91rBUEvFk763nMjMndj8="');
769
+ done();
770
+ });
771
+
772
+ it('returns a valid authorization header (empty payload)', function (done) {
773
+
774
+ var credentials = {
775
+ id: '123456',
776
+ key: '2983d45yun89q',
777
+ algorithm: 'sha1'
778
+ };
779
+
780
+ var header = Browser.client.header('http://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: '' }).field;
781
+ expect(header).to.equal('Hawk id=\"123456\", ts=\"1353809207\", nonce=\"Ygvqdz\", hash=\"404ghL7K+hfyhByKKejFBRGgTjU=\", ext=\"Bazinga!\", mac=\"Bh1sj1DOfFRWOdi3ww52nLCJdBE=\"');
782
+ done();
783
+ });
784
+
785
+ it('returns a valid authorization header (no ext)', function (done) {
786
+
787
+ var credentials = {
788
+ id: '123456',
789
+ key: '2983d45yun89q',
790
+ algorithm: 'sha256'
791
+ };
792
+
793
+ 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;
794
+ expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="');
795
+ done();
796
+ });
797
+
798
+ it('returns a valid authorization header (null ext)', function (done) {
799
+
800
+ var credentials = {
801
+ id: '123456',
802
+ key: '2983d45yun89q',
803
+ algorithm: 'sha256'
804
+ };
805
+
806
+ 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;
807
+ expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="');
808
+ done();
809
+ });
810
+
811
+ it('returns a valid authorization header (uri object)', function (done) {
812
+
813
+ var credentials = {
814
+ id: '123456',
815
+ key: '2983d45yun89q',
816
+ algorithm: 'sha256'
817
+ };
818
+
819
+ var uri = Browser.utils.parseUri('https://example.net/somewhere/over/the/rainbow');
820
+ var header = Browser.client.header(uri, 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }).field;
821
+ expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="');
822
+ done();
823
+ });
824
+
825
+ it('errors on missing options', function (done) {
826
+
827
+ var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST');
828
+ expect(header.field).to.equal('');
829
+ expect(header.err).to.equal('Invalid argument type');
830
+ done();
831
+ });
832
+
833
+ it('errors on empty uri', function (done) {
834
+
835
+ var credentials = {
836
+ id: '123456',
837
+ key: '2983d45yun89q',
838
+ algorithm: 'sha256'
839
+ };
840
+
841
+ var header = Browser.client.header('', 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' });
842
+ expect(header.field).to.equal('');
843
+ expect(header.err).to.equal('Invalid argument type');
844
+ done();
845
+ });
846
+
847
+ it('errors on invalid uri', function (done) {
848
+
849
+ var credentials = {
850
+ id: '123456',
851
+ key: '2983d45yun89q',
852
+ algorithm: 'sha256'
853
+ };
854
+
855
+ var header = Browser.client.header(4, 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' });
856
+ expect(header.field).to.equal('');
857
+ expect(header.err).to.equal('Invalid argument type');
858
+ done();
859
+ });
860
+
861
+ it('errors on missing method', function (done) {
862
+
863
+ var credentials = {
864
+ id: '123456',
865
+ key: '2983d45yun89q',
866
+ algorithm: 'sha256'
867
+ };
868
+
869
+ 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' });
870
+ expect(header.field).to.equal('');
871
+ expect(header.err).to.equal('Invalid argument type');
872
+ done();
873
+ });
874
+
875
+ it('errors on invalid method', function (done) {
876
+
877
+ var credentials = {
878
+ id: '123456',
879
+ key: '2983d45yun89q',
880
+ algorithm: 'sha256'
881
+ };
882
+
883
+ 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' });
884
+ expect(header.field).to.equal('');
885
+ expect(header.err).to.equal('Invalid argument type');
886
+ done();
887
+ });
888
+
889
+ it('errors on missing credentials', function (done) {
890
+
891
+ var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { ext: 'Bazinga!', timestamp: 1353809207 });
892
+ expect(header.field).to.equal('');
893
+ expect(header.err).to.equal('Invalid credentials object');
894
+ done();
895
+ });
896
+
897
+ it('errors on invalid credentials (id)', function (done) {
898
+
899
+ var credentials = {
900
+ key: '2983d45yun89q',
901
+ algorithm: 'sha256'
902
+ };
903
+
904
+ var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207 });
905
+ expect(header.field).to.equal('');
906
+ expect(header.err).to.equal('Invalid credentials object');
907
+ done();
908
+ });
909
+
910
+ it('errors on invalid credentials (key)', function (done) {
911
+
912
+ var credentials = {
913
+ id: '123456',
914
+ algorithm: 'sha256'
915
+ };
916
+
917
+ var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207 });
918
+ expect(header.field).to.equal('');
919
+ expect(header.err).to.equal('Invalid credentials object');
920
+ done();
921
+ });
922
+
923
+ it('errors on invalid algorithm', function (done) {
924
+
925
+ var credentials = {
926
+ id: '123456',
927
+ key: '2983d45yun89q',
928
+ algorithm: 'hmac-sha-0'
929
+ };
930
+
931
+ var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, payload: 'something, anything!', ext: 'Bazinga!', timestamp: 1353809207 });
932
+ expect(header.field).to.equal('');
933
+ expect(header.err).to.equal('Unknown algorithm');
934
+ done();
935
+ });
936
+
937
+ it('uses a pre-calculated payload hash', function (done) {
938
+
939
+ var credentials = {
940
+ id: '123456',
941
+ key: '2983d45yun89q',
942
+ algorithm: 'sha256'
943
+ };
944
+
945
+ var options = { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' };
946
+ options.hash = Browser.crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType);
947
+ var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', options).field;
948
+ expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", ext="Bazinga!", mac="q1CwFoSHzPZSkbIvl0oYlD+91rBUEvFk763nMjMndj8="');
949
+ done();
950
+ });
951
+ });
952
+
953
+ describe('authenticate()', function () {
954
+
955
+ it('skips tsm validation when missing ts', function (done) {
956
+
957
+ var res = {
958
+ headers: {
959
+ 'www-authenticate': 'Hawk error="Stale timestamp"'
960
+ },
961
+ getResponseHeader: function (header) {
962
+
963
+ return res.headers[header.toLowerCase()];
964
+ }
965
+ };
966
+
967
+ var credentials = {
968
+ id: '123456',
969
+ key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
970
+ algorithm: 'sha256',
971
+ user: 'steve'
972
+ };
973
+
974
+ var artifacts = {
975
+ ts: 1402135580,
976
+ nonce: 'iBRB6t',
977
+ method: 'GET',
978
+ resource: '/resource/4?filter=a',
979
+ host: 'example.com',
980
+ port: '8080',
981
+ ext: 'some-app-data'
982
+ };
983
+
984
+ expect(Browser.client.authenticate(res, credentials, artifacts)).to.equal(true);
985
+ done();
986
+ });
987
+
988
+ it('returns false on invalid header', function (done) {
989
+
990
+ var res = {
991
+ headers: {
992
+ 'server-authorization': 'Hawk mac="abc", bad="xyz"'
993
+ },
994
+ getResponseHeader: function (header) {
995
+
996
+ return res.headers[header.toLowerCase()];
997
+ }
998
+ };
999
+
1000
+ expect(Browser.client.authenticate(res, {})).to.equal(false);
1001
+ done();
1002
+ });
1003
+
1004
+ it('returns false on invalid mac', function (done) {
1005
+
1006
+ var res = {
1007
+ headers: {
1008
+ 'content-type': 'text/plain',
1009
+ 'server-authorization': 'Hawk mac="_IJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"'
1010
+ },
1011
+ getResponseHeader: function (header) {
1012
+
1013
+ return res.headers[header.toLowerCase()];
1014
+ }
1015
+ };
1016
+
1017
+ var artifacts = {
1018
+ method: 'POST',
1019
+ host: 'example.com',
1020
+ port: '8080',
1021
+ resource: '/resource/4?filter=a',
1022
+ ts: '1362336900',
1023
+ nonce: 'eb5S_L',
1024
+ hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
1025
+ ext: 'some-app-data',
1026
+ app: undefined,
1027
+ dlg: undefined,
1028
+ mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=',
1029
+ id: '123456'
1030
+ };
1031
+
1032
+ var credentials = {
1033
+ id: '123456',
1034
+ key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
1035
+ algorithm: 'sha256',
1036
+ user: 'steve'
1037
+ };
1038
+
1039
+ expect(Browser.client.authenticate(res, credentials, artifacts)).to.equal(false);
1040
+ done();
1041
+ });
1042
+
1043
+ it('returns true on ignoring hash', function (done) {
1044
+
1045
+ var res = {
1046
+ headers: {
1047
+ 'content-type': 'text/plain',
1048
+ 'server-authorization': 'Hawk mac="XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"'
1049
+ },
1050
+ getResponseHeader: function (header) {
1051
+
1052
+ return res.headers[header.toLowerCase()];
1053
+ }
1054
+ };
1055
+
1056
+ var artifacts = {
1057
+ method: 'POST',
1058
+ host: 'example.com',
1059
+ port: '8080',
1060
+ resource: '/resource/4?filter=a',
1061
+ ts: '1362336900',
1062
+ nonce: 'eb5S_L',
1063
+ hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
1064
+ ext: 'some-app-data',
1065
+ app: undefined,
1066
+ dlg: undefined,
1067
+ mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=',
1068
+ id: '123456'
1069
+ };
1070
+
1071
+ var credentials = {
1072
+ id: '123456',
1073
+ key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
1074
+ algorithm: 'sha256',
1075
+ user: 'steve'
1076
+ };
1077
+
1078
+ expect(Browser.client.authenticate(res, credentials, artifacts)).to.equal(true);
1079
+ done();
1080
+ });
1081
+
1082
+ it('errors on invalid WWW-Authenticate header format', function (done) {
1083
+
1084
+ var res = {
1085
+ headers: {
1086
+ 'www-authenticate': 'Hawk ts="1362346425875", tsm="PhwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", x="Stale timestamp"'
1087
+ },
1088
+ getResponseHeader: function (header) {
1089
+
1090
+ return res.headers[header.toLowerCase()];
1091
+ }
1092
+ };
1093
+
1094
+ expect(Browser.client.authenticate(res, {})).to.equal(false);
1095
+ done();
1096
+ });
1097
+
1098
+ it('errors on invalid WWW-Authenticate header format', function (done) {
1099
+
1100
+ var credentials = {
1101
+ id: '123456',
1102
+ key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
1103
+ algorithm: 'sha256',
1104
+ user: 'steve'
1105
+ };
1106
+
1107
+ var res = {
1108
+ headers: {
1109
+ 'www-authenticate': 'Hawk ts="1362346425875", tsm="hwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", error="Stale timestamp"'
1110
+ },
1111
+ getResponseHeader: function (header) {
1112
+
1113
+ return res.headers[header.toLowerCase()];
1114
+ }
1115
+ };
1116
+
1117
+ expect(Browser.client.authenticate(res, credentials)).to.equal(false);
1118
+ done();
1119
+ });
1120
+ });
1121
+
1122
+ describe('message()', function () {
1123
+
1124
+ it('generates an authorization then successfully parse it', function (done) {
1125
+
1126
+ credentialsFunc('123456', function (err, credentials1) {
1127
+
1128
+ var auth = Browser.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
1129
+ expect(auth).to.exist();
1130
+
1131
+ Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials2) {
1132
+
1133
+ expect(err).to.not.exist();
1134
+ expect(credentials2.user).to.equal('steve');
1135
+ done();
1136
+ });
1137
+ });
1138
+ });
1139
+
1140
+ it('generates an authorization using custom nonce/timestamp', function (done) {
1141
+
1142
+ credentialsFunc('123456', function (err, credentials) {
1143
+
1144
+ var auth = Browser.client.message('example.com', 8080, 'some message', { credentials: credentials, nonce: 'abc123', timestamp: 1398536270957 });
1145
+ expect(auth).to.exist();
1146
+ expect(auth.nonce).to.equal('abc123');
1147
+ expect(auth.ts).to.equal(1398536270957);
1148
+ done();
1149
+ });
1150
+ });
1151
+
1152
+ it('errors on missing host', function (done) {
1153
+
1154
+ credentialsFunc('123456', function (err, credentials) {
1155
+
1156
+ var auth = Browser.client.message(null, 8080, 'some message', { credentials: credentials });
1157
+ expect(auth).to.not.exist();
1158
+ done();
1159
+ });
1160
+ });
1161
+
1162
+ it('errors on invalid host', function (done) {
1163
+
1164
+ credentialsFunc('123456', function (err, credentials) {
1165
+
1166
+ var auth = Browser.client.message(5, 8080, 'some message', { credentials: credentials });
1167
+ expect(auth).to.not.exist();
1168
+ done();
1169
+ });
1170
+ });
1171
+
1172
+ it('errors on missing port', function (done) {
1173
+
1174
+ credentialsFunc('123456', function (err, credentials) {
1175
+
1176
+ var auth = Browser.client.message('example.com', 0, 'some message', { credentials: credentials });
1177
+ expect(auth).to.not.exist();
1178
+ done();
1179
+ });
1180
+ });
1181
+
1182
+ it('errors on invalid port', function (done) {
1183
+
1184
+ credentialsFunc('123456', function (err, credentials) {
1185
+
1186
+ var auth = Browser.client.message('example.com', 'a', 'some message', { credentials: credentials });
1187
+ expect(auth).to.not.exist();
1188
+ done();
1189
+ });
1190
+ });
1191
+
1192
+ it('errors on missing message', function (done) {
1193
+
1194
+ credentialsFunc('123456', function (err, credentials) {
1195
+
1196
+ var auth = Browser.client.message('example.com', 8080, undefined, { credentials: credentials });
1197
+ expect(auth).to.not.exist();
1198
+ done();
1199
+ });
1200
+ });
1201
+
1202
+ it('errors on null message', function (done) {
1203
+
1204
+ credentialsFunc('123456', function (err, credentials) {
1205
+
1206
+ var auth = Browser.client.message('example.com', 8080, null, { credentials: credentials });
1207
+ expect(auth).to.not.exist();
1208
+ done();
1209
+ });
1210
+ });
1211
+
1212
+ it('errors on invalid message', function (done) {
1213
+
1214
+ credentialsFunc('123456', function (err, credentials) {
1215
+
1216
+ var auth = Browser.client.message('example.com', 8080, 5, { credentials: credentials });
1217
+ expect(auth).to.not.exist();
1218
+ done();
1219
+ });
1220
+ });
1221
+
1222
+ it('errors on missing credentials', function (done) {
1223
+
1224
+ var auth = Browser.client.message('example.com', 8080, 'some message', {});
1225
+ expect(auth).to.not.exist();
1226
+ done();
1227
+ });
1228
+
1229
+ it('errors on missing options', function (done) {
1230
+
1231
+ var auth = Browser.client.message('example.com', 8080, 'some message');
1232
+ expect(auth).to.not.exist();
1233
+ done();
1234
+ });
1235
+
1236
+ it('errors on invalid credentials (id)', function (done) {
1237
+
1238
+ credentialsFunc('123456', function (err, credentials) {
1239
+
1240
+ var creds = Hoek.clone(credentials);
1241
+ delete creds.id;
1242
+ var auth = Browser.client.message('example.com', 8080, 'some message', { credentials: creds });
1243
+ expect(auth).to.not.exist();
1244
+ done();
1245
+ });
1246
+ });
1247
+
1248
+ it('errors on invalid credentials (key)', function (done) {
1249
+
1250
+ credentialsFunc('123456', function (err, credentials) {
1251
+
1252
+ var creds = Hoek.clone(credentials);
1253
+ delete creds.key;
1254
+ var auth = Browser.client.message('example.com', 8080, 'some message', { credentials: creds });
1255
+ expect(auth).to.not.exist();
1256
+ done();
1257
+ });
1258
+ });
1259
+
1260
+ it('errors on invalid algorithm', function (done) {
1261
+
1262
+ credentialsFunc('123456', function (err, credentials) {
1263
+
1264
+ var creds = Hoek.clone(credentials);
1265
+ creds.algorithm = 'blah';
1266
+ var auth = Browser.client.message('example.com', 8080, 'some message', { credentials: creds });
1267
+ expect(auth).to.not.exist();
1268
+ done();
1269
+ });
1270
+ });
1271
+ });
1272
+
1273
+ describe('authenticateTimestamp()', function (done) {
1274
+
1275
+ it('validates a timestamp', function (done) {
1276
+
1277
+ credentialsFunc('123456', function (err, credentials) {
1278
+
1279
+ var tsm = Hawk.crypto.timestampMessage(credentials);
1280
+ expect(Browser.client.authenticateTimestamp(tsm, credentials)).to.equal(true);
1281
+ done();
1282
+ });
1283
+ });
1284
+
1285
+ it('validates a timestamp without updating local time', function (done) {
1286
+
1287
+ credentialsFunc('123456', function (err, credentials) {
1288
+
1289
+ var offset = Browser.utils.getNtpOffset();
1290
+ var tsm = Hawk.crypto.timestampMessage(credentials, 10000);
1291
+ expect(Browser.client.authenticateTimestamp(tsm, credentials, false)).to.equal(true);
1292
+ expect(offset).to.equal(Browser.utils.getNtpOffset());
1293
+ done();
1294
+ });
1295
+ });
1296
+
1297
+ it('detects a bad timestamp', function (done) {
1298
+
1299
+ credentialsFunc('123456', function (err, credentials) {
1300
+
1301
+ var tsm = Hawk.crypto.timestampMessage(credentials);
1302
+ tsm.ts = 4;
1303
+ expect(Browser.client.authenticateTimestamp(tsm, credentials)).to.equal(false);
1304
+ done();
1305
+ });
1306
+ });
1307
+ });
1308
+ });
1309
+
1310
+ describe('internals', function () {
1311
+
1312
+ describe('LocalStorage', function () {
1313
+
1314
+ it('goes through the full lifecycle', function (done) {
1315
+
1316
+ var storage = new Browser.internals.LocalStorage();
1317
+ expect(storage.length).to.equal(0);
1318
+ expect(storage.getItem('a')).to.equal(null);
1319
+ storage.setItem('a', 5);
1320
+ expect(storage.length).to.equal(1);
1321
+ expect(storage.key()).to.equal('a');
1322
+ expect(storage.key(0)).to.equal('a');
1323
+ expect(storage.getItem('a')).to.equal('5');
1324
+ storage.setItem('b', 'test');
1325
+ expect(storage.key()).to.equal('a');
1326
+ expect(storage.key(0)).to.equal('a');
1327
+ expect(storage.key(1)).to.equal('b');
1328
+ expect(storage.length).to.equal(2);
1329
+ expect(storage.getItem('b')).to.equal('test');
1330
+ storage.removeItem('a');
1331
+ expect(storage.length).to.equal(1);
1332
+ expect(storage.getItem('a')).to.equal(null);
1333
+ expect(storage.getItem('b')).to.equal('test');
1334
+ storage.clear();
1335
+ expect(storage.length).to.equal(0);
1336
+ expect(storage.getItem('a')).to.equal(null);
1337
+ expect(storage.getItem('b')).to.equal(null);
1338
+ done();
1339
+ });
1340
+ });
1341
+ });
1342
+
1343
+ describe('utils', function () {
1344
+
1345
+ describe('setStorage()', function () {
1346
+
1347
+ it('sets storage for the first time', function (done) {
1348
+
1349
+ Browser.utils.storage = new Browser.internals.LocalStorage(); // Reset state
1350
+
1351
+ expect(Browser.utils.storage.getItem('hawk_ntp_offset')).to.not.exist();
1352
+ Browser.utils.storage.setItem('test', '1');
1353
+ Browser.utils.setStorage(new Browser.internals.LocalStorage());
1354
+ expect(Browser.utils.storage.getItem('test')).to.not.exist();
1355
+ Browser.utils.storage.setItem('test', '2');
1356
+ expect(Browser.utils.storage.getItem('test')).to.equal('2');
1357
+ done();
1358
+ });
1359
+ });
1360
+
1361
+ describe('setNtpOffset()', function (done) {
1362
+
1363
+ it('catches localStorage errors', { parallel: false }, function (done) {
1364
+
1365
+ var orig = Browser.utils.storage.setItem;
1366
+ var consoleOrig = console.error;
1367
+ var count = 0;
1368
+ console.error = function () {
1369
+
1370
+ if (count++ === 2) {
1371
+
1372
+ console.error = consoleOrig;
1373
+ }
1374
+ };
1375
+
1376
+ Browser.utils.storage.setItem = function () {
1377
+
1378
+ Browser.utils.storage.setItem = orig;
1379
+ throw new Error();
1380
+ };
1381
+
1382
+ expect(function () {
1383
+
1384
+ Browser.utils.setNtpOffset(100);
1385
+ }).not.to.throw();
1386
+
1387
+ done();
1388
+ });
1389
+ });
1390
+
1391
+ describe('parseAuthorizationHeader()', function (done) {
1392
+
1393
+ it('returns null on missing header', function (done) {
1394
+
1395
+ expect(Browser.utils.parseAuthorizationHeader()).to.equal(null);
1396
+ done();
1397
+ });
1398
+
1399
+ it('returns null on bad header syntax (structure)', function (done) {
1400
+
1401
+ expect(Browser.utils.parseAuthorizationHeader('Hawk')).to.equal(null);
1402
+ done();
1403
+ });
1404
+
1405
+ it('returns null on bad header syntax (parts)', function (done) {
1406
+
1407
+ expect(Browser.utils.parseAuthorizationHeader(' ')).to.equal(null);
1408
+ done();
1409
+ });
1410
+
1411
+ it('returns null on bad scheme name', function (done) {
1412
+
1413
+ expect(Browser.utils.parseAuthorizationHeader('Basic asdasd')).to.equal(null);
1414
+ done();
1415
+ });
1416
+
1417
+ it('returns null on bad attribute value', function (done) {
1418
+
1419
+ expect(Browser.utils.parseAuthorizationHeader('Hawk test="\t"', ['test'])).to.equal(null);
1420
+ done();
1421
+ });
1422
+
1423
+ it('returns null on duplicated attribute', function (done) {
1424
+
1425
+ expect(Browser.utils.parseAuthorizationHeader('Hawk test="a", test="b"', ['test'])).to.equal(null);
1426
+ done();
1427
+ });
1428
+ });
1429
+
1430
+ describe('parseUri()', function () {
1431
+
1432
+ it('returns empty object on invalid', function (done) {
1433
+
1434
+ var uri = Browser.utils.parseUri('ftp');
1435
+ expect(uri).to.deep.equal({ host: '', port: '', resource: '' });
1436
+ done();
1437
+ });
1438
+
1439
+ it('returns empty port when unknown scheme', function (done) {
1440
+
1441
+ var uri = Browser.utils.parseUri('ftp://example.com');
1442
+ expect(uri.port).to.equal('');
1443
+ done();
1444
+ });
1445
+
1446
+ it('returns default port when missing', function (done) {
1447
+
1448
+ var uri = Browser.utils.parseUri('http://example.com');
1449
+ expect(uri.port).to.equal('80');
1450
+ done();
1451
+ });
1452
+
1453
+ it('handles unusual characters correctly', function (done) {
1454
+
1455
+ var parts = {
1456
+ protocol: 'http+vnd.my-extension',
1457
+ user: 'user!$&\'()*+,;=%40my-domain.com',
1458
+ password: 'pass!$&\'()*+,;=%40:word',
1459
+ hostname: 'foo-bar.com',
1460
+ port: '99',
1461
+ pathname: '/path/%40/!$&\'()*+,;=:@/',
1462
+ query: 'query%40/!$&\'()*+,;=:@/?',
1463
+ fragment: 'fragm%40/!$&\'()*+,;=:@/?'
1464
+ };
1465
+
1466
+ parts.userInfo = parts.user + ':' + parts.password;
1467
+ parts.authority = parts.userInfo + '@' + parts.hostname + ':' + parts.port;
1468
+ parts.relative = parts.pathname + '?' + parts.query;
1469
+ parts.resource = parts.relative + '#' + parts.fragment;
1470
+ parts.source = parts.protocol + '://' + parts.authority + parts.resource;
1471
+
1472
+ var uri = Browser.utils.parseUri(parts.source);
1473
+ expect(uri.host).to.equal('foo-bar.com');
1474
+ expect(uri.port).to.equal('99');
1475
+ expect(uri.resource).to.equal(parts.pathname + '?' + parts.query);
1476
+ done();
1477
+ });
1478
+ });
1479
+
1480
+ var str = 'https://www.google.ca/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=url';
1481
+ var base64str = 'aHR0cHM6Ly93d3cuZ29vZ2xlLmNhL3dlYmhwP3NvdXJjZWlkPWNocm9tZS1pbnN0YW50Jmlvbj0xJmVzcHY9MiZpZT1VVEYtOCNxPXVybA';
1482
+
1483
+ describe('base64urlEncode()', function () {
1484
+
1485
+ it('should base64 URL-safe decode a string', function (done) {
1486
+
1487
+ expect(Browser.utils.base64urlEncode(str)).to.equal(base64str);
1488
+ done();
1489
+ });
1490
+ });
1491
+ });
1492
+ });