@@ -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,31 @@ 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+ const result = await jose . compactDecrypt ( request , this . encryptionKey )
143+ return JSON . parse ( new TextDecoder ( ) . decode ( result . plaintext ) ) as T
144+ }
145+
146+ async getSsoToken (
129147 tokenSource : TokenSource ,
130148 login : boolean = false ,
131149 cancellationToken ?: CancellationToken
132150 ) : Promise < GetSsoTokenResult > {
133- return this . client . sendRequest (
151+ const response : GetSsoTokenResult = await this . client . sendRequest (
134152 getSsoTokenRequestType . method ,
135153 {
136154 clientName : this . clientName ,
@@ -142,14 +160,17 @@ export class LanguageClientAuth {
142160 } satisfies GetSsoTokenParams ,
143161 cancellationToken
144162 )
163+ // Decrypt the access token
164+ response . ssoToken . accessToken = await this . decrypt ( response . ssoToken . accessToken )
165+ return response
145166 }
146167
147- getIamCredential (
168+ async getIamCredential (
148169 profileName : string ,
149170 login : boolean = false ,
150171 cancellationToken ?: CancellationToken
151172 ) : Promise < GetIamCredentialResult > {
152- return this . client . sendRequest (
173+ const response : GetIamCredentialResult = await this . client . sendRequest (
153174 getIamCredentialRequestType . method ,
154175 {
155176 profileName : profileName ,
@@ -159,16 +180,25 @@ export class LanguageClientAuth {
159180 } satisfies GetIamCredentialParams ,
160181 cancellationToken
161182 )
183+ // Decrypt the response credentials
184+ const { accessKeyId, secretAccessKey, sessionToken, expiration } = response . credential . credentials
185+ response . credential . credentials = {
186+ accessKeyId : await this . decrypt ( accessKeyId ) ,
187+ secretAccessKey : await this . decrypt ( secretAccessKey ) ,
188+ sessionToken : sessionToken ? await this . decrypt ( sessionToken ) : undefined ,
189+ expiration : expiration ,
190+ }
191+ return response
162192 }
163193
164- updateSsoProfile (
194+ async updateSsoProfile (
165195 profileName : string ,
166196 startUrl : string ,
167197 region : string ,
168198 scopes : string [ ]
169199 ) : Promise < UpdateProfileResult > {
170200 // Add SSO settings and delete credentials from profile
171- return this . client . sendRequest ( updateProfileRequestType . method , {
201+ const params = await this . encrypt ( {
172202 profile : {
173203 kinds : [ ProfileKind . SsoTokenProfile ] ,
174204 name : profileName ,
@@ -188,10 +218,11 @@ export class LanguageClientAuth {
188218 sso_registration_scopes : scopes ,
189219 } ,
190220 } ,
191- } satisfies UpdateProfileParams )
221+ } )
222+ return this . client . sendRequest ( updateProfileRequestType . method , params )
192223 }
193224
194- updateIamProfile ( profileName : string , opts : IamProfileOptions ) : Promise < UpdateProfileResult > {
225+ async updateIamProfile ( profileName : string , opts : IamProfileOptions ) : Promise < UpdateProfileResult > {
195226 // Substitute missing fields for defaults
196227 const fields = { ...IamProfileOptionsDefaults , ...opts }
197228 // Get the profile kind matching the provided fields
@@ -204,7 +235,7 @@ export class LanguageClientAuth {
204235 kind = ProfileKind . Unknown
205236 }
206237
207- return this . client . sendRequest ( updateProfileRequestType . method , {
238+ const params = await this . encrypt ( {
208239 profile : {
209240 kinds : [ kind ] ,
210241 name : profileName ,
@@ -217,10 +248,12 @@ export class LanguageClientAuth {
217248 } ,
218249 } ,
219250 } )
251+ return this . client . sendRequest ( updateProfileRequestType . method , params )
220252 }
221253
222- listProfiles ( ) {
223- return this . client . sendRequest ( listProfilesRequestType . method , { } ) as Promise < ListProfilesResult >
254+ async listProfiles ( ) {
255+ const response : string = await this . client . sendRequest ( listProfilesRequestType . method , { } )
256+ return await this . decrypt < ListProfilesResult > ( response )
224257 }
225258
226259 /**
@@ -352,19 +385,6 @@ export abstract class BaseLogin {
352385 this . eventEmitter . fire ( { id : this . profileName , state : this . connectionState } )
353386 }
354387 }
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- }
368388}
369389
370390/**
@@ -436,9 +456,8 @@ export class SsoLogin extends BaseLogin {
436456 */
437457 async getCredential ( ) {
438458 const response = await this . _getSsoToken ( false )
439- const accessToken = await this . decrypt ( response . ssoToken . accessToken )
440459 return {
441- credential : accessToken ,
460+ credential : response . ssoToken . accessToken ,
442461 updateCredentialsParams : response . updateCredentialsParams ,
443462 }
444463 }
@@ -562,7 +581,7 @@ export class IamLogin extends BaseLogin {
562581 sourceProfile : sourceProfile ,
563582 } )
564583 } else {
565- // Create the target profile
584+ // Create the credentials profile
566585 await this . lspAuth . updateIamProfile ( this . profileName , {
567586 accessKey : opts . accessKey ,
568587 secretKey : opts . secretKey ,
@@ -575,14 +594,6 @@ export class IamLogin extends BaseLogin {
575594 * Restore the connection state and connection details to memory, if they exist.
576595 */
577596 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- }
586597 try {
587598 await this . _getIamCredential ( false )
588599 } catch ( err ) {
@@ -596,15 +607,8 @@ export class IamLogin extends BaseLogin {
596607 */
597608 async getCredential ( ) {
598609 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- }
606610 return {
607- credential : credentials ,
611+ credential : response . credential . credentials ,
608612 updateCredentialsParams : response . updateCredentialsParams ,
609613 }
610614 }
@@ -639,7 +643,7 @@ export class IamLogin extends BaseLogin {
639643 }
640644
641645 // Update cached credentials and credential ID
642- if ( response . credential ? .credentials ? .accessKeyId && response . credential ? .credentials ? .secretAccessKey ) {
646+ if ( response . credential . credentials . accessKeyId && response . credential . credentials . secretAccessKey ) {
643647 this . _data = {
644648 accessKey : response . credential . credentials . accessKeyId ,
645649 secretKey : response . credential . credentials . secretAccessKey ,
0 commit comments