mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-21 00:59:03 +01:00
Remove quick pick flow for protocol handler (#270455)
Remove quick pick flow Since we have device code flow, that's better. ref https://github.com/microsoft/vscode/issues/270452
This commit is contained in:
committed by
GitHub
parent
b676e12277
commit
bcbd0b4a98
@@ -5,17 +5,14 @@
|
||||
|
||||
import type { ILoopbackClient, ServerAuthorizationCodeResponse } from '@azure/msal-node';
|
||||
import type { UriEventHandler } from '../UriEventHandler';
|
||||
import { Disposable, env, l10n, LogOutputChannel, Uri, window } from 'vscode';
|
||||
import { DeferredPromise, toPromise } from './async';
|
||||
import { isSupportedClient } from './env';
|
||||
import { env, LogOutputChannel, Uri } from 'vscode';
|
||||
import { toPromise } from './async';
|
||||
|
||||
export interface ILoopbackClientAndOpener extends ILoopbackClient {
|
||||
openBrowser(url: string): Promise<void>;
|
||||
}
|
||||
|
||||
export class UriHandlerLoopbackClient implements ILoopbackClientAndOpener {
|
||||
private _responseDeferred: DeferredPromise<ServerAuthorizationCodeResponse> | undefined;
|
||||
|
||||
constructor(
|
||||
private readonly _uriHandler: UriEventHandler,
|
||||
private readonly _redirectUri: string,
|
||||
@@ -24,14 +21,16 @@ export class UriHandlerLoopbackClient implements ILoopbackClientAndOpener {
|
||||
) { }
|
||||
|
||||
async listenForAuthCode(): Promise<ServerAuthorizationCodeResponse> {
|
||||
await this._responseDeferred?.cancel();
|
||||
this._responseDeferred = new DeferredPromise();
|
||||
const result = await this._responseDeferred.p;
|
||||
this._responseDeferred = undefined;
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
throw new Error('No valid response received for authorization code.');
|
||||
const url = await toPromise(this._uriHandler.event);
|
||||
this._logger.debug(`Received URL event. Authority: ${url.authority}`);
|
||||
const result = new URL(url.toString(true));
|
||||
return {
|
||||
code: result.searchParams.get('code') ?? undefined,
|
||||
state: result.searchParams.get('state') ?? undefined,
|
||||
error: result.searchParams.get('error') ?? undefined,
|
||||
error_description: result.searchParams.get('error_description') ?? undefined,
|
||||
error_uri: result.searchParams.get('error_uri') ?? undefined,
|
||||
};
|
||||
}
|
||||
|
||||
getRedirectUri(): string {
|
||||
@@ -45,93 +44,7 @@ export class UriHandlerLoopbackClient implements ILoopbackClientAndOpener {
|
||||
}
|
||||
|
||||
async openBrowser(url: string): Promise<void> {
|
||||
if (isSupportedClient(this._callbackUri)) {
|
||||
void this._getCodeResponseFromUriHandler();
|
||||
} else {
|
||||
// Unsupported clients will be shown the code in the browser, but it will not redirect back since this
|
||||
// isn't a supported client. Instead, they will copy that code in the browser and paste it in an input box
|
||||
// that will be shown to them by the extension.
|
||||
void this._getCodeResponseFromQuickPick();
|
||||
}
|
||||
|
||||
const uri = Uri.parse(url + `&state=${encodeURI(this._callbackUri.toString(true))}`);
|
||||
await env.openExternal(uri);
|
||||
}
|
||||
|
||||
private async _getCodeResponseFromUriHandler(): Promise<void> {
|
||||
if (!this._responseDeferred) {
|
||||
throw new Error('No listener for auth code');
|
||||
}
|
||||
const url = await toPromise(this._uriHandler.event);
|
||||
this._logger.debug(`Received URL event. Authority: ${url.authority}`);
|
||||
const result = new URL(url.toString(true));
|
||||
|
||||
this._responseDeferred?.complete({
|
||||
code: result.searchParams.get('code') ?? undefined,
|
||||
state: result.searchParams.get('state') ?? undefined,
|
||||
error: result.searchParams.get('error') ?? undefined,
|
||||
error_description: result.searchParams.get('error_description') ?? undefined,
|
||||
error_uri: result.searchParams.get('error_uri') ?? undefined,
|
||||
});
|
||||
}
|
||||
|
||||
private async _getCodeResponseFromQuickPick(): Promise<void> {
|
||||
if (!this._responseDeferred) {
|
||||
throw new Error('No listener for auth code');
|
||||
}
|
||||
const inputBox = window.createInputBox();
|
||||
inputBox.ignoreFocusOut = true;
|
||||
inputBox.title = l10n.t('Microsoft Authentication');
|
||||
inputBox.prompt = l10n.t('Provide the authorization code to complete the sign in flow.');
|
||||
inputBox.placeholder = l10n.t('Paste authorization code here...');
|
||||
inputBox.show();
|
||||
const code = await new Promise<string | undefined>((resolve) => {
|
||||
let resolvedValue: string | undefined = undefined;
|
||||
const disposable = Disposable.from(
|
||||
inputBox,
|
||||
inputBox.onDidAccept(async () => {
|
||||
if (!inputBox.value) {
|
||||
inputBox.validationMessage = l10n.t('Authorization code is required.');
|
||||
return;
|
||||
}
|
||||
const code = inputBox.value;
|
||||
resolvedValue = code;
|
||||
resolve(code);
|
||||
inputBox.hide();
|
||||
}),
|
||||
inputBox.onDidChangeValue(() => {
|
||||
inputBox.validationMessage = undefined;
|
||||
}),
|
||||
inputBox.onDidHide(() => {
|
||||
disposable.dispose();
|
||||
if (!resolvedValue) {
|
||||
resolve(undefined);
|
||||
}
|
||||
})
|
||||
);
|
||||
Promise.allSettled([this._responseDeferred?.p]).then(() => disposable.dispose());
|
||||
});
|
||||
// Something canceled the original deferred promise, so just return.
|
||||
if (this._responseDeferred.isSettled) {
|
||||
return;
|
||||
}
|
||||
if (code) {
|
||||
this._logger.debug('Received auth code from quick pick');
|
||||
this._responseDeferred.complete({
|
||||
code,
|
||||
state: undefined,
|
||||
error: undefined,
|
||||
error_description: undefined,
|
||||
error_uri: undefined
|
||||
});
|
||||
return;
|
||||
}
|
||||
this._responseDeferred.complete({
|
||||
code: undefined,
|
||||
state: undefined,
|
||||
error: 'User cancelled',
|
||||
error_description: 'User cancelled',
|
||||
error_uri: undefined
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ suite('UriHandlerLoopbackClient', () => {
|
||||
});
|
||||
|
||||
// Skipped for now until `listenForAuthCode` is refactored to not show quick pick
|
||||
suite.skip('listenForAuthCode', () => {
|
||||
suite('listenForAuthCode', () => {
|
||||
test('should return auth code from URL', async () => {
|
||||
const code = '1234';
|
||||
const state = '5678';
|
||||
|
||||
Reference in New Issue
Block a user