Skip to content

Commit

Permalink
Use GitHub app for VSO, closes #92675
Browse files Browse the repository at this point in the history
  • Loading branch information
Rachel Macfarlane committed Mar 23, 2020
1 parent d21cadb commit d9d90a0
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 5 deletions.
17 changes: 17 additions & 0 deletions build/azure-pipelines/darwin/product-build-darwin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,23 @@ steps:
yarn postinstall
displayName: Run postinstall scripts
condition: and(succeeded(), eq(variables['CacheRestored'], 'true'))
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)

- script: |
set -e
Expand Down
17 changes: 17 additions & 0 deletions build/azure-pipelines/linux/product-build-linux-multiarch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,23 @@ steps:
yarn postinstall
displayName: Run postinstall scripts
condition: and(succeeded(), eq(variables['CacheRestored'], 'true'))
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)

- script: |
set -e
Expand Down
17 changes: 17 additions & 0 deletions build/azure-pipelines/linux/product-build-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,23 @@ steps:
yarn postinstall
displayName: Run postinstall scripts
condition: and(succeeded(), eq(variables['CacheRestored'], 'true'))
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)

- script: |
set -e
Expand Down
2 changes: 2 additions & 0 deletions build/azure-pipelines/product-compile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ steps:
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)

# Mixin must run before optimize, because the CSS loader will
# inline small SVGs
Expand Down
17 changes: 17 additions & 0 deletions build/azure-pipelines/win32/product-build-win32.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,23 @@ steps:
exec { yarn postinstall }
displayName: Run postinstall scripts
condition: and(succeeded(), eq(variables['CacheRestored'], 'true'))
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)

- powershell: |
. build/azure-pipelines/win32/exec.ps1
Expand Down
7 changes: 7 additions & 0 deletions extensions/github-authentication/build/postinstall.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ function main() {
}
}

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));
}
Expand Down
14 changes: 13 additions & 1 deletion extensions/github-authentication/src/common/clientRegistrar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ export interface ClientConfig {
VSO: ClientDetails;
VSO_PPE: ClientDetails;
VSO_DEV: ClientDetails;

GITHUB_APP: ClientDetails;
}

export class Registrar {
Expand All @@ -38,10 +40,20 @@ export class Registrar {
EXPLORATION: {},
VSO: {},
VSO_PPE: {},
VSO_DEV: {}
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) {
Expand Down
4 changes: 2 additions & 2 deletions extensions/github-authentication/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ export async function activate(context: vscode.ExtensionContext) {
displayName: 'GitHub',
onDidChangeSessions: onDidChangeSessions.event,
getSessions: () => Promise.resolve(loginService.sessions),
login: async (scopes: string[]) => {
login: async (scopeList: string[]) => {
try {
const session = await loginService.login(scopes.join(' '));
const session = await loginService.login(scopeList.join(' '));
Logger.info('Login success!');
return session;
} catch (e) {
Expand Down
12 changes: 11 additions & 1 deletion extensions/github-authentication/src/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,22 @@ export class GitHubAuthenticationProvider {
}

public async login(scopes: string): Promise<vscode.AuthenticationSession> {
const token = await this._githubServer.login(scopes);
const token = scopes === 'vso' ? await this.loginAndInstallApp(scopes) : 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<string> {
const token = await this._githubServer.login(scopes);
const hasUserInstallation = await this._githubServer.hasUserInstallation(token);
if (hasUserInstallation) {
return token;
} else {
return this._githubServer.installApp();
}
}

private async tokenToSession(token: string, scopes: string[]): Promise<vscode.AuthenticationSession> {
const userInfo = await this._githubServer.getUserInfo(token);
return {
Expand Down
47 changes: 46 additions & 1 deletion extensions/github-authentication/src/githubServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,58 @@ export class GitHubServer {
Logger.info('Logging in...');
const state = uuid();
const callbackUri = await vscode.env.asExternalUri(vscode.Uri.parse(`${vscode.env.uriScheme}://vscode.github-authentication/did-authenticate`));
const clientDetails = ClientRegistrar.getClientDetails(callbackUri);
const clientDetails = scopes === 'vso' ? ClientRegistrar.getGitHubAppDetails() : ClientRegistrar.getClientDetails(callbackUri);
const uri = vscode.Uri.parse(`https://github.com/login/oauth/authorize?redirect_uri=${encodeURIComponent(callbackUri.toString())}&scope=${scopes}&state=${state}&client_id=${clientDetails.id}`);

vscode.env.openExternal(uri);
return promiseFromEvent(uriHandler.event, exchangeCodeForToken(state, clientDetails));
}

public async hasUserInstallation(token: string): Promise<boolean> {
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<string> {
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, clientDetails));
}

public async getUserInfo(token: string): Promise<{ id: string, accountName: string }> {
return new Promise((resolve, reject) => {
Logger.info('Getting account info...');
Expand Down

0 comments on commit d9d90a0

Please sign in to comment.