Skip to content

Commit 41f177e

Browse files
author
Rachel Macfarlane
committed
Extract auth urls to product service
1 parent 4e2cefd commit 41f177e

2 files changed

Lines changed: 38 additions & 15 deletions

File tree

src/vs/platform/auth/electron-browser/authTokenService.ts

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,13 @@ import { URI } from 'vs/base/common/uri';
1313
import { generateUuid } from 'vs/base/common/uuid';
1414
import { shell } from 'electron';
1515
import { createServer, startServer } from 'vs/platform/auth/electron-browser/authServer';
16+
import { IProductService } from 'vs/platform/product/common/productService';
1617

1718
const SERVICE_NAME = 'VS Code';
1819
const ACCOUNT = 'MyAccount';
1920

20-
const redirectUrlAAD = 'https://vscode-redirect.azurewebsites.net/';
21-
const activeDirectoryEndpointUrl = 'https://login.microsoftonline.com/';
2221
const activeDirectoryResourceId = 'https://management.core.windows.net/';
2322

24-
const clientId = 'aebc6443-996d-45c2-90f0-388ff96faa56';
25-
const tenantId = 'common';
26-
2723
function toQuery(obj: any): string {
2824
return Object.keys(obj).map(key => `${key}=${obj[key]}`).join('&');
2925
}
@@ -54,8 +50,13 @@ export class AuthTokenService extends Disposable implements IAuthTokenService {
5450

5551
constructor(
5652
@ICredentialsService private readonly credentialsService: ICredentialsService,
53+
@IProductService private readonly productService: IProductService
5754
) {
5855
super();
56+
if (!this.productService.auth) {
57+
return;
58+
}
59+
5960
this.credentialsService.getPassword(SERVICE_NAME, ACCOUNT).then(storedRefreshToken => {
6061
if (storedRefreshToken) {
6162
this.refresh(storedRefreshToken);
@@ -66,6 +67,10 @@ export class AuthTokenService extends Disposable implements IAuthTokenService {
6667
}
6768

6869
public async login(): Promise<void> {
70+
if (!this.productService.auth) {
71+
throw new Error('Authentication is not configured.');
72+
}
73+
6974
this.setStatus(AuthTokenStatus.SigningIn);
7075

7176
const nonce = generateUuid();
@@ -88,14 +93,13 @@ export class AuthTokenService extends Disposable implements IAuthTokenService {
8893
const updatedPort = updatedPortStr ? parseInt(updatedPortStr, 10) : port;
8994

9095
const state = `${updatedPort},${encodeURIComponent(nonce)}`;
91-
const signInUrl = `${activeDirectoryEndpointUrl}${tenantId}/oauth2/authorize`;
9296

9397
const codeVerifier = toBase64UrlEncoding(crypto.randomBytes(32).toString('base64'));
9498
const codeChallenge = toBase64UrlEncoding(crypto.createHash('sha256').update(codeVerifier).digest('base64'));
9599

96-
let uri = URI.parse(signInUrl);
100+
let uri = URI.parse(this.productService.auth.loginUrl);
97101
uri = uri.with({
98-
query: `response_type=code&client_id=${encodeURIComponent(clientId)}&redirect_uri=${redirectUrlAAD}&state=${encodeURIComponent(state)}&resource=${activeDirectoryResourceId}&prompt=select_account&code_challenge_method=S256&code_challenge=${codeChallenge}`
102+
query: `response_type=code&client_id=${encodeURIComponent(this.productService.auth.clientId)}&redirect_uri=${this.productService.auth.redirectUrl}&state=${encodeURIComponent(state)}&resource=${activeDirectoryResourceId}&prompt=select_account&code_challenge_method=S256&code_challenge=${codeChallenge}`
99103
});
100104

101105
await redirectReq.res.writeHead(302, { Location: uri.toString(true) });
@@ -145,17 +149,23 @@ export class AuthTokenService extends Disposable implements IAuthTokenService {
145149
private exchangeCodeForToken(code: string, codeVerifier: string): Promise<IToken> {
146150
return new Promise((resolve: (value: IToken) => void, reject) => {
147151
try {
152+
if (!this.productService.auth) {
153+
throw new Error('Authentication is not configured.');
154+
}
155+
148156
const postData = toQuery({
149157
grant_type: 'authorization_code',
150158
code: code,
151-
client_id: clientId,
159+
client_id: this.productService.auth?.clientId,
152160
code_verifier: codeVerifier,
153-
redirect_uri: redirectUrlAAD
161+
redirect_uri: this.productService.auth?.redirectUrl
154162
});
155163

164+
const tokenUrl = URI.parse(this.productService.auth.tokenUrl);
165+
156166
const post = https.request({
157-
host: 'login.microsoftonline.com',
158-
path: `/${tenantId}/oauth2/token`,
167+
host: tokenUrl.authority,
168+
path: tokenUrl.path,
159169
method: 'POST',
160170
headers: {
161171
'Content-Type': 'application/x-www-form-urlencoded',
@@ -196,17 +206,23 @@ export class AuthTokenService extends Disposable implements IAuthTokenService {
196206

197207
private async refresh(refreshToken: string): Promise<void> {
198208
return new Promise((resolve, reject) => {
209+
if (!this.productService.auth) {
210+
throw new Error('Authentication is not configured.');
211+
}
212+
199213
this.setStatus(AuthTokenStatus.RefreshingToken);
200214
const postData = toQuery({
201215
refresh_token: refreshToken,
202-
client_id: clientId,
216+
client_id: this.productService.auth?.clientId,
203217
grant_type: 'refresh_token',
204218
resource: activeDirectoryResourceId
205219
});
206220

221+
const tokenUrl = URI.parse(this.productService.auth.tokenUrl);
222+
207223
const post = https.request({
208-
host: 'login.microsoftonline.com',
209-
path: `/${tenantId}/oauth2/token`,
224+
host: tokenUrl.authority,
225+
path: tokenUrl.path,
210226
method: 'POST',
211227
headers: {
212228
'Content-Type': 'application/x-www-form-urlencoded',

src/vs/platform/product/common/productService.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,13 @@ export interface IProductConfiguration {
102102

103103
readonly msftInternalDomains?: string[];
104104
readonly linkProtectionTrustedDomains?: readonly string[];
105+
106+
readonly auth?: {
107+
loginUrl: string;
108+
tokenUrl: string;
109+
redirectUrl: string;
110+
clientId: string;
111+
};
105112
}
106113

107114
export interface IExeBasedExtensionTip {

0 commit comments

Comments
 (0)