"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/hawk/lib/client.js" (7 Feb 2017, 10207 Bytes) of archive /windows/misc/atom-windows.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Javascript source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

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