From a6c47beb1bb07c1dfa389c44d9149b773c035ba3 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Wed, 27 May 2020 08:42:26 -0700 Subject: [PATCH] Remove unused code in github auth provider --- build/azure-pipelines/product-compile.yml | 23 --- .../build/generateconfig.js | 35 ---- .../src/common/clientRegistrar.ts | 102 ----------- .../github-authentication/src/github.ts | 22 +-- .../github-authentication/src/githubServer.ts | 162 +----------------- package.json | 3 +- 6 files changed, 10 insertions(+), 337 deletions(-) delete mode 100644 extensions/github-authentication/build/generateconfig.js delete mode 100644 extensions/github-authentication/src/common/clientRegistrar.ts diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index c3db41e80d5..db6524be03b 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -72,29 +72,6 @@ steps: vstsFeed: 'npm-vscode' condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) -- script: | - set -e - yarn generate-github-config - displayName: Generate GitHub config - env: - OSS_GITHUB_ID: "a5d3c261b032765a78de" - OSS_GITHUB_SECRET: $(oss-github-client-secret) - INSIDERS_GITHUB_ID: "31f02627809389d9f111" - INSIDERS_GITHUB_SECRET: $(insiders-github-client-secret) - STABLE_GITHUB_ID: "baa8a44b5e861d918709" - STABLE_GITHUB_SECRET: $(stable-github-client-secret) - EXPLORATION_GITHUB_ID: "94e8376d3a90429aeaea" - EXPLORATION_GITHUB_SECRET: $(exploration-github-client-secret) - VSO_GITHUB_ID: "3d4be8f37a0325b5817d" - VSO_GITHUB_SECRET: $(vso-github-client-secret) - VSO_PPE_GITHUB_ID: "eabf35024dc2e891a492" - VSO_PPE_GITHUB_SECRET: $(vso-ppe-github-client-secret) - VSO_DEV_GITHUB_ID: "84383ebd8a7c5f5efc5c" - VSO_DEV_GITHUB_SECRET: $(vso-dev-github-client-secret) - GITHUB_APP_ID: "Iv1.ae51e546bef24ff1" - GITHUB_APP_SECRET: $(github-app-client-secret) - condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true')) - - script: | set -e yarn postinstall diff --git a/extensions/github-authentication/build/generateconfig.js b/extensions/github-authentication/build/generateconfig.js deleted file mode 100644 index 2f311efc223..00000000000 --- a/extensions/github-authentication/build/generateconfig.js +++ /dev/null @@ -1,35 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -const fs = require('fs'); -const path = require('path'); - -const schemes = ['OSS', 'INSIDERS', 'STABLE', 'EXPLORATION', 'VSO', 'VSO_PPE', 'VSO_DEV']; - -function main() { - let content = {}; - - for (const scheme of schemes) { - const id = process.env[`${scheme}_GITHUB_ID`]; - const secret = process.env[`${scheme}_GITHUB_SECRET`]; - - if (id && secret) { - content[scheme] = { id, secret }; - } - } - - const githubAppId = process.env.GITHUB_APP_ID; - const githubAppSecret = process.env.GITHUB_APP_SECRET; - - if (githubAppId && githubAppSecret) { - content.GITHUB_APP = { id: githubAppId, secret: githubAppSecret } - } - - if (Object.keys(content).length > 0) { - fs.writeFileSync(path.join(__dirname, '../src/common/config.json'), JSON.stringify(content)); - } -} - -main(); diff --git a/extensions/github-authentication/src/common/clientRegistrar.ts b/extensions/github-authentication/src/common/clientRegistrar.ts deleted file mode 100644 index 4666ec6a6c0..00000000000 --- a/extensions/github-authentication/src/common/clientRegistrar.ts +++ /dev/null @@ -1,102 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Uri, env } from 'vscode'; -import * as fs from 'fs'; -import * as path from 'path'; - -export interface ClientDetails { - id?: string; - secret?: string; -} - -export interface ClientConfig { - OSS: ClientDetails; - INSIDERS: ClientDetails; - STABLE: ClientDetails; - EXPLORATION: ClientDetails; - - VSO: ClientDetails; - VSO_PPE: ClientDetails; - VSO_DEV: ClientDetails; - - GITHUB_APP: ClientDetails; -} - -export class Registrar { - private _config: ClientConfig; - - constructor() { - try { - const fileContents = fs.readFileSync(path.join(env.appRoot, 'extensions/github-authentication/src/common/config.json')).toString(); - this._config = JSON.parse(fileContents); - } catch (e) { - this._config = { - OSS: {}, - INSIDERS: {}, - STABLE: {}, - EXPLORATION: {}, - VSO: {}, - VSO_PPE: {}, - VSO_DEV: {}, - GITHUB_APP: {} - }; - } - } - - getGitHubAppDetails(): ClientDetails { - if (!this._config.GITHUB_APP.id || !this._config.GITHUB_APP.secret) { - throw new Error(`No GitHub App client configuration available`); - } - - return this._config.GITHUB_APP; - } - - getClientDetails(callbackUri: Uri): ClientDetails { - let details: ClientDetails | undefined; - switch (callbackUri.scheme) { - case 'code-oss': - details = this._config.OSS; - break; - - case 'vscode-insiders': - details = this._config.INSIDERS; - break; - - case 'vscode': - details = this._config.STABLE; - break; - - case 'vscode-exploration': - details = this._config.EXPLORATION; - break; - - case 'https': - switch (callbackUri.authority) { - case 'online.visualstudio.com': - details = this._config.VSO; - break; - case 'online-ppe.core.vsengsaas.visualstudio.com': - details = this._config.VSO_PPE; - break; - case 'online.dev.core.vsengsaas.visualstudio.com': - details = this._config.VSO_DEV; - break; - } - - default: - throw new Error(`Unrecognized callback ${callbackUri}`); - } - - if (!details.id || !details.secret) { - throw new Error(`No client configuration available for ${callbackUri}`); - } - - return details; - } -} - -const ClientRegistrar = new Registrar(); -export default ClientRegistrar; diff --git a/extensions/github-authentication/src/github.ts b/extensions/github-authentication/src/github.ts index 7ad1b238499..f4741e9eb54 100644 --- a/extensions/github-authentication/src/github.ts +++ b/extensions/github-authentication/src/github.ts @@ -44,8 +44,6 @@ export class GitHubAuthenticationProvider { // Ignore, network request failed } - // TODO revert Cannot validate tokens from auth server, no available clientId - // await this.validateSessions(); this.pollForChange(); } @@ -144,22 +142,12 @@ export class GitHubAuthenticationProvider { } public async login(scopes: string): Promise { - const token = scopes === 'vso' ? await this.loginAndInstallApp(scopes) : await this._githubServer.login(scopes); + const token = await this._githubServer.login(scopes); const session = await this.tokenToSession(token, scopes.split(' ')); await this.setToken(session); return session; } - public async loginAndInstallApp(scopes: string): Promise { - const token = await this._githubServer.login(scopes); - const hasUserInstallation = await this._githubServer.hasUserInstallation(token); - if (hasUserInstallation) { - return token; - } else { - return this._githubServer.installApp(); - } - } - public async manuallyProvideToken(): Promise { this._githubServer.manuallyProvideToken(); } @@ -184,14 +172,6 @@ export class GitHubAuthenticationProvider { const sessionIndex = this._sessions.findIndex(session => session.id === id); if (sessionIndex > -1) { this._sessions.splice(sessionIndex, 1); - // TODO revert - // Cannot revoke tokens from auth server, no clientId available - // const token = await session.getAccessToken(); - // try { - // await this._githubServer.revokeToken(token); - // } catch (_) { - // // ignore, should still remove from keychain - // } } await this.storeSessions(); diff --git a/extensions/github-authentication/src/githubServer.ts b/extensions/github-authentication/src/githubServer.ts index 5e9b2732d46..8499c43fab6 100644 --- a/extensions/github-authentication/src/githubServer.ts +++ b/extensions/github-authentication/src/githubServer.ts @@ -9,7 +9,6 @@ import * as vscode from 'vscode'; import * as uuid from 'uuid'; import { PromiseAdapter, promiseFromEvent } from './common/utils'; import Logger from './common/logger'; -import ClientRegistrar from './common/clientRegistrar'; const localize = nls.loadMessageBundle(); @@ -24,8 +23,8 @@ class UriEventHandler extends vscode.EventEmitter implements vscode. export const uriHandler = new UriEventHandler; -const exchangeCodeForToken: (state: string, host: string, getPath: (code: string) => string) => PromiseAdapter = - (state, host, getPath) => async (uri, resolve, reject) => { +const exchangeCodeForToken: (state: string) => PromiseAdapter = + (state) => async (uri, resolve, reject) => { Logger.info('Exchanging code for token...'); const query = parseQuery(uri); const code = query.code; @@ -36,8 +35,8 @@ const exchangeCodeForToken: (state: string, host: string, getPath: (code: string } const post = https.request({ - host: host, - path: getPath(code), + host: AUTH_RELAY_SERVER, + path: `/token?code=${code}&state=${state}`, method: 'POST', headers: { Accept: 'application/json' @@ -81,26 +80,13 @@ export class GitHubServer { const state = uuid(); const callbackUri = await vscode.env.asExternalUri(vscode.Uri.parse(`${vscode.env.uriScheme}://vscode.github-authentication/did-authenticate`)); - let uri = vscode.Uri.parse(`https://${AUTH_RELAY_SERVER}/authorize/?callbackUri=${encodeURIComponent(callbackUri.toString())}&scope=${scopes}&state=${state}&responseType=code`); - if (scopes === 'vso') { - const clientDetails = ClientRegistrar.getGitHubAppDetails(); - uri = vscode.Uri.parse(`https://github.com/login/oauth/authorize?redirect_uri=${encodeURIComponent(callbackUri.toString())}&scope=${scopes}&state=${state}&client_id=${clientDetails.id}`); - } + const uri = vscode.Uri.parse(`https://${AUTH_RELAY_SERVER}/authorize/?callbackUri=${encodeURIComponent(callbackUri.toString())}&scope=${scopes}&state=${state}&responseType=code`); vscode.env.openExternal(uri); - return promiseFromEvent(uriHandler.event, exchangeCodeForToken(state, - scopes === 'vso' ? 'github.com' : AUTH_RELAY_SERVER, - (code) => { - if (scopes === 'vso') { - const clientDetails = ClientRegistrar.getGitHubAppDetails(); - return `/login/oauth/access_token?client_id=${clientDetails.id}&client_secret=${clientDetails.secret}&state=${state}&code=${code}`; - } else { - return `/token?code=${code}&state=${state}`; - } - })).finally(() => { - this.updateStatusBarItem(false); - }); + return promiseFromEvent(uriHandler.event, exchangeCodeForToken(state)).finally(() => { + this.updateStatusBarItem(false); + }); } private updateStatusBarItem(isStart?: boolean) { @@ -130,51 +116,6 @@ export class GitHubServer { } } - public async hasUserInstallation(token: string): Promise { - return new Promise((resolve, reject) => { - Logger.info('Getting user installations...'); - const post = https.request({ - host: 'api.github.com', - path: `/user/installations`, - method: 'GET', - headers: { - Accept: 'application/vnd.github.machine-man-preview+json', - Authorization: `token ${token}`, - 'User-Agent': 'Visual-Studio-Code' - } - }, result => { - const buffer: Buffer[] = []; - result.on('data', (chunk: Buffer) => { - buffer.push(chunk); - }); - result.on('end', () => { - if (result.statusCode === 200) { - const json = JSON.parse(Buffer.concat(buffer).toString()); - Logger.info('Got installation info!'); - const hasInstallation = json.installations.some((installation: { app_slug: string }) => installation.app_slug === 'microsoft-visual-studio-code'); - resolve(hasInstallation); - } else { - reject(new Error(result.statusMessage)); - } - }); - }); - - post.end(); - post.on('error', err => { - reject(err); - }); - }); - } - - public async installApp(): Promise { - const clientDetails = ClientRegistrar.getGitHubAppDetails(); - const state = uuid(); - const uri = vscode.Uri.parse(`https://github.com/apps/microsoft-visual-studio-code/installations/new?state=${state}`); - - vscode.env.openExternal(uri); - return promiseFromEvent(uriHandler.event, exchangeCodeForToken(state, 'github.com', (code) => `/login/oauth/access_token?client_id=${clientDetails.id}&client_secret=${clientDetails.secret}&state=${state}&code=${code}`)); - } - public async getUserInfo(token: string): Promise<{ id: string, accountName: string }> { return new Promise((resolve, reject) => { Logger.info('Getting account info...'); @@ -210,91 +151,4 @@ export class GitHubServer { }); }); } - - public async validateToken(token: string): Promise { - return new Promise(async (resolve, reject) => { - const callbackUri = await vscode.env.asExternalUri(vscode.Uri.parse(`${vscode.env.uriScheme}://vscode.github-authentication/did-authenticate`)); - const clientDetails = ClientRegistrar.getClientDetails(callbackUri); - const detailsString = `${clientDetails.id}:${clientDetails.secret}`; - - const payload = JSON.stringify({ access_token: token }); - - Logger.info('Validating token...'); - const post = https.request({ - host: 'api.github.com', - path: `/applications/${clientDetails.id}/token`, - method: 'POST', - headers: { - Authorization: `Basic ${Buffer.from(detailsString).toString('base64')}`, - 'User-Agent': 'Visual-Studio-Code', - 'Content-Type': 'application/json', - 'Content-Length': Buffer.byteLength(payload) - } - }, result => { - const buffer: Buffer[] = []; - result.on('data', (chunk: Buffer) => { - buffer.push(chunk); - }); - result.on('end', () => { - if (result.statusCode === 200) { - Logger.info('Validated token!'); - resolve(); - } else { - Logger.info(`Validating token failed: ${result.statusMessage}`); - reject(new Error(result.statusMessage)); - } - }); - }); - - post.write(payload); - post.end(); - post.on('error', err => { - Logger.error(err.message); - reject(new Error(NETWORK_ERROR)); - }); - }); - } - - public async revokeToken(token: string): Promise { - return new Promise(async (resolve, reject) => { - const callbackUri = await vscode.env.asExternalUri(vscode.Uri.parse(`${vscode.env.uriScheme}://vscode.github-authentication/did-authenticate`)); - const clientDetails = ClientRegistrar.getClientDetails(callbackUri); - const detailsString = `${clientDetails.id}:${clientDetails.secret}`; - - const payload = JSON.stringify({ access_token: token }); - - Logger.info('Revoking token...'); - const post = https.request({ - host: 'api.github.com', - path: `/applications/${clientDetails.id}/token`, - method: 'DELETE', - headers: { - Authorization: `Basic ${Buffer.from(detailsString).toString('base64')}`, - 'User-Agent': 'Visual-Studio-Code', - 'Content-Type': 'application/json', - 'Content-Length': Buffer.byteLength(payload) - } - }, result => { - const buffer: Buffer[] = []; - result.on('data', (chunk: Buffer) => { - buffer.push(chunk); - }); - result.on('end', () => { - if (result.statusCode === 204) { - Logger.info('Revoked token!'); - resolve(); - } else { - Logger.info(`Revoking token failed: ${result.statusMessage}`); - reject(new Error(result.statusMessage)); - } - }); - }); - - post.write(payload); - post.end(); - post.on('error', err => { - reject(err); - }); - }); - } } diff --git a/package.json b/package.json index 932f4abcc31..76c8d067d86 100644 --- a/package.json +++ b/package.json @@ -33,8 +33,7 @@ "strict-function-types-watch": "tsc --watch -p src/tsconfig.json --noEmit --strictFunctionTypes", "update-distro": "node build/npm/update-distro.js", "web": "node scripts/code-web.js", - "eslint": "eslint -c .eslintrc.json --rulesdir ./build/lib/eslint --ext .ts --ext .js ./src/vs ./extensions", - "generate-github-config": "node extensions/github-authentication/build/generateconfig.js" + "eslint": "eslint -c .eslintrc.json --rulesdir ./build/lib/eslint --ext .ts --ext .js ./src/vs ./extensions" }, "dependencies": { "applicationinsights": "1.0.8",