@@ -19,7 +19,6 @@ import {
1919 invalidateSsoTokenRequestType ,
2020 invalidateStsCredentialRequestType ,
2121 ProfileKind ,
22- UpdateProfileParams ,
2322 updateProfileRequestType ,
2423 SsoTokenChangedParams ,
2524 StsCredentialChangedParams ,
@@ -50,8 +49,8 @@ import {
5049 Profile ,
5150 SsoSession ,
5251 GetMfaCodeParams ,
53- GetMfaCodeResult ,
5452 getMfaCodeRequestType ,
53+ GetMfaCodeResult ,
5554} from '@aws/language-server-runtimes/protocol'
5655import { LanguageClient } from 'vscode-languageclient'
5756import { getLogger } from '../shared/logger/logger'
@@ -125,12 +124,36 @@ export class LanguageClientAuth {
125124 return this . #ssoCacheWatcher
126125 }
127126
128- getSsoToken (
127+ /**
128+ * Encrypts an object
129+ */
130+ private async encrypt < T > ( request : T ) : Promise < string > {
131+ const payload = new TextEncoder ( ) . encode ( JSON . stringify ( request ) )
132+ const encrypted = await new jose . CompactEncrypt ( payload )
133+ . setProtectedHeader ( { alg : 'dir' , enc : 'A256GCM' } )
134+ . encrypt ( this . encryptionKey )
135+ return encrypted
136+ }
137+
138+ /**
139+ * Decrypts an object
140+ */
141+ private async decrypt < T > ( request : string ) : Promise < T > {
142+ try {
143+ const result = await jose . compactDecrypt ( request , this . encryptionKey )
144+ return JSON . parse ( new TextDecoder ( ) . decode ( result . plaintext ) ) as T
145+ } catch ( e ) {
146+ getLogger ( ) . error ( `Failed to decrypt: ${ request } ` )
147+ return request as T
148+ }
149+ }
150+
151+ async getSsoToken (
129152 tokenSource : TokenSource ,
130153 login : boolean = false ,
131154 cancellationToken ?: CancellationToken
132155 ) : Promise < GetSsoTokenResult > {
133- return this . client . sendRequest (
156+ const response : GetSsoTokenResult = await this . client . sendRequest (
134157 getSsoTokenRequestType . method ,
135158 {
136159 clientName : this . clientName ,
@@ -142,14 +165,17 @@ export class LanguageClientAuth {
142165 } satisfies GetSsoTokenParams ,
143166 cancellationToken
144167 )
168+ // Decrypt the access token
169+ response . ssoToken . accessToken = await this . decrypt ( response . ssoToken . accessToken )
170+ return response
145171 }
146172
147- getIamCredential (
173+ async getIamCredential (
148174 profileName : string ,
149175 login : boolean = false ,
150176 cancellationToken ?: CancellationToken
151177 ) : Promise < GetIamCredentialResult > {
152- return this . client . sendRequest (
178+ const response : GetIamCredentialResult = await this . client . sendRequest (
153179 getIamCredentialRequestType . method ,
154180 {
155181 profileName : profileName ,
@@ -159,16 +185,25 @@ export class LanguageClientAuth {
159185 } satisfies GetIamCredentialParams ,
160186 cancellationToken
161187 )
188+ // Decrypt the response credentials
189+ const { accessKeyId, secretAccessKey, sessionToken, expiration } = response . credential . credentials
190+ response . credential . credentials = {
191+ accessKeyId : await this . decrypt ( accessKeyId ) ,
192+ secretAccessKey : await this . decrypt ( secretAccessKey ) ,
193+ sessionToken : sessionToken ? await this . decrypt ( sessionToken ) : undefined ,
194+ expiration : expiration ,
195+ }
196+ return response
162197 }
163198
164- updateSsoProfile (
199+ async updateSsoProfile (
165200 profileName : string ,
166201 startUrl : string ,
167202 region : string ,
168203 scopes : string [ ]
169204 ) : Promise < UpdateProfileResult > {
170205 // Add SSO settings and delete credentials from profile
171- return this . client . sendRequest ( updateProfileRequestType . method , {
206+ const params = await this . encrypt ( {
172207 profile : {
173208 kinds : [ ProfileKind . SsoTokenProfile ] ,
174209 name : profileName ,
@@ -188,10 +223,11 @@ export class LanguageClientAuth {
188223 sso_registration_scopes : scopes ,
189224 } ,
190225 } ,
191- } satisfies UpdateProfileParams )
226+ } )
227+ return this . client . sendRequest ( updateProfileRequestType . method , params )
192228 }
193229
194- updateIamProfile ( profileName : string , opts : IamProfileOptions ) : Promise < UpdateProfileResult > {
230+ async updateIamProfile ( profileName : string , opts : IamProfileOptions ) : Promise < UpdateProfileResult > {
195231 // Substitute missing fields for defaults
196232 const fields = { ...IamProfileOptionsDefaults , ...opts }
197233 // Get the profile kind matching the provided fields
@@ -204,7 +240,7 @@ export class LanguageClientAuth {
204240 kind = ProfileKind . Unknown
205241 }
206242
207- return this . client . sendRequest ( updateProfileRequestType . method , {
243+ const params = await this . encrypt ( {
208244 profile : {
209245 kinds : [ kind ] ,
210246 name : profileName ,
@@ -217,10 +253,12 @@ export class LanguageClientAuth {
217253 } ,
218254 } ,
219255 } )
256+ return this . client . sendRequest ( updateProfileRequestType . method , params )
220257 }
221258
222- listProfiles ( ) {
223- return this . client . sendRequest ( listProfilesRequestType . method , { } ) as Promise < ListProfilesResult >
259+ async listProfiles ( ) {
260+ const response : string = await this . client . sendRequest ( listProfilesRequestType . method , { } )
261+ return await this . decrypt < ListProfilesResult > ( response )
224262 }
225263
226264 /**
@@ -352,19 +390,6 @@ export abstract class BaseLogin {
352390 this . eventEmitter . fire ( { id : this . profileName , state : this . connectionState } )
353391 }
354392 }
355-
356- /**
357- * Decrypts an encrypted string, removes its quotes, and returns the resulting string
358- */
359- protected async decrypt ( encrypted : string ) : Promise < string > {
360- try {
361- const decrypted = await jose . compactDecrypt ( encrypted , this . lspAuth . encryptionKey )
362- return decrypted . plaintext . toString ( ) . replaceAll ( '"' , '' )
363- } catch ( e ) {
364- getLogger ( ) . error ( `Failed to decrypt: ${ encrypted } ` )
365- return encrypted
366- }
367- }
368393}
369394
370395/**
@@ -436,9 +461,8 @@ export class SsoLogin extends BaseLogin {
436461 */
437462 async getCredential ( ) {
438463 const response = await this . _getSsoToken ( false )
439- const accessToken = await this . decrypt ( response . ssoToken . accessToken )
440464 return {
441- credential : accessToken ,
465+ credential : response . ssoToken . accessToken ,
442466 updateCredentialsParams : response . updateCredentialsParams ,
443467 }
444468 }
@@ -562,7 +586,7 @@ export class IamLogin extends BaseLogin {
562586 sourceProfile : sourceProfile ,
563587 } )
564588 } else {
565- // Create the target profile
589+ // Create the credentials profile
566590 await this . lspAuth . updateIamProfile ( this . profileName , {
567591 accessKey : opts . accessKey ,
568592 secretKey : opts . secretKey ,
@@ -575,14 +599,6 @@ export class IamLogin extends BaseLogin {
575599 * Restore the connection state and connection details to memory, if they exist.
576600 */
577601 async restore ( ) {
578- const sessionData = await this . getProfile ( )
579- const credentials = sessionData ?. profile ?. settings
580- if ( credentials ?. aws_access_key_id && credentials ?. aws_secret_access_key ) {
581- this . _data = {
582- accessKey : credentials . aws_access_key_id ,
583- secretKey : credentials . aws_secret_access_key ,
584- }
585- }
586602 try {
587603 await this . _getIamCredential ( false )
588604 } catch ( err ) {
@@ -596,15 +612,8 @@ export class IamLogin extends BaseLogin {
596612 */
597613 async getCredential ( ) {
598614 const response = await this . _getIamCredential ( false )
599- const credentials : IamCredentials = {
600- accessKeyId : await this . decrypt ( response . credential . credentials . accessKeyId ) ,
601- secretAccessKey : await this . decrypt ( response . credential . credentials . secretAccessKey ) ,
602- sessionToken : response . credential . credentials . sessionToken
603- ? await this . decrypt ( response . credential . credentials . sessionToken )
604- : undefined ,
605- }
606615 return {
607- credential : credentials ,
616+ credential : response . credential . credentials ,
608617 updateCredentialsParams : response . updateCredentialsParams ,
609618 }
610619 }
@@ -639,7 +648,7 @@ export class IamLogin extends BaseLogin {
639648 }
640649
641650 // Update cached credentials and credential ID
642- if ( response . credential ? .credentials ? .accessKeyId && response . credential ? .credentials ? .secretAccessKey ) {
651+ if ( response . credential . credentials . accessKeyId && response . credential . credentials . secretAccessKey ) {
643652 this . _data = {
644653 accessKey : response . credential . credentials . accessKeyId ,
645654 secretKey : response . credential . credentials . secretAccessKey ,
0 commit comments