@@ -8,11 +8,14 @@ import { CancellationToken } from 'vs/base/common/cancellation';
8
8
import { Event } from 'vs/base/common/event' ;
9
9
import { hash } from 'vs/base/common/hash' ;
10
10
import { Disposable } from 'vs/base/common/lifecycle' ;
11
+ import { withNullAsUndefined } from 'vs/base/common/types' ;
11
12
import { generateUuid } from 'vs/base/common/uuid' ;
12
13
import { ICredentialsMainService } from 'vs/platform/credentials/common/credentials' ;
13
14
import { IEncryptionMainService } from 'vs/platform/encryption/common/encryptionService' ;
14
15
import { ILogService } from 'vs/platform/log/common/log' ;
15
16
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' ;
16
19
import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows' ;
17
20
18
21
interface ElectronAuthenticationResponseDetails extends AuthenticationResponseDetails {
@@ -56,7 +59,8 @@ enum ProxyAuthState {
56
59
57
60
export class ProxyAuthHandler extends Disposable {
58
61
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://' ;
60
64
61
65
private pendingProxyResolve : Promise < Credentials | undefined > | undefined = undefined ;
62
66
@@ -69,6 +73,7 @@ export class ProxyAuthHandler extends Disposable {
69
73
@IWindowsMainService private readonly windowsMainService : IWindowsMainService ,
70
74
@ICredentialsMainService private readonly credentialsService : ICredentialsMainService ,
71
75
@IEncryptionMainService private readonly encryptionMainService : IEncryptionMainService ,
76
+ @IApplicationStorageMainService private readonly applicationStorageMainService : IApplicationStorageMainService ,
72
77
@IProductService private readonly productService : IProductService
73
78
) {
74
79
super ( ) ;
@@ -141,29 +146,43 @@ export class ProxyAuthHandler extends Disposable {
141
146
return undefined ;
142
147
}
143
148
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 } > {
153
151
// Find any previously stored credentials
154
- let storedUsername : string | undefined = undefined ;
155
- let storedPassword : string | undefined = undefined ;
156
152
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
+ }
158
166
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 ) ) ;
160
168
161
- storedUsername = credentials . username ;
162
- storedPassword = credentials . password ;
169
+ return { storedUsername : credentials . username , storedPassword : credentials . password } ;
163
170
}
164
171
} catch ( error ) {
165
172
this . logService . error ( error ) ; // handle errors by asking user for login via dialog
166
173
}
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 ) ;
167
186
168
187
// Reply with stored credentials unless we used them already.
169
188
// In that case we need to show a login dialog again because
@@ -212,9 +231,9 @@ export class ProxyAuthHandler extends Disposable {
212
231
try {
213
232
if ( reply . remember ) {
214
233
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 ) ;
216
235
} else {
217
- await this . credentialsService . deletePassword ( this . PROXY_CREDENTIALS_SERVICE_KEY , authInfoHash ) ;
236
+ this . applicationStorageMainService . remove ( this . PROXY_CREDENTIALS_SERVICE_KEY + authInfoHash , StorageScope . APPLICATION ) ;
218
237
}
219
238
} catch ( error ) {
220
239
this . logService . error ( error ) ; // handle gracefully
0 commit comments