Merge from vscode merge-base (#22780)

* Revert "Revert "Merge from vscode merge-base (#22769)" (#22779)"

This reverts commit 47a1745180.

* Fix notebook download task

* Remove done call from extensions-ci
This commit is contained in:
Karl Burtram
2023-04-19 21:48:46 -07:00
committed by GitHub
parent decbe8dded
commit e7d3d047ec
2389 changed files with 92155 additions and 42602 deletions

View File

@@ -11,7 +11,7 @@ import * as nls from 'vscode-nls';
import { v4 as uuid } from 'uuid';
import fetch, { Response } from 'node-fetch';
import Logger from './logger';
import { toBase64UrlEncoding } from './utils';
import { isSupportedEnvironment, toBase64UrlEncoding } from './utils';
import { sha256 } from './env/node/sha256';
import { BetterTokenStorage, IDidChangeInOtherWindowEvent } from './betterSecretStorage';
import { LoopbackAuthServer } from './authServer';
@@ -109,7 +109,7 @@ export class AzureActiveDirectoryService {
public async initialize(): Promise<void> {
Logger.info('Reading sessions from secret storage...');
let sessions = await this._tokenStorage.getAll();
const sessions = await this._tokenStorage.getAll();
Logger.info(`Got ${sessions.length} stored sessions`);
const refreshes = sessions.map(async session => {
@@ -319,13 +319,7 @@ export class AzureActiveDirectoryService {
}, 5000);
}
const token = await this.exchangeCodeForToken(codeToExchange, codeVerifier, scopeData);
if (token.expiresIn) {
this.setSessionTimeout(token.sessionId, token.refreshToken, scopeData, token.expiresIn * AzureActiveDirectoryService.REFRESH_TIMEOUT_MODIFIER);
}
await this.setToken(token, scopeData);
Logger.info(`Login successful for scopes: ${scopeData.scopeStr}`);
const session = await this.convertToSession(token);
const session = await this.exchangeCodeForSession(codeToExchange, codeVerifier, scopeData);
return session;
}
@@ -352,12 +346,14 @@ export class AzureActiveDirectoryService {
code_challenge_method: 'S256',
code_challenge: codeChallenge,
});
let uri = vscode.Uri.parse(`${signInUrl}?${oauthStartQuery.toString()}`);
const uri = vscode.Uri.parse(`${signInUrl}?${oauthStartQuery.toString()}`);
vscode.env.openExternal(uri);
let inputBox: vscode.InputBox | undefined;
const timeoutPromise = new Promise((_: (value: vscode.AuthenticationSession) => void, reject) => {
const wait = setTimeout(() => {
clearTimeout(wait);
inputBox?.dispose();
reject('Login timed out.');
}, 1000 * 60 * 5);
});
@@ -369,7 +365,12 @@ export class AzureActiveDirectoryService {
// before completing it.
let existingPromise = this._codeExchangePromises.get(scopeData.scopeStr);
if (!existingPromise) {
existingPromise = this.handleCodeResponse(scopeData);
if (isSupportedEnvironment(callbackUri)) {
existingPromise = this.handleCodeResponse(scopeData);
} else {
inputBox = vscode.window.createInputBox();
existingPromise = Promise.race([this.handleCodeInputBox(inputBox, codeVerifier, scopeData), this.handleCodeResponse(scopeData)]);
}
this._codeExchangePromises.set(scopeData.scopeStr, existingPromise);
}
@@ -659,13 +660,7 @@ export class AzureActiveDirectoryService {
throw new Error('No available code verifier');
}
const token = await this.exchangeCodeForToken(code, verifier, scopeData);
if (token.expiresIn) {
this.setSessionTimeout(token.sessionId, token.refreshToken, scopeData, token.expiresIn * AzureActiveDirectoryService.REFRESH_TIMEOUT_MODIFIER);
}
await this.setToken(token, scopeData);
const session = await this.convertToSession(token);
const session = await this.exchangeCodeForSession(code, verifier, scopeData);
resolve(session);
} catch (err) {
reject(err);
@@ -680,8 +675,33 @@ export class AzureActiveDirectoryService {
});
}
private async exchangeCodeForToken(code: string, codeVerifier: string, scopeData: IScopeData): Promise<IToken> {
private async handleCodeInputBox(inputBox: vscode.InputBox, verifier: string, scopeData: IScopeData): Promise<vscode.AuthenticationSession> {
inputBox.ignoreFocusOut = true;
inputBox.title = localize('pasteCodeTitle', 'Microsoft Authentication');
inputBox.prompt = localize('pasteCodePrompt', 'Provide the authorization code to complete the sign in flow.');
inputBox.placeholder = localize('pasteCodePlaceholder', 'Paste authorization code here...');
return new Promise((resolve: (value: vscode.AuthenticationSession) => void, reject) => {
inputBox.show();
inputBox.onDidAccept(async () => {
const code = inputBox.value;
if (code) {
inputBox.dispose();
const session = await this.exchangeCodeForSession(code, verifier, scopeData);
resolve(session);
}
});
inputBox.onDidHide(() => {
if (!inputBox.value) {
inputBox.dispose();
reject('Cancelled');
}
});
});
}
private async exchangeCodeForSession(code: string, codeVerifier: string, scopeData: IScopeData): Promise<vscode.AuthenticationSession> {
Logger.info(`Exchanging login code for token for scopes: ${scopeData.scopeStr}`);
let token: IToken | undefined;
try {
const postData = querystring.stringify({
grant_type: 'authorization_code',
@@ -698,11 +718,18 @@ export class AzureActiveDirectoryService {
const json = await this.fetchTokenResponse(endpoint, postData, scopeData);
Logger.info(`Exchanging login code for token (for scopes: ${scopeData.scopeStr}) succeeded!`);
return this.convertToTokenSync(json, scopeData);
token = this.convertToTokenSync(json, scopeData);
} catch (e) {
Logger.error(`Error exchanging code for token (for scopes ${scopeData.scopeStr}): ${e}`);
throw e;
}
if (token.expiresIn) {
this.setSessionTimeout(token.sessionId, token.refreshToken, scopeData, token.expiresIn * AzureActiveDirectoryService.REFRESH_TIMEOUT_MODIFIER);
}
await this.setToken(token, scopeData);
Logger.info(`Login successful for scopes: ${scopeData.scopeStr}`);
return await this.convertToSession(token);
}
private async fetchTokenResponse(endpoint: string, postData: string, scopeData: IScopeData): Promise<ITokenResponse> {

View File

@@ -21,7 +21,9 @@ export async function activate(context: vscode.ExtensionContext) {
try {
/* __GDPR__
"login" : {
"scopes": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
"owner": "TylerLeonhardt",
"comment": "Used to determine the usage of the Microsoft Auth Provider.",
"scopes": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight", "comment": "Used to determine what scope combinations are being requested." }
}
*/
telemetryReporter.sendTelemetryEvent('login', {
@@ -34,7 +36,7 @@ export async function activate(context: vscode.ExtensionContext) {
return session;
} catch (e) {
/* __GDPR__
"loginFailed" : { }
"loginFailed" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often users run into issues with the login flow." }
*/
telemetryReporter.sendTelemetryEvent('loginFailed');
@@ -44,7 +46,7 @@ export async function activate(context: vscode.ExtensionContext) {
removeSession: async (id: string) => {
try {
/* __GDPR__
"logout" : { }
"logout" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often users log out." }
*/
telemetryReporter.sendTelemetryEvent('logout');
@@ -54,7 +56,7 @@ export async function activate(context: vscode.ExtensionContext) {
}
} catch (e) {
/* __GDPR__
"logoutFailed" : { }
"logoutFailed" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often fail to log out." }
*/
telemetryReporter.sendTelemetryEvent('logoutFailed');
}

View File

@@ -2,7 +2,40 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { env, UIKind, Uri } from 'vscode';
export function toBase64UrlEncoding(base64string: string) {
return base64string.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_'); // Need to use base64url encoding
}
const LOCALHOST_ADDRESSES = ['localhost', '127.0.0.1', '0:0:0:0:0:0:0:1', '::1'];
function isLocalhost(uri: Uri): boolean {
if (!/^https?$/i.test(uri.scheme)) {
return false;
}
const host = uri.authority.split(':')[0];
return LOCALHOST_ADDRESSES.indexOf(host) >= 0;
}
export function isSupportedEnvironment(uri: Uri): boolean {
if (env.uiKind === UIKind.Desktop) {
return true;
}
// local development (localhost:* or 127.0.0.1:*)
if (isLocalhost(uri)) {
return true;
}
// At this point we should only ever see https
if (uri.scheme !== 'https') {
return false;
}
return (
// vscode.dev & insiders.vscode.dev
/(?:^|\.)vscode\.dev$/.test(uri.authority) ||
// github.dev & codespaces
/(?:^|\.)github\.dev$/.test(uri.authority) ||
// github.dev/codespaces local setup (github.localhost)
/(?:^|\.)github\.localhost$/.test(uri.authority)
);
}