From d86affb83f1e7747d9de590cff7d3f77ec9edecd Mon Sep 17 00:00:00 2001 From: lwin Date: Fri, 27 Mar 2026 11:05:44 +0800 Subject: [PATCH 01/11] feat: user login process audit --- .gitignore | 2 ++ package-lock.json | 21 ++++++++++++++++- package.json | 2 +- src/helpers/citadelUtils.ts | 47 +++++++++++++++++++++++++++++++++++-- src/interfaces.ts | 17 ++++++++++++++ src/torus.ts | 36 ++++++++++++++++++++++++++-- 6 files changed, 119 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index a1b106cd..e4303c8b 100644 --- a/.gitignore +++ b/.gitignore @@ -105,3 +105,5 @@ dist .env.test **/*.DS_Store + +.npmrc diff --git a/package-lock.json b/package-lock.json index f3b537f0..e3ba0355 100644 --- a/package-lock.json +++ b/package-lock.json @@ -89,6 +89,7 @@ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -1668,6 +1669,7 @@ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", "license": "MIT", + "peer": true, "engines": { "node": ">=6.9.0" } @@ -3052,6 +3054,7 @@ "integrity": "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@octokit/auth-token": "^6.0.0", "@octokit/graphql": "^9.0.3", @@ -4415,6 +4418,7 @@ "integrity": "sha512-DZ8VwRFUNzuqJ5khrvwMXHmvPe+zGayJhr2CDNiKB1WBE1ST8Djl00D0IC4vvNmHMdj6DlbYRIaFE7WHjlDl5w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -4478,6 +4482,7 @@ "integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.56.1", "@typescript-eslint/types": "8.56.1", @@ -5139,6 +5144,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5628,6 +5634,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -6802,6 +6809,7 @@ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -6862,6 +6870,7 @@ "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", + "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -6988,6 +6997,7 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -9748,6 +9758,7 @@ "integrity": "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", @@ -10704,6 +10715,7 @@ "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -11219,6 +11231,7 @@ "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -12093,7 +12106,8 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, - "license": "0BSD" + "license": "0BSD", + "peer": true }, "node_modules/tsx": { "version": "4.21.0", @@ -12101,6 +12115,7 @@ "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" @@ -12224,6 +12239,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -12340,6 +12356,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "dependencies": { "napi-postinstall": "^0.3.0" }, @@ -12463,6 +12480,7 @@ "integrity": "sha512-1gFhNi+bHhRE/qKZOJXACm6tX4bA3Isy9KuKF15AgSRuRazNBOJfdDemPBU16/mpMxApDPrWvZ08DcLPEoRnuA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.3", @@ -12541,6 +12559,7 @@ "integrity": "sha512-yF+o4POL41rpAzj5KVILUxm1GCjKnELvaqmU9TLLUbMfDzuN0UpUR9uaDs+mCtjPe+uYPksXDRLQGGPvj1cTmA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/expect": "4.1.1", "@vitest/mocker": "4.1.1", diff --git a/package.json b/package.json index 92e4dc75..2ca0a710 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@toruslabs/torus.js", - "version": "17.2.2", + "version": "17.2.3", "description": "Handle communication with torus nodes", "main": "dist/lib.cjs/index.js", "module": "dist/lib.esm/index.js", diff --git a/src/helpers/citadelUtils.ts b/src/helpers/citadelUtils.ts index 9796bf2e..ab1988e2 100644 --- a/src/helpers/citadelUtils.ts +++ b/src/helpers/citadelUtils.ts @@ -1,5 +1,7 @@ -import { BUILD_ENV_TYPE, CITADEL_SERVER_MAP } from "@toruslabs/constants"; -import { get } from "@toruslabs/http-helpers"; +import { BUILD_ENV_TYPE, CITADEL_SERVER_MAP, TORUS_NETWORK_TYPE } from "@toruslabs/constants"; +import { get, put } from "@toruslabs/http-helpers"; + +import { RetrieveSharesParams } from "../interfaces"; export interface CitadelAllowParams { buildEnv: BUILD_ENV_TYPE; @@ -14,6 +16,24 @@ export interface CitadelAllowParams { torusLoginFailed?: boolean; } +export interface CitadelAuthFlowAuditParams { + oauthInitiated?: boolean; + oauthVerified?: boolean; + oauthCompleted?: boolean; + oauthVerificationFailed?: boolean; + oauthFailed?: boolean; +} + +export interface CitadelAuditParams extends CitadelAuthFlowAuditParams { + recordId: string; + authConnection: string; + authConnectionId: string; + groupedAuthConnectionId: string; + userId: string; + web3AuthNetwork: string; + web3AuthClientId: string; +} + export function buildAllowUrl(params: CitadelAllowParams): string { const url = new URL(`${CITADEL_SERVER_MAP[params.buildEnv]}/v1/signer/allow`); url.searchParams.set("recordid", params.recordId); @@ -36,10 +56,33 @@ export function buildAllowUrl(params: CitadelAllowParams): string { return url.toString(); } +export function buildAuditPayload( + network: TORUS_NETWORK_TYPE, + clientId: string, + params: RetrieveSharesParams, + authFlowAuditParams: CitadelAuthFlowAuditParams +): CitadelAuditParams { + return { + ...authFlowAuditParams, + recordId: params.recordId, + authConnection: params.authConnection || "", + authConnectionId: params.verifierParams.sub_verifier_ids?.[0] || "", + groupedAuthConnectionId: params.verifier || "", + userId: params.verifierParams.verifier_id || "", + web3AuthNetwork: network, + web3AuthClientId: clientId, + }; +} + export async function callAllowApi(params: CitadelAllowParams): Promise { await get(buildAllowUrl(params)); } +export async function callAuditApi(buildEnv: BUILD_ENV_TYPE, params: CitadelAuditParams): Promise { + const url = new URL(`${CITADEL_SERVER_MAP[buildEnv]}/v1/user/audit`); + await put(url.toString(), params); +} + export function generateRecordId(): string { const cr = typeof globalThis === "object" ? globalThis.crypto : null; if (typeof cr?.randomUUID !== "function") throw new Error("crypto.randomUUID must be defined"); diff --git a/src/interfaces.ts b/src/interfaces.ts index b7ead091..c6f6cc9b 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -221,6 +221,7 @@ export interface VerifierParams { [key: string]: unknown; verifier_id: string; extended_verifier_id?: string; + sub_verifier_ids?: string[]; } export type StringifiedType = Record; @@ -283,6 +284,11 @@ export interface ImportKeyParams { newPrivateKey: string; extraParams?: TorusUtilsExtraParams; checkCommitment?: boolean; + + /** + * Optional recordId to used for the analytics tracking. + */ + recordId?: string; } export interface RetrieveSharesParams { @@ -295,4 +301,15 @@ export interface RetrieveSharesParams { extraParams?: TorusUtilsExtraParams; useDkg?: boolean; checkCommitment?: boolean; + + /** + * User social login provider name. + * This is used for the analytics tracking. + */ + authConnection?: string; + + /** + * Optional recordId to used for the analytics tracking. + */ + recordId?: string; } diff --git a/src/torus.ts b/src/torus.ts index c368b8e7..36b763b9 100644 --- a/src/torus.ts +++ b/src/torus.ts @@ -4,9 +4,12 @@ import { setAPIKey, setEmbedHost } from "@toruslabs/http-helpers"; import { config } from "./config"; import { bigintToHex, + buildAuditPayload, bytesToHex, callAllowApi, + callAuditApi, CitadelAllowParams, + CitadelAuthFlowAuditParams, Curve, encodeEd25519Point, generateAddressFromPubKey, @@ -150,6 +153,8 @@ class Torus { extraParams.session_token_exp_second = Torus.sessionTime; } + const recordId = params.recordId || generateRecordId(); + const allowParams = { buildEnv: this.buildEnv, verifier, @@ -157,10 +162,15 @@ class Torus { network: this.network, clientId: this.clientId, source: this.source, - recordId: generateRecordId(), + recordId, }; let result: TorusKey; + + // report oauth completed + // if recordId isn't provided in the params, we will also report oauth initiated + this.reportUserAuthFlowAudit({ ...params, recordId }, { oauthCompleted: true, ...(params.recordId ? {} : { oauthInitiated: true }) }); + try { result = await retrieveOrImportShare({ recordId: allowParams.recordId, @@ -185,8 +195,13 @@ class Torus { checkCommitment, source: this.source, }); + + // report oauth verified + this.reportUserAuthFlowAudit({ ...params, recordId }, { oauthVerified: true, ...(params.recordId ? {} : { oauthInitiated: true }) }); } catch (error) { this.reportSignerAllow({ ...allowParams, torusLoginFailed: true }); + // report oauth verification failed + this.reportUserAuthFlowAudit({ ...params, recordId }, { oauthVerificationFailed: true }); throw error; } @@ -202,6 +217,21 @@ class Torus { } } + /** + * Report user auth flow audit to the citadel server. + * @param recordId - The record id to be used for the analytics tracking. + * @param params - The parameters for the retrieve shares operation. + * @param authStepStatus - The status of the authentication steps. + */ + async reportUserAuthFlowAudit(params: RetrieveSharesParams, authFlowAuditParams: CitadelAuthFlowAuditParams): Promise { + try { + const auditParams = buildAuditPayload(this.network, this.clientId, params, authFlowAuditParams); + await callAuditApi(this.buildEnv, auditParams); + } catch (error) { + log.error("Failed to log user auth flow audit", error); + } + } + async getPublicAddress( endpoints: string[], torusNodePubs: INodePub[], @@ -262,8 +292,10 @@ class Torus { } } + const recordId = params.recordId || generateRecordId(); + return retrieveOrImportShare({ - recordId: generateRecordId(), + recordId, legacyMetadataHost: this.legacyMetadataHost, serverTimeOffset: this.serverTimeOffset, enableOneKey: this.enableOneKey, From e170660bdfa6a13e526805bcf33a88f841d9dc72 Mon Sep 17 00:00:00 2001 From: lwin Date: Fri, 27 Mar 2026 11:08:54 +0800 Subject: [PATCH 02/11] chore: some comments --- src/torus.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/torus.ts b/src/torus.ts index 36b763b9..07905e36 100644 --- a/src/torus.ts +++ b/src/torus.ts @@ -167,7 +167,7 @@ class Torus { let result: TorusKey; - // report oauth completed + // report oauth completed, we won't await this call as it's only for analytics tracking // if recordId isn't provided in the params, we will also report oauth initiated this.reportUserAuthFlowAudit({ ...params, recordId }, { oauthCompleted: true, ...(params.recordId ? {} : { oauthInitiated: true }) }); @@ -196,11 +196,11 @@ class Torus { source: this.source, }); - // report oauth verified - this.reportUserAuthFlowAudit({ ...params, recordId }, { oauthVerified: true, ...(params.recordId ? {} : { oauthInitiated: true }) }); + // report oauth verified, we won't await this call as it's only for analytics tracking + this.reportUserAuthFlowAudit({ ...params, recordId }, { oauthVerified: true }); } catch (error) { this.reportSignerAllow({ ...allowParams, torusLoginFailed: true }); - // report oauth verification failed + // report oauth verification failed, we won't await this call as it's only for analytics tracking this.reportUserAuthFlowAudit({ ...params, recordId }, { oauthVerificationFailed: true }); throw error; } From 34d4b0d7e7c15b15cdf16931d916dbabf9072584 Mon Sep 17 00:00:00 2001 From: lwin Date: Fri, 27 Mar 2026 12:16:13 +0800 Subject: [PATCH 03/11] chore: revert package version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2ca0a710..92e4dc75 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@toruslabs/torus.js", - "version": "17.2.3", + "version": "17.2.2", "description": "Handle communication with torus nodes", "main": "dist/lib.cjs/index.js", "module": "dist/lib.esm/index.js", From 0ccfacbc29278ef5e775dfd96a8944756c6aec4d Mon Sep 17 00:00:00 2001 From: lwin Date: Fri, 27 Mar 2026 14:05:16 +0800 Subject: [PATCH 04/11] chore: update audit payload --- src/helpers/citadelUtils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/helpers/citadelUtils.ts b/src/helpers/citadelUtils.ts index ab1988e2..0ff58813 100644 --- a/src/helpers/citadelUtils.ts +++ b/src/helpers/citadelUtils.ts @@ -29,7 +29,7 @@ export interface CitadelAuditParams extends CitadelAuthFlowAuditParams { authConnection: string; authConnectionId: string; groupedAuthConnectionId: string; - userId: string; + oauthUserId: string; web3AuthNetwork: string; web3AuthClientId: string; } @@ -68,7 +68,7 @@ export function buildAuditPayload( authConnection: params.authConnection || "", authConnectionId: params.verifierParams.sub_verifier_ids?.[0] || "", groupedAuthConnectionId: params.verifier || "", - userId: params.verifierParams.verifier_id || "", + oauthUserId: params.verifierParams.verifier_id || "", web3AuthNetwork: network, web3AuthClientId: clientId, }; From ad21d2dda6f85a5bf326ccbcd8cf07d8e1d9342b Mon Sep 17 00:00:00 2001 From: lwin Date: Fri, 27 Mar 2026 15:17:09 +0800 Subject: [PATCH 05/11] feat: update Allow requests --- src/helpers/citadelUtils.ts | 16 ++-------------- src/helpers/nodeUtils.ts | 1 - src/torus.ts | 4 ++-- 3 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/helpers/citadelUtils.ts b/src/helpers/citadelUtils.ts index 0ff58813..1c922a86 100644 --- a/src/helpers/citadelUtils.ts +++ b/src/helpers/citadelUtils.ts @@ -11,9 +11,6 @@ export interface CitadelAllowParams { clientId: string; recordId: string; source?: string; - torusLoginInitiated?: boolean; - torusLoginSuccess?: boolean; - torusLoginFailed?: boolean; } export interface CitadelAuthFlowAuditParams { @@ -29,7 +26,7 @@ export interface CitadelAuditParams extends CitadelAuthFlowAuditParams { authConnection: string; authConnectionId: string; groupedAuthConnectionId: string; - oauthUserId: string; + oAuthUserId: string; web3AuthNetwork: string; web3AuthClientId: string; } @@ -44,15 +41,6 @@ export function buildAllowUrl(params: CitadelAllowParams): string { if (params.source) { url.searchParams.set("source", params.source); } - if (typeof params.torusLoginInitiated !== "undefined") { - url.searchParams.set("toruslogininitiated", params.torusLoginInitiated.toString()); - } - if (typeof params.torusLoginSuccess !== "undefined") { - url.searchParams.set("torusloginsuccess", params.torusLoginSuccess.toString()); - } - if (typeof params.torusLoginFailed !== "undefined") { - url.searchParams.set("torusloginfailed", params.torusLoginFailed.toString()); - } return url.toString(); } @@ -68,7 +56,7 @@ export function buildAuditPayload( authConnection: params.authConnection || "", authConnectionId: params.verifierParams.sub_verifier_ids?.[0] || "", groupedAuthConnectionId: params.verifier || "", - oauthUserId: params.verifierParams.verifier_id || "", + oAuthUserId: params.verifierParams.verifier_id || "", web3AuthNetwork: network, web3AuthClientId: clientId, }; diff --git a/src/helpers/nodeUtils.ts b/src/helpers/nodeUtils.ts index dee63f0e..7346a5ae 100644 --- a/src/helpers/nodeUtils.ts +++ b/src/helpers/nodeUtils.ts @@ -398,7 +398,6 @@ export async function retrieveOrImportShare(params: { clientId, source, recordId, - torusLoginInitiated: true, }); // generate temporary private and public key that is used to secure receive shares diff --git a/src/torus.ts b/src/torus.ts index 07905e36..e49d3241 100644 --- a/src/torus.ts +++ b/src/torus.ts @@ -199,13 +199,13 @@ class Torus { // report oauth verified, we won't await this call as it's only for analytics tracking this.reportUserAuthFlowAudit({ ...params, recordId }, { oauthVerified: true }); } catch (error) { - this.reportSignerAllow({ ...allowParams, torusLoginFailed: true }); + this.reportSignerAllow(allowParams); // report oauth verification failed, we won't await this call as it's only for analytics tracking this.reportUserAuthFlowAudit({ ...params, recordId }, { oauthVerificationFailed: true }); throw error; } - this.reportSignerAllow({ ...allowParams, torusLoginSuccess: true }); + this.reportSignerAllow(allowParams); return result; } From 65c92e2cf23027086bbe9bfb987261943b6c31b8 Mon Sep 17 00:00:00 2001 From: lwin Date: Sun, 29 Mar 2026 21:47:00 +0800 Subject: [PATCH 06/11] chore: resolved cursor comment --- src/helpers/citadelUtils.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/helpers/citadelUtils.ts b/src/helpers/citadelUtils.ts index 1c922a86..00fdca0e 100644 --- a/src/helpers/citadelUtils.ts +++ b/src/helpers/citadelUtils.ts @@ -50,6 +50,10 @@ export function buildAuditPayload( params: RetrieveSharesParams, authFlowAuditParams: CitadelAuthFlowAuditParams ): CitadelAuditParams { + if (!params.recordId) { + params.recordId = generateRecordId(); + } + return { ...authFlowAuditParams, recordId: params.recordId, From 3cef028721d713ad3d7e0d562874939ca2ceef37 Mon Sep 17 00:00:00 2001 From: lwin Date: Mon, 30 Mar 2026 16:55:16 +0800 Subject: [PATCH 07/11] feat: updated audit logics --- src/helpers/citadelUtils.ts | 35 +++++++++++++++++++++++++---------- src/helpers/nodeUtils.ts | 1 + src/torus.ts | 29 +++++++++++++++++++---------- 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/src/helpers/citadelUtils.ts b/src/helpers/citadelUtils.ts index 00fdca0e..69b70b6a 100644 --- a/src/helpers/citadelUtils.ts +++ b/src/helpers/citadelUtils.ts @@ -3,7 +3,15 @@ import { get, put } from "@toruslabs/http-helpers"; import { RetrieveSharesParams } from "../interfaces"; -export interface CitadelAllowParams { +export interface CitadelAuthFlowAuditParams { + oauthInitiated?: boolean; + oauthVerified?: boolean; + oauthCompleted?: boolean; + oauthVerificationFailed?: boolean; + oauthFailed?: boolean; +} + +export interface CitadelAllowParams extends CitadelAuthFlowAuditParams { buildEnv: BUILD_ENV_TYPE; verifier: string; verifierId: string; @@ -13,14 +21,6 @@ export interface CitadelAllowParams { source?: string; } -export interface CitadelAuthFlowAuditParams { - oauthInitiated?: boolean; - oauthVerified?: boolean; - oauthCompleted?: boolean; - oauthVerificationFailed?: boolean; - oauthFailed?: boolean; -} - export interface CitadelAuditParams extends CitadelAuthFlowAuditParams { recordId: string; authConnection: string; @@ -41,6 +41,21 @@ export function buildAllowUrl(params: CitadelAllowParams): string { if (params.source) { url.searchParams.set("source", params.source); } + if (params.oauthInitiated) { + url.searchParams.set("oauthinitiated", params.oauthInitiated.toString()); + } + if (params.oauthVerified) { + url.searchParams.set("oauthverified", params.oauthVerified.toString()); + } + if (params.oauthCompleted) { + url.searchParams.set("oauthcompleted", params.oauthCompleted.toString()); + } + if (params.oauthVerificationFailed) { + url.searchParams.set("oauthverificationfailed", params.oauthVerificationFailed.toString()); + } + if (params.oauthFailed) { + url.searchParams.set("oauthfailed", params.oauthFailed.toString()); + } return url.toString(); } @@ -71,7 +86,7 @@ export async function callAllowApi(params: CitadelAllowParams): Promise { } export async function callAuditApi(buildEnv: BUILD_ENV_TYPE, params: CitadelAuditParams): Promise { - const url = new URL(`${CITADEL_SERVER_MAP[buildEnv]}/v1/user/audit`); + const url = new URL(`${CITADEL_SERVER_MAP[buildEnv]}/v1/auth/audit`); await put(url.toString(), params); } diff --git a/src/helpers/nodeUtils.ts b/src/helpers/nodeUtils.ts index 7346a5ae..602e0889 100644 --- a/src/helpers/nodeUtils.ts +++ b/src/helpers/nodeUtils.ts @@ -390,6 +390,7 @@ export async function retrieveOrImportShare(params: { source, recordId, } = params; + // call feature-gating check before share retrieval await callAllowApi({ buildEnv, verifier, diff --git a/src/torus.ts b/src/torus.ts index e49d3241..af8f35e9 100644 --- a/src/torus.ts +++ b/src/torus.ts @@ -167,9 +167,13 @@ class Torus { let result: TorusKey; - // report oauth completed, we won't await this call as it's only for analytics tracking - // if recordId isn't provided in the params, we will also report oauth initiated - this.reportUserAuthFlowAudit({ ...params, recordId }, { oauthCompleted: true, ...(params.recordId ? {} : { oauthInitiated: true }) }); + if (!params.recordId) { + // report oauth completed, we won't await this call as it's only for analytics tracking + // if recordId isn't provided in the params, we will also report oauth initiated + this.reportSignerAllow({ ...allowParams, oauthCompleted: true, oauthInitiated: true }); + } else { + this.reportUserAuthFlowAudit({ ...params, recordId }, { oauthCompleted: true }); + } try { result = await retrieveOrImportShare({ @@ -195,17 +199,22 @@ class Torus { checkCommitment, source: this.source, }); - - // report oauth verified, we won't await this call as it's only for analytics tracking - this.reportUserAuthFlowAudit({ ...params, recordId }, { oauthVerified: true }); } catch (error) { - this.reportSignerAllow(allowParams); - // report oauth verification failed, we won't await this call as it's only for analytics tracking - this.reportUserAuthFlowAudit({ ...params, recordId }, { oauthVerificationFailed: true }); + if (params.recordId) { + // report oauth verification failed, we won't await this call as it's only for analytics tracking + this.reportUserAuthFlowAudit({ ...params, recordId }, { oauthVerificationFailed: true }); + } else { + this.reportSignerAllow({ ...allowParams, oauthVerificationFailed: true }); + } throw error; } - this.reportSignerAllow(allowParams); + if (!params.recordId) { + this.reportSignerAllow({ ...allowParams, oauthVerified: true }); + } else { + // report oauth verified, we won't await this call as it's only for analytics tracking + this.reportUserAuthFlowAudit({ ...params, recordId }, { oauthVerified: true }); + } return result; } From f10014c96225357aae13c92cbaff801c07da106d Mon Sep 17 00:00:00 2001 From: lwin Date: Mon, 30 Mar 2026 17:56:29 +0800 Subject: [PATCH 08/11] fix: fixed citadelAllowParams for oauth audit flags --- src/helpers/citadelUtils.ts | 21 +++++++++++---------- src/helpers/common.ts | 4 ++++ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/helpers/citadelUtils.ts b/src/helpers/citadelUtils.ts index 69b70b6a..098e5689 100644 --- a/src/helpers/citadelUtils.ts +++ b/src/helpers/citadelUtils.ts @@ -2,6 +2,7 @@ import { BUILD_ENV_TYPE, CITADEL_SERVER_MAP, TORUS_NETWORK_TYPE } from "@torusla import { get, put } from "@toruslabs/http-helpers"; import { RetrieveSharesParams } from "../interfaces"; +import { isNullOrUndefined } from "./common"; export interface CitadelAuthFlowAuditParams { oauthInitiated?: boolean; @@ -41,20 +42,20 @@ export function buildAllowUrl(params: CitadelAllowParams): string { if (params.source) { url.searchParams.set("source", params.source); } - if (params.oauthInitiated) { - url.searchParams.set("oauthinitiated", params.oauthInitiated.toString()); + if (!isNullOrUndefined(params.oauthInitiated)) { + url.searchParams.set("oauthInitiated", params.oauthInitiated.toString()); } - if (params.oauthVerified) { - url.searchParams.set("oauthverified", params.oauthVerified.toString()); + if (!isNullOrUndefined(params.oauthVerified)) { + url.searchParams.set("oauthVerified", params.oauthVerified.toString()); } - if (params.oauthCompleted) { - url.searchParams.set("oauthcompleted", params.oauthCompleted.toString()); + if (!isNullOrUndefined(params.oauthCompleted)) { + url.searchParams.set("oauthCompleted", params.oauthCompleted.toString()); } - if (params.oauthVerificationFailed) { - url.searchParams.set("oauthverificationfailed", params.oauthVerificationFailed.toString()); + if (!isNullOrUndefined(params.oauthVerificationFailed)) { + url.searchParams.set("oauthVerificationFailed", params.oauthVerificationFailed.toString()); } - if (params.oauthFailed) { - url.searchParams.set("oauthfailed", params.oauthFailed.toString()); + if (!isNullOrUndefined(params.oauthFailed)) { + url.searchParams.set("oauthFailed", params.oauthFailed.toString()); } return url.toString(); } diff --git a/src/helpers/common.ts b/src/helpers/common.ts index f41c8cf1..ce4a68b4 100644 --- a/src/helpers/common.ts +++ b/src/helpers/common.ts @@ -161,3 +161,7 @@ export function retryCommitment(executionPromise: () => Promise Date: Tue, 31 Mar 2026 13:50:39 +0800 Subject: [PATCH 09/11] chore: combine signer allow api with oauthInitiated track --- src/helpers/citadelUtils.ts | 13 ++++++++++++- src/helpers/nodeUtils.ts | 4 +++- src/torus.ts | 25 +++++++++++++------------ 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/helpers/citadelUtils.ts b/src/helpers/citadelUtils.ts index 098e5689..d4310849 100644 --- a/src/helpers/citadelUtils.ts +++ b/src/helpers/citadelUtils.ts @@ -4,6 +4,11 @@ import { get, put } from "@toruslabs/http-helpers"; import { RetrieveSharesParams } from "../interfaces"; import { isNullOrUndefined } from "./common"; +export enum CitadelAllowParamsSetOrUnsetFlag { + SET = 1, + UNSET = 0, +} + export interface CitadelAuthFlowAuditParams { oauthInitiated?: boolean; oauthVerified?: boolean; @@ -12,7 +17,7 @@ export interface CitadelAuthFlowAuditParams { oauthFailed?: boolean; } -export interface CitadelAllowParams extends CitadelAuthFlowAuditParams { +export interface CitadelAllowParams { buildEnv: BUILD_ENV_TYPE; verifier: string; verifierId: string; @@ -20,6 +25,12 @@ export interface CitadelAllowParams extends CitadelAuthFlowAuditParams { clientId: string; recordId: string; source?: string; + // flags for auditing the auth flow + oauthInitiated?: CitadelAllowParamsSetOrUnsetFlag; + oauthVerified?: CitadelAllowParamsSetOrUnsetFlag; + oauthCompleted?: CitadelAllowParamsSetOrUnsetFlag; + oauthVerificationFailed?: CitadelAllowParamsSetOrUnsetFlag; + oauthFailed?: CitadelAllowParamsSetOrUnsetFlag; } export interface CitadelAuditParams extends CitadelAuthFlowAuditParams { diff --git a/src/helpers/nodeUtils.ts b/src/helpers/nodeUtils.ts index 602e0889..604e35a3 100644 --- a/src/helpers/nodeUtils.ts +++ b/src/helpers/nodeUtils.ts @@ -27,7 +27,7 @@ import { import log from "../loglevel"; import { Some } from "../some"; import { TorusUtilsExtraParams } from "../TorusUtilsExtraParams"; -import { callAllowApi } from "./citadelUtils"; +import { callAllowApi, CitadelAllowParamsSetOrUnsetFlag } from "./citadelUtils"; import { base64ToBytes, bigintToHex, @@ -399,6 +399,8 @@ export async function retrieveOrImportShare(params: { clientId, source, recordId, + oauthInitiated: CitadelAllowParamsSetOrUnsetFlag.SET, + oauthCompleted: CitadelAllowParamsSetOrUnsetFlag.SET, }); // generate temporary private and public key that is used to secure receive shares diff --git a/src/torus.ts b/src/torus.ts index af8f35e9..931c4f54 100644 --- a/src/torus.ts +++ b/src/torus.ts @@ -9,6 +9,7 @@ import { callAllowApi, callAuditApi, CitadelAllowParams, + CitadelAllowParamsSetOrUnsetFlag, CitadelAuthFlowAuditParams, Curve, encodeEd25519Point, @@ -165,15 +166,13 @@ class Torus { recordId, }; - let result: TorusKey; + // for auditing the auth flow + const auditParams: CitadelAuthFlowAuditParams = { + // at this point, user has completed the oauth login + oauthCompleted: true, + }; - if (!params.recordId) { - // report oauth completed, we won't await this call as it's only for analytics tracking - // if recordId isn't provided in the params, we will also report oauth initiated - this.reportSignerAllow({ ...allowParams, oauthCompleted: true, oauthInitiated: true }); - } else { - this.reportUserAuthFlowAudit({ ...params, recordId }, { oauthCompleted: true }); - } + let result: TorusKey; try { result = await retrieveOrImportShare({ @@ -202,18 +201,20 @@ class Torus { } catch (error) { if (params.recordId) { // report oauth verification failed, we won't await this call as it's only for analytics tracking - this.reportUserAuthFlowAudit({ ...params, recordId }, { oauthVerificationFailed: true }); + auditParams.oauthVerificationFailed = true; + this.reportUserAuthFlowAudit({ ...params, recordId }, auditParams); } else { - this.reportSignerAllow({ ...allowParams, oauthVerificationFailed: true }); + this.reportSignerAllow({ ...allowParams, oauthVerificationFailed: CitadelAllowParamsSetOrUnsetFlag.SET }); } throw error; } if (!params.recordId) { - this.reportSignerAllow({ ...allowParams, oauthVerified: true }); + this.reportSignerAllow({ ...allowParams, oauthVerified: CitadelAllowParamsSetOrUnsetFlag.SET }); } else { // report oauth verified, we won't await this call as it's only for analytics tracking - this.reportUserAuthFlowAudit({ ...params, recordId }, { oauthVerified: true }); + auditParams.oauthVerified = true; + this.reportUserAuthFlowAudit({ ...params, recordId }, auditParams); } return result; } From 524ac3c8deaef391d9c10ffa43b0afd9c27a11f7 Mon Sep 17 00:00:00 2001 From: chaitanyapotti Date: Tue, 31 Mar 2026 14:23:01 +0800 Subject: [PATCH 10/11] lock file --- package-lock.json | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/package-lock.json b/package-lock.json index e3ba0355..f3b537f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -89,7 +89,6 @@ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -1669,7 +1668,6 @@ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -3054,7 +3052,6 @@ "integrity": "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@octokit/auth-token": "^6.0.0", "@octokit/graphql": "^9.0.3", @@ -4418,7 +4415,6 @@ "integrity": "sha512-DZ8VwRFUNzuqJ5khrvwMXHmvPe+zGayJhr2CDNiKB1WBE1ST8Djl00D0IC4vvNmHMdj6DlbYRIaFE7WHjlDl5w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -4482,7 +4478,6 @@ "integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.56.1", "@typescript-eslint/types": "8.56.1", @@ -5144,7 +5139,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5634,7 +5628,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -6809,7 +6802,6 @@ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -6870,7 +6862,6 @@ "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", - "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -6997,7 +6988,6 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -9758,7 +9748,6 @@ "integrity": "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", @@ -10715,7 +10704,6 @@ "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -11231,7 +11219,6 @@ "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -12106,8 +12093,7 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, - "license": "0BSD", - "peer": true + "license": "0BSD" }, "node_modules/tsx": { "version": "4.21.0", @@ -12115,7 +12101,6 @@ "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" @@ -12239,7 +12224,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -12356,7 +12340,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "dependencies": { "napi-postinstall": "^0.3.0" }, @@ -12480,7 +12463,6 @@ "integrity": "sha512-1gFhNi+bHhRE/qKZOJXACm6tX4bA3Isy9KuKF15AgSRuRazNBOJfdDemPBU16/mpMxApDPrWvZ08DcLPEoRnuA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.3", @@ -12559,7 +12541,6 @@ "integrity": "sha512-yF+o4POL41rpAzj5KVILUxm1GCjKnELvaqmU9TLLUbMfDzuN0UpUR9uaDs+mCtjPe+uYPksXDRLQGGPvj1cTmA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@vitest/expect": "4.1.1", "@vitest/mocker": "4.1.1", From c3c05b941d592cb0f03770338a0b5c6c4464dd28 Mon Sep 17 00:00:00 2001 From: chaitanyapotti Date: Tue, 31 Mar 2026 14:23:17 +0800 Subject: [PATCH 11/11] 17.2.3 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index f3b537f0..f663d173 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@toruslabs/torus.js", - "version": "17.2.2", + "version": "17.2.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@toruslabs/torus.js", - "version": "17.2.2", + "version": "17.2.3", "license": "MIT", "dependencies": { "@toruslabs/constants": "^16.1.1", diff --git a/package.json b/package.json index 92e4dc75..2ca0a710 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@toruslabs/torus.js", - "version": "17.2.2", + "version": "17.2.3", "description": "Handle communication with torus nodes", "main": "dist/lib.cjs/index.js", "module": "dist/lib.esm/index.js",