Skip to content

Commit 8dcddb4

Browse files
Have auth proxy use application storage service (microsoft#187094)
* Have auth proxy use application storage service Since this code is already using the encryption service, it already takes advantage of the better encryption provided by Electron so it can be stored in the normal storage service. With that said, we do need a migration path, so this handles that migration. * re-encrypt to force using the new electron algorithm * it should already be removed from the old location
1 parent 48d1ad4 commit 8dcddb4

File tree

1 file changed

+37
-18
lines changed

1 file changed

+37
-18
lines changed

src/vs/code/electron-main/auth.ts

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@ import { CancellationToken } from 'vs/base/common/cancellation';
88
import { Event } from 'vs/base/common/event';
99
import { hash } from 'vs/base/common/hash';
1010
import { Disposable } from 'vs/base/common/lifecycle';
11+
import { withNullAsUndefined } from 'vs/base/common/types';
1112
import { generateUuid } from 'vs/base/common/uuid';
1213
import { ICredentialsMainService } from 'vs/platform/credentials/common/credentials';
1314
import { IEncryptionMainService } from 'vs/platform/encryption/common/encryptionService';
1415
import { ILogService } from 'vs/platform/log/common/log';
1516
import { IProductService } from 'vs/platform/product/common/productService';
17+
import { StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
18+
import { IApplicationStorageMainService } from 'vs/platform/storage/electron-main/storageMainService';
1619
import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows';
1720

1821
interface ElectronAuthenticationResponseDetails extends AuthenticationResponseDetails {
@@ -56,7 +59,8 @@ enum ProxyAuthState {
5659

5760
export class ProxyAuthHandler extends Disposable {
5861

59-
private readonly PROXY_CREDENTIALS_SERVICE_KEY = `${this.productService.urlProtocol}.proxy-credentials`;
62+
private readonly OLD_PROXY_CREDENTIALS_SERVICE_KEY = `${this.productService.urlProtocol}.proxy-credentials`;
63+
private readonly PROXY_CREDENTIALS_SERVICE_KEY = 'proxy-credentials://';
6064

6165
private pendingProxyResolve: Promise<Credentials | undefined> | undefined = undefined;
6266

@@ -69,6 +73,7 @@ export class ProxyAuthHandler extends Disposable {
6973
@IWindowsMainService private readonly windowsMainService: IWindowsMainService,
7074
@ICredentialsMainService private readonly credentialsService: ICredentialsMainService,
7175
@IEncryptionMainService private readonly encryptionMainService: IEncryptionMainService,
76+
@IApplicationStorageMainService private readonly applicationStorageMainService: IApplicationStorageMainService,
7277
@IProductService private readonly productService: IProductService
7378
) {
7479
super();
@@ -141,29 +146,43 @@ export class ProxyAuthHandler extends Disposable {
141146
return undefined;
142147
}
143148

144-
private async doResolveProxyCredentials(authInfo: AuthInfo): Promise<Credentials | undefined> {
145-
this.logService.trace('auth#doResolveProxyCredentials - enter', authInfo);
146-
147-
// Compute a hash over the authentication info to be used
148-
// with the credentials store to return the right credentials
149-
// given the properties of the auth request
150-
// (see https://github.com/microsoft/vscode/issues/109497)
151-
const authInfoHash = String(hash({ scheme: authInfo.scheme, host: authInfo.host, port: authInfo.port }));
152-
149+
// TODO: remove this migration in a release or two.
150+
private async getAndMigrateProxyCredentials(authInfoHash: string): Promise<{ storedUsername: string | undefined; storedPassword: string | undefined }> {
153151
// Find any previously stored credentials
154-
let storedUsername: string | undefined = undefined;
155-
let storedPassword: string | undefined = undefined;
156152
try {
157-
const encryptedSerializedProxyCredentials = await this.credentialsService.getPassword(this.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash);
153+
let encryptedSerializedProxyCredentials = this.applicationStorageMainService.get(this.PROXY_CREDENTIALS_SERVICE_KEY + authInfoHash, StorageScope.APPLICATION);
154+
let decryptedSerializedProxyCredentials: string | undefined;
155+
if (!encryptedSerializedProxyCredentials) {
156+
encryptedSerializedProxyCredentials = withNullAsUndefined(await this.credentialsService.getPassword(this.OLD_PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash));
157+
if (encryptedSerializedProxyCredentials) {
158+
// re-encrypt to force new encryption algorithm to apply
159+
decryptedSerializedProxyCredentials = await this.encryptionMainService.decrypt(encryptedSerializedProxyCredentials);
160+
encryptedSerializedProxyCredentials = await this.encryptionMainService.encrypt(decryptedSerializedProxyCredentials);
161+
this.applicationStorageMainService.store(this.PROXY_CREDENTIALS_SERVICE_KEY + authInfoHash, encryptedSerializedProxyCredentials, StorageScope.APPLICATION, StorageTarget.MACHINE);
162+
// Remove it from the old location since it's in the new location.
163+
await this.credentialsService.deletePassword(this.OLD_PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash);
164+
}
165+
}
158166
if (encryptedSerializedProxyCredentials) {
159-
const credentials: Credentials = JSON.parse(await this.encryptionMainService.decrypt(encryptedSerializedProxyCredentials));
167+
const credentials: Credentials = JSON.parse(decryptedSerializedProxyCredentials ?? await this.encryptionMainService.decrypt(encryptedSerializedProxyCredentials));
160168

161-
storedUsername = credentials.username;
162-
storedPassword = credentials.password;
169+
return { storedUsername: credentials.username, storedPassword: credentials.password };
163170
}
164171
} catch (error) {
165172
this.logService.error(error); // handle errors by asking user for login via dialog
166173
}
174+
return { storedUsername: undefined, storedPassword: undefined };
175+
}
176+
177+
private async doResolveProxyCredentials(authInfo: AuthInfo): Promise<Credentials | undefined> {
178+
this.logService.trace('auth#doResolveProxyCredentials - enter', authInfo);
179+
180+
// Compute a hash over the authentication info to be used
181+
// with the credentials store to return the right credentials
182+
// given the properties of the auth request
183+
// (see https://github.com/microsoft/vscode/issues/109497)
184+
const authInfoHash = String(hash({ scheme: authInfo.scheme, host: authInfo.host, port: authInfo.port }));
185+
const { storedUsername, storedPassword } = await this.getAndMigrateProxyCredentials(authInfoHash);
167186

168187
// Reply with stored credentials unless we used them already.
169188
// In that case we need to show a login dialog again because
@@ -212,9 +231,9 @@ export class ProxyAuthHandler extends Disposable {
212231
try {
213232
if (reply.remember) {
214233
const encryptedSerializedCredentials = await this.encryptionMainService.encrypt(JSON.stringify(credentials));
215-
await this.credentialsService.setPassword(this.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash, encryptedSerializedCredentials);
234+
this.applicationStorageMainService.store(this.PROXY_CREDENTIALS_SERVICE_KEY + authInfoHash, encryptedSerializedCredentials, StorageScope.APPLICATION, StorageTarget.MACHINE);
216235
} else {
217-
await this.credentialsService.deletePassword(this.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash);
236+
this.applicationStorageMainService.remove(this.PROXY_CREDENTIALS_SERVICE_KEY + authInfoHash, StorageScope.APPLICATION);
218237
}
219238
} catch (error) {
220239
this.logService.error(error); // handle gracefully

0 commit comments

Comments
 (0)