Skip to content

Commit

Permalink
fix(auth): get auth working with all the little details
Browse files Browse the repository at this point in the history
  • Loading branch information
zkat committed Mar 14, 2018
1 parent e6ebfb4 commit 84b94ba
Show file tree
Hide file tree
Showing 3 changed files with 301 additions and 79 deletions.
86 changes: 39 additions & 47 deletions auth.js
Original file line number Diff line number Diff line change
@@ -1,54 +1,46 @@
'use strict'

module.exports = getAuth
function getAuth (conf) {
const AUTH = {}
const iterator = typeof conf.forEach === 'function'
? conf
: conf.keys
iterator.forEach((k) => {
const authMatchGlobal = k.match(
/^(_authToken|username|_password|password|email|always-auth|_auth)$/
)
const authMatchScoped = k[0] === '/' && k.match(
/(.*):(_authToken|username|_password|password|email|always-auth|_auth)$/
)
const url = require('url')

// if it matches scoped it will also match global
if (authMatchGlobal || authMatchScoped) {
let nerfDart = null
let key = null
let val = null
module.exports = getAuth
function getAuth (registry, conf) {
if (!registry) { throw new Error('registry is required') }
if (!conf) { conf = new Map() }
let AUTH = {}
const regKey = registry && registryKey(registry)
const doKey = (key, alias) => addKey(conf, AUTH, regKey, key, alias)
doKey('_authToken', 'token')
doKey('username')
doKey('password')
doKey('_password', 'password')
doKey('email')
doKey('_auth')
doKey('otp')
doKey('always-auth', 'alwaysAuth')
if (AUTH.password) {
AUTH.password = Buffer.from(AUTH.password, 'base64').toString('utf8')
}
AUTH.alwaysAuth = AUTH.alwaysAuth === 'false' ? false : !!AUTH.alwaysAuth
return AUTH
}

if (authMatchScoped) {
nerfDart = authMatchScoped[1]
key = authMatchScoped[2]
val = conf.get(k)
if (!AUTH[nerfDart]) {
AUTH[nerfDart] = {
alwaysAuth: !!conf.get('always-auth')
}
}
} else {
key = authMatchGlobal[1]
val = conf.get(k)
AUTH.alwaysAuth = !!conf.get('always-auth')
}
function addKey (conf, obj, scope, key, objKey) {
if (conf.get(key)) {
obj[objKey || key] = conf.get(key)
}
if (scope && conf.get(`${scope}:${key}`)) {
obj[objKey || key] = conf.get(`${scope}:${key}`)
}
}

const auth = authMatchScoped ? AUTH[nerfDart] : AUTH
if (key === '_authToken') {
auth.token = val
} else if (key.match(/password$/i)) {
auth.password =
// the config file stores password auth already-encoded. pacote expects
// the actual username/password pair.
Buffer.from(val, 'base64').toString('utf8')
} else if (key === 'always-auth') {
auth.alwaysAuth = val === 'false' ? false : !!val
} else {
auth[key] = val
}
}
// Called a nerf dart in the main codebase. Used as a "safe"
// key when fetching registry info from config.
function registryKey (registry) {
const parsed = url.parse(registry)
const formatted = url.format({
host: parsed.host,
pathname: parsed.pathname,
slashes: parsed.slashes
})
return AUTH
return url.resolve(formatted, '.')
}
26 changes: 6 additions & 20 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,16 +130,11 @@ function getHeaders (registry, uri, opts) {
'user-agent': opts.config.get('user-agent'),
'referer': opts.refer
}, opts.headers)
// check for auth settings specific to this registry
let auth = (opts.auth && opts.auth[registryKey(registry)]) ||
opts.auth
if (!auth) {
const fromConfig = getAuth(opts.config)
auth = fromConfig[registryKey(registry)] || fromConfig
}

const auth = getAuth(registry, opts.config)
// If a tarball is hosted on a different place than the manifest, only send
// credentials on `alwaysAuth`
const shouldAuth = auth && (
const shouldAuth = (
auth.alwaysAuth ||
url.parse(uri).host === url.parse(registry).host
)
Expand All @@ -153,17 +148,8 @@ function getHeaders (registry, uri, opts) {
} else if (shouldAuth && auth._auth) {
headers.authorization = `Basic ${auth._auth}`
}
if (shouldAuth && auth.otp) {
headers['npm-otp'] = auth.otp
}
return headers
}

// Called a nerf dart in the main codebase. Used as a "safe"
// key when fetching registry info from config.
function registryKey (registry) {
const parsed = url.parse(registry)
const formatted = url.format({
host: parsed.host,
pathname: parsed.pathname,
slashes: parsed.slashes
})
return url.resolve(formatted, '.')
}
Loading

0 comments on commit 84b94ba

Please sign in to comment.