"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/mksnapshot/node_modules/request/lib/auth.js" (7 Feb 2017, 4165 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 'use strict'
    2 
    3 var caseless = require('caseless')
    4   , uuid = require('node-uuid')
    5   , helpers = require('./helpers')
    6 
    7 var md5 = helpers.md5
    8   , toBase64 = helpers.toBase64
    9 
   10 
   11 function Auth (request) {
   12   // define all public properties here
   13   this.request = request
   14   this.hasAuth = false
   15   this.sentAuth = false
   16   this.bearerToken = null
   17   this.user = null
   18   this.pass = null
   19 }
   20 
   21 Auth.prototype.basic = function (user, pass, sendImmediately) {
   22   var self = this
   23   if (typeof user !== 'string' || (pass !== undefined && typeof pass !== 'string')) {
   24     throw new Error('auth() received invalid user or password')
   25   }
   26   self.user = user
   27   self.pass = pass
   28   self.hasAuth = true
   29   var header = user + ':' + (pass || '')
   30   if (sendImmediately || typeof sendImmediately === 'undefined') {
   31     var authHeader = 'Basic ' + toBase64(header)
   32     self.sentAuth = true
   33     return authHeader
   34   }
   35 }
   36 
   37 Auth.prototype.bearer = function (bearer, sendImmediately) {
   38   var self = this
   39   self.bearerToken = bearer
   40   self.hasAuth = true
   41   if (sendImmediately || typeof sendImmediately === 'undefined') {
   42     if (typeof bearer === 'function') {
   43       bearer = bearer()
   44     }
   45     var authHeader = 'Bearer ' + (bearer || '')
   46     self.sentAuth = true
   47     return authHeader
   48   }
   49 }
   50 
   51 Auth.prototype.digest = function (method, path, authHeader) {
   52   // TODO: More complete implementation of RFC 2617.
   53   //   - check challenge.algorithm
   54   //   - support algorithm="MD5-sess"
   55   //   - handle challenge.domain
   56   //   - support qop="auth-int" only
   57   //   - handle Authentication-Info (not necessarily?)
   58   //   - check challenge.stale (not necessarily?)
   59   //   - increase nc (not necessarily?)
   60   // For reference:
   61   // http://tools.ietf.org/html/rfc2617#section-3
   62   // https://github.com/bagder/curl/blob/master/lib/http_digest.c
   63 
   64   var self = this
   65 
   66   var challenge = {}
   67   var re = /([a-z0-9_-]+)=(?:"([^"]+)"|([a-z0-9_-]+))/gi
   68   for (;;) {
   69     var match = re.exec(authHeader)
   70     if (!match) {
   71       break
   72     }
   73     challenge[match[1]] = match[2] || match[3]
   74   }
   75 
   76   var ha1 = md5(self.user + ':' + challenge.realm + ':' + self.pass)
   77   var ha2 = md5(method + ':' + path)
   78   var qop = /(^|,)\s*auth\s*($|,)/.test(challenge.qop) && 'auth'
   79   var nc = qop && '00000001'
   80   var cnonce = qop && uuid().replace(/-/g, '')
   81   var digestResponse = qop
   82     ? md5(ha1 + ':' + challenge.nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + ha2)
   83     : md5(ha1 + ':' + challenge.nonce + ':' + ha2)
   84   var authValues = {
   85     username: self.user,
   86     realm: challenge.realm,
   87     nonce: challenge.nonce,
   88     uri: path,
   89     qop: qop,
   90     response: digestResponse,
   91     nc: nc,
   92     cnonce: cnonce,
   93     algorithm: challenge.algorithm,
   94     opaque: challenge.opaque
   95   }
   96 
   97   authHeader = []
   98   for (var k in authValues) {
   99     if (authValues[k]) {
  100       if (k === 'qop' || k === 'nc' || k === 'algorithm') {
  101         authHeader.push(k + '=' + authValues[k])
  102       } else {
  103         authHeader.push(k + '="' + authValues[k] + '"')
  104       }
  105     }
  106   }
  107   authHeader = 'Digest ' + authHeader.join(', ')
  108   self.sentAuth = true
  109   return authHeader
  110 }
  111 
  112 Auth.prototype.onRequest = function (user, pass, sendImmediately, bearer) {
  113   var self = this
  114     , request = self.request
  115 
  116   var authHeader
  117   if (bearer === undefined && user === undefined) {
  118     throw new Error('no auth mechanism defined')
  119   } else if (bearer !== undefined) {
  120     authHeader = self.bearer(bearer, sendImmediately)
  121   } else {
  122     authHeader = self.basic(user, pass, sendImmediately)
  123   }
  124   if (authHeader) {
  125     request.setHeader('authorization', authHeader)
  126   }
  127 }
  128 
  129 Auth.prototype.onResponse = function (response) {
  130   var self = this
  131     , request = self.request
  132 
  133   if (!self.hasAuth || self.sentAuth) { return null }
  134 
  135   var c = caseless(response.headers)
  136 
  137   var authHeader = c.get('www-authenticate')
  138   var authVerb = authHeader && authHeader.split(' ')[0].toLowerCase()
  139   // debug('reauth', authVerb)
  140 
  141   switch (authVerb) {
  142     case 'basic':
  143       return self.basic(self.user, self.pass, true)
  144 
  145     case 'bearer':
  146       return self.bearer(self.bearerToken, true)
  147 
  148     case 'digest':
  149       return self.digest(request.method, request.path, authHeader)
  150   }
  151 }
  152 
  153 exports.Auth = Auth