From a790196c1910c92e617603056cacb99817470f0f Mon Sep 17 00:00:00 2001 From: Tyler James Leonhardt Date: Thu, 29 Dec 2022 14:28:57 -0500 Subject: [PATCH] Improve PAT auth flow (#170239) This improves the PAT auth flow by showing a modal to open github.com with the scopes already pre-filled. This should allow for less room for error during the PAT auth. Additionally, this allows PAT auth flow to be used as a fallback for GH Enterprise flows. --- .../github-authentication/src/githubServer.ts | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/extensions/github-authentication/src/githubServer.ts b/extensions/github-authentication/src/githubServer.ts index f292b3a42dd..8565178bf10 100644 --- a/extensions/github-authentication/src/githubServer.ts +++ b/extensions/github-authentication/src/githubServer.ts @@ -189,7 +189,11 @@ export class GitHubServer implements IGitHubServer { this._logger.error(e); userCancelled = e.message ?? e === 'User Cancelled'; } - } else if (!supported) { + } + + // In a supported environment, we can't use PAT auth because we use this auth for Settings Sync and it doesn't support PATs. + // With that said, GitHub Enterprise isn't used by Settings Sync so we can use PATs for that. + if (!supported || this._type === AuthProviderType.githubEnterprise) { try { await promptToContinue(); return await this.doLoginWithPat(scopes); @@ -338,7 +342,23 @@ export class GitHubServer implements IGitHubServer { private async doLoginWithPat(scopes: string): Promise { this._logger.info(`Trying to retrieve PAT... (${scopes})`); - const token = await vscode.window.showInputBox({ prompt: 'GitHub Personal Access Token', ignoreFocusOut: true }); + + const button = vscode.l10n.t('Continue to GitHub'); + const modalResult = await vscode.window.showInformationMessage( + vscode.l10n.t('Continue to GitHub to create a Personal Access Token (PAT)'), + { + modal: true, + detail: vscode.l10n.t('To finish authenticating, navigate to GitHub to create a PAT then paste the PAT into the input box.') + }, button); + + if (modalResult !== button) { + throw new Error('User Cancelled'); + } + + const description = `${vscode.env.appName} (${scopes})`; + const uriToOpen = await vscode.env.asExternalUri(this.baseUri.with({ path: '/settings/tokens/new', query: `description=${description}&scopes=${scopes.split(' ').join(',')}` })); + await vscode.env.openExternal(uriToOpen); + const token = await vscode.window.showInputBox({ placeHolder: `ghp_1a2b3c4...`, prompt: `GitHub Personal Access Token - ${scopes}`, ignoreFocusOut: true }); if (!token) { throw new Error('User Cancelled'); } const tokenScopes = await getScopes(token, this.getServerUri('/'), this._logger); // Example: ['repo', 'user']