From 294e2eb14b60146b9ddd06e9c45e5d8c352a9130 Mon Sep 17 00:00:00 2001 From: isaacs Date: Fri, 23 Apr 2021 14:05:18 -0700 Subject: [PATCH] Send auth when hostname matches registry, and reg has auth PR-URL: https://github.com/npm/npm-registry-fetch/pull/46 Credit: @isaacs Close: #46 Reviewed-by: @wraithgar --- auth.js | 41 ++++++++++++++++++++++++++++------------- test/auth.js | 30 ++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 13 deletions(-) diff --git a/auth.js b/auth.js index fafea54f..80aed9ca 100644 --- a/auth.js +++ b/auth.js @@ -27,6 +27,21 @@ const hasAuth = (regKey, opts) => ( opts[`${regKey}:username`] && opts[`${regKey}:_password`] ) +const sameHost = (a, b) => { + const parsedA = new URL(a) + const parsedB = new URL(b) + return parsedA.host === parsedB.host +} + +const getRegistry = opts => { + const { spec } = opts + const { scope: specScope, subSpec } = spec ? npa(spec) : {} + const subSpecScope = subSpec && subSpec.scope + const scope = subSpec ? subSpecScope : specScope + const scopeReg = scope && opts[`${scope}:registry`] + return scopeReg || opts.registry +} + const getAuth = (uri, opts = {}) => { const { forceAuth } = opts if (!uri) @@ -44,19 +59,19 @@ const getAuth = (uri, opts = {}) => { }) } - // no auth for this URI - if (!regKey && opts.spec) { - // If making a tarball request to a different base URI than the - // registry where we logged in, but the same auth SHOULD be sent - // to that artifact host, then we track where it was coming in from, - // and warn the user if we get a 4xx error on it. - const { spec } = opts - const { scope: specScope, subSpec } = npa(spec) - const subSpecScope = subSpec && subSpec.scope - const scope = subSpec ? subSpecScope : specScope - const scopeReg = scope && opts[`${scope}:registry`] - const scopeAuthKey = scopeReg && regKeyFromURI(scopeReg, opts) - return new Auth({ scopeAuthKey }) + // no auth for this URI, but might have it for the registry + if (!regKey) { + const registry = getRegistry(opts) + if (registry && uri !== registry && sameHost(uri, registry)) + return getAuth(registry, opts) + else if (registry !== opts.registry) { + // If making a tarball request to a different base URI than the + // registry where we logged in, but the same auth SHOULD be sent + // to that artifact host, then we track where it was coming in from, + // and warn the user if we get a 4xx error on it. + const scopeAuthKey = regKeyFromURI(registry, opts) + return new Auth({ scopeAuthKey }) + } } const { diff --git a/test/auth.js b/test/auth.js index 87f3f8cc..a64394e7 100644 --- a/test/auth.js +++ b/test/auth.js @@ -428,3 +428,33 @@ t.test('scopeAuthKey tests', t => { t.end() }) + +t.test('registry host matches, path does not, send auth', t => { + const opts = { + '@other-scope:registry': 'https://other-scope-registry.com/other/scope/', + '//other-scope-registry.com/other/scope/:_authToken': 'cafebad', + '@scope:registry': 'https://scope-host.com/scope/host/', + '//scope-host.com/scope/host/:_authToken': 'c0ffee', + registry: 'https://registry.example.com/some/path/', + } + const uri = 'https://scope-host.com/blahblah/bloobloo/foo.tgz' + t.same(getAuth(uri, { ...opts, spec: '@scope/foo' }), { + scopeAuthKey: null, + token: 'c0ffee', + auth: null, + isBasicAuth: false, + }) + t.same(getAuth(uri, { ...opts, spec: '@other-scope/foo' }), { + scopeAuthKey: '//other-scope-registry.com/other/scope/', + token: null, + auth: null, + isBasicAuth: false, + }) + t.same(getAuth(uri, { ...opts, registry: 'https://scope-host.com/scope/host/' }), { + scopeAuthKey: null, + token: 'c0ffee', + auth: null, + isBasicAuth: false, + }) + t.end() +})