From 20cfef5c8895baa93b47d9c9d43be3f3f52e6430 Mon Sep 17 00:00:00 2001 From: dougama Date: Wed, 7 Jan 2026 17:43:38 +0100 Subject: [PATCH] feat(auth): add public keys validation for account recovery --- package.json | 2 +- src/auth/index.ts | 6 ++-- src/auth/types.ts | 10 ++++++ test/auth/index.test.ts | 70 +++++++++++++++++++++++++++++++++++++++-- 4 files changed, 83 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index cbb24a3..787bad2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@internxt/sdk", "author": "Internxt ", - "version": "1.11.26", + "version": "1.12.0", "description": "An sdk for interacting with Internxt's services", "repository": { "type": "git", diff --git a/src/auth/index.ts b/src/auth/index.ts index 3ccc88a..5855a47 100644 --- a/src/auth/index.ts +++ b/src/auth/index.ts @@ -9,6 +9,7 @@ import { Keys, LoginDetails, PrivateKeys, + RecoveryKeys, RegisterDetails, RegisterOpaqueDetails, RegisterPreCreatedUser, @@ -669,7 +670,7 @@ export class Auth { password: string, salt: string, mnemonic: string, - keys?: PrivateKeys, + keys?: RecoveryKeys, ): Promise { return this.client.put( `/users/recover-account-v2?token=${token}&reset=false`, @@ -677,7 +678,8 @@ export class Auth { password: password, salt: salt, mnemonic: mnemonic, - privateKeys: keys, + privateKeys: keys?.private, + publicKeys: keys?.public, }, this.basicHeaders(), ); diff --git a/src/auth/types.ts b/src/auth/types.ts index fa66d62..013e981 100644 --- a/src/auth/types.ts +++ b/src/auth/types.ts @@ -97,6 +97,16 @@ export interface PrivateKeys { kyber?: string; } +export interface PublicKeys { + ecc?: string; + kyber?: string; +} + +export interface RecoveryKeys { + private?: PrivateKeys; + public?: PublicKeys; +} + export interface PrivateKeysExtended { ecc: { public: string; diff --git a/test/auth/index.test.ts b/test/auth/index.test.ts index 4bc5a72..2d91f74 100644 --- a/test/auth/index.test.ts +++ b/test/auth/index.test.ts @@ -838,7 +838,7 @@ describe('# auth service tests', () => { }); }); describe('-> change password with link v2', () => { - it('Should call with right params without private keys', async () => { + it('Should call with right params without keys', async () => { const callStub = sinon.stub(httpClient, 'put').resolves({}); const { client, headers } = clientAndHeaders(); const token = 'token'; @@ -871,7 +871,42 @@ describe('# auth service tests', () => { kyber: 'newKyberKey', }; - await client.changePasswordWithLinkV2(token, password, salt, mnemonic, privateKeys); + await client.changePasswordWithLinkV2(token, password, salt, mnemonic, { private: privateKeys }); + + // Assert + expect(callStub.firstCall.args).toEqual([ + `/users/recover-account-v2?token=${token}&reset=false`, + { + password, + salt, + mnemonic, + privateKeys, + publicKeys: undefined, + }, + headers, + ]); + }); + + it('Should call with right params including private and public keys', async () => { + const callStub = sinon.stub(httpClient, 'put').resolves({}); + const { client, headers } = clientAndHeaders(); + const token = 'token'; + const password = 'newPassword'; + const salt = 'newSalt'; + const mnemonic = 'newMnemonic'; + const privateKeys = { + ecc: 'newEccPrivateKey', + kyber: 'newKyberPrivateKey', + }; + const publicKeys = { + ecc: 'eccPublicKey', + kyber: 'kyberPublicKey', + }; + + await client.changePasswordWithLinkV2(token, password, salt, mnemonic, { + private: privateKeys, + public: publicKeys, + }); // Assert expect(callStub.firstCall.args).toEqual([ @@ -881,6 +916,37 @@ describe('# auth service tests', () => { salt, mnemonic, privateKeys, + publicKeys, + }, + headers, + ]); + }); + + it('Should call with right params including only public keys (legacy backup without private keys)', async () => { + const callStub = sinon.stub(httpClient, 'put').resolves({}); + const { client, headers } = clientAndHeaders(); + const token = 'token'; + const password = 'newPassword'; + const salt = 'newSalt'; + const mnemonic = 'newMnemonic'; + const publicKeys = { + ecc: 'eccPublicKey', + kyber: 'kyberPublicKey', + }; + + await client.changePasswordWithLinkV2(token, password, salt, mnemonic, { + public: publicKeys, + }); + + // Assert + expect(callStub.firstCall.args).toEqual([ + `/users/recover-account-v2?token=${token}&reset=false`, + { + password, + salt, + mnemonic, + privateKeys: undefined, + publicKeys, }, headers, ]);