Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"@iconscout/react-unicons": "^1.1.6",
"@internxt/css-config": "1.1.0",
"@internxt/lib": "1.4.1",
"@internxt/sdk": "=1.11.17",
"@internxt/sdk": "=1.12.0",
"@internxt/ui": "0.1.1",
"@phosphor-icons/react": "^2.1.7",
"@popperjs/core": "^2.11.6",
Expand Down
21 changes: 13 additions & 8 deletions src/services/auth.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -687,7 +687,7 @@ describe('updateCredentialsWithToken', () => {
expect(keys).toBeUndefined();
});

it('should successfully update credentials with token and with backup data (ECC only)', async () => {
it('should not send keys when backup data has no publicKeys (legacy backup)', async () => {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if doesn't mind, change the test that are modifying to "when X, then Y" format

const mockToken = 'test-reset-token';
const mockNewPassword = 'newPassword123';
const mockMnemonic =
Expand Down Expand Up @@ -721,13 +721,10 @@ describe('updateCredentialsWithToken', () => {
expect(encryptedPassword).toBeDefined();
expect(encryptedSalt).toBeDefined();
expect(encryptedMnemonic).toBeDefined();
expect(keys).toBeDefined();

expect(keys.ecc).toBe('mock-encrypted-data');
expect(keys.kyber).toBeUndefined();
expect(keys).toBeUndefined();
});

it('should successfully update credentials with token and with backup data (ECC and Kyber)', async () => {
it('should send both private and public keys when backup data has publicKeys', async () => {
const mockToken = 'test-reset-token';
const mockNewPassword = 'newPassword123';
const mockMnemonic =
Expand All @@ -739,6 +736,10 @@ describe('updateCredentialsWithToken', () => {
ecc: 'test-ecc-private-key',
kyber: 'test-kyber-private-key',
},
publicKeys: {
ecc: 'test-ecc-public-key',
kyber: 'test-kyber-public-key',
},
};

(validateMnemonic as any).mockReturnValue(true);
Expand All @@ -763,8 +764,12 @@ describe('updateCredentialsWithToken', () => {
expect(encryptedMnemonic).toBeDefined();
expect(keys).toBeDefined();

expect(keys.ecc).toBe('mock-encrypted-data');
expect(keys.kyber).toBe('mock-encrypted-data');
expect(keys.private.ecc).toBe('mock-encrypted-data');
expect(keys.private.kyber).toBe('mock-encrypted-data');
expect(keys.public).toEqual({
ecc: 'test-ecc-public-key',
kyber: 'test-kyber-public-key',
});
});

it('should throw an error when mnemonic is invalid', async () => {
Expand Down
10 changes: 9 additions & 1 deletion src/services/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,14 +339,22 @@ export const updateCredentialsWithToken = async (

const authClient = SdkFactory.getNewApiInstance().createAuthClient();

const keys =
const privateKeys =
encryptedEccPrivateKey || encryptedKyberPrivateKey
? {
ecc: encryptedEccPrivateKey,
kyber: encryptedKyberPrivateKey,
}
: undefined;

const keys =
privateKeys && backupData?.publicKeys
? {
private: privateKeys,
public: backupData?.publicKeys,
}
: undefined;

return authClient.changePasswordWithLinkV2(
token,
encryptedHashedNewPassword,
Expand Down
17 changes: 17 additions & 0 deletions src/utils/backupKeyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import { encryptMessageWithPublicKey, hybridEncryptMessageWithPublicKey } from '
* @property {Object} keys - The user's encryption keys
* @property {string} keys.ecc - The user's ECC private key
* @property {string} keys.kyber - The user's Kyber private key
* @property {Object} [publicKeys] - The user's public keys (for backup validation)
* @property {string} [publicKeys.ecc] - The user's ECC public key
* @property {string} [publicKeys.kyber] - The user's Kyber public key
*/
export interface BackupData {
mnemonic: string;
Expand All @@ -24,6 +27,10 @@ export interface BackupData {
ecc: string;
kyber: string;
};
publicKeys?: {
ecc?: string;
kyber?: string;
};
}

/**
Expand All @@ -49,6 +56,10 @@ export function handleExportBackupKey(translate) {
ecc: user.keys?.ecc?.privateKey || user.privateKey,
kyber: user.keys?.kyber?.privateKey || '',
},
publicKeys: {
ecc: user.keys?.ecc?.publicKey || '',
kyber: user.keys?.kyber?.publicKey || '',
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that if for some reason the public keys are not there, empty strings will be exported.
When attempting to send this empty string, do we notify the user?
Shouldn't we notify them if empty strings are going to be exported?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If both ecc and kyber public keys are not present, publicKeys shouldn't be exported at all. In order to keep backward compatibility, I've changed that.

},
};

const backupContent = JSON.stringify(backupData, null, 2);
Expand Down Expand Up @@ -84,6 +95,12 @@ export const detectBackupKeyFormat = (
ecc: parsedData.keys.ecc,
kyber: parsedData.keys.kyber,
},
publicKeys: parsedData.publicKeys
? {
ecc: parsedData.publicKeys.ecc,
kyber: parsedData.publicKeys.kyber,
}
: undefined,
};
return {
type: 'new',
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1906,10 +1906,10 @@
version "1.0.2"
resolved "https://codeload.github.com/internxt/prettier-config/tar.gz/9fa74e9a2805e1538b50c3809324f1c9d0f3e4f9"

"@internxt/sdk@=1.11.17":
version "1.11.17"
resolved "https://registry.yarnpkg.com/@internxt/sdk/-/sdk-1.11.17.tgz#2f5bdada5d3cbf5cfc685a21c24b5df3ff51d8c8"
integrity sha512-91iEUvZizlwX6KBEFJ3JdFiGrhMBQ9R54sTc3Pei9QtV2FYTU8nTVEPYAg39tLOGzT/kVuplYOtBxfk6wFtSDA==
"@internxt/sdk@1.12.0":
version "1.12.0"
resolved "https://registry.yarnpkg.com/@internxt/sdk/-/sdk-1.12.0.tgz#cf9c2f0ca8864a688e4c161f470e171997bff7bb"
integrity sha512-QrjH2yJP7MjxAVvkOe6quqX7RYzC6e3M0XcXralJEFybDpimJBJbvRTPUe7+9XRQ6gHdmYi1u3ySDVoZyZpkug==
dependencies:
axios "1.13.2"
uuid "11.1.0"
Expand Down
Loading