]> gerrit.simantics Code Review - simantics/district.git/blob - org.simantics.maps.server/node/node-v4.8.0-win-x64/node_modules/npm/node_modules/request/node_modules/hawk/dist/client.js
Adding integrated tile server
[simantics/district.git] / org.simantics.maps.server / node / node-v4.8.0-win-x64 / node_modules / npm / node_modules / request / node_modules / hawk / dist / client.js
1 'use strict'
2
3 // Load modules
4
5 ;
6
7 var _typeof = function (obj) {
8
9     return obj && typeof Symbol !== 'undefined' && obj.constructor === Symbol ? 'symbol' : typeof obj;
10 };
11
12 var Url = require('url');
13 var Hoek = require('hoek');
14 var Cryptiles = require('cryptiles');
15 var Crypto = require('./crypto');
16 var Utils = require('./utils');
17
18 // Declare internals
19
20 var internals = {};
21
22 // Generate an Authorization header for a given request
23
24 /*
25     uri: 'http://example.com/resource?a=b' or object from Url.parse()
26     method: HTTP verb (e.g. 'GET', 'POST')
27     options: {
28
29         // Required
30
31         credentials: {
32             id: 'dh37fgj492je',
33             key: 'aoijedoaijsdlaksjdl',
34             algorithm: 'sha256'                                 // 'sha1', 'sha256'
35         },
36
37         // Optional
38
39         ext: 'application-specific',                        // Application specific data sent via the ext attribute
40         timestamp: Date.now(),                              // A pre-calculated timestamp
41         nonce: '2334f34f',                                  // A pre-generated nonce
42         localtimeOffsetMsec: 400,                           // Time offset to sync with server time (ignored if timestamp provided)
43         payload: '{"some":"payload"}',                      // UTF-8 encoded string for body hash generation (ignored if hash provided)
44         contentType: 'application/json',                    // Payload content-type (ignored if hash provided)
45         hash: 'U4MKKSmiVxk37JCCrAVIjV=',                    // Pre-calculated payload hash
46         app: '24s23423f34dx',                               // Oz application id
47         dlg: '234sz34tww3sd'                                // Oz delegated-by application id
48     }
49 */
50
51 exports.header = function (uri, method, options) {
52
53     var result = {
54         field: '',
55         artifacts: {}
56     };
57
58     // Validate inputs
59
60     if (!uri || typeof uri !== 'string' && (typeof uri === 'undefined' ? 'undefined' : _typeof(uri)) !== 'object' || !method || typeof method !== 'string' || !options || (typeof options === 'undefined' ? 'undefined' : _typeof(options)) !== 'object') {
61
62         result.err = 'Invalid argument type';
63         return result;
64     }
65
66     // Application time
67
68     var timestamp = options.timestamp || Utils.nowSecs(options.localtimeOffsetMsec);
69
70     // Validate credentials
71
72     var credentials = options.credentials;
73     if (!credentials || !credentials.id || !credentials.key || !credentials.algorithm) {
74
75         result.err = 'Invalid credential object';
76         return result;
77     }
78
79     if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
80         result.err = 'Unknown algorithm';
81         return result;
82     }
83
84     // Parse URI
85
86     if (typeof uri === 'string') {
87         uri = Url.parse(uri);
88     }
89
90     // Calculate signature
91
92     var artifacts = {
93         ts: timestamp,
94         nonce: options.nonce || Cryptiles.randomString(6),
95         method: method,
96         resource: uri.pathname + (uri.search || ''), // Maintain trailing '?'
97         host: uri.hostname,
98         port: uri.port || (uri.protocol === 'http:' ? 80 : 443),
99         hash: options.hash,
100         ext: options.ext,
101         app: options.app,
102         dlg: options.dlg
103     };
104
105     result.artifacts = artifacts;
106
107     // Calculate payload hash
108
109     if (!artifacts.hash && (options.payload || options.payload === '')) {
110
111         artifacts.hash = Crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType);
112     }
113
114     var mac = Crypto.calculateMac('header', credentials, artifacts);
115
116     // Construct header
117
118     var hasExt = artifacts.ext !== null && artifacts.ext !== undefined && artifacts.ext !== ''; // Other falsey values allowed
119     var header = 'Hawk id="' + credentials.id + '", ts="' + artifacts.ts + '", nonce="' + artifacts.nonce + (artifacts.hash ? '", hash="' + artifacts.hash : '') + (hasExt ? '", ext="' + Hoek.escapeHeaderAttribute(artifacts.ext) : '') + '", mac="' + mac + '"';
120
121     if (artifacts.app) {
122         header = header + ', app="' + artifacts.app + (artifacts.dlg ? '", dlg="' + artifacts.dlg : '') + '"';
123     }
124
125     result.field = header;
126
127     return result;
128 };
129
130 // Validate server response
131
132 /*
133     res:        node's response object
134     artifacts:  object received from header().artifacts
135     options: {
136         payload:    optional payload received
137         required:   specifies if a Server-Authorization header is required. Defaults to 'false'
138     }
139 */
140
141 exports.authenticate = function (res, credentials, artifacts, options) {
142
143     artifacts = Hoek.clone(artifacts);
144     options = options || {};
145
146     if (res.headers['www-authenticate']) {
147
148         // Parse HTTP WWW-Authenticate header
149
150         var wwwAttributes = Utils.parseAuthorizationHeader(res.headers['www-authenticate'], ['ts', 'tsm', 'error']);
151         if (wwwAttributes instanceof Error) {
152             return false;
153         }
154
155         // Validate server timestamp (not used to update clock since it is done via the SNPT client)
156
157         if (wwwAttributes.ts) {
158             var tsm = Crypto.calculateTsMac(wwwAttributes.ts, credentials);
159             if (tsm !== wwwAttributes.tsm) {
160                 return false;
161             }
162         }
163     }
164
165     // Parse HTTP Server-Authorization header
166
167     if (!res.headers['server-authorization'] && !options.required) {
168
169         return true;
170     }
171
172     var attributes = Utils.parseAuthorizationHeader(res.headers['server-authorization'], ['mac', 'ext', 'hash']);
173     if (attributes instanceof Error) {
174         return false;
175     }
176
177     artifacts.ext = attributes.ext;
178     artifacts.hash = attributes.hash;
179
180     var mac = Crypto.calculateMac('response', credentials, artifacts);
181     if (mac !== attributes.mac) {
182         return false;
183     }
184
185     if (!options.payload && options.payload !== '') {
186
187         return true;
188     }
189
190     if (!attributes.hash) {
191         return false;
192     }
193
194     var calculatedHash = Crypto.calculatePayloadHash(options.payload, credentials.algorithm, res.headers['content-type']);
195     return calculatedHash === attributes.hash;
196 };
197
198 // Generate a bewit value for a given URI
199
200 /*
201     uri: 'http://example.com/resource?a=b' or object from Url.parse()
202     options: {
203
204         // Required
205
206         credentials: {
207             id: 'dh37fgj492je',
208             key: 'aoijedoaijsdlaksjdl',
209             algorithm: 'sha256'                             // 'sha1', 'sha256'
210         },
211         ttlSec: 60 * 60,                                    // TTL in seconds
212
213         // Optional
214
215         ext: 'application-specific',                        // Application specific data sent via the ext attribute
216         localtimeOffsetMsec: 400                            // Time offset to sync with server time
217     };
218 */
219
220 exports.getBewit = function (uri, options) {
221
222     // Validate inputs
223
224     if (!uri || typeof uri !== 'string' && (typeof uri === 'undefined' ? 'undefined' : _typeof(uri)) !== 'object' || !options || (typeof options === 'undefined' ? 'undefined' : _typeof(options)) !== 'object' || !options.ttlSec) {
225
226         return '';
227     }
228
229     options.ext = options.ext === null || options.ext === undefined ? '' : options.ext; // Zero is valid value
230
231     // Application time
232
233     var now = Utils.now(options.localtimeOffsetMsec);
234
235     // Validate credentials
236
237     var credentials = options.credentials;
238     if (!credentials || !credentials.id || !credentials.key || !credentials.algorithm) {
239
240         return '';
241     }
242
243     if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
244         return '';
245     }
246
247     // Parse URI
248
249     if (typeof uri === 'string') {
250         uri = Url.parse(uri);
251     }
252
253     // Calculate signature
254
255     var exp = Math.floor(now / 1000) + options.ttlSec;
256     var mac = Crypto.calculateMac('bewit', credentials, {
257         ts: exp,
258         nonce: '',
259         method: 'GET',
260         resource: uri.pathname + (uri.search || ''), // Maintain trailing '?'
261         host: uri.hostname,
262         port: uri.port || (uri.protocol === 'http:' ? 80 : 443),
263         ext: options.ext
264     });
265
266     // Construct bewit: id\exp\mac\ext
267
268     var bewit = credentials.id + '\\' + exp + '\\' + mac + '\\' + options.ext;
269     return Hoek.base64urlEncode(bewit);
270 };
271
272 // Generate an authorization string for a message
273
274 /*
275     host: 'example.com',
276     port: 8000,
277     message: '{"some":"payload"}',                          // UTF-8 encoded string for body hash generation
278     options: {
279
280         // Required
281
282         credentials: {
283             id: 'dh37fgj492je',
284             key: 'aoijedoaijsdlaksjdl',
285             algorithm: 'sha256'                             // 'sha1', 'sha256'
286         },
287
288         // Optional
289
290         timestamp: Date.now(),                              // A pre-calculated timestamp
291         nonce: '2334f34f',                                  // A pre-generated nonce
292         localtimeOffsetMsec: 400,                           // Time offset to sync with server time (ignored if timestamp provided)
293     }
294 */
295
296 exports.message = function (host, port, message, options) {
297
298     // Validate inputs
299
300     if (!host || typeof host !== 'string' || !port || typeof port !== 'number' || message === null || message === undefined || typeof message !== 'string' || !options || (typeof options === 'undefined' ? 'undefined' : _typeof(options)) !== 'object') {
301
302         return null;
303     }
304
305     // Application time
306
307     var timestamp = options.timestamp || Utils.nowSecs(options.localtimeOffsetMsec);
308
309     // Validate credentials
310
311     var credentials = options.credentials;
312     if (!credentials || !credentials.id || !credentials.key || !credentials.algorithm) {
313
314         // Invalid credential object
315         return null;
316     }
317
318     if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
319         return null;
320     }
321
322     // Calculate signature
323
324     var artifacts = {
325         ts: timestamp,
326         nonce: options.nonce || Cryptiles.randomString(6),
327         host: host,
328         port: port,
329         hash: Crypto.calculatePayloadHash(message, credentials.algorithm)
330     };
331
332     // Construct authorization
333
334     var result = {
335         id: credentials.id,
336         ts: artifacts.ts,
337         nonce: artifacts.nonce,
338         hash: artifacts.hash,
339         mac: Crypto.calculateMac('message', credentials, artifacts)
340     };
341
342     return result;
343 };