@@ -500,6 +500,7 @@ async function createMockVault(
500500 revokeToken : mockRevokeToken ,
501501 accessToken : mockAccessToken ,
502502 } ) ;
503+ console . log ( 'serializedKeyData' , serializedKeyData ) ;
503504
504505 const { vault : encryptedMockVault , exportedKeyString } =
505506 await encryptor . encryptWithDetail ( MOCK_PASSWORD , serializedKeyData ) ;
@@ -1288,6 +1289,7 @@ describe('SeedlessOnboardingController', () => {
12881289 pwEncKey ,
12891290 authKeyPair ,
12901291 MOCK_PASSWORD ,
1292+ controller . state . revokeToken ,
12911293 ) ;
12921294
12931295 const expectedVaultValue = await encryptor . decrypt (
@@ -1299,7 +1301,7 @@ describe('SeedlessOnboardingController', () => {
12991301 controller . state . vault as string ,
13001302 ) ;
13011303
1302- expect ( expectedVaultValue ) . toStrictEqual ( resultedVaultValue ) ;
1304+ expect ( resultedVaultValue ) . toStrictEqual ( expectedVaultValue ) ;
13031305
13041306 // should be able to get the hash of the seed phrase backup from the state
13051307 expect (
@@ -1377,6 +1379,36 @@ describe('SeedlessOnboardingController', () => {
13771379 ) ;
13781380 } ) ;
13791381
1382+ it ( 'should throw error if revokeToken is missing when creating new vault' , async ( ) => {
1383+ await withController (
1384+ {
1385+ state : getMockInitialControllerState ( {
1386+ withMockAuthenticatedUser : true ,
1387+ withMockAuthPubKey : true ,
1388+ withoutMockRevokeToken : true ,
1389+ } ) ,
1390+ } ,
1391+ async ( { controller, toprfClient } ) => {
1392+ mockcreateLocalKey ( toprfClient , MOCK_PASSWORD ) ;
1393+
1394+ // persist the local enc key
1395+ jest . spyOn ( toprfClient , 'persistLocalKey' ) . mockResolvedValueOnce ( ) ;
1396+
1397+ // encrypt and store the secret data
1398+ handleMockSecretDataAdd ( ) ;
1399+ await expect (
1400+ controller . createToprfKeyAndBackupSeedPhrase (
1401+ MOCK_PASSWORD ,
1402+ MOCK_SEED_PHRASE ,
1403+ MOCK_KEYRING_ID ,
1404+ ) ,
1405+ ) . rejects . toThrow (
1406+ SeedlessOnboardingControllerErrorMessage . InvalidRevokeToken ,
1407+ ) ;
1408+ } ,
1409+ ) ;
1410+ } ) ;
1411+
13801412 it ( 'should throw an error if create encryption key fails' , async ( ) => {
13811413 await withController (
13821414 {
@@ -2084,27 +2116,6 @@ describe('SeedlessOnboardingController', () => {
20842116 ) ;
20852117 } ) ;
20862118
2087- it ( 'should throw an error if the user is not authenticated' , async ( ) => {
2088- await withController (
2089- {
2090- state : {
2091- userId,
2092- authConnectionId,
2093- groupedAuthConnectionId,
2094- metadataAccessToken,
2095- refreshToken,
2096- revokeToken,
2097- nodeAuthTokens : MOCK_NODE_AUTH_TOKENS ,
2098- } ,
2099- } ,
2100- async ( { controller } ) => {
2101- await expect ( controller . fetchAllSecretData ( ) ) . rejects . toThrow (
2102- SeedlessOnboardingControllerErrorMessage . InvalidAccessToken ,
2103- ) ;
2104- } ,
2105- ) ;
2106- } ) ;
2107-
21082119 it ( 'should be able to fetch seed phrases with cached encryption key without providing password' , async ( ) => {
21092120 const mockToprfEncryptor = createMockToprfEncryptor ( ) ;
21102121
@@ -5331,6 +5342,24 @@ describe('SeedlessOnboardingController', () => {
53315342 } ) ;
53325343 } ) ;
53335344
5345+ it ( 'should return true if access token is missing' , async ( ) => {
5346+ await withController (
5347+ {
5348+ state : getMockInitialControllerState ( {
5349+ withMockAuthenticatedUser : true ,
5350+ withoutMockAccessToken : true ,
5351+ } ) ,
5352+ } ,
5353+ async ( { controller } ) => {
5354+ // Restore the original implementation to test the real logic
5355+ jest . spyOn ( controller , 'checkAccessTokenExpired' ) . mockRestore ( ) ;
5356+
5357+ const result = controller . checkAccessTokenExpired ( ) ;
5358+ expect ( result ) . toBe ( true ) ;
5359+ } ,
5360+ ) ;
5361+ } ) ;
5362+
53345363 it ( 'should return true if token has invalid format' , async ( ) => {
53355364 await withController (
53365365 {
@@ -5350,6 +5379,113 @@ describe('SeedlessOnboardingController', () => {
53505379 } ) ;
53515380 } ) ;
53525381
5382+ describe ( '#getAccessToken' , ( ) => {
5383+ const MOCK_PASSWORD = 'mock-password' ;
5384+
5385+ it ( 'should retrieve the access token from the vault if it is not available in the state' , async ( ) => {
5386+ const mockToprfEncryptor = createMockToprfEncryptor ( ) ;
5387+ const MOCK_ENCRYPTION_KEY =
5388+ mockToprfEncryptor . deriveEncKey ( MOCK_PASSWORD ) ;
5389+ const MOCK_PASSWORD_ENCRYPTION_KEY =
5390+ mockToprfEncryptor . derivePwEncKey ( MOCK_PASSWORD ) ;
5391+ const MOCK_AUTH_KEY_PAIR =
5392+ mockToprfEncryptor . deriveAuthKeyPair ( MOCK_PASSWORD ) ;
5393+
5394+ const mockResult = await createMockVault (
5395+ MOCK_ENCRYPTION_KEY ,
5396+ MOCK_PASSWORD_ENCRYPTION_KEY ,
5397+ MOCK_AUTH_KEY_PAIR ,
5398+ MOCK_PASSWORD ,
5399+ ) ;
5400+
5401+ const MOCK_VAULT = mockResult . encryptedMockVault ;
5402+ const MOCK_VAULT_ENCRYPTION_KEY = mockResult . vaultEncryptionKey ;
5403+ const MOCK_VAULT_ENCRYPTION_SALT = mockResult . vaultEncryptionSalt ;
5404+
5405+ await withController (
5406+ {
5407+ state : getMockInitialControllerState ( {
5408+ withMockAuthenticatedUser : true ,
5409+ withoutMockAccessToken : true ,
5410+ vault : MOCK_VAULT ,
5411+ vaultEncryptionKey : MOCK_VAULT_ENCRYPTION_KEY ,
5412+ vaultEncryptionSalt : MOCK_VAULT_ENCRYPTION_SALT ,
5413+ } ) ,
5414+ } ,
5415+ async ( { controller, toprfClient } ) => {
5416+ // fetch and decrypt the secret data
5417+ mockRecoverEncKey ( toprfClient , MOCK_PASSWORD ) ;
5418+
5419+ // mock the secret data get
5420+ jest
5421+ . spyOn ( toprfClient , 'fetchAllSecretDataItems' )
5422+ . mockResolvedValueOnce ( [
5423+ stringToBytes (
5424+ JSON . stringify ( {
5425+ data : bytesToBase64 ( MOCK_SEED_PHRASE ) ,
5426+ timestamp : 1234567890 ,
5427+ type : SecretType . Mnemonic ,
5428+ version : 'v1' ,
5429+ } ) ,
5430+ ) ,
5431+ stringToBytes (
5432+ JSON . stringify ( {
5433+ data : bytesToBase64 ( MOCK_PRIVATE_KEY ) ,
5434+ timestamp : 1234567890 ,
5435+ type : SecretType . PrivateKey ,
5436+ version : 'v1' ,
5437+ } ) ,
5438+ ) ,
5439+ ] ) ;
5440+
5441+ const secretData = await controller . fetchAllSecretData ( MOCK_PASSWORD ) ;
5442+ expect ( secretData ) . toBeDefined ( ) ;
5443+ expect ( secretData ) . toHaveLength ( 2 ) ;
5444+ expect ( secretData [ 0 ] . type ) . toStrictEqual ( SecretType . Mnemonic ) ;
5445+ expect ( secretData [ 0 ] . data ) . toStrictEqual ( MOCK_SEED_PHRASE ) ;
5446+ expect ( secretData [ 1 ] . type ) . toStrictEqual ( SecretType . PrivateKey ) ;
5447+ expect ( secretData [ 1 ] . data ) . toStrictEqual ( MOCK_PRIVATE_KEY ) ;
5448+
5449+ // expect(mockSecretDataGet.isDone()).toBe(true);
5450+ } ,
5451+ ) ;
5452+ } ) ;
5453+
5454+ it ( 'should throw error if access token is not available either in the state or the vault' , async ( ) => {
5455+ await withController (
5456+ {
5457+ state : getMockInitialControllerState ( {
5458+ withMockAuthenticatedUser : true ,
5459+ withoutMockAccessToken : true ,
5460+ } ) ,
5461+ } ,
5462+ async ( { controller, toprfClient } ) => {
5463+ // fetch and decrypt the secret data
5464+ mockRecoverEncKey ( toprfClient , MOCK_PASSWORD ) ;
5465+ // mock the incorrect data shape
5466+ jest
5467+ . spyOn ( toprfClient , 'fetchAllSecretDataItems' )
5468+ . mockResolvedValueOnce ( [
5469+ stringToBytes (
5470+ JSON . stringify ( {
5471+ data : 'value' ,
5472+ timestamp : 1234567890 ,
5473+ type : 'mnemonic' ,
5474+ version : 'v1' ,
5475+ } ) ,
5476+ ) ,
5477+ ] ) ;
5478+
5479+ await expect (
5480+ controller . fetchAllSecretData ( MOCK_PASSWORD ) ,
5481+ ) . rejects . toThrow (
5482+ SeedlessOnboardingControllerErrorMessage . InvalidAccessToken ,
5483+ ) ;
5484+ } ,
5485+ ) ;
5486+ } ) ;
5487+ } ) ;
5488+
53535489 describe ( 'renewRefreshToken' , ( ) => {
53545490 const MOCK_PASSWORD = 'mock-password' ;
53555491 const MOCK_REVOKE_TOKEN = 'newRevokeToken' ;
0 commit comments