Prompt users in interactive mode for where to store the credentials if a local auth config file exists (#11188)
parent
8ff237afb6
commit
b1f3f8b8fa
|
@ -102,6 +102,8 @@ class Config
|
||||||
private $configSource;
|
private $configSource;
|
||||||
/** @var ConfigSourceInterface */
|
/** @var ConfigSourceInterface */
|
||||||
private $authConfigSource;
|
private $authConfigSource;
|
||||||
|
/** @var ConfigSourceInterface|null */
|
||||||
|
private $localAuthConfigSource = null;
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
private $useEnvironment;
|
private $useEnvironment;
|
||||||
/** @var array<string, true> */
|
/** @var array<string, true> */
|
||||||
|
@ -153,6 +155,16 @@ class Config
|
||||||
return $this->authConfigSource;
|
return $this->authConfigSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setLocalAuthConfigSource(ConfigSourceInterface $source): void
|
||||||
|
{
|
||||||
|
$this->localAuthConfigSource = $source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLocalAuthConfigSource(): ?ConfigSourceInterface
|
||||||
|
{
|
||||||
|
return $this->localAuthConfigSource;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merges new config values with the existing ones (overriding)
|
* Merges new config values with the existing ones (overriding)
|
||||||
*
|
*
|
||||||
|
|
|
@ -336,7 +336,7 @@ class Factory
|
||||||
$io->writeError('Loading config file ' . $localAuthFile->getPath(), true, IOInterface::DEBUG);
|
$io->writeError('Loading config file ' . $localAuthFile->getPath(), true, IOInterface::DEBUG);
|
||||||
self::validateJsonSchema($io, $localAuthFile, JsonFile::AUTH_SCHEMA);
|
self::validateJsonSchema($io, $localAuthFile, JsonFile::AUTH_SCHEMA);
|
||||||
$config->merge(['config' => $localAuthFile->read()], $localAuthFile->getPath());
|
$config->merge(['config' => $localAuthFile->read()], $localAuthFile->getPath());
|
||||||
$config->setAuthConfigSource(new JsonConfigSource($localAuthFile, true));
|
$config->setLocalAuthConfigSource(new JsonConfigSource($localAuthFile, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -141,11 +141,17 @@ class Bitbucket
|
||||||
$this->io->writeError($message);
|
$this->io->writeError($message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$localAuthConfig = $this->config->getLocalAuthConfigSource();
|
||||||
$url = 'https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/';
|
$url = 'https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/';
|
||||||
$this->io->writeError(sprintf('Follow the instructions on %s', $url));
|
$this->io->writeError(sprintf('Follow the instructions on %s', $url));
|
||||||
$this->io->writeError(sprintf('to create a consumer. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
|
$this->io->writeError(sprintf('to create a consumer. It will be stored in "%s" for future use by Composer.', ($localAuthConfig !== null ? $localAuthConfig->getName() . ' OR ' : '') . $this->config->getAuthConfigSource()->getName()));
|
||||||
$this->io->writeError('Ensure you enter a "Callback URL" (http://example.com is fine) or it will not be possible to create an Access Token (this callback url will not be used by composer)');
|
$this->io->writeError('Ensure you enter a "Callback URL" (http://example.com is fine) or it will not be possible to create an Access Token (this callback url will not be used by composer)');
|
||||||
|
|
||||||
|
$storeInLocalAuthConfig = false;
|
||||||
|
if ($localAuthConfig !== null) {
|
||||||
|
$storeInLocalAuthConfig = $this->io->askConfirmation('A local auth config source was found, do you want to store the token there?', true);
|
||||||
|
}
|
||||||
|
|
||||||
$consumerKey = trim((string) $this->io->askAndHideAnswer('Consumer Key (hidden): '));
|
$consumerKey = trim((string) $this->io->askAndHideAnswer('Consumer Key (hidden): '));
|
||||||
|
|
||||||
if (!$consumerKey) {
|
if (!$consumerKey) {
|
||||||
|
@ -171,7 +177,8 @@ class Bitbucket
|
||||||
}
|
}
|
||||||
|
|
||||||
// store value in user config
|
// store value in user config
|
||||||
$this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
|
$authConfigSource = $storeInLocalAuthConfig && $localAuthConfig !== null ? $localAuthConfig : $this->config->getAuthConfigSource();
|
||||||
|
$this->storeInAuthConfig($authConfigSource, $originUrl, $consumerKey, $consumerSecret);
|
||||||
|
|
||||||
// Remove conflicting basic auth credentials (if available)
|
// Remove conflicting basic auth credentials (if available)
|
||||||
$this->config->getAuthConfigSource()->removeConfigSetting('http-basic.' . $originUrl);
|
$this->config->getAuthConfigSource()->removeConfigSetting('http-basic.' . $originUrl);
|
||||||
|
@ -195,7 +202,7 @@ class Bitbucket
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
|
$this->storeInAuthConfig($this->config->getLocalAuthConfigSource() ?? $this->config->getAuthConfigSource(), $originUrl, $consumerKey, $consumerSecret);
|
||||||
|
|
||||||
if (!isset($this->token['access_token'])) {
|
if (!isset($this->token['access_token'])) {
|
||||||
throw new \LogicException('Failed to initialize token above');
|
throw new \LogicException('Failed to initialize token above');
|
||||||
|
@ -207,7 +214,7 @@ class Bitbucket
|
||||||
/**
|
/**
|
||||||
* Store the new/updated credentials to the configuration
|
* Store the new/updated credentials to the configuration
|
||||||
*/
|
*/
|
||||||
private function storeInAuthConfig(string $originUrl, string $consumerKey, string $consumerSecret): void
|
private function storeInAuthConfig(Config\ConfigSourceInterface $authConfigSource, string $originUrl, string $consumerKey, string $consumerSecret): void
|
||||||
{
|
{
|
||||||
$this->config->getConfigSource()->removeConfigSetting('bitbucket-oauth.'.$originUrl);
|
$this->config->getConfigSource()->removeConfigSetting('bitbucket-oauth.'.$originUrl);
|
||||||
|
|
||||||
|
|
|
@ -95,12 +95,18 @@ class GitHub
|
||||||
$this->io->writeError(sprintf('When working with _public_ GitHub repositories only, head to %s to retrieve a token.', $url));
|
$this->io->writeError(sprintf('When working with _public_ GitHub repositories only, head to %s to retrieve a token.', $url));
|
||||||
$this->io->writeError('This token will have read-only permission for public information only.');
|
$this->io->writeError('This token will have read-only permission for public information only.');
|
||||||
|
|
||||||
|
$localAuthConfig = $this->config->getLocalAuthConfigSource();
|
||||||
$url = 'https://'.$originUrl.'/settings/tokens/new?scopes=repo&description=' . str_replace('%20', '+', rawurlencode($note));
|
$url = 'https://'.$originUrl.'/settings/tokens/new?scopes=repo&description=' . str_replace('%20', '+', rawurlencode($note));
|
||||||
$this->io->writeError(sprintf('When you need to access _private_ GitHub repositories as well, go to %s', $url));
|
$this->io->writeError(sprintf('When you need to access _private_ GitHub repositories as well, go to %s', $url));
|
||||||
$this->io->writeError('Note that such tokens have broad read/write permissions on your behalf, even if not needed by Composer.');
|
$this->io->writeError('Note that such tokens have broad read/write permissions on your behalf, even if not needed by Composer.');
|
||||||
$this->io->writeError(sprintf('Tokens will be stored in plain text in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
|
$this->io->writeError(sprintf('Tokens will be stored in plain text in "%s" for future use by Composer.', ($localAuthConfig !== null ? $localAuthConfig->getName() . ' OR ' : '') . $this->config->getAuthConfigSource()->getName()));
|
||||||
$this->io->writeError('For additional information, check https://getcomposer.org/doc/articles/authentication-for-private-packages.md#github-oauth');
|
$this->io->writeError('For additional information, check https://getcomposer.org/doc/articles/authentication-for-private-packages.md#github-oauth');
|
||||||
|
|
||||||
|
$storeInLocalAuthConfig = false;
|
||||||
|
if ($localAuthConfig !== null) {
|
||||||
|
$storeInLocalAuthConfig = $this->io->askConfirmation('A local auth config source was found, do you want to store the token there?', true);
|
||||||
|
}
|
||||||
|
|
||||||
$token = trim((string) $this->io->askAndHideAnswer('Token (hidden): '));
|
$token = trim((string) $this->io->askAndHideAnswer('Token (hidden): '));
|
||||||
|
|
||||||
if ($token === '') {
|
if ($token === '') {
|
||||||
|
@ -129,9 +135,10 @@ class GitHub
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
|
|
||||||
// store value in user config
|
// store value in local/user config
|
||||||
|
$authConfigSource = $storeInLocalAuthConfig && $localAuthConfig !== null ? $localAuthConfig : $this->config->getAuthConfigSource();
|
||||||
$this->config->getConfigSource()->removeConfigSetting('github-oauth.'.$originUrl);
|
$this->config->getConfigSource()->removeConfigSetting('github-oauth.'.$originUrl);
|
||||||
$this->config->getAuthConfigSource()->addConfigSetting('github-oauth.'.$originUrl, $token);
|
$authConfigSource->addConfigSetting('github-oauth.'.$originUrl, $token);
|
||||||
|
|
||||||
$this->io->writeError('<info>Token stored successfully.</info>');
|
$this->io->writeError('<info>Token stored successfully.</info>');
|
||||||
|
|
||||||
|
|
|
@ -125,10 +125,16 @@ class GitLab
|
||||||
$this->io->writeError($message);
|
$this->io->writeError($message);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->io->writeError(sprintf('A token will be created and stored in "%s", your password will never be stored', $this->config->getAuthConfigSource()->getName()));
|
$localAuthConfig = $this->config->getLocalAuthConfigSource();
|
||||||
|
$this->io->writeError(sprintf('A token will be created and stored in "%s", your password will never be stored', ($localAuthConfig !== null ? $localAuthConfig->getName() . ' OR ' : '') . $this->config->getAuthConfigSource()->getName()));
|
||||||
$this->io->writeError('To revoke access to this token you can visit '.$scheme.'://'.$originUrl.'/-/profile/applications');
|
$this->io->writeError('To revoke access to this token you can visit '.$scheme.'://'.$originUrl.'/-/profile/applications');
|
||||||
$this->io->writeError('Alternatively you can setup an personal access token on '.$scheme.'://'.$originUrl.'/-/profile/personal_access_tokens and store it under "gitlab-token" see https://getcomposer.org/doc/articles/authentication-for-private-packages.md#gitlab-token for more details.');
|
$this->io->writeError('Alternatively you can setup an personal access token on '.$scheme.'://'.$originUrl.'/-/profile/personal_access_tokens and store it under "gitlab-token" see https://getcomposer.org/doc/articles/authentication-for-private-packages.md#gitlab-token for more details.');
|
||||||
|
|
||||||
|
$storeInLocalAuthConfig = false;
|
||||||
|
if ($localAuthConfig !== null) {
|
||||||
|
$storeInLocalAuthConfig = $this->io->askConfirmation('A local auth config source was found, do you want to store the token there?', true);
|
||||||
|
}
|
||||||
|
|
||||||
$attemptCounter = 0;
|
$attemptCounter = 0;
|
||||||
|
|
||||||
while ($attemptCounter++ < 5) {
|
while ($attemptCounter++ < 5) {
|
||||||
|
@ -160,9 +166,10 @@ class GitLab
|
||||||
|
|
||||||
$this->io->setAuthentication($originUrl, $response['access_token'], 'oauth2');
|
$this->io->setAuthentication($originUrl, $response['access_token'], 'oauth2');
|
||||||
|
|
||||||
|
$authConfigSource = $storeInLocalAuthConfig && $localAuthConfig !== null ? $localAuthConfig : $this->config->getAuthConfigSource();
|
||||||
// store value in user config in auth file
|
// store value in user config in auth file
|
||||||
if (isset($response['expires_in'])) {
|
if (isset($response['expires_in'])) {
|
||||||
$this->config->getAuthConfigSource()->addConfigSetting(
|
$authConfigSource->addConfigSetting(
|
||||||
'gitlab-oauth.'.$originUrl,
|
'gitlab-oauth.'.$originUrl,
|
||||||
[
|
[
|
||||||
'expires-at' => intval($response['created_at']) + intval($response['expires_in']),
|
'expires-at' => intval($response['created_at']) + intval($response['expires_in']),
|
||||||
|
@ -171,7 +178,7 @@ class GitLab
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
$this->config->getAuthConfigSource()->addConfigSetting('gitlab-oauth.'.$originUrl, $response['access_token']);
|
$authConfigSource->addConfigSetting('gitlab-oauth.'.$originUrl, $response['access_token']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in New Issue