Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
29 changes: 29 additions & 0 deletions .github/workflows/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
## Jira Link

<!-- Link to the Jira ticket (if applicable) -->

## Description

<!-- Describe your changes in detail -->

## How has this been tested?

<!-- Please describe how you tested your changes -->

## Screenshots (if appropriate)

<!-- Add screenshots if UI changes are involved -->

## Types of changes

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)

## Checklist

- [ ] My code follows the code style of this project. (run lint)
- [ ] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly.
- [ ] I have added tests to cover my changes.
- [ ] All new and existing tests passed.
Copy link

Choose a reason for hiding this comment

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

PR template placed in wrong directory

Medium Severity

The PULL_REQUEST_TEMPLATE.md file is placed inside .github/workflows/ instead of .github/. GitHub only recognizes PR templates at .github/pull_request_template.md, the repository root, or docs/. Files inside .github/workflows/ are treated as GitHub Actions workflow definitions, so this template will never be auto-populated when creating a new pull request.

Fix in Cursor Fix in Web

2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jobs:
build:
strategy:
matrix:
node: ["22.x"]
node: ["24.x"]
os: [ubuntu-latest]

runs-on: ${{ matrix.os }}
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
>=20.x
>=24.x
6,765 changes: 2,275 additions & 4,490 deletions package-lock.json

Large diffs are not rendered by default.

43 changes: 22 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
"description": "CustomAuth login with torus to get user private key",
"main": "dist/lib.cjs/index.js",
"module": "dist/lib.esm/index.js",
"unpkg": "dist/customauth.umd.min.js",
"jsdelivr": "dist/customauth.umd.min.js",
"unpkg": "dist/lib.esm/index.js",
"jsdelivr": "dist/lib.esm/index.js",
"types": "dist/lib.cjs/types/index.d.ts",
"sideEffects": false,
"scripts": {
"build": "torus-scripts build",
"start": "torus-scripts start",
"release": "torus-scripts release",
"lint:ts": "eslint --fix 'src/**/*.ts'",
"lint:ts": "torus-scripts lint --fix",
"prepack": "npm run build",
"test": "echo \"Error: no test specified\" && exit 1",
"prepare": "husky"
Expand All @@ -32,30 +32,31 @@
},
"dependencies": {
"@chaitanyapotti/register-service-worker": "^1.7.4",
"@toruslabs/broadcast-channel": "^12.0.0",
"@toruslabs/constants": "^15.0.0",
"@toruslabs/eccrypto": "^6.2.0",
"@toruslabs/fetch-node-details": "^15.0.0",
"@toruslabs/http-helpers": "^8.1.1",
"@toruslabs/metadata-helpers": "^7.0.2",
"@toruslabs/session-manager": "^4.0.2",
"@toruslabs/torus.js": "^16.0.0",
"@toruslabs/broadcast-channel": "^13.0.1",
"@toruslabs/constants": "^16.0.0",
"@toruslabs/eccrypto": "^7.0.0",
"@toruslabs/fetch-node-details": "^16.0.0",
"@toruslabs/http-helpers": "^9.0.0",
"@toruslabs/metadata-helpers": "^8.0.0",
"@toruslabs/session-manager": "^5.1.0",
"@toruslabs/torus.js": "^17.0.0",
"base64url": "^3.0.1",
"bowser": "^2.12.1",
"deepmerge": "^4.3.1",
"events": "^3.3.0",
"loglevel": "^1.9.2"
},
"devDependencies": {
"@sentry/core": "^9.12.0",
"@toruslabs/config": "^3.1.0",
"@toruslabs/eslint-config-typescript": "^4.1.4",
"@toruslabs/torus-scripts": "^7.1.6",
"eslint": "^9.39.1",
"@sentry/core": "^10.38.0",
"@toruslabs/config": "^4.0.0",
"@toruslabs/eslint-config-typescript": "^5.0.0",
"@toruslabs/torus-scripts": "^8.0.0",
"@types/node": "^22",
"eslint": "^9.39.2",
"husky": "^9.1.7",
"lint-staged": "^16.2.6",
"prettier": "^3.6.2",
"rimraf": "^6.1.0",
"lint-staged": "^16.2.7",
"prettier": "^3.8.1",
"rimraf": "^6.1.3",
"typed-emitter": "^2.1.0",
"typescript": "^5.9.3"
},
Expand Down Expand Up @@ -87,7 +88,7 @@
"direct auth"
],
"engines": {
"node": ">=20.x",
"npm": ">=9.x"
"node": ">=22.x",
"npm": ">=10.x"
}
}
1 change: 0 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@ export * from "./utils/error";
export * from "./utils/helpers";
export * from "./utils/interfaces";
export * from "./utils/PopupHandler";
export * from "./utils/StorageHelper";
47 changes: 34 additions & 13 deletions src/login.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { type INodeDetails, TORUS_NETWORK_TYPE } from "@toruslabs/constants";
import { NodeDetailManager } from "@toruslabs/fetch-node-details";
import { utf8ToBytes } from "@toruslabs/metadata-helpers";
import { SessionManager } from "@toruslabs/session-manager";
import { keccak256, type KeyType, Torus, TorusKey } from "@toruslabs/torus.js";

import { createHandler } from "./handlers/HandlerFactory";
Expand All @@ -22,7 +24,6 @@ import {
VerifierParams,
} from "./utils/interfaces";
import log from "./utils/loglevel";
import { StorageHelper } from "./utils/StorageHelper";

export class CustomAuth {
isInitialized: boolean;
Expand All @@ -46,10 +47,10 @@ export class CustomAuth {

nodeDetailManager: NodeDetailManager;

storageHelper: StorageHelper<LoginDetails>;

sentryHandler: SentryHandler;

private sessionManager: SessionManager<LoginDetails>;

constructor({
baseUrl,
network,
Expand Down Expand Up @@ -104,12 +105,15 @@ export class CustomAuth {
this.nodeDetailManager = new NodeDetailManager({ network });
if (enableLogging) log.enableAll();
else log.disableAll();
this.storageHelper = new StorageHelper(storageServerUrl);
this.sessionManager = new SessionManager<LoginDetails>({
sessionServerBaseUrl: storageServerUrl,
allowedOrigin: true,
useLocalStorage: true,
});
this.sentryHandler = new SentryHandler(sentry);
}

async init({ skipSw = false, skipInit = false, skipPrefetch = false }: InitParams = {}): Promise<void> {
this.storageHelper.init();
if (skipInit) {
this.isInitialized = true;
return;
Expand Down Expand Up @@ -167,9 +171,10 @@ export class CustomAuth {
// State has to be last here otherwise it will be overwritten
loginParams = { accessToken, idToken: idToken || tgAuthResult || "", ...rest, state: instanceParameters };
} else {
this.storageHelper.clearOrphanedData(`torus_login_`);
this.sessionManager.clearOrphanedData();
if (this.config.uxMode === UX_MODE.REDIRECT) {
await this.storageHelper.storeData(`torus_login_${loginHandler.nonce}`, { args });
this.sessionManager.sessionId = this.getSessionId(`torus_login_${loginHandler.nonce}`);
await this.sessionManager.createSession({ args });
}
loginParams = await loginHandler.handleLoginWindow({
locationReplaceOnRedirect: this.config.locationReplaceOnRedirect,
Expand Down Expand Up @@ -214,7 +219,7 @@ export class CustomAuth {
if (groupedAuthConnectionId) {
verifierParams["verify_params"] = [{ verifier_id: userId, idtoken: finalIdToken }];
verifierParams["sub_verifier_ids"] = [authConnectionId];
aggregateIdToken = keccak256(Buffer.from(finalIdToken, "utf8")).slice(2);
aggregateIdToken = keccak256(utf8ToBytes(finalIdToken)).slice(2);
}

const nodeDetails = await this.sentryHandler.startSpan(
Expand Down Expand Up @@ -279,9 +284,19 @@ export class CustomAuth {

log.info(instanceId, "instanceId");

const loginDetails = storageData || (await this.storageHelper.retrieveData(`torus_login_${instanceId}`));
let loginDetails = storageData;
if (!loginDetails) {
try {
this.sessionManager.sessionId = this.getSessionId(`torus_login_${instanceId}`);
loginDetails = await this.sessionManager.authorizeSession();
} catch (error) {
log.error(error, "Unable to read login details from session manager");
throw error;
}
}
const { args, ...rest } = loginDetails || {};
log.info(args, "args", this.storageHelper.storageMethodUsed);
const storageMethodUsed = "localStorage + server";
log.info(args, "args", storageMethodUsed);

let result: TorusLoginResponse;

Expand All @@ -297,7 +312,8 @@ export class CustomAuth {
const serializedError = await serializeError(err);
log.error(serializedError);
if (clearLoginDetails) {
this.storageHelper.clearStorage(`torus_login_${instanceId}`);
this.sessionManager.sessionId = this.getSessionId(`torus_login_${instanceId}`);
this.sessionManager.clearStorage();
}
return {
error: `${serializedError.message || ""}`,
Expand All @@ -311,7 +327,7 @@ export class CustomAuth {

if (!result)
return {
error: `Init parameters not found. It might be because storage is not available. Please retry the login in a different browser. Used storage method: ${this.storageHelper.storageMethodUsed}`,
error: `Init parameters not found. It might be because storage is not available. Please retry the login in a different browser. Used storage method: ${storageMethodUsed}`,
state: instanceParameters || {},
result: {},
hashParameters,
Expand All @@ -325,7 +341,7 @@ export class CustomAuth {
}

if (clearLoginDetails) {
this.storageHelper.clearStorage(`torus_login_${instanceId}`);
this.sessionManager.clearStorage();
}

return { result, state: instanceParameters || {}, hashParameters, args, ...rest };
Expand Down Expand Up @@ -364,4 +380,9 @@ export class CustomAuth {
}
});
}

private getSessionId(key: string): string {
// SessionManager expects a hex private key as sessionId; hashing the legacy string key keeps compatibility
return keccak256(utf8ToBytes(key)).slice(2);
}
}
101 changes: 0 additions & 101 deletions src/utils/StorageHelper.ts

This file was deleted.

1 change: 1 addition & 0 deletions src/utils/sessionHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export async function fetchDataFromBroadcastServer<T>(identifier: string, storag
sessionId: identifier,
sessionServerBaseUrl: storageServerUrl,
allowedOrigin: true,
useLocalStorage: true,
});

const data = await configManager.authorizeSession();
Expand Down