var url = require('url') var base64 = require('./base64') var decodeBase64 = base64.decodeBase64 var encodeBase64 = base64.encodeBase64 var tokenKey = ':_authToken' var legacyTokenKey = ':_auth' var userKey = ':username' var passwordKey = ':_password' module.exports = function () { var checkUrl var options if (arguments.length >= 2) { checkUrl = arguments[0] options = arguments[1] } else if (typeof arguments[0] === 'string') { checkUrl = arguments[0] } else { options = arguments[0] } options = options || {} options.npmrc = options.npmrc || require('rc')('npm', { registry: 'https://registry.npmjs.org/' }, { config: process.env.npm_config_userconfig || process.env.NPM_CONFIG_USERCONFIG }) checkUrl = checkUrl || options.npmrc.registry return getRegistryAuthInfo(checkUrl, options) || getLegacyAuthInfo(options.npmrc) } function getRegistryAuthInfo (checkUrl, options) { var parsed = url.parse(checkUrl, false, true) var pathname while (pathname !== '/' && parsed.pathname !== pathname) { pathname = parsed.pathname || '/' var regUrl = '//' + parsed.host + pathname.replace(/\/$/, '') var authInfo = getAuthInfoForUrl(regUrl, options.npmrc) if (authInfo) { return authInfo } // break if not recursive if (!options.recursive) { return /\/$/.test(checkUrl) ? undefined : getRegistryAuthInfo(url.resolve(checkUrl, '.'), options) } parsed.pathname = url.resolve(normalizePath(pathname), '..') || '/' } return undefined } function getLegacyAuthInfo (npmrc) { if (!npmrc._auth) { return undefined } var token = replaceEnvironmentVariable(npmrc._auth) return { token: token, type: 'Basic' } } function normalizePath (path) { return path[path.length - 1] === '/' ? path : path + '/' } function getAuthInfoForUrl (regUrl, npmrc) { // try to get bearer token var bearerAuth = getBearerToken(npmrc[regUrl + tokenKey] || npmrc[regUrl + '/' + tokenKey]) if (bearerAuth) { return bearerAuth } // try to get basic token var username = npmrc[regUrl + userKey] || npmrc[regUrl + '/' + userKey] var password = npmrc[regUrl + passwordKey] || npmrc[regUrl + '/' + passwordKey] var basicAuth = getTokenForUsernameAndPassword(username, password) if (basicAuth) { return basicAuth } var basicAuthWithToken = getLegacyAuthToken(npmrc[regUrl + legacyTokenKey] || npmrc[regUrl + '/' + legacyTokenKey]) if (basicAuthWithToken) { return basicAuthWithToken } return undefined } function replaceEnvironmentVariable (token) { return token.replace(/^\$\{?([^}]*)\}?$/, function (fullMatch, envVar) { return process.env[envVar] }) } function getBearerToken (tok) { if (!tok) { return undefined } // check if bearer token is set as environment variable var token = replaceEnvironmentVariable(tok) return { token: token, type: 'Bearer' } } function getTokenForUsernameAndPassword (username, password) { if (!username || !password) { return undefined } // passwords are base64 encoded, so we need to decode it // See https://github.com/npm/npm/blob/v3.10.6/lib/config/set-credentials-by-uri.js#L26 var pass = decodeBase64(replaceEnvironmentVariable(password)) // a basic auth token is base64 encoded 'username:password' // See https://github.com/npm/npm/blob/v3.10.6/lib/config/get-credentials-by-uri.js#L70 var token = encodeBase64(username + ':' + pass) // we found a basicToken token so let's exit the loop return { token: token, type: 'Basic', password: pass, username: username } } function getLegacyAuthToken (tok) { if (!tok) { return undefined } // check if legacy auth token is set as environment variable var token = replaceEnvironmentVariable(tok) return { token: token, type: 'Basic' } }