From 5b5adbb2e1d29cd8e49b1d08a232b23092fa3b80 Mon Sep 17 00:00:00 2001 From: Karl Burtram Date: Thu, 9 Nov 2017 15:12:05 -0800 Subject: [PATCH] Fix some build errors using latest typescript version --- build/npm/postinstall.js | 1 - dataprotocol-node/jsonrpc/src/main.ts | 2 +- .../jsonrpc/src/messageWriter.ts | 2 +- extensions/account-provider-azure/.gitignore | 0 .../account-provider-azure/package.json | 34 -- .../account-provider-azure/package.nls.json | 3 - .../account-provider/azureAccountProvider.ts | 371 ------------------ .../azureAccountProviderService.ts | 87 ---- .../src/account-provider/interfaces.ts | 167 -------- .../media/microsoft_account.svg | 1 - .../media/work_school_account.svg | 1 - .../media/work_school_account_inverse.svg | 1 - .../src/account-provider/providerSettings.ts | 102 ----- .../src/account-provider/tokenCache.ts | 244 ------------ .../account-provider-azure/src/constants.ts | 12 - extensions/account-provider-azure/src/main.ts | 35 -- .../src/typings/ref.d.ts | 7 - .../account-provider-azure/tsconfig.json | 20 - 18 files changed, 2 insertions(+), 1088 deletions(-) delete mode 100644 extensions/account-provider-azure/.gitignore delete mode 100644 extensions/account-provider-azure/package.json delete mode 100644 extensions/account-provider-azure/package.nls.json delete mode 100644 extensions/account-provider-azure/src/account-provider/azureAccountProvider.ts delete mode 100644 extensions/account-provider-azure/src/account-provider/azureAccountProviderService.ts delete mode 100644 extensions/account-provider-azure/src/account-provider/interfaces.ts delete mode 100644 extensions/account-provider-azure/src/account-provider/media/microsoft_account.svg delete mode 100644 extensions/account-provider-azure/src/account-provider/media/work_school_account.svg delete mode 100644 extensions/account-provider-azure/src/account-provider/media/work_school_account_inverse.svg delete mode 100644 extensions/account-provider-azure/src/account-provider/providerSettings.ts delete mode 100644 extensions/account-provider-azure/src/account-provider/tokenCache.ts delete mode 100644 extensions/account-provider-azure/src/constants.ts delete mode 100644 extensions/account-provider-azure/src/main.ts delete mode 100644 extensions/account-provider-azure/src/typings/ref.d.ts delete mode 100644 extensions/account-provider-azure/tsconfig.json diff --git a/build/npm/postinstall.js b/build/npm/postinstall.js index 98e2340bd1..2929a7a8be 100644 --- a/build/npm/postinstall.js +++ b/build/npm/postinstall.js @@ -40,7 +40,6 @@ const extensions = [ 'extension-editing', 'markdown', 'merge-conflict', - 'account-provider-azure', 'insights-default' ]; diff --git a/dataprotocol-node/jsonrpc/src/main.ts b/dataprotocol-node/jsonrpc/src/main.ts index d27c0fc7fa..b61c6e299d 100644 --- a/dataprotocol-node/jsonrpc/src/main.ts +++ b/dataprotocol-node/jsonrpc/src/main.ts @@ -467,7 +467,7 @@ function createMessageConnection(messageReader: Mes eventHandlers[type.method] = handler; }, - sendRequest: (type: RequestType, params: P, token?: CancellationToken) => { + sendRequest: (type: RequestType, params: P, token?: CancellationToken): any => { throwIfClosedOrDisposed(); let id = sequenceNumber++; diff --git a/dataprotocol-node/jsonrpc/src/messageWriter.ts b/dataprotocol-node/jsonrpc/src/messageWriter.ts index bcf0d6b976..f4cbe30bb6 100644 --- a/dataprotocol-node/jsonrpc/src/messageWriter.ts +++ b/dataprotocol-node/jsonrpc/src/messageWriter.ts @@ -108,7 +108,7 @@ export class IPCMessageWriter extends AbstractMessageWriter implements MessageWr public write(msg: Message): void { try { - this.process.send(msg); + (this.process).send(msg); this.errorCount = 0; } catch (error) { this.errorCount++; diff --git a/extensions/account-provider-azure/.gitignore b/extensions/account-provider-azure/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/extensions/account-provider-azure/package.json b/extensions/account-provider-azure/package.json deleted file mode 100644 index ad3d0b61d4..0000000000 --- a/extensions/account-provider-azure/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "account-provider-azure", - "version": "0.0.1", - "publisher": "Microsoft", - "engines": { "vscode": "*" }, - "main": "./out/main", - "activationEvents": [ "*" ], - "scripts": { - "compile": "gulp compile-extension:account-provider-azure" - }, - "dependencies": { - "adal-node": "^0.1.16", - "decompress": "^4.0.0", - "extensions-modules": "file:../../extensions-modules", - "fs-extra-promise": "^0.3.1", - "opener": "1.4.2", - "request": "2.63.0", - "urijs": "^1.18.12", - "vscode-extension-telemetry": "^0.0.5", - "vscode-nls": "2.0.2" - }, - "devDependencies": { - "@types/node": "^8.0.24" - }, - "contributes": { - "commands": [ - { - "command": "extension.clearTokenCache", - "title": "%extension.clearTokenCache%", - "category": "Azure Accounts" - } - ] - } -} diff --git a/extensions/account-provider-azure/package.nls.json b/extensions/account-provider-azure/package.nls.json deleted file mode 100644 index de41c17e94..0000000000 --- a/extensions/account-provider-azure/package.nls.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extension.clearTokenCache": "Clear Azure Account Token Cache" -} \ No newline at end of file diff --git a/extensions/account-provider-azure/src/account-provider/azureAccountProvider.ts b/extensions/account-provider-azure/src/account-provider/azureAccountProvider.ts deleted file mode 100644 index ecbef36390..0000000000 --- a/extensions/account-provider-azure/src/account-provider/azureAccountProvider.ts +++ /dev/null @@ -1,371 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import * as fs from 'fs'; -import * as path from 'path'; -import * as adal from 'adal-node'; -import * as data from 'data'; -import * as request from 'request'; -import * as nls from 'vscode-nls'; -import { - Arguments, - AzureAccount, - AzureAccountProviderMetadata, - AzureAccountSecurityTokenCollection, - Tenant -} from './interfaces'; - -const localize = nls.loadMessageBundle(); - -export class AzureAccountProvider implements data.AccountProvider { - private static WorkSchoolAccountLogo: data.AccountContextualLogo = { - light: AzureAccountProvider.loadIcon('work_school_account.svg'), - dark: AzureAccountProvider.loadIcon('work_school_account_inverse.svg') - }; - private static MicrosoftAccountLogo: data.AccountContextualLogo = { - light: AzureAccountProvider.loadIcon('microsoft_account.svg'), - dark: AzureAccountProvider.loadIcon('microsoft_account.svg') - }; - - private _args: Arguments; - private _isInitialized: boolean; - private _tokenCache: adal.TokenCache; - - public metadata: AzureAccountProviderMetadata; - - constructor(metadata: AzureAccountProviderMetadata, tokenCache: adal.TokenCache) { - this.metadata = metadata; - this._args = { - host: metadata.settings.host, - clientId: metadata.settings.clientId - }; - this._isInitialized = false; - this._tokenCache = tokenCache; - } - - // PUBLIC METHODS ////////////////////////////////////////////////////// - public clear(accountKey: data.AccountKey): Thenable { - throw new Error('Not implemented'); - } - - public clearTokenCache(): Thenable { - return this._tokenCache.clear(); - } - - public getSecurityToken(account: AzureAccount): Thenable { - let self = this; - return this.doIfInitialized(() => self.getAccessTokens(account)); - } - - public initialize(restoredAccounts: data.Account[]): Thenable { - let self = this; - - return new Promise(resolve => { - // Rehydrate the accounts - restoredAccounts.forEach((account) => { - // Set the icon for the account - account.displayInfo.contextualLogo = account.properties.isMsAccount - ? AzureAccountProvider.MicrosoftAccountLogo - : AzureAccountProvider.WorkSchoolAccountLogo; - - // TODO: Set stale status based on whether we can authenticate or not - }); - - self._isInitialized = true; - - resolve(restoredAccounts); - }); - } - - public prompt(): Thenable { - let self = this; - return this.doIfInitialized(() => self.signIn()); - } - - public refresh(account: AzureAccount): Thenable { - let self = this; - return this.doIfInitialized(() => self.signIn(account.properties.isMsAccount, account.key.accountId)); - } - - // PRIVATE METHODS ///////////////////////////////////////////////////// - private static loadIcon(iconName: string) { - let filePath = path.join(__dirname, 'media', iconName); - try { - return 'image/svg+xml,' + fs.readFileSync(filePath); - } catch(e) { - return ''; - } - } - - private authenticate(tenantId: string, msa: boolean, userId: string, silent: boolean): Thenable { - let authorityUrl = `${this.metadata.settings.host}/${tenantId}`; - // TODO: Rewrite using urijs - let authorizeUrl = `${authorityUrl}/oauth2/authorize` - + `?client_id=${this.metadata.settings.clientId}` // Specify the client ID - + `&response_type=code` // Request the authorization code grant flow - + (userId ? (msa ? '&domain_hint=live.com' : '&msafed=0') : '') // Optimize prompt given existing MSA or org ID - + ((!userId && !silent) ? '&prompt=login' : '') // Require login if not silent - + (userId ? `&login_hint=${encodeURIComponent(userId)}` : '') // Show login hint if we have an existing user ID - + (this.metadata.settings.siteId ? `&site_id=${this.metadata.settings.siteId}` : '') // Site ID to use as brand on the prompt - + '&display=popup' // Causes a popup version of the UI to be shown - + `&resource=${encodeURIComponent(this.metadata.settings.signInResourceId)}` // Specify the resource for which an access token should be retrieved - + `&redirect_uri=${encodeURIComponent(this.metadata.settings.redirectUri)}`; // TODO: add locale parameter like in VSAccountProvider.TryAppendLocalParameter - - // Get the authorization code. If this is the initial authentication (the user is unknown), - // do not silently prompt. If this is a subsequent authentication for an additional tenant, - // the browser cookie cache will be used to authenticate without prompting, so run the - // browser silently. - return data.accounts.performOAuthAuthorization(authorizeUrl, silent) - .then((code: string) => { - return new Promise((resolve, reject) => { - let context = new adal.AuthenticationContext(authorityUrl, null, this._tokenCache); - context.acquireTokenWithAuthorizationCode( - code, - this.metadata.settings.redirectUri, - this.metadata.settings.signInResourceId, - this.metadata.settings.clientId, - null, - (error, response) => { - if (error) { - reject(error); - } else { - resolve( response); - } - } - ); - }); - }); - } - - private doIfInitialized(op: () => Thenable): Thenable { - return this._isInitialized - ? op() - : Promise.reject(localize('accountProviderNotInitialized', 'Account provider not initialized, cannot perform action')); - } - - private getAccessTokens(account: AzureAccount): Thenable { - let self = this; - - // TODO: Could we add some better typing here? - let accessTokenPromises: Thenable[] = []; - let tokenCollection: AzureAccountSecurityTokenCollection = {}; - for (let tenant of account.properties.tenants) { - let promise = new Promise((resolve, reject) => { - // TODO: use urijs to generate this URI - let authorityUrl = `${self.metadata.settings.host}/${tenant.id}`; - let context = new adal.AuthenticationContext(authorityUrl, null, self._tokenCache); - - // TODO: This is where we should mark the account as stale - context.acquireToken( - self.metadata.settings.armResource.id, - tenant.userId, - self.metadata.settings.clientId, - (error: adal.ErrorResponse, response: adal.SuccessResponse) => { - // Handle errors first - if (error) { - reject(error); - return; - } - - // Generate a token object and add it to the collection - tokenCollection[tenant.id] = { - expiresOn: response.expiresOn, - resource: response.resource, - token: response.accessToken, - tokenType: response.tokenType - }; - resolve(); - } - ); - }); - accessTokenPromises.push(promise); - } - - // Wait until all the tokens have been acquired then return the collection - return Promise.all(accessTokenPromises) - .then(() => tokenCollection); - } - - private getTenantDisplayName(msa: boolean, tenantId: string, userId: string): Thenable { - let self = this; - if(msa) { - return Promise.resolve(localize('microsoftAccountDisplayName', 'Microsoft Account')); - } - - return new Promise((resolve, reject) => { - // Get an access token to the AAD graph resource - // TODO: Use urijs to generate this URI - let authorityUrl = `${self.metadata.settings.host}/${tenantId}`; - let context = new adal.AuthenticationContext(authorityUrl, null, self._tokenCache); - context.acquireToken(self.metadata.settings.graphResource.id, userId, self.metadata.settings.clientId, (error, response) => { - if (error) { - reject(error); - return; - } - - request.get( - `${self.metadata.settings.graphResource.endpoint}/${tenantId}/tenantDetails?api-version=2013-04-05`, - { - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${(response).accessToken}` - }, - json: true - }, - (graphError, graphResponse, body: {error: any; value: any[];}) => { - if (graphError || body['odata.error']) { - reject(graphError || body['odata.error']); - } else if (body.value.length && body.value[0].displayName) { - resolve(body.value[0].displayName); - } else { - resolve(localize('azureWorkAccountDisplayName', 'Work or school account')); - } - } - ); - }); - }); - } - - private getTenants(msa: boolean, userId: string, tenantIds: string[], homeTenant: string): Thenable { - let self = this; - - // Lookup each tenant ID that was provided - let getTenantPromises: Thenable[] = []; - for (let tenantId of tenantIds) { - let promise = this.authenticate(tenantId, msa, userId, false) - .then((response) => self.getTenantDisplayName(msa, response.tenantId, response.userId)) - .then((displayName) => { - return { - displayName: displayName, - id: tenantId, - userId: userId - }; - }); - getTenantPromises.push(promise); - } - - return Promise.all(getTenantPromises) - .then((tenants) => { - // Resort the tenants to make sure that the 'home' tenant is the first in the list - let homeTenantIndex = tenants.findIndex((tenant) => tenant.id === homeTenant); - if (homeTenantIndex >= 0) { - let homeTenant = tenants.splice(homeTenantIndex, 1); - tenants.unshift(homeTenant[0]); - } - return tenants; - }); - } - - private getTenantIds(userId: string): Thenable { - return new Promise((resolve, reject) => { - // Get an access token to the ARM resource - // TODO: Build this URL with urijs - let authorityUrl = `${this.metadata.settings.host}/common`; - let context = new adal.AuthenticationContext(authorityUrl, null, this._tokenCache); - context.acquireToken(this.metadata.settings.armResource.id, userId, this.metadata.settings.clientId, (error, response) => { - if (error) { - reject(error); - return; - } - - if (!!this.metadata.settings.adTenants && this.metadata.settings.adTenants.length > 0) { - resolve(this.metadata.settings.adTenants); - } else { - request.get( - `${this.metadata.settings.armResource.endpoint}/tenants?api-version=2015-01-01`, - { - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${(response).accessToken}` - }, - json: true - }, - (armError, armResponse, body: {error: any; value: any[];}) => { - if (armError || body.error) { - reject(armError || body.error); - } else { - resolve(body.value.map(item => item.tenantId)); - } - } - ); - } - }); - }); - } - - private signIn(msa?: boolean, userId?: string): Thenable { - let self = this; - - // Initial authentication is via the common/discovery tenant - return this.authenticate('common', msa, userId, false) - .then((response: adal.TokenResponse) => { - let identityProvider = response.identityProvider; - if (identityProvider) { - identityProvider = identityProvider.toLowerCase(); - } - - // Determine if this is a microsoft account - msa = identityProvider && ( - identityProvider.indexOf('live.com') !== -1 || - identityProvider.indexOf('live-int.com') !== -1 || - identityProvider.indexOf('f8cdef31-a31e-4b4a-93e4-5f571e91255a') !== -1 || - identityProvider.indexOf('ea8a4392-515e-481f-879e-6571ff2a8a36') !== -1); - - // Get the user information - userId = response.userId; - let displayName = (response.givenName && response.familyName) - ? `${response.givenName} ${response.familyName}` - : userId; - - // Get all the additional tenants - return this.getTenantIds(userId) - .then(tenantIds => self.getTenants(msa, userId, tenantIds, response.tenantId)) - .then(tenants => { - return { - key: { - providerId: self.metadata.id, - accountId: userId - }, - name: userId, - displayInfo: { - contextualLogo: msa - ? AzureAccountProvider.MicrosoftAccountLogo - : AzureAccountProvider.WorkSchoolAccountLogo, - contextualDisplayName: tenants[0].displayName, - displayName: displayName - }, - properties: { - isMsAccount: msa, - tenants: tenants - }, - isStale: false - }; - }); - }); - } -} - -// ADAL MONKEY PATCH /////////////////////////////////////////////////////// -// Monkey patch the ADAL TokenRequest class to fix the fact that when you request a token from an -// authorization code, it doesn't update the cache -import * as TokenRequest from 'adal-node/lib/token-request'; -let getTokenWithAuthorizationCodeOriginal = TokenRequest.prototype.getTokenWithAuthorizationCode; -TokenRequest.prototype.getTokenWithAuthorizationCode = function ( - authorizationCode: string, - clientSecret: string, - callback: adal.AcquireTokenCallback -) { - this._cacheDriver = this._createCacheDriver(); - getTokenWithAuthorizationCodeOriginal.call(this, authorizationCode, clientSecret, (error: Error, response: adal.ErrorResponse|adal.TokenResponse) => { - if (error) { - callback(error, response); - } else { - this._userId = ( response).userId; - this._cacheDriver.add(response, () => callback(null, response)); - } - }); -}; \ No newline at end of file diff --git a/extensions/account-provider-azure/src/account-provider/azureAccountProviderService.ts b/extensions/account-provider-azure/src/account-provider/azureAccountProviderService.ts deleted file mode 100644 index 8526f5ee6d..0000000000 --- a/extensions/account-provider-azure/src/account-provider/azureAccountProviderService.ts +++ /dev/null @@ -1,87 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import * as constants from '../constants'; -import * as data from 'data'; -import * as events from 'events'; -import * as nls from 'vscode-nls'; -import * as path from 'path'; -import * as vscode from 'vscode'; -import CredentialServiceTokenCache from './tokenCache'; -import providerSettings from './providerSettings'; -import { AzureAccountProvider } from './azureAccountProvider'; -import { AzureAccountProviderMetadata } from './interfaces'; - -let localize = nls.loadMessageBundle(); - -export class AzureAccountProviderService implements vscode.Disposable { - // CONSTANTS /////////////////////////////////////////////////////////////// - private static CommandClearTokenCache = 'extension.clearTokenCache'; - private static CredentialNamespace = 'azureAccountProviderCredentials'; - - // MEMBER VARIABLES //////////////////////////////////////////////////////// - private _accountProviders: { [accountProviderId: string]: AzureAccountProvider }; - private _event: events.EventEmitter; - - constructor(private _context: vscode.ExtensionContext, private _userStoragePath: string) { - this._accountProviders = {}; - this._event = new events.EventEmitter(); - } - - // PUBLIC METHODS ////////////////////////////////////////////////////// - public activate(): Thenable { - let self = this; - - // Register commands - this._context.subscriptions.push(vscode.commands.registerCommand( - AzureAccountProviderService.CommandClearTokenCache, - () => { self._event.emit(AzureAccountProviderService.CommandClearTokenCache); } - )); - this._event.on(AzureAccountProviderService.CommandClearTokenCache, () => { self.onClearTokenCache(); }); - - // Create the token caches - // 1) Get a credential provider - // 2) Iterate over the enabled providers - // 2a) Create a token cache for provider - // 2b) Create the provider from the provider's settings - // 2c) Register the provider with the account service - return data.credentials.getProvider(AzureAccountProviderService.CredentialNamespace) - .then(credProvider => { - providerSettings.forEach(provider => { - let tokenCacheKey = `azureTokenCache-${provider.metadata.id}`; - let tokenCachePath = path.join(self._userStoragePath, tokenCacheKey); - let tokenCache = new CredentialServiceTokenCache(credProvider, tokenCacheKey, tokenCachePath); - let accountProvider = new AzureAccountProvider(provider.metadata, tokenCache); - self._accountProviders[provider.metadata.id] = accountProvider; - data.accounts.registerAccountProvider(provider.metadata, accountProvider); - }); - }) - .then(() => { return true; }); - } - - public dispose() { } - - // PRIVATE HELPERS ///////////////////////////////////////////////////// - private onClearTokenCache(): Thenable { - let self = this; - - let promises: Thenable[] = providerSettings.map(provider => { - return self._accountProviders[provider.metadata.id].clearTokenCache(); - }); - - return Promise.all(promises) - .then( - () => { - let message = localize('clearTokenCacheSuccess', 'Token cache successfully cleared'); - vscode.window.showInformationMessage(`${constants.extensionName}: ${message}`); - }, - err => { - let message = localize('clearTokenCacheFailure', 'Failed to clear token cache'); - vscode.window.showErrorMessage(`${constants.extensionName}: ${message}: ${err}`); - }); - } -} diff --git a/extensions/account-provider-azure/src/account-provider/interfaces.ts b/extensions/account-provider-azure/src/account-provider/interfaces.ts deleted file mode 100644 index 34433a4022..0000000000 --- a/extensions/account-provider-azure/src/account-provider/interfaces.ts +++ /dev/null @@ -1,167 +0,0 @@ -'use strict'; - -import * as data from 'data'; - -/** - * Represents a tenant (an Azure Active Directory instance) to which a user has access - */ -export interface Tenant { - /** - * Globally unique identifier of the tenant - */ - id: string; - - /** - * Display name of the tenant - */ - displayName: string; - - /** - * Identifier of the user in the tenant - */ - userId: string; -} - -/** - * Represents a resource exposed by an Azure Active Directory - */ -export interface Resource { - /** - * Identifier of the resource - */ - id: string; - - /** - * Endpoint url used to access the resource - */ - endpoint: string; -} - -/** - * Represents the arguments that identify an instantiation of the AAD account provider - */ -export interface Arguments { - /** - * Host of the authority - */ - host: string; - - /** - * Identifier of the client application - */ - clientId: string; -} - -/** - * Represents settings for an AAD account provider - */ -export interface Settings { - /** - * Host of the authority - */ - host?: string; - - /** - * Identifier of the client application - */ - clientId?: string; - - /** - * Identifier of the resource to request when signing in - */ - signInResourceId?: string; - - /** - * Information that describes the AAD graph resource - */ - graphResource?: Resource; - - /** - * Information that describes the Azure resource management resource - */ - armResource?: Resource; - - /** - * A list of tenant IDs to authenticate against. If defined, then these IDs will be used - * instead of querying the tenants endpoint of the armResource - */ - adTenants?: string[]; - - // AuthorizationCodeGrantFlowSettings ////////////////////////////////// - - /** - * An optional site ID that brands the interactive aspect of sign in - */ - siteId?: string; - - /** - * Redirect URI that is used to signify the end of the interactive aspect of sign it - */ - redirectUri?: string; -} - -/** - * - */ -export interface AzureAccountProviderMetadata extends data.AccountProviderMetadata { - /** - * Azure specific account provider settings. - */ - settings: Settings; -} - -/** - * Properties specific to an Azure account - */ -export interface AzureAccountProperties { - /** - * Whether or not the account is a Microsoft account - */ - isMsAccount: boolean; - - /** - * A list of tenants (aka directories) that the account belongs to - */ - tenants: Tenant[]; -} - -/** - * Override of the Account type to enforce properties that are AzureAccountProperties - */ -export interface AzureAccount extends data.Account { - /** - * AzureAccountProperties specifically used for Azure accounts - */ - properties: AzureAccountProperties; -} - -/** - * Token returned from a request for an access token - */ -export interface AzureAccountSecurityToken { - /** - * Access token, itself - */ - token: string; - - /** - * Date that the token expires on - */ - expiresOn: Date; - - /** - * Name of the resource the token is good for (ie, management.core.windows.net) - */ - resource: string; - - /** - * Type of the token (pretty much always 'Bearer') - */ - tokenType: string; -} - -/** - * Azure account security token maps a tenant ID to the information returned from a request to get - * an access token. The list of tenants correspond to the tenants in the account properties. - */ -export type AzureAccountSecurityTokenCollection = {[tenantId: string]: AzureAccountSecurityToken}; diff --git a/extensions/account-provider-azure/src/account-provider/media/microsoft_account.svg b/extensions/account-provider-azure/src/account-provider/media/microsoft_account.svg deleted file mode 100644 index cf6cfdbcdc..0000000000 --- a/extensions/account-provider-azure/src/account-provider/media/microsoft_account.svg +++ /dev/null @@ -1 +0,0 @@ -microsoft_account_16x16 \ No newline at end of file diff --git a/extensions/account-provider-azure/src/account-provider/media/work_school_account.svg b/extensions/account-provider-azure/src/account-provider/media/work_school_account.svg deleted file mode 100644 index 2e1f6e72b2..0000000000 --- a/extensions/account-provider-azure/src/account-provider/media/work_school_account.svg +++ /dev/null @@ -1 +0,0 @@ -other_account_16x16 \ No newline at end of file diff --git a/extensions/account-provider-azure/src/account-provider/media/work_school_account_inverse.svg b/extensions/account-provider-azure/src/account-provider/media/work_school_account_inverse.svg deleted file mode 100644 index a31370b089..0000000000 --- a/extensions/account-provider-azure/src/account-provider/media/work_school_account_inverse.svg +++ /dev/null @@ -1 +0,0 @@ -other_account_inverse_16x16 \ No newline at end of file diff --git a/extensions/account-provider-azure/src/account-provider/providerSettings.ts b/extensions/account-provider-azure/src/account-provider/providerSettings.ts deleted file mode 100644 index ef16e7594c..0000000000 --- a/extensions/account-provider-azure/src/account-provider/providerSettings.ts +++ /dev/null @@ -1,102 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import * as data from 'data'; -import * as nls from 'vscode-nls'; -import { Settings } from './interfaces'; - -const localize = nls.loadMessageBundle(); - -const publicAzureSettings = { - configKey: 'accounts.azure.enablePublicCloud', - metadata: { - displayName: localize('publicCloudDisplayName', 'Azure'), - id: 'azurePublicCloud', - settings: { - host: 'https://login.microsoftonline.com', - clientId: 'TBD', - signInResourceId: 'https://management.core.windows.net/', - graphResource: { - id: 'https://graph.windows.net/', - endpoint: 'https://graph.windows.net' - }, - armResource: { - id: 'https://management.core.windows.net/', - endpoint: 'https://management.azure.com' - }, - redirectUri: 'http://localhost/redirect' - } - } -}; - -const usGovAzureSettings = { - configKey: 'accounts.azure.enableUsGovCloud', - metadata: { - displayName: localize('usGovCloudDisplayName', 'Azure (US Government)'), - id: 'usGovAzureCloud', - settings: { - host: 'https://login.microsoftonline.com/', - clientId: 'TBD', - signInResourceId: 'https://management.core.usgovcloudapi.net/', - graphResource: { - id: 'https://graph.usgovcloudapi.net/', - endpoint: 'https://graph.usgovcloudapi.net' - }, - armResource: { - id: 'https://management.core.usgovcloudapi.net/', - endpoint: 'https://management.usgovcloudapi.net' - }, - redirectUri: 'http://localhost/redirect' - } - } -}; - -const chinaAzureSettings = { - configKey: 'accounts.azure.enableChinaCloud', - metadata: { - displayName: localize('chinaCloudDisplayName', 'Azure (China)'), - id: 'chinaAzureCloud', - settings: { - host: 'https://login.chinacloudapi.cn/', - clientId: 'TBD', - signInResourceId: 'https://management.core.chinacloudapi.cn/', - graphResource: { - id: 'https://graph.chinacloudapi.cn/', - endpoint: 'https://graph.chinacloudapi.cn' - }, - armResource: { - id: 'https://management.core.chinacloudapi.cn/', - endpoint: 'https://managemement.chinacloudapi.net' - }, - redirectUri: 'http://localhost/redirect' - } - } -}; - -const germanyAzureSettings = { - configKey: 'accounts.azure.enableGermanyCloud', - metadata: { - displayName: localize('germanyCloud', 'Azure (Germany)'), - id: 'germanyAzureCloud', - settings: { - host: 'https://login.microsoftazure.de/', - clientId: 'TBD', - signInResourceId: 'https://management.core.cloudapi.de/', - graphResource: { - id: 'https://graph.cloudapi.de/', - endpoint: 'https://graph.cloudapi.de' - }, - armResource: { - id: 'https://management.core.cloudapi.de/', - endpoint: 'https://management.microsoftazure.de' - }, - redirectUri: 'http://localhost/redirect' - } - } -}; - -export default [publicAzureSettings/*, chinaAzureSettings, germanyAzureSettings, usGovAzureSettings*/]; diff --git a/extensions/account-provider-azure/src/account-provider/tokenCache.ts b/extensions/account-provider-azure/src/account-provider/tokenCache.ts deleted file mode 100644 index 4dee000ee2..0000000000 --- a/extensions/account-provider-azure/src/account-provider/tokenCache.ts +++ /dev/null @@ -1,244 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import * as adal from 'adal-node'; -import * as data from 'data'; -import * as crypto from 'crypto'; -import * as fs from 'fs'; - -export default class TokenCache implements adal.TokenCache { - private static CipherAlgorithm = 'aes256'; - private static CipherAlgorithmIvLength = 16; - private static CipherKeyLength = 32; - private static FsOptions = { encoding: 'ascii' }; - - private _activeOperation: Thenable; - - constructor( - private _credentialProvider: data.CredentialProvider, - private _credentialServiceKey: string, - private _cacheSerializationPath: string - ) { - } - - // PUBLIC METHODS ////////////////////////////////////////////////////// - public add(entries: adal.TokenCacheEntry[], callback: (error?: Error) => void): void { - let self = this; - - this.doOperation(() => { - return self.readCache() - .then(cache => self.addToCache(cache, entries)) - .then(updatedCache => self.writeCache(updatedCache)) - .then( - () => callback(null), - (err) => callback(err) - ); - }); - } - - public clear(): Thenable { - let self = this; - - // 1) Delete encrypted serialization file - // If we got an 'ENOENT' response, the file doesn't exist, which is fine - // 3) Delete the encryption key - return new Promise((resolve, reject) => { - fs.unlink(self._cacheSerializationPath, err => { - if (err && err.code !== 'ENOENT') { - reject(err); - } else { - resolve(); - } - }); - }) - .then(() => { return self._credentialProvider.deleteCredential(self._credentialServiceKey); }) - .then(() => {}); - } - - public find(query: adal.TokenCacheQuery, callback: (error: Error, results: adal.TokenCacheEntry[]) => void): void { - let self = this; - - this.doOperation(() => { - return self.readCache() - .then(cache => { - return cache.filter( - entry => TokenCache.findByPartial(entry, query) - ); - }) - .then( - results => callback(null, results), - (err) => callback(err, null) - ); - }); - } - - public remove(entries: adal.TokenCacheEntry[], callback: (error?: Error) => void): void { - let self = this; - - this.doOperation(() => { - return this.readCache() - .then(cache => self.removeFromCache(cache, entries)) - .then(updatedCache => self.writeCache(updatedCache)) - .then( - () => callback(null), - (err) => callback(err) - ); - }); - } - - // PRIVATE METHODS ///////////////////////////////////////////////////// - private static findByKeyHelper(entry1: adal.TokenCacheEntry, entry2: adal.TokenCacheEntry): boolean { - return entry1._authority === entry2._authority - && entry1._clientId === entry2._clientId - && entry1.userId === entry2.userId - && entry1.resource === entry2.resource; - } - - private static findByPartial(entry: adal.TokenCacheEntry, query: object): boolean { - for (let key in query) { - if (entry[key] === undefined || entry[key] !== query[key]) { - return false; - } - } - return true; - } - - private doOperation(op: () => Thenable): void { - // Initialize the active operation to an empty promise if necessary - let activeOperation = this._activeOperation || Promise.resolve(null); - - // Chain the operation to perform to the end of the existing promise - activeOperation = activeOperation.then(op); - - // Add a catch at the end to make sure we can continue after any errors - activeOperation = activeOperation.then(null, err => { - console.error(`Failed to perform token cache operation: ${err}`); - }); - - // Point the current active operation to this one - this._activeOperation = activeOperation; - } - - private addToCache(cache: adal.TokenCacheEntry[], entries: adal.TokenCacheEntry[]): adal.TokenCacheEntry[] { - // First remove entries from the db that are being updated - cache = this.removeFromCache(cache, entries); - - // Then add the new entries to the cache - entries.forEach((entry: adal.TokenCacheEntry) => { - cache.push(entry); - }); - - return cache; - } - - private getOrCreateEncryptionParams(): Thenable { - let self = this; - - return this._credentialProvider.readCredential(this._credentialServiceKey) - .then(credential => { - if (credential.password) { - // We already have encryption params, deserialize them - let splitValues = credential.password.split('|'); - if (splitValues.length === 2 && splitValues[0] && splitValues[1]) { - try { - return { - key: new Buffer(splitValues[0], 'hex'), - initializationVector: new Buffer(splitValues[1], 'hex') - }; - } catch(e) { - // Swallow the error and fall through to generate new params - console.warn('Failed to deserialize encryption params, new ones will be generated.'); - } - } - } - - // We haven't stored encryption values, so generate them - let encryptKey = crypto.randomBytes(TokenCache.CipherKeyLength); - let initializationVector = crypto.randomBytes(TokenCache.CipherAlgorithmIvLength); - - // Serialize the values - let serializedValues = `${encryptKey.toString('hex')}|${initializationVector.toString('hex')}`; - return self._credentialProvider.saveCredential(self._credentialServiceKey, serializedValues) - .then(() => { - return { - key: encryptKey, - initializationVector: initializationVector - }; - }); - }); - } - - private readCache(): Thenable { - let self = this; - - // NOTE: File system operations are performed synchronously to avoid annoying nested callbacks - // 1) Get the encryption key - // 2) Read the encrypted token cache file - // 3) Decrypt the file contents - // 4) Deserialize and return - return this.getOrCreateEncryptionParams() - .then(encryptionParams => { - try { - let cacheCipher = fs.readFileSync(self._cacheSerializationPath, TokenCache.FsOptions); - - let decipher = crypto.createDecipheriv(TokenCache.CipherAlgorithm, encryptionParams.key, encryptionParams.initializationVector); - let cacheJson = decipher.update(cacheCipher, 'hex', 'binary'); - cacheJson += decipher.final('binary'); - - return JSON.parse(cacheJson); - } catch(e) { - throw e; - } - }) - .then(null, err => { - // If reading the token cache fails, we'll just assume the tokens are garbage - console.warn(`Failed to read token cache: ${err}`); - return []; - }); - } - - private removeFromCache(cache: adal.TokenCacheEntry[], entries: adal.TokenCacheEntry[]): adal.TokenCacheEntry[] { - entries.forEach((entry: adal.TokenCacheEntry) => { - // Check to see if the entry exists - let match = cache.findIndex(entry2 => TokenCache.findByKeyHelper(entry, entry2)); - if (match >= 0) { - // Entry exists, remove it from cache - cache.splice(match, 1); - } - }); - - return cache; - } - - private writeCache(cache: adal.TokenCacheEntry[]): Thenable { - let self = this; - // NOTE: File system operations are being done synchronously to avoid annoying callback nesting - // 1) Get (or generate) the encryption key - // 2) Stringify the token cache entries - // 4) Encrypt the JSON - // 3) Write to the file - return this.getOrCreateEncryptionParams() - .then(encryptionParams => { - try { - let cacheJson = JSON.stringify(cache); - - let cipher = crypto.createCipheriv(TokenCache.CipherAlgorithm, encryptionParams.key, encryptionParams.initializationVector); - let cacheCipher = cipher.update(cacheJson, 'binary', 'hex'); - cacheCipher += cipher.final('hex'); - - fs.writeFileSync(self._cacheSerializationPath, cacheCipher, TokenCache.FsOptions); - } catch (e) { - throw e; - } - }); - } -} - -interface EncryptionParams { - key: Buffer; - initializationVector: Buffer; -} diff --git a/extensions/account-provider-azure/src/constants.ts b/extensions/account-provider-azure/src/constants.ts deleted file mode 100644 index 2cf82dd183..0000000000 --- a/extensions/account-provider-azure/src/constants.ts +++ /dev/null @@ -1,12 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import * as nls from 'vscode-nls'; - -let localize = nls.loadMessageBundle(); - -export const extensionName = localize('extensionName', 'Azure Accounts'); diff --git a/extensions/account-provider-azure/src/main.ts b/extensions/account-provider-azure/src/main.ts deleted file mode 100644 index 87197555bc..0000000000 --- a/extensions/account-provider-azure/src/main.ts +++ /dev/null @@ -1,35 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -'use strict'; - -import * as fs from 'fs'; -import * as path from 'path'; -import * as vscode from 'vscode'; -import { Utils } from 'extensions-modules'; - -import * as constants from './constants'; -import { AzureAccountProviderService } from './account-provider/azureAccountProviderService'; - -// EXTENSION ACTIVATION //////////////////////////////////////////////////// -export function activate(context: vscode.ExtensionContext): void { - // Create the folder for storing the token caches - let storagePath = path.join(Utils.getDefaultLogLocation(), constants.extensionName); - try { - if (!fs.existsSync(storagePath)) { - fs.mkdirSync(storagePath); - console.log('Initialized Azure account extension storage.'); - } - } catch(e) { - console.error(`Initialization of Azure account extension storage failed: ${e}`); - console.error('Azure accounts will not be available'); - return; - } - - // Create the provider service and activate - const accountProviderService = new AzureAccountProviderService(context, storagePath); - context.subscriptions.push(accountProviderService); - accountProviderService.activate(); -} diff --git a/extensions/account-provider-azure/src/typings/ref.d.ts b/extensions/account-provider-azure/src/typings/ref.d.ts deleted file mode 100644 index e21045c0c8..0000000000 --- a/extensions/account-provider-azure/src/typings/ref.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/// -/// diff --git a/extensions/account-provider-azure/tsconfig.json b/extensions/account-provider-azure/tsconfig.json deleted file mode 100644 index be1e5ee9ce..0000000000 --- a/extensions/account-provider-azure/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compileOnSave": true, - "compilerOptions": { - "module": "commonjs", - "target": "es6", - "outDir": "./out", - "lib": [ - "es6", "es2015.promise" - ], - "sourceMap": true, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "moduleResolution": "node", - "declaration": true, - "types": ["node"] - }, - "exclude": [ - "./node_modules" - ] -}