Skip to content

Commit 84b94ba

Browse files
committed
fix(auth): get auth working with all the little details
1 parent e6ebfb4 commit 84b94ba

File tree

3 files changed

+301
-79
lines changed

3 files changed

+301
-79
lines changed

auth.js

Lines changed: 39 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,46 @@
11
'use strict'
22

3-
module.exports = getAuth
4-
function getAuth (conf) {
5-
const AUTH = {}
6-
const iterator = typeof conf.forEach === 'function'
7-
? conf
8-
: conf.keys
9-
iterator.forEach((k) => {
10-
const authMatchGlobal = k.match(
11-
/^(_authToken|username|_password|password|email|always-auth|_auth)$/
12-
)
13-
const authMatchScoped = k[0] === '/' && k.match(
14-
/(.*):(_authToken|username|_password|password|email|always-auth|_auth)$/
15-
)
3+
const url = require('url')
164

17-
// if it matches scoped it will also match global
18-
if (authMatchGlobal || authMatchScoped) {
19-
let nerfDart = null
20-
let key = null
21-
let val = null
5+
module.exports = getAuth
6+
function getAuth (registry, conf) {
7+
if (!registry) { throw new Error('registry is required') }
8+
if (!conf) { conf = new Map() }
9+
let AUTH = {}
10+
const regKey = registry && registryKey(registry)
11+
const doKey = (key, alias) => addKey(conf, AUTH, regKey, key, alias)
12+
doKey('_authToken', 'token')
13+
doKey('username')
14+
doKey('password')
15+
doKey('_password', 'password')
16+
doKey('email')
17+
doKey('_auth')
18+
doKey('otp')
19+
doKey('always-auth', 'alwaysAuth')
20+
if (AUTH.password) {
21+
AUTH.password = Buffer.from(AUTH.password, 'base64').toString('utf8')
22+
}
23+
AUTH.alwaysAuth = AUTH.alwaysAuth === 'false' ? false : !!AUTH.alwaysAuth
24+
return AUTH
25+
}
2226

23-
if (authMatchScoped) {
24-
nerfDart = authMatchScoped[1]
25-
key = authMatchScoped[2]
26-
val = conf.get(k)
27-
if (!AUTH[nerfDart]) {
28-
AUTH[nerfDart] = {
29-
alwaysAuth: !!conf.get('always-auth')
30-
}
31-
}
32-
} else {
33-
key = authMatchGlobal[1]
34-
val = conf.get(k)
35-
AUTH.alwaysAuth = !!conf.get('always-auth')
36-
}
27+
function addKey (conf, obj, scope, key, objKey) {
28+
if (conf.get(key)) {
29+
obj[objKey || key] = conf.get(key)
30+
}
31+
if (scope && conf.get(`${scope}:${key}`)) {
32+
obj[objKey || key] = conf.get(`${scope}:${key}`)
33+
}
34+
}
3735

38-
const auth = authMatchScoped ? AUTH[nerfDart] : AUTH
39-
if (key === '_authToken') {
40-
auth.token = val
41-
} else if (key.match(/password$/i)) {
42-
auth.password =
43-
// the config file stores password auth already-encoded. pacote expects
44-
// the actual username/password pair.
45-
Buffer.from(val, 'base64').toString('utf8')
46-
} else if (key === 'always-auth') {
47-
auth.alwaysAuth = val === 'false' ? false : !!val
48-
} else {
49-
auth[key] = val
50-
}
51-
}
36+
// Called a nerf dart in the main codebase. Used as a "safe"
37+
// key when fetching registry info from config.
38+
function registryKey (registry) {
39+
const parsed = url.parse(registry)
40+
const formatted = url.format({
41+
host: parsed.host,
42+
pathname: parsed.pathname,
43+
slashes: parsed.slashes
5244
})
53-
return AUTH
45+
return url.resolve(formatted, '.')
5446
}

index.js

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -130,16 +130,11 @@ function getHeaders (registry, uri, opts) {
130130
'user-agent': opts.config.get('user-agent'),
131131
'referer': opts.refer
132132
}, opts.headers)
133-
// check for auth settings specific to this registry
134-
let auth = (opts.auth && opts.auth[registryKey(registry)]) ||
135-
opts.auth
136-
if (!auth) {
137-
const fromConfig = getAuth(opts.config)
138-
auth = fromConfig[registryKey(registry)] || fromConfig
139-
}
133+
134+
const auth = getAuth(registry, opts.config)
140135
// If a tarball is hosted on a different place than the manifest, only send
141136
// credentials on `alwaysAuth`
142-
const shouldAuth = auth && (
137+
const shouldAuth = (
143138
auth.alwaysAuth ||
144139
url.parse(uri).host === url.parse(registry).host
145140
)
@@ -153,17 +148,8 @@ function getHeaders (registry, uri, opts) {
153148
} else if (shouldAuth && auth._auth) {
154149
headers.authorization = `Basic ${auth._auth}`
155150
}
151+
if (shouldAuth && auth.otp) {
152+
headers['npm-otp'] = auth.otp
153+
}
156154
return headers
157155
}
158-
159-
// Called a nerf dart in the main codebase. Used as a "safe"
160-
// key when fetching registry info from config.
161-
function registryKey (registry) {
162-
const parsed = url.parse(registry)
163-
const formatted = url.format({
164-
host: parsed.host,
165-
pathname: parsed.pathname,
166-
slashes: parsed.slashes
167-
})
168-
return url.resolve(formatted, '.')
169-
}

0 commit comments

Comments
 (0)