@salesforce/core
Advanced tools
Comparing version
@@ -0,1 +1,8 @@ | ||
# [2.2.0](https://github.com/forcedotcom/sfdx-core/compare/v2.1.6...v2.2.0) (2020-02-11) | ||
### Features | ||
* create authinfo with a parent authinfo ([9b21226](https://github.com/forcedotcom/sfdx-core/commit/9b212264bafe458c95ae22fce11298c706d23393)), closes [#202](https://github.com/forcedotcom/sfdx-core/issues/202) | ||
## [2.1.6](https://github.com/forcedotcom/sfdx-core/compare/v2.1.5...v2.1.6) (2020-01-13) | ||
@@ -2,0 +9,0 @@ |
@@ -228,2 +228,3 @@ import { AsyncCreatable } from '@salesforce/kit'; | ||
private initAuthOptions; | ||
private loadAuthFromConfig; | ||
private isTokenOptions; | ||
@@ -259,3 +260,9 @@ private refreshFn; | ||
oauth2?: OAuth2; | ||
/** | ||
* In certain situations, a new auth info wants to use the connected app | ||
* information from another parent org. Typically for scratch org or sandbox | ||
* creation. | ||
*/ | ||
parentUsername?: string; | ||
} | ||
} |
@@ -490,2 +490,17 @@ "use strict"; | ||
else { | ||
if (this.options.parentUsername) { | ||
const parentUserFields = await this.loadAuthFromConfig(this.options.parentUsername); | ||
const parentFields = this.authInfoCrypto.decryptFields(parentUserFields); | ||
options.clientId = parentFields.clientId; | ||
if (process.env.SFDX_CLIENT_SECRET) { | ||
options.clientSecret = process.env.SFDX_CLIENT_SECRET; | ||
} | ||
else { | ||
// Grab whatever flow is defined | ||
Object.assign(options, { | ||
clientSecret: parentFields.clientSecret, | ||
privateKey: parentFields.privateKey | ||
}); | ||
} | ||
} | ||
// jwt flow | ||
@@ -518,20 +533,3 @@ // Support both sfdx and jsforce private key values | ||
const username = ts_types_1.ensure(this.getUsername()); | ||
if (AuthInfo.cache.has(username)) { | ||
authConfig = ts_types_1.ensure(AuthInfo.cache.get(username)); | ||
} | ||
else { | ||
// Fetch from the persisted auth file | ||
try { | ||
const config = await authInfoConfig_1.AuthInfoConfig.create(Object.assign({}, authInfoConfig_1.AuthInfoConfig.getOptions(username), { throwOnNotFound: true })); | ||
authConfig = config.toObject(); | ||
} | ||
catch (e) { | ||
if (e.code === 'ENOENT') { | ||
throw sfdxError_1.SfdxError.create('@salesforce/core', 'core', 'NamedOrgNotFound', [username]); | ||
} | ||
else { | ||
throw e; | ||
} | ||
} | ||
} | ||
authConfig = await this.loadAuthFromConfig(username); | ||
// Update the auth fields WITHOUT encryption (already encrypted) | ||
@@ -544,2 +542,22 @@ this.update(authConfig, false); | ||
} | ||
async loadAuthFromConfig(username) { | ||
if (AuthInfo.cache.has(username)) { | ||
return ts_types_1.ensure(AuthInfo.cache.get(username)); | ||
} | ||
else { | ||
// Fetch from the persisted auth file | ||
try { | ||
const config = await authInfoConfig_1.AuthInfoConfig.create(Object.assign({}, authInfoConfig_1.AuthInfoConfig.getOptions(username), { throwOnNotFound: true })); | ||
return config.toObject(); | ||
} | ||
catch (e) { | ||
if (e.code === 'ENOENT') { | ||
throw sfdxError_1.SfdxError.create('@salesforce/core', 'core', 'NamedOrgNotFound', [username]); | ||
} | ||
else { | ||
throw e; | ||
} | ||
} | ||
} | ||
} | ||
isTokenOptions(options) { | ||
@@ -663,18 +681,22 @@ // Although OAuth2Options does not contain refreshToken, privateKey, or privateKeyFile, a JS consumer could still pass those in | ||
const { userId, orgId } = _parseIdUrl(_authFields.id); | ||
// Make a REST call for the username directly. Normally this is done via a connection | ||
// but we don't want to create circular dependencies or lots of snowflakes | ||
// within this file to support it. | ||
const apiVersion = 'v42.0'; // hardcoding to v42.0 just for this call is okay. | ||
const instance = ts_types_1.ensure(ts_types_1.getString(_authFields, 'instance_url')); | ||
const url = `${instance}/services/data/${apiVersion}/sobjects/User/${userId}`; | ||
const headers = Object.assign({ Authorization: `Bearer ${_authFields.access_token}` }, connection_1.SFDX_HTTP_HEADERS); | ||
let username; | ||
try { | ||
this.logger.info(`Sending request for Username after successful auth code exchange to URL: ${url}`); | ||
const response = await new Transport().httpRequest({ url, headers }); | ||
username = ts_types_1.asString(kit_1.parseJsonMap(response.body).Username); | ||
let username = this.getUsername(); | ||
// Only need to query for the username if it isn't known. For example, a new auth code exchange | ||
// rather than refreshing a token on an existing connection. | ||
if (!username) { | ||
// Make a REST call for the username directly. Normally this is done via a connection | ||
// but we don't want to create circular dependencies or lots of snowflakes | ||
// within this file to support it. | ||
const apiVersion = 'v42.0'; // hardcoding to v42.0 just for this call is okay. | ||
const instance = ts_types_1.ensure(ts_types_1.getString(_authFields, 'instance_url')); | ||
const url = `${instance}/services/data/${apiVersion}/sobjects/User/${userId}`; | ||
const headers = Object.assign({ Authorization: `Bearer ${_authFields.access_token}` }, connection_1.SFDX_HTTP_HEADERS); | ||
try { | ||
this.logger.info(`Sending request for Username after successful auth code exchange to URL: ${url}`); | ||
const response = await new Transport().httpRequest({ url, headers }); | ||
username = ts_types_1.asString(kit_1.parseJsonMap(response.body).Username); | ||
} | ||
catch (err) { | ||
throw sfdxError_1.SfdxError.create('@salesforce/core', 'core', 'AuthCodeUsernameRetrievalError', [orgId, err.message]); | ||
} | ||
} | ||
catch (err) { | ||
throw sfdxError_1.SfdxError.create('@salesforce/core', 'core', 'AuthCodeUsernameRetrievalError', [orgId, err.message]); | ||
} | ||
return { | ||
@@ -688,3 +710,5 @@ accessToken: _authFields.access_token, | ||
loginUrl: options.loginUrl || _authFields.instance_url, | ||
refreshToken: _authFields.refresh_token | ||
refreshToken: _authFields.refresh_token, | ||
clientId: options.clientId, | ||
clientSecret: options.clientSecret | ||
}; | ||
@@ -691,0 +715,0 @@ } |
{ | ||
"name": "@salesforce/core", | ||
"version": "2.1.6", | ||
"version": "2.2.0", | ||
"description": "Core libraries to interact with SFDX projects, orgs, and APIs.", | ||
@@ -5,0 +5,0 @@ "main": "lib/exported", |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
447424
0.4%11165
0.28%20
11.11%