From b210ed1a641cd63eb2d66d8b569ad2d39b084509 Mon Sep 17 00:00:00 2001 From: Kavindu Sachinthe Date: Thu, 13 Aug 2026 10:40:12 +0530 Subject: [PATCH] refactor: remove __legacy__ folders from packages and refactor usage Signed-off-by: Kavindu Sachinthe --- .changeset/remove-legacy-folders.md | 8 + packages/browser/.eslintignore | 1 - .../client.ts => AsgardeoSPAClient.ts} | 2 +- .../src/{__legacy__ => }/clients/index.ts | 0 .../clients/main-thread-client.ts | 2 +- .../clients/web-worker-client.ts | 0 .../src/{__legacy__ => }/constants/errors.ts | 0 .../src/{__legacy__ => }/constants/hooks.ts | 0 .../src/{__legacy__ => }/constants/index.ts | 0 .../constants/messages-types.ts | 0 .../{__legacy__ => }/constants/parameters.ts | 0 .../constants/session-management.ts | 0 .../src/{__legacy__ => }/constants/storage.ts | 0 .../helpers/authentication-helper.ts | 0 .../src/{__legacy__ => }/helpers/index.ts | 0 .../helpers/session-management-helper.ts | 0 .../{__legacy__ => }/helpers/spa-helper.ts | 0 packages/browser/src/index.ts | 22 +- .../{__legacy__ => }/models/client-config.ts | 0 .../src/{__legacy__ => }/models/client.ts | 0 .../{__legacy__ => }/models/http-client.ts | 0 .../src/{__legacy__ => }/models/index.ts | 0 .../src/{__legacy__ => }/models/message.ts | 0 .../models/request-custom-grant.ts | 0 .../models/session-management-helper.ts | 0 .../src/{__legacy__ => }/models/sign-in.ts | 0 .../{__legacy__ => }/models/sign-out-error.ts | 0 .../src/{__legacy__ => }/models/storage.ts | 0 .../src/{__legacy__ => }/models/web-worker.ts | 0 .../src/{__legacy__ => }/stores/index.ts | 0 .../{__legacy__ => }/stores/local-store.ts | 0 .../{__legacy__ => }/stores/memory-store.ts | 0 .../{__legacy__ => }/stores/session-store.ts | 0 .../{__legacy__ => }/utils/crypto-utils.ts | 0 packages/browser/src/utils/http.ts | 2 +- .../src/{__legacy__ => }/utils/index.ts | 0 .../{__legacy__ => }/utils/message-utils.ts | 0 .../src/{__legacy__ => }/utils/spa-utils.ts | 0 packages/browser/src/web.worker.ts | 6 +- .../src/{__legacy__ => }/worker/index.ts | 0 .../{__legacy__ => }/worker/worker-core.ts | 2 +- .../worker/worker-receiver.ts | 0 packages/express/.eslintignore | 1 - ...ient.ts => LegacyAsgardeoExpressClient.ts} | 0 .../constants/default-options.ts | 0 .../src/{__legacy__ => }/constants/index.ts | 0 .../constants/logger-config.ts | 0 packages/express/src/index.ts | 5 +- .../middleware/authentication.ts | 2 +- .../src/{__legacy__ => }/middleware/index.ts | 0 .../middleware/protect-route.ts | 2 +- .../{__legacy__ => }/models/client-config.ts | 0 .../src/{__legacy__ => }/models/data.ts | 0 .../src/{__legacy__ => }/models/index.ts | 0 .../{__legacy__ => }/models/protect-route.ts | 0 .../{__legacy__ => }/utils/express-utils.ts | 0 packages/javascript/src/AsgardeoAuthClient.ts | 432 ++++++ .../src/AsgardeoJavaScriptClient.ts | 4 +- packages/javascript/src/StorageManager.ts | 2 +- packages/javascript/src/__legacy__/client.ts | 1205 ----------------- .../helpers/authentication-helper.ts | 336 ----- .../src/__legacy__/helpers/index.ts | 19 - packages/javascript/src/api/exchangeToken.ts | 114 ++ .../javascript/src/api/handleTokenResponse.ts | 65 + .../api/loadOpenIDProviderConfiguration.ts | 104 ++ .../javascript/src/api/refreshAccessToken.ts | 93 ++ .../javascript/src/api/requestAccessToken.ts | 146 ++ .../javascript/src/api/revokeAccessToken.ts | 81 ++ .../javascript/src/api/validateIdToken.ts | 82 ++ packages/javascript/src/index.ts | 4 +- .../auth-client-config.ts} | 8 +- .../models/index.ts => utils/clearSession.ts} | 12 +- .../src/utils/getAuthenticatedUserInfo.ts | 40 + .../utils/replaceCustomGrantTemplateTags.ts | 76 ++ .../javascript/src/utils/resolveEndpoints.ts | 39 + .../src/utils/resolveEndpointsByBaseURL.ts | 80 ++ .../src/utils/resolveEndpointsExplicitly.ts | 75 + .../client.ts => LegacyAsgardeoNodeClient.ts} | 0 .../src/{__legacy__ => }/constants/index.ts | 0 .../constants/logger-config.ts | 0 .../{__legacy__ => }/constants/uuid-config.ts | 0 .../{__legacy__ => }/core/authentication.ts | 0 .../node/src/{__legacy__ => }/core/index.ts | 0 packages/node/src/index.ts | 6 +- .../node/src/{__legacy__ => }/models/index.ts | 0 .../{__legacy__ => }/models/session-data.ts | 0 .../{__legacy__ => }/models/url-callback.ts | 0 .../node/src/{__legacy__ => }/stores/index.ts | 0 .../stores/memory-cache-store.ts | 0 .../{__legacy__ => }/utils/crypto-utils.ts | 0 .../node/src/{__legacy__ => }/utils/index.ts | 0 .../{__legacy__ => }/utils/logger-utils.ts | 0 .../{__legacy__ => }/utils/session-utils.ts | 0 packages/vue/tsconfig.lib.json | 1 - scripts/aggregate-changelogs.js | 2 +- 95 files changed, 1481 insertions(+), 1600 deletions(-) create mode 100644 .changeset/remove-legacy-folders.md rename packages/browser/src/{__legacy__/client.ts => AsgardeoSPAClient.ts} (99%) rename packages/browser/src/{__legacy__ => }/clients/index.ts (100%) rename packages/browser/src/{__legacy__ => }/clients/main-thread-client.ts (99%) rename packages/browser/src/{__legacy__ => }/clients/web-worker-client.ts (100%) rename packages/browser/src/{__legacy__ => }/constants/errors.ts (100%) rename packages/browser/src/{__legacy__ => }/constants/hooks.ts (100%) rename packages/browser/src/{__legacy__ => }/constants/index.ts (100%) rename packages/browser/src/{__legacy__ => }/constants/messages-types.ts (100%) rename packages/browser/src/{__legacy__ => }/constants/parameters.ts (100%) rename packages/browser/src/{__legacy__ => }/constants/session-management.ts (100%) rename packages/browser/src/{__legacy__ => }/constants/storage.ts (100%) rename packages/browser/src/{__legacy__ => }/helpers/authentication-helper.ts (100%) rename packages/browser/src/{__legacy__ => }/helpers/index.ts (100%) rename packages/browser/src/{__legacy__ => }/helpers/session-management-helper.ts (100%) rename packages/browser/src/{__legacy__ => }/helpers/spa-helper.ts (100%) rename packages/browser/src/{__legacy__ => }/models/client-config.ts (100%) rename packages/browser/src/{__legacy__ => }/models/client.ts (100%) rename packages/browser/src/{__legacy__ => }/models/http-client.ts (100%) rename packages/browser/src/{__legacy__ => }/models/index.ts (100%) rename packages/browser/src/{__legacy__ => }/models/message.ts (100%) rename packages/browser/src/{__legacy__ => }/models/request-custom-grant.ts (100%) rename packages/browser/src/{__legacy__ => }/models/session-management-helper.ts (100%) rename packages/browser/src/{__legacy__ => }/models/sign-in.ts (100%) rename packages/browser/src/{__legacy__ => }/models/sign-out-error.ts (100%) rename packages/browser/src/{__legacy__ => }/models/storage.ts (100%) rename packages/browser/src/{__legacy__ => }/models/web-worker.ts (100%) rename packages/browser/src/{__legacy__ => }/stores/index.ts (100%) rename packages/browser/src/{__legacy__ => }/stores/local-store.ts (100%) rename packages/browser/src/{__legacy__ => }/stores/memory-store.ts (100%) rename packages/browser/src/{__legacy__ => }/stores/session-store.ts (100%) rename packages/browser/src/{__legacy__ => }/utils/crypto-utils.ts (100%) rename packages/browser/src/{__legacy__ => }/utils/index.ts (100%) rename packages/browser/src/{__legacy__ => }/utils/message-utils.ts (100%) rename packages/browser/src/{__legacy__ => }/utils/spa-utils.ts (100%) rename packages/browser/src/{__legacy__ => }/worker/index.ts (100%) rename packages/browser/src/{__legacy__ => }/worker/worker-core.ts (99%) rename packages/browser/src/{__legacy__ => }/worker/worker-receiver.ts (100%) rename packages/express/src/{__legacy__/client.ts => LegacyAsgardeoExpressClient.ts} (100%) rename packages/express/src/{__legacy__ => }/constants/default-options.ts (100%) rename packages/express/src/{__legacy__ => }/constants/index.ts (100%) rename packages/express/src/{__legacy__ => }/constants/logger-config.ts (100%) rename packages/express/src/{__legacy__ => }/middleware/authentication.ts (98%) rename packages/express/src/{__legacy__ => }/middleware/index.ts (100%) rename packages/express/src/{__legacy__ => }/middleware/protect-route.ts (96%) rename packages/express/src/{__legacy__ => }/models/client-config.ts (100%) rename packages/express/src/{__legacy__ => }/models/data.ts (100%) rename packages/express/src/{__legacy__ => }/models/index.ts (100%) rename packages/express/src/{__legacy__ => }/models/protect-route.ts (100%) rename packages/express/src/{__legacy__ => }/utils/express-utils.ts (100%) create mode 100644 packages/javascript/src/AsgardeoAuthClient.ts delete mode 100644 packages/javascript/src/__legacy__/client.ts delete mode 100644 packages/javascript/src/__legacy__/helpers/authentication-helper.ts delete mode 100644 packages/javascript/src/__legacy__/helpers/index.ts create mode 100644 packages/javascript/src/api/exchangeToken.ts create mode 100644 packages/javascript/src/api/handleTokenResponse.ts create mode 100644 packages/javascript/src/api/loadOpenIDProviderConfiguration.ts create mode 100644 packages/javascript/src/api/refreshAccessToken.ts create mode 100644 packages/javascript/src/api/requestAccessToken.ts create mode 100644 packages/javascript/src/api/revokeAccessToken.ts create mode 100644 packages/javascript/src/api/validateIdToken.ts rename packages/javascript/src/{__legacy__/models/client-config.ts => models/auth-client-config.ts} (93%) rename packages/javascript/src/{__legacy__/models/index.ts => utils/clearSession.ts} (64%) create mode 100644 packages/javascript/src/utils/getAuthenticatedUserInfo.ts create mode 100644 packages/javascript/src/utils/replaceCustomGrantTemplateTags.ts create mode 100644 packages/javascript/src/utils/resolveEndpoints.ts create mode 100644 packages/javascript/src/utils/resolveEndpointsByBaseURL.ts create mode 100644 packages/javascript/src/utils/resolveEndpointsExplicitly.ts rename packages/node/src/{__legacy__/client.ts => LegacyAsgardeoNodeClient.ts} (100%) rename packages/node/src/{__legacy__ => }/constants/index.ts (100%) rename packages/node/src/{__legacy__ => }/constants/logger-config.ts (100%) rename packages/node/src/{__legacy__ => }/constants/uuid-config.ts (100%) rename packages/node/src/{__legacy__ => }/core/authentication.ts (100%) rename packages/node/src/{__legacy__ => }/core/index.ts (100%) rename packages/node/src/{__legacy__ => }/models/index.ts (100%) rename packages/node/src/{__legacy__ => }/models/session-data.ts (100%) rename packages/node/src/{__legacy__ => }/models/url-callback.ts (100%) rename packages/node/src/{__legacy__ => }/stores/index.ts (100%) rename packages/node/src/{__legacy__ => }/stores/memory-cache-store.ts (100%) rename packages/node/src/{__legacy__ => }/utils/crypto-utils.ts (100%) rename packages/node/src/{__legacy__ => }/utils/index.ts (100%) rename packages/node/src/{__legacy__ => }/utils/logger-utils.ts (100%) rename packages/node/src/{__legacy__ => }/utils/session-utils.ts (100%) diff --git a/.changeset/remove-legacy-folders.md b/.changeset/remove-legacy-folders.md new file mode 100644 index 000000000..3da06731c --- /dev/null +++ b/.changeset/remove-legacy-folders.md @@ -0,0 +1,8 @@ +--- +"@asgardeo/javascript": patch +"@asgardeo/browser": patch +"@asgardeo/node": patch +"@asgardeo/express": patch +--- + +refactor to remove `__legacy__` folders from packages and relocate contents to root source folders. diff --git a/packages/browser/.eslintignore b/packages/browser/.eslintignore index ca1d662bb..99b0b518a 100644 --- a/packages/browser/.eslintignore +++ b/packages/browser/.eslintignore @@ -2,4 +2,3 @@ /build /node_modules /coverage -/src/__legacy__ diff --git a/packages/browser/src/__legacy__/client.ts b/packages/browser/src/AsgardeoSPAClient.ts similarity index 99% rename from packages/browser/src/__legacy__/client.ts rename to packages/browser/src/AsgardeoSPAClient.ts index fc5d1186c..034869006 100755 --- a/packages/browser/src/__legacy__/client.ts +++ b/packages/browser/src/AsgardeoSPAClient.ts @@ -28,7 +28,7 @@ import { User, createPackageComponentLogger, } from '@asgardeo/javascript'; -import WorkerFile from '../web.worker'; +import WorkerFile from './web.worker'; import {MainThreadClient, WebWorkerClient} from './clients'; import {Hooks, REFRESH_ACCESS_TOKEN_ERR0R} from './constants'; import {AuthenticationHelper, SPAHelper} from './helpers'; diff --git a/packages/browser/src/__legacy__/clients/index.ts b/packages/browser/src/clients/index.ts similarity index 100% rename from packages/browser/src/__legacy__/clients/index.ts rename to packages/browser/src/clients/index.ts diff --git a/packages/browser/src/__legacy__/clients/main-thread-client.ts b/packages/browser/src/clients/main-thread-client.ts similarity index 99% rename from packages/browser/src/__legacy__/clients/main-thread-client.ts rename to packages/browser/src/clients/main-thread-client.ts index 1b43d85d4..964d7645d 100755 --- a/packages/browser/src/__legacy__/clients/main-thread-client.ts +++ b/packages/browser/src/clients/main-thread-client.ts @@ -35,7 +35,7 @@ import {SILENT_SIGN_IN_STATE, TOKEN_REQUEST_CONFIG_KEY} from '../constants'; import {AuthenticationHelper} from '../helpers/authentication-helper'; import {SessionManagementHelper} from '../helpers/session-management-helper'; import {SPAHelper} from '../helpers/spa-helper'; -import {FetchHttpClient} from '../../FetchHttpClient'; +import {FetchHttpClient} from '../FetchHttpClient'; import {HttpError, HttpRequestConfig, HttpResponse, MainThreadClientConfig, MainThreadClientInterface} from '../models'; import {SPACustomGrantConfig} from '../models/request-custom-grant'; import {BrowserStorage} from '../models/storage'; diff --git a/packages/browser/src/__legacy__/clients/web-worker-client.ts b/packages/browser/src/clients/web-worker-client.ts similarity index 100% rename from packages/browser/src/__legacy__/clients/web-worker-client.ts rename to packages/browser/src/clients/web-worker-client.ts diff --git a/packages/browser/src/__legacy__/constants/errors.ts b/packages/browser/src/constants/errors.ts similarity index 100% rename from packages/browser/src/__legacy__/constants/errors.ts rename to packages/browser/src/constants/errors.ts diff --git a/packages/browser/src/__legacy__/constants/hooks.ts b/packages/browser/src/constants/hooks.ts similarity index 100% rename from packages/browser/src/__legacy__/constants/hooks.ts rename to packages/browser/src/constants/hooks.ts diff --git a/packages/browser/src/__legacy__/constants/index.ts b/packages/browser/src/constants/index.ts similarity index 100% rename from packages/browser/src/__legacy__/constants/index.ts rename to packages/browser/src/constants/index.ts diff --git a/packages/browser/src/__legacy__/constants/messages-types.ts b/packages/browser/src/constants/messages-types.ts similarity index 100% rename from packages/browser/src/__legacy__/constants/messages-types.ts rename to packages/browser/src/constants/messages-types.ts diff --git a/packages/browser/src/__legacy__/constants/parameters.ts b/packages/browser/src/constants/parameters.ts similarity index 100% rename from packages/browser/src/__legacy__/constants/parameters.ts rename to packages/browser/src/constants/parameters.ts diff --git a/packages/browser/src/__legacy__/constants/session-management.ts b/packages/browser/src/constants/session-management.ts similarity index 100% rename from packages/browser/src/__legacy__/constants/session-management.ts rename to packages/browser/src/constants/session-management.ts diff --git a/packages/browser/src/__legacy__/constants/storage.ts b/packages/browser/src/constants/storage.ts similarity index 100% rename from packages/browser/src/__legacy__/constants/storage.ts rename to packages/browser/src/constants/storage.ts diff --git a/packages/browser/src/__legacy__/helpers/authentication-helper.ts b/packages/browser/src/helpers/authentication-helper.ts similarity index 100% rename from packages/browser/src/__legacy__/helpers/authentication-helper.ts rename to packages/browser/src/helpers/authentication-helper.ts diff --git a/packages/browser/src/__legacy__/helpers/index.ts b/packages/browser/src/helpers/index.ts similarity index 100% rename from packages/browser/src/__legacy__/helpers/index.ts rename to packages/browser/src/helpers/index.ts diff --git a/packages/browser/src/__legacy__/helpers/session-management-helper.ts b/packages/browser/src/helpers/session-management-helper.ts similarity index 100% rename from packages/browser/src/__legacy__/helpers/session-management-helper.ts rename to packages/browser/src/helpers/session-management-helper.ts diff --git a/packages/browser/src/__legacy__/helpers/spa-helper.ts b/packages/browser/src/helpers/spa-helper.ts similarity index 100% rename from packages/browser/src/__legacy__/helpers/spa-helper.ts rename to packages/browser/src/helpers/spa-helper.ts diff --git a/packages/browser/src/index.ts b/packages/browser/src/index.ts index 915425028..0d960b743 100644 --- a/packages/browser/src/index.ts +++ b/packages/browser/src/index.ts @@ -20,31 +20,31 @@ * Entry point for all public APIs of this SDK. */ // eslint-disable-next-line import/no-cycle -export * from './__legacy__/client'; +export * from './AsgardeoSPAClient'; // eslint-disable-next-line import/no-cycle -export * from './__legacy__/models'; +export * from './models'; // Utils // eslint-disable-next-line import/no-cycle -export * from './__legacy__/utils/spa-utils'; +export * from './utils/spa-utils'; // Constants -export * from './__legacy__/constants/storage'; -export * from './__legacy__/constants/hooks'; +export * from './constants/storage'; +export * from './constants/hooks'; // clients -export * from './__legacy__/clients/main-thread-client'; -export * from './__legacy__/clients/web-worker-client'; +export * from './clients/main-thread-client'; +export * from './clients/web-worker-client'; // models -export * from './__legacy__/models/request-custom-grant'; +export * from './models/request-custom-grant'; // helpers -export * from './__legacy__/helpers/authentication-helper'; -export * from './__legacy__/helpers/spa-helper'; +export * from './helpers/authentication-helper'; +export * from './helpers/spa-helper'; // worker receiver -export * from './__legacy__/worker/worker-receiver'; +export * from './worker/worker-receiver'; export {AsgardeoBrowserConfig} from './models/config'; diff --git a/packages/browser/src/__legacy__/models/client-config.ts b/packages/browser/src/models/client-config.ts similarity index 100% rename from packages/browser/src/__legacy__/models/client-config.ts rename to packages/browser/src/models/client-config.ts diff --git a/packages/browser/src/__legacy__/models/client.ts b/packages/browser/src/models/client.ts similarity index 100% rename from packages/browser/src/__legacy__/models/client.ts rename to packages/browser/src/models/client.ts diff --git a/packages/browser/src/__legacy__/models/http-client.ts b/packages/browser/src/models/http-client.ts similarity index 100% rename from packages/browser/src/__legacy__/models/http-client.ts rename to packages/browser/src/models/http-client.ts diff --git a/packages/browser/src/__legacy__/models/index.ts b/packages/browser/src/models/index.ts similarity index 100% rename from packages/browser/src/__legacy__/models/index.ts rename to packages/browser/src/models/index.ts diff --git a/packages/browser/src/__legacy__/models/message.ts b/packages/browser/src/models/message.ts similarity index 100% rename from packages/browser/src/__legacy__/models/message.ts rename to packages/browser/src/models/message.ts diff --git a/packages/browser/src/__legacy__/models/request-custom-grant.ts b/packages/browser/src/models/request-custom-grant.ts similarity index 100% rename from packages/browser/src/__legacy__/models/request-custom-grant.ts rename to packages/browser/src/models/request-custom-grant.ts diff --git a/packages/browser/src/__legacy__/models/session-management-helper.ts b/packages/browser/src/models/session-management-helper.ts similarity index 100% rename from packages/browser/src/__legacy__/models/session-management-helper.ts rename to packages/browser/src/models/session-management-helper.ts diff --git a/packages/browser/src/__legacy__/models/sign-in.ts b/packages/browser/src/models/sign-in.ts similarity index 100% rename from packages/browser/src/__legacy__/models/sign-in.ts rename to packages/browser/src/models/sign-in.ts diff --git a/packages/browser/src/__legacy__/models/sign-out-error.ts b/packages/browser/src/models/sign-out-error.ts similarity index 100% rename from packages/browser/src/__legacy__/models/sign-out-error.ts rename to packages/browser/src/models/sign-out-error.ts diff --git a/packages/browser/src/__legacy__/models/storage.ts b/packages/browser/src/models/storage.ts similarity index 100% rename from packages/browser/src/__legacy__/models/storage.ts rename to packages/browser/src/models/storage.ts diff --git a/packages/browser/src/__legacy__/models/web-worker.ts b/packages/browser/src/models/web-worker.ts similarity index 100% rename from packages/browser/src/__legacy__/models/web-worker.ts rename to packages/browser/src/models/web-worker.ts diff --git a/packages/browser/src/__legacy__/stores/index.ts b/packages/browser/src/stores/index.ts similarity index 100% rename from packages/browser/src/__legacy__/stores/index.ts rename to packages/browser/src/stores/index.ts diff --git a/packages/browser/src/__legacy__/stores/local-store.ts b/packages/browser/src/stores/local-store.ts similarity index 100% rename from packages/browser/src/__legacy__/stores/local-store.ts rename to packages/browser/src/stores/local-store.ts diff --git a/packages/browser/src/__legacy__/stores/memory-store.ts b/packages/browser/src/stores/memory-store.ts similarity index 100% rename from packages/browser/src/__legacy__/stores/memory-store.ts rename to packages/browser/src/stores/memory-store.ts diff --git a/packages/browser/src/__legacy__/stores/session-store.ts b/packages/browser/src/stores/session-store.ts similarity index 100% rename from packages/browser/src/__legacy__/stores/session-store.ts rename to packages/browser/src/stores/session-store.ts diff --git a/packages/browser/src/__legacy__/utils/crypto-utils.ts b/packages/browser/src/utils/crypto-utils.ts similarity index 100% rename from packages/browser/src/__legacy__/utils/crypto-utils.ts rename to packages/browser/src/utils/crypto-utils.ts diff --git a/packages/browser/src/utils/http.ts b/packages/browser/src/utils/http.ts index a69932708..7d9a8f9e0 100644 --- a/packages/browser/src/utils/http.ts +++ b/packages/browser/src/utils/http.ts @@ -17,7 +17,7 @@ */ // eslint-disable-next-line import/no-cycle -import {AsgardeoSPAClient} from '../__legacy__/client'; +import {AsgardeoSPAClient} from '../AsgardeoSPAClient'; /** * Creates an HTTP utility for making requests using a specific AsgardeoSPAClient instance. diff --git a/packages/browser/src/__legacy__/utils/index.ts b/packages/browser/src/utils/index.ts similarity index 100% rename from packages/browser/src/__legacy__/utils/index.ts rename to packages/browser/src/utils/index.ts diff --git a/packages/browser/src/__legacy__/utils/message-utils.ts b/packages/browser/src/utils/message-utils.ts similarity index 100% rename from packages/browser/src/__legacy__/utils/message-utils.ts rename to packages/browser/src/utils/message-utils.ts diff --git a/packages/browser/src/__legacy__/utils/spa-utils.ts b/packages/browser/src/utils/spa-utils.ts similarity index 100% rename from packages/browser/src/__legacy__/utils/spa-utils.ts rename to packages/browser/src/utils/spa-utils.ts diff --git a/packages/browser/src/web.worker.ts b/packages/browser/src/web.worker.ts index f4981ba9c..4452eb9fe 100644 --- a/packages/browser/src/web.worker.ts +++ b/packages/browser/src/web.worker.ts @@ -19,9 +19,9 @@ import {AsgardeoAuthClient} from '@asgardeo/javascript'; import {Buffer} from 'buffer/'; // eslint-disable-next-line import/no-cycle -import {AuthenticationHelper, SPAHelper} from './__legacy__/helpers'; -import {WebWorkerClientConfig} from './__legacy__/models'; -import {workerReceiver} from './__legacy__/worker/worker-receiver'; +import {AuthenticationHelper, SPAHelper} from './helpers'; +import {WebWorkerClientConfig} from './models'; +import {workerReceiver} from './worker/worker-receiver'; /* eslint-disable no-restricted-globals */ // Set up global polyfills diff --git a/packages/browser/src/__legacy__/worker/index.ts b/packages/browser/src/worker/index.ts similarity index 100% rename from packages/browser/src/__legacy__/worker/index.ts rename to packages/browser/src/worker/index.ts diff --git a/packages/browser/src/__legacy__/worker/worker-core.ts b/packages/browser/src/worker/worker-core.ts similarity index 99% rename from packages/browser/src/__legacy__/worker/worker-core.ts rename to packages/browser/src/worker/worker-core.ts index e33d79471..9791a6c6d 100755 --- a/packages/browser/src/__legacy__/worker/worker-core.ts +++ b/packages/browser/src/worker/worker-core.ts @@ -30,7 +30,7 @@ import { Storage, } from '@asgardeo/javascript'; import {AuthenticationHelper, SPAHelper} from '../helpers'; -import {FetchHttpClient} from '../../FetchHttpClient'; +import {FetchHttpClient} from '../FetchHttpClient'; import { AuthorizationResponse, HttpRequestConfig, diff --git a/packages/browser/src/__legacy__/worker/worker-receiver.ts b/packages/browser/src/worker/worker-receiver.ts similarity index 100% rename from packages/browser/src/__legacy__/worker/worker-receiver.ts rename to packages/browser/src/worker/worker-receiver.ts diff --git a/packages/express/.eslintignore b/packages/express/.eslintignore index ca1d662bb..99b0b518a 100644 --- a/packages/express/.eslintignore +++ b/packages/express/.eslintignore @@ -2,4 +2,3 @@ /build /node_modules /coverage -/src/__legacy__ diff --git a/packages/express/src/__legacy__/client.ts b/packages/express/src/LegacyAsgardeoExpressClient.ts similarity index 100% rename from packages/express/src/__legacy__/client.ts rename to packages/express/src/LegacyAsgardeoExpressClient.ts diff --git a/packages/express/src/__legacy__/constants/default-options.ts b/packages/express/src/constants/default-options.ts similarity index 100% rename from packages/express/src/__legacy__/constants/default-options.ts rename to packages/express/src/constants/default-options.ts diff --git a/packages/express/src/__legacy__/constants/index.ts b/packages/express/src/constants/index.ts similarity index 100% rename from packages/express/src/__legacy__/constants/index.ts rename to packages/express/src/constants/index.ts diff --git a/packages/express/src/__legacy__/constants/logger-config.ts b/packages/express/src/constants/logger-config.ts similarity index 100% rename from packages/express/src/__legacy__/constants/logger-config.ts rename to packages/express/src/constants/logger-config.ts diff --git a/packages/express/src/index.ts b/packages/express/src/index.ts index 376006554..eca5b804f 100644 --- a/packages/express/src/index.ts +++ b/packages/express/src/index.ts @@ -16,7 +16,8 @@ * under the License. */ -export * from './__legacy__/models'; -export * from './__legacy__/client'; +export * from './models'; +export {AsgardeoExpressClient as LegacyAsgardeoExpressClient} from './LegacyAsgardeoExpressClient'; +export {default as AsgardeoExpressClient} from './AsgardeoExpressClient'; export * from '@asgardeo/node'; diff --git a/packages/express/src/__legacy__/middleware/authentication.ts b/packages/express/src/middleware/authentication.ts similarity index 98% rename from packages/express/src/__legacy__/middleware/authentication.ts rename to packages/express/src/middleware/authentication.ts index cc4b7be88..e5e6aa091 100644 --- a/packages/express/src/__legacy__/middleware/authentication.ts +++ b/packages/express/src/middleware/authentication.ts @@ -18,7 +18,7 @@ import { AsgardeoAuthException, Storage, TokenResponse, Logger } from "@asgardeo/node"; import express from "express"; -import { AsgardeoExpressClient } from "../client"; +import { AsgardeoExpressClient } from "../LegacyAsgardeoExpressClient"; import { DEFAULT_LOGIN_PATH, DEFAULT_LOGOUT_PATH } from "../constants"; import { ExpressClientConfig } from "../models"; diff --git a/packages/express/src/__legacy__/middleware/index.ts b/packages/express/src/middleware/index.ts similarity index 100% rename from packages/express/src/__legacy__/middleware/index.ts rename to packages/express/src/middleware/index.ts diff --git a/packages/express/src/__legacy__/middleware/protect-route.ts b/packages/express/src/middleware/protect-route.ts similarity index 96% rename from packages/express/src/__legacy__/middleware/protect-route.ts rename to packages/express/src/middleware/protect-route.ts index 545e0d598..161b1de86 100644 --- a/packages/express/src/__legacy__/middleware/protect-route.ts +++ b/packages/express/src/middleware/protect-route.ts @@ -17,7 +17,7 @@ */ import express from 'express'; -import {AsgardeoExpressClient} from '../client'; +import {AsgardeoExpressClient} from '../LegacyAsgardeoExpressClient'; import {UnauthenticatedCallback} from '../models'; import {Logger} from '@asgardeo/node'; diff --git a/packages/express/src/__legacy__/models/client-config.ts b/packages/express/src/models/client-config.ts similarity index 100% rename from packages/express/src/__legacy__/models/client-config.ts rename to packages/express/src/models/client-config.ts diff --git a/packages/express/src/__legacy__/models/data.ts b/packages/express/src/models/data.ts similarity index 100% rename from packages/express/src/__legacy__/models/data.ts rename to packages/express/src/models/data.ts diff --git a/packages/express/src/__legacy__/models/index.ts b/packages/express/src/models/index.ts similarity index 100% rename from packages/express/src/__legacy__/models/index.ts rename to packages/express/src/models/index.ts diff --git a/packages/express/src/__legacy__/models/protect-route.ts b/packages/express/src/models/protect-route.ts similarity index 100% rename from packages/express/src/__legacy__/models/protect-route.ts rename to packages/express/src/models/protect-route.ts diff --git a/packages/express/src/__legacy__/utils/express-utils.ts b/packages/express/src/utils/express-utils.ts similarity index 100% rename from packages/express/src/__legacy__/utils/express-utils.ts rename to packages/express/src/utils/express-utils.ts diff --git a/packages/javascript/src/AsgardeoAuthClient.ts b/packages/javascript/src/AsgardeoAuthClient.ts new file mode 100644 index 000000000..aa0fc505c --- /dev/null +++ b/packages/javascript/src/AsgardeoAuthClient.ts @@ -0,0 +1,432 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {AuthClientConfig, StrictAuthClientConfig} from './models/auth-client-config'; +import OIDCDiscoveryConstants from './constants/OIDCDiscoveryConstants'; +import OIDCRequestConstants from './constants/OIDCRequestConstants'; +import PKCEConstants from './constants/PKCEConstants'; +import OIDCDiscoveryConstantsV2 from './constants/v2/OIDCDiscoveryConstants'; +import {AsgardeoAuthException} from './errors/exception'; +import {IsomorphicCrypto} from './IsomorphicCrypto'; +import {Crypto} from './models/crypto'; +import {ExtendedAuthorizeRequestUrlParams} from './models/oauth-request'; +import {OIDCDiscoveryApiResponse} from './models/oidc-discovery'; +import {OIDCEndpoints} from './models/oidc-endpoints'; +import {Platform} from './models/platforms'; +import {SessionData, UserSession} from './models/session'; +import {Storage, TemporaryStore} from './models/store'; +import {TokenResponse, IdToken, TokenExchangeRequestConfig} from './models/token'; +import {TokenEndpointAuthMethod} from './models/token-endpoint-auth'; +import {User} from './models/user'; +import StorageManager from './StorageManager'; +import deepMerge from './utils/deepMerge'; +import extractPkceStorageKeyFromState from './utils/extractPkceStorageKeyFromState'; +import generatePkceStorageKey from './utils/generatePkceStorageKey'; +import getAuthorizeRequestUrlParams from './utils/getAuthorizeRequestUrlParams'; +import processOpenIDScopes from './utils/processOpenIDScopes'; +import getAuthenticatedUserInfo from './utils/getAuthenticatedUserInfo'; +import clearSession from './utils/clearSession'; +import requestAccessToken from './api/requestAccessToken'; +import loadOpenIDProviderConfiguration from './api/loadOpenIDProviderConfiguration'; +import revokeAccessToken from './api/revokeAccessToken'; +import refreshAccessToken from './api/refreshAccessToken'; +import exchangeToken from './api/exchangeToken'; + +/** + * Default configurations. + */ +const DefaultConfig: Partial> = { + enablePKCE: true, + responseMode: 'query', + sendCookiesInRequests: true, + tokenValidation: { + idToken: { + clockTolerance: 300, + validate: true, + validateIssuer: true, + }, + }, +}; + +/** + * This class provides the necessary methods needed to implement authentication. + */ +export class AsgardeoAuthClient { + private storageManager!: StorageManager; + + private cryptoUtils: Crypto; + + private cryptoHelper: IsomorphicCrypto; + + private instanceIdValue: number; + + static _storageManager: any; + + public constructor() { + // intentionally empty + } + + public async initialize( + config: AuthClientConfig, + store: Storage, + inputCryptoUtils: Crypto, + instanceID?: number, + ): Promise { + const {clientId} = config; + + if (!this.instanceIdValue) { + this.instanceIdValue = 0; + } else { + this.instanceIdValue += 1; + } + + if (instanceID !== undefined) { + this.instanceIdValue = instanceID; + } + + if (!clientId) { + this.storageManager = new StorageManager(`instance_${this.instanceIdValue}`, store); + } else { + this.storageManager = new StorageManager(`instance_${this.instanceIdValue}-${clientId}`, store); + } + + this.cryptoUtils = inputCryptoUtils; + this.cryptoHelper = new IsomorphicCrypto(inputCryptoUtils); + + AsgardeoAuthClient._storageManager = this.storageManager; + + const {applicationId, platform, endpoints} = config; + let resolvedApplicationId: string | undefined = applicationId; + + if (applicationId) { + await this.storageManager.setPersistedData({ + applicationId, + }); + } else { + const persistedData: TemporaryStore = await this.storageManager.getPersistedData(); + + if (persistedData['applicationId']) { + resolvedApplicationId = persistedData['applicationId'] as string; + } + } + + const resolvedEndpoints: Partial = endpoints || {}; + + if (platform === Platform.AsgardeoV2) { + if (!resolvedEndpoints['wellKnown']) { + resolvedEndpoints['wellKnown'] = OIDCDiscoveryConstantsV2.Endpoints.WELL_KNOWN; + } + } + + await this.storageManager.setConfigData({ + ...DefaultConfig, + ...config, + applicationId: resolvedApplicationId, + endpoints: resolvedEndpoints, + scope: processOpenIDScopes(config.scopes), + }); + } + + public getStorageManager(): StorageManager { + return this.storageManager; + } + + public getInstanceId(): number { + return this.instanceIdValue; + } + + public async getSignInUrl(requestConfig?: ExtendedAuthorizeRequestUrlParams, userId?: string): Promise { + const authRequestConfig: ExtendedAuthorizeRequestUrlParams = {...requestConfig}; + + delete authRequestConfig?.forceInit; + + const buildSignInUrl = async (): Promise => { + const authorizeEndpoint: string = (await this.storageManager.getOIDCProviderMetaDataParameter( + OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.AUTHORIZATION as keyof OIDCDiscoveryApiResponse, + )) as string; + + if (!authorizeEndpoint || authorizeEndpoint.trim().length === 0) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-GAU-NF01', + 'No authorization endpoint found.', + 'No authorization endpoint was found in the OIDC provider meta data from the well-known endpoint ' + + 'or the authorization endpoint passed to the SDK is empty.', + ); + } + + const authorizeRequest: URL = new URL(authorizeEndpoint); + const configData: StrictAuthClientConfig = await this.storageManager.getConfigData() as unknown as StrictAuthClientConfig; + const tempStore: TemporaryStore = await this.storageManager.getTemporaryData(userId); + const pkceKey: string = await generatePkceStorageKey(tempStore); + + let codeVerifier: string | undefined; + let codeChallenge: string | undefined; + + if (configData.enablePKCE) { + codeVerifier = this.cryptoHelper?.getCodeVerifier(); + codeChallenge = await this.cryptoHelper?.getCodeChallenge(codeVerifier); + await this.storageManager.setTemporaryDataParameter(pkceKey, codeVerifier, userId); + } + + if (authRequestConfig['client_secret']) { + authRequestConfig['client_secret'] = configData.clientSecret; + } + + const authorizeRequestParams: Map = getAuthorizeRequestUrlParams( + { + clientId: configData.clientId, + codeChallenge, + codeChallengeMethod: PKCEConstants.DEFAULT_CODE_CHALLENGE_METHOD, + instanceId: this.getInstanceId().toString(), + prompt: configData.prompt, + redirectUri: configData.afterSignInUrl, + responseMode: configData.responseMode, + scopes: processOpenIDScopes(configData.scopes), + }, + {key: pkceKey}, + authRequestConfig, + ); + + Array.from(authorizeRequestParams.entries()).forEach(([paramKey, paramValue]: [string, string]) => { + authorizeRequest.searchParams.append(paramKey, paramValue); + }); + + return authorizeRequest.toString(); + }; + + if ( + await this.storageManager.getTemporaryDataParameter( + OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, + ) + ) { + return buildSignInUrl(); + } + + return this.loadOpenIDProviderConfiguration(requestConfig?.forceInit as boolean).then(() => buildSignInUrl()); + } + + public async requestAccessToken( + authorizationCode: string, + sessionState: string, + state: string, + userId?: string, + tokenRequestConfig?: { + params: Record; + }, + ): Promise { + return requestAccessToken( + this.storageManager, + this.cryptoHelper, + authorizationCode, + sessionState, + state, + userId, + tokenRequestConfig, + ); + } + + public async loadOpenIDProviderConfiguration(forceInit: boolean): Promise { + return loadOpenIDProviderConfiguration(this.storageManager, this.cryptoHelper, forceInit); + } + + public async getSignOutUrl(userId?: string): Promise { + const logoutEndpoint: string | undefined = (await this.storageManager.loadOpenIDProviderConfiguration())?.end_session_endpoint; + const configData: StrictAuthClientConfig = await this.storageManager.getConfigData() as unknown as StrictAuthClientConfig; + + if (!logoutEndpoint || logoutEndpoint.trim().length === 0) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-GSOU-NF01', + 'Sign-out endpoint not found.', + 'No sign-out endpoint was found in the OIDC provider meta data returned by the well-known endpoint ' + + 'or the sign-out endpoint passed to the SDK is empty.', + ); + } + + const callbackURL: string = configData?.afterSignOutUrl ?? configData?.afterSignInUrl; + + if (!callbackURL || callbackURL.trim().length === 0) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-GSOU-NF03', + 'No sign-out redirect URL found.', + 'The sign-out redirect URL cannot be found or the URL passed to the SDK is empty. ' + + 'No sign-in redirect URL has been found either. ', + ); + } + const queryParams: URLSearchParams = new URLSearchParams(); + + queryParams.set('post_logout_redirect_uri', callbackURL); + + if (configData.sendIdTokenInLogoutRequest) { + const idToken: string = (await this.storageManager.getSessionData(userId))?.id_token; + + if (!idToken || idToken.trim().length === 0) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-GSOU-NF02', + 'ID token not found.', + 'No ID token could be found. Either the session information is lost or you have not signed in.', + ); + } + queryParams.set('id_token_hint', idToken); + } else { + queryParams.set('client_id', configData.clientId); + } + + queryParams.set('state', OIDCRequestConstants.Params.SIGN_OUT_SUCCESS); + + return `${logoutEndpoint}?${queryParams.toString()}`; + } + + public async getOpenIDProviderEndpoints(): Promise> { + const oidcProviderMetaData: OIDCDiscoveryApiResponse = await this.storageManager.loadOpenIDProviderConfiguration(); + + return { + authorizationEndpoint: oidcProviderMetaData.authorization_endpoint ?? '', + checkSessionIframe: oidcProviderMetaData.check_session_iframe ?? '', + endSessionEndpoint: oidcProviderMetaData.end_session_endpoint ?? '', + introspectionEndpoint: oidcProviderMetaData.introspection_endpoint ?? '', + issuer: oidcProviderMetaData.issuer ?? '', + jwksUri: oidcProviderMetaData.jwks_uri ?? '', + registrationEndpoint: oidcProviderMetaData.registration_endpoint ?? '', + revocationEndpoint: oidcProviderMetaData.revocation_endpoint ?? '', + tokenEndpoint: oidcProviderMetaData.token_endpoint ?? '', + userinfoEndpoint: oidcProviderMetaData.userinfo_endpoint ?? '', + }; + } + + public async decodeJwtToken>(token: string): Promise { + return this.cryptoHelper.decodeJwtToken(token); + } + + public async getDecodedIdToken(userId?: string, idToken?: string): Promise { + const storedIdToken: string = (await this.storageManager.getSessionData(userId)).id_token; + const payload: IdToken = this.cryptoHelper.decodeJwtToken(storedIdToken ?? idToken); + + return payload; + } + + public async getIdToken(userId?: string): Promise { + return (await this.storageManager.getSessionData(userId)).id_token; + } + + public async getUser(userId?: string): Promise { + const sessionData: SessionData = await this.storageManager.getSessionData(userId); + const authenticatedUser: User = getAuthenticatedUserInfo(this.cryptoHelper, sessionData?.id_token); + + Object.keys(authenticatedUser).forEach((key: string) => { + if (authenticatedUser[key] === undefined || authenticatedUser[key] === '' || authenticatedUser[key] === null) { + delete authenticatedUser[key]; + } + }); + + return authenticatedUser; + } + + public async getUserSession(userId?: string): Promise { + const sessionData: SessionData = await this.storageManager.getSessionData(userId); + + return { + scopes: sessionData?.scope?.split(' '), + sessionState: sessionData?.session_state ?? '', + }; + } + + public async getCrypto(): Promise { + return this.cryptoHelper; + } + + public async revokeAccessToken(userId?: string): Promise { + return revokeAccessToken(this.storageManager, userId); + } + + public async refreshAccessToken(userId?: string): Promise { + return refreshAccessToken(this.storageManager, this.cryptoHelper, userId); + } + + public async getAccessToken(userId?: string): Promise { + return (await this.storageManager.getSessionData(userId))?.access_token; + } + + public async exchangeToken(config: TokenExchangeRequestConfig, userId?: string): Promise { + return exchangeToken(this.storageManager, this.cryptoHelper, config, userId); + } + + public async isSignedIn(userId?: string): Promise { + const isAccessTokenAvailable: boolean = Boolean(await this.getAccessToken(userId)); + + // Check if the access token is expired. + const createdAt: number = (await this.storageManager.getSessionData(userId))?.created_at; + + // Get the expires in value. + const expiresInString: string = (await this.storageManager.getSessionData(userId))?.expires_in; + + // If the expires in value is not available, the token is invalid and the user is not authenticated. + if (!expiresInString) { + return false; + } + + // Convert to milliseconds. + const expiresIn: number = parseInt(expiresInString, 10) * 1000; + const currentTime: number = new Date().getTime(); + const isAccessTokenValid: boolean = createdAt + expiresIn > currentTime; + + const isSignedIn: boolean = isAccessTokenAvailable && isAccessTokenValid; + + return isSignedIn; + } + + public async getPKCECode(state: string, userId?: string): Promise { + return (await this.storageManager.getTemporaryDataParameter( + extractPkceStorageKeyFromState(state), + userId, + )) as string; + } + + public async setPKCECode(pkce: string, state: string, userId?: string): Promise { + return this.storageManager.setTemporaryDataParameter(extractPkceStorageKeyFromState(state), pkce, userId); + } + + public static isSignOutSuccessful(afterSignOutUrl: string): boolean { + const url: URL = new URL(afterSignOutUrl); + const stateParam: string | null = url.searchParams.get(OIDCRequestConstants.Params.STATE); + const error: boolean = Boolean(url.searchParams.get('error')); + + return stateParam ? stateParam === OIDCRequestConstants.Params.SIGN_OUT_SUCCESS && !error : false; + } + + public static didSignOutFail(afterSignOutUrl: string): boolean { + const url: URL = new URL(afterSignOutUrl); + const stateParam: string | null = url.searchParams.get(OIDCRequestConstants.Params.STATE); + const error: boolean = Boolean(url.searchParams.get('error')); + + return stateParam ? stateParam === OIDCRequestConstants.Params.SIGN_OUT_SUCCESS && error : false; + } + + public async reInitialize(config: Partial>): Promise { + const currentConfig: AuthClientConfig = await this.storageManager.getConfigData() as unknown as AuthClientConfig; + const newConfig: AuthClientConfig = deepMerge(currentConfig, config); + + await this.storageManager.setConfigData(newConfig); + await this.loadOpenIDProviderConfiguration(true); + } + + public static async clearSession(userId?: string): Promise { + if (AsgardeoAuthClient._storageManager) { + await clearSession(AsgardeoAuthClient._storageManager, userId); + } + } +} diff --git a/packages/javascript/src/AsgardeoJavaScriptClient.ts b/packages/javascript/src/AsgardeoJavaScriptClient.ts index 660b4ebf9..b0935f789 100644 --- a/packages/javascript/src/AsgardeoJavaScriptClient.ts +++ b/packages/javascript/src/AsgardeoJavaScriptClient.ts @@ -16,8 +16,8 @@ * under the License. */ -import {AsgardeoAuthClient} from './__legacy__/client'; -import {AuthClientConfig} from './__legacy__/models/client-config'; +import {AsgardeoAuthClient} from './AsgardeoAuthClient'; +import {AuthClientConfig} from './models/auth-client-config'; import executeEmbeddedSignInFlow from './api/executeEmbeddedSignInFlow'; import initializeEmbeddedSignInFlow from './api/initializeEmbeddedSignInFlow'; import {DefaultCacheStore} from './DefaultCacheStore'; diff --git a/packages/javascript/src/StorageManager.ts b/packages/javascript/src/StorageManager.ts index 1225bf917..6f8f2b95f 100644 --- a/packages/javascript/src/StorageManager.ts +++ b/packages/javascript/src/StorageManager.ts @@ -16,7 +16,7 @@ * under the License. */ -import {AuthClientConfig} from './__legacy__/models'; +import {AuthClientConfig} from './models/auth-client-config'; import {OIDCDiscoveryApiResponse} from './models/oidc-discovery'; import {SessionData} from './models/session'; import {Stores, Storage, TemporaryStore, TemporaryStoreValue} from './models/store'; diff --git a/packages/javascript/src/__legacy__/client.ts b/packages/javascript/src/__legacy__/client.ts deleted file mode 100644 index a1c99566d..000000000 --- a/packages/javascript/src/__legacy__/client.ts +++ /dev/null @@ -1,1205 +0,0 @@ -/** - * Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import {AuthenticationHelper} from './helpers'; -import {AuthClientConfig, StrictAuthClientConfig} from './models'; -import OIDCDiscoveryConstants from '../constants/OIDCDiscoveryConstants'; -import OIDCRequestConstants from '../constants/OIDCRequestConstants'; -import PKCEConstants from '../constants/PKCEConstants'; -import OIDCDiscoveryConstantsV2 from '../constants/v2/OIDCDiscoveryConstants'; -import {AsgardeoAuthException} from '../errors/exception'; -import {IsomorphicCrypto} from '../IsomorphicCrypto'; -import {Crypto} from '../models/crypto'; -import {ExtendedAuthorizeRequestUrlParams} from '../models/oauth-request'; -import {OIDCDiscoveryApiResponse} from '../models/oidc-discovery'; -import {OIDCEndpoints} from '../models/oidc-endpoints'; -import {Platform} from '../models/platforms'; -import {SessionData, UserSession} from '../models/session'; -import {Storage, TemporaryStore} from '../models/store'; -import {TokenResponse, IdToken, TokenExchangeRequestConfig} from '../models/token'; -import {TokenEndpointAuthMethod} from '../models/token-endpoint-auth'; -import {User} from '../models/user'; -import StorageManager from '../StorageManager'; -import base64Encode from '../utils/base64Encode'; -import deepMerge from '../utils/deepMerge'; -import extractPkceStorageKeyFromState from '../utils/extractPkceStorageKeyFromState'; -import generatePkceStorageKey from '../utils/generatePkceStorageKey'; -import getAuthorizeRequestUrlParams from '../utils/getAuthorizeRequestUrlParams'; -import processOpenIDScopes from '../utils/processOpenIDScopes'; - -/** - * Default configurations. - */ -const DefaultConfig: Partial> = { - enablePKCE: true, - responseMode: 'query', - sendCookiesInRequests: true, - tokenValidation: { - idToken: { - clockTolerance: 300, - validate: true, - validateIssuer: true, - }, - }, -}; - -/** - * This class provides the necessary methods needed to implement authentication. - */ -export class AsgardeoAuthClient { - private storageManager!: StorageManager; - - private configProvider: () => Promise; - - private oidcProviderMetaDataProvider: () => Promise; - - private authHelper: AuthenticationHelper; - - private cryptoUtils: Crypto; - - private cryptoHelper: IsomorphicCrypto; - - private instanceIdValue: number; - - // FIXME: Validate this. - // Ref: https://github.com/asgardeo/asgardeo-auth-js-core/pull/205 - static authHelperInstance: any; - - /** - * This is the constructor method that returns an instance of the . - * - * @param store - The store object. - * - * @example - * ``` - * const _store: Store = new DataStore(); - * const auth = new AsgardeoAuthClient(_store); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#constructor} - * - * @preserve - */ - public constructor() { - // intentionally empty - } - - /** - * - * This method initializes the SDK with the config data. - * - * @param config - The config object to initialize with. - * - * @example - * const config = \{ - * afterSignInUrl: "http://localhost:3000/sign-in", - * clientId: "client ID", - * baseUrl: "https://localhost:9443" - * \} - * - * await auth.initialize(config); - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#initialize} - * - * @preserve - */ - public async initialize( - config: AuthClientConfig, - store: Storage, - inputCryptoUtils: Crypto, - instanceID?: number, - ): Promise { - const {clientId} = config; - - if (!this.instanceIdValue) { - this.instanceIdValue = 0; - } else { - this.instanceIdValue += 1; - } - - if (instanceID !== undefined) { - this.instanceIdValue = instanceID; - } - - if (!clientId) { - this.storageManager = new StorageManager(`instance_${this.instanceIdValue}`, store); - } else { - this.storageManager = new StorageManager(`instance_${this.instanceIdValue}-${clientId}`, store); - } - - this.cryptoUtils = inputCryptoUtils; - this.cryptoHelper = new IsomorphicCrypto(inputCryptoUtils); - this.authHelper = new AuthenticationHelper(this.storageManager, this.cryptoHelper); - this.configProvider = async (): Promise => this.storageManager.getConfigData(); - this.oidcProviderMetaDataProvider = async (): Promise => - this.storageManager.loadOpenIDProviderConfiguration(); - - // FIXME: Validate this. - // Ref: https://github.com/asgardeo/asgardeo-auth-js-core/pull/205 - AsgardeoAuthClient.authHelperInstance = this.authHelper; - - const {applicationId, platform, endpoints} = config; - let resolvedApplicationId: string | undefined = applicationId; - - if (applicationId) { - await this.storageManager.setPersistedData({ - applicationId, - }); - } else { - const persistedData: TemporaryStore = await this.storageManager.getPersistedData(); - - if (persistedData['applicationId']) { - resolvedApplicationId = persistedData['applicationId'] as string; - } - } - - const resolvedEndpoints: Partial = endpoints || {}; - - if (platform === Platform.AsgardeoV2) { - if (!resolvedEndpoints['wellKnown']) { - resolvedEndpoints['wellKnown'] = OIDCDiscoveryConstantsV2.Endpoints.WELL_KNOWN; - } - } - - await this.storageManager.setConfigData({ - ...DefaultConfig, - ...config, - applicationId: resolvedApplicationId, - endpoints: resolvedEndpoints, - scope: processOpenIDScopes(config.scopes), - }); - } - - /** - * This method returns the `StorageManager` object that allows you to access authentication data. - * - * @returns - The `StorageManager` object. - * - * @example - * ``` - * const data = auth.getStorageManager(); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getStorageManager} - * - * @preserve - */ - public getStorageManager(): StorageManager { - return this.storageManager; - } - - /** - * This method returns the `instanceID` variable of the given instance. - * - * @returns - The `instanceID` number. - * - * @example - * ``` - * const instanceId = auth.getInstanceId(); - * ``` - * - * @preserve - */ - // eslint-disable-next-line class-methods-use-this - public getInstanceId(): number { - return this.instanceIdValue; - } - - /** - * This is an async method that returns a Promise that resolves with the authorization URL. - * - * @param config - (Optional) A config object to force initialization and pass - * custom path parameters such as the fidp parameter. - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * @returns - A promise that resolves with the authorization URL. - * - * @example - * ``` - * auth.getSignInUrl().then((url)=>{ - * // console.log(url); - * }).catch((error)=>{ - * // console.error(error); - * }); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getSignInUrl} - * - * @preserve - */ - public async getSignInUrl(requestConfig?: ExtendedAuthorizeRequestUrlParams, userId?: string): Promise { - const authRequestConfig: ExtendedAuthorizeRequestUrlParams = {...requestConfig}; - - delete authRequestConfig?.forceInit; - - const buildSignInUrl = async (): Promise => { - const authorizeEndpoint: string = (await this.storageManager.getOIDCProviderMetaDataParameter( - OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.AUTHORIZATION as keyof OIDCDiscoveryApiResponse, - )) as string; - - if (!authorizeEndpoint || authorizeEndpoint.trim().length === 0) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-GAU-NF01', - 'No authorization endpoint found.', - 'No authorization endpoint was found in the OIDC provider meta data from the well-known endpoint ' + - 'or the authorization endpoint passed to the SDK is empty.', - ); - } - - const authorizeRequest: URL = new URL(authorizeEndpoint); - const configData: StrictAuthClientConfig = await this.configProvider(); - const tempStore: TemporaryStore = await this.storageManager.getTemporaryData(userId); - const pkceKey: string = await generatePkceStorageKey(tempStore); - - let codeVerifier: string | undefined; - let codeChallenge: string | undefined; - - if (configData.enablePKCE) { - codeVerifier = this.cryptoHelper?.getCodeVerifier(); - codeChallenge = await this.cryptoHelper?.getCodeChallenge(codeVerifier); - await this.storageManager.setTemporaryDataParameter(pkceKey, codeVerifier, userId); - } - - if (authRequestConfig['client_secret']) { - authRequestConfig['client_secret'] = configData.clientSecret; - } - - const authorizeRequestParams: Map = getAuthorizeRequestUrlParams( - { - clientId: configData.clientId, - codeChallenge, - codeChallengeMethod: PKCEConstants.DEFAULT_CODE_CHALLENGE_METHOD, - instanceId: this.getInstanceId().toString(), - prompt: configData.prompt, - redirectUri: configData.afterSignInUrl, - responseMode: configData.responseMode, - scopes: processOpenIDScopes(configData.scopes), - }, - {key: pkceKey}, - authRequestConfig, - ); - - Array.from(authorizeRequestParams.entries()).forEach(([paramKey, paramValue]: [string, string]) => { - authorizeRequest.searchParams.append(paramKey, paramValue); - }); - - return authorizeRequest.toString(); - }; - - if ( - await this.storageManager.getTemporaryDataParameter( - OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, - ) - ) { - return buildSignInUrl(); - } - - return this.loadOpenIDProviderConfiguration(requestConfig?.forceInit as boolean).then(() => buildSignInUrl()); - } - - /** - * This is an async method that sends a request to obtain the access token and returns a Promise - * that resolves with the token and other relevant data. - * - * @param authorizationCode - The authorization code. - * @param sessionState - The session state. - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * @returns - A Promise that resolves with the token response. - * - * @example - * ``` - * auth.requestAccessToken(authCode, sessionState).then((token)=>{ - * // console.log(token); - * }).catch((error)=>{ - * // console.error(error); - * }); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#requestAccessToken} - * - * - * @preserve - */ - public async requestAccessToken( - authorizationCode: string, - sessionState: string, - state: string, - userId?: string, - tokenRequestConfig?: { - params: Record; - }, - ): Promise { - if ( - !(await this.storageManager.getTemporaryDataParameter( - OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, - )) - ) { - await this.loadOpenIDProviderConfiguration(false); - } - - const tokenEndpoint: string | undefined = (await this.oidcProviderMetaDataProvider()).token_endpoint; - const configData: StrictAuthClientConfig = await this.configProvider(); - - if (!tokenEndpoint || tokenEndpoint.trim().length === 0) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RAT1-NF01', - 'Token endpoint not found.', - 'No token endpoint was found in the OIDC provider meta data returned by the well-known endpoint ' + - 'or the token endpoint passed to the SDK is empty.', - ); - } - - if (sessionState) { - await this.storageManager.setSessionDataParameter( - OIDCRequestConstants.Params.SESSION_STATE as keyof SessionData, - sessionState, - userId, - ); - } - - const body: URLSearchParams = new URLSearchParams(); - - body.set('client_id', configData.clientId); - - const hasSecret: boolean = Boolean(configData.clientSecret && configData.clientSecret.trim().length > 0); - const tokenEndpointAuthMethod: TokenEndpointAuthMethod = - configData.tokenRequest?.authMethod ?? - ((configData as any).platform === Platform.AsgardeoV2 ? 'client_secret_basic' : 'client_secret_post'); - - if (hasSecret && tokenEndpointAuthMethod === 'client_secret_post') { - body.set('client_secret', configData.clientSecret); - } - - const code: string = authorizationCode; - - body.set('code', code); - - body.set('grant_type', 'authorization_code'); - body.set('redirect_uri', configData.afterSignInUrl); - - if (tokenRequestConfig?.params) { - Object.entries(tokenRequestConfig.params).forEach(([key, value]: [key: string, value: unknown]) => { - body.append(key, value as string); - }); - } - - if (configData.enablePKCE) { - body.set( - 'code_verifier', - `${await this.storageManager.getTemporaryDataParameter(extractPkceStorageKeyFromState(state), userId)}`, - ); - - await this.storageManager.removeTemporaryDataParameter(extractPkceStorageKeyFromState(state), userId); - } - - const tokenRequestHeaders: Record = { - Accept: 'application/json', - 'Content-Type': 'application/x-www-form-urlencoded', - }; - - if (hasSecret && tokenEndpointAuthMethod === 'client_secret_basic') { - const credential: string = `${encodeURIComponent(configData.clientId)}:${encodeURIComponent( - configData.clientSecret, - )}`; - tokenRequestHeaders['Authorization'] = `Basic ${base64Encode(credential)}`; - } - - let tokenResponse: Response; - - try { - tokenResponse = await fetch(tokenEndpoint, { - body, - credentials: configData.sendCookiesInRequests ? 'include' : 'same-origin', - headers: tokenRequestHeaders, - method: 'POST', - }); - } catch (error: any) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RAT1-NE02', - 'Requesting access token failed', - error ?? 'The request to get the access token from the server failed.', - ); - } - - if (!tokenResponse.ok) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RAT1-HE03', - `Requesting access token failed with ${tokenResponse.statusText}`, - (await tokenResponse.json()) as string, - ); - } - - return this.authHelper.handleTokenResponse(tokenResponse, userId); - } - - public async loadOpenIDProviderConfiguration(forceInit: boolean): Promise { - const configData: StrictAuthClientConfig = await this.configProvider(); - - if ( - !forceInit && - (await this.storageManager.getTemporaryDataParameter( - OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, - )) - ) { - return Promise.resolve(); - } - - const {wellKnownEndpoint, platform, discovery, baseUrl, endpoints} = configData as any; - - const resolvedWellKnownEndpoint: string | undefined = - wellKnownEndpoint || - (platform === Platform.AsgardeoV2 && discovery?.wellKnown?.enabled - ? `${baseUrl}${endpoints?.wellKnown ?? '/.well-known/openid-configuration'}` - : undefined); - - if (resolvedWellKnownEndpoint) { - let response: Response; - - try { - response = await fetch(resolvedWellKnownEndpoint); - if (response.status !== 200 || !response.ok) { - throw new Error(); - } - } catch { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-GOPMD-HE01', - 'Invalid well-known response', - 'The well known endpoint response has been failed with an error.', - ); - } - - await this.storageManager.setOIDCProviderMetaData(await this.authHelper.resolveEndpoints(await response.json())); - await this.storageManager.setTemporaryDataParameter( - OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, - true, - ); - - return Promise.resolve(); - } - if ((configData as any).baseUrl) { - try { - await this.storageManager.setOIDCProviderMetaData(await this.authHelper.resolveEndpointsByBaseURL()); - } catch (error: any) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-GOPMD-IV02', - 'Resolving endpoints failed.', - error ?? 'Resolving endpoints by base url failed.', - ); - } - await this.storageManager.setTemporaryDataParameter( - OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, - true, - ); - - return Promise.resolve(); - } - await this.storageManager.setOIDCProviderMetaData(await this.authHelper.resolveEndpointsExplicitly()); - - await this.storageManager.setTemporaryDataParameter( - OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, - true, - ); - - return Promise.resolve(); - } - - /** - * This method returns the sign-out URL. - * - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * **This doesn't clear the authentication data.** - * - * @returns - A Promise that resolves with the sign-out URL. - * - * @example - * ``` - * const signOutUrl = await auth.getSignOutUrl(); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getSignOutUrl} - * - * @preserve - */ - public async getSignOutUrl(userId?: string): Promise { - const logoutEndpoint: string | undefined = (await this.oidcProviderMetaDataProvider())?.end_session_endpoint; - const configData: StrictAuthClientConfig = await this.configProvider(); - - if (!logoutEndpoint || logoutEndpoint.trim().length === 0) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-GSOU-NF01', - 'Sign-out endpoint not found.', - 'No sign-out endpoint was found in the OIDC provider meta data returned by the well-known endpoint ' + - 'or the sign-out endpoint passed to the SDK is empty.', - ); - } - - const callbackURL: string = configData?.afterSignOutUrl ?? configData?.afterSignInUrl; - - if (!callbackURL || callbackURL.trim().length === 0) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-GSOU-NF03', - 'No sign-out redirect URL found.', - 'The sign-out redirect URL cannot be found or the URL passed to the SDK is empty. ' + - 'No sign-in redirect URL has been found either. ', - ); - } - const queryParams: URLSearchParams = new URLSearchParams(); - - queryParams.set('post_logout_redirect_uri', callbackURL); - - if (configData.sendIdTokenInLogoutRequest) { - const idToken: string = (await this.storageManager.getSessionData(userId))?.id_token; - - if (!idToken || idToken.trim().length === 0) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-GSOU-NF02', - 'ID token not found.', - 'No ID token could be found. Either the session information is lost or you have not signed in.', - ); - } - queryParams.set('id_token_hint', idToken); - } else { - queryParams.set('client_id', configData.clientId); - } - - queryParams.set('state', OIDCRequestConstants.Params.SIGN_OUT_SUCCESS); - - return `${logoutEndpoint}?${queryParams.toString()}`; - } - - /** - * This method returns OIDC service endpoints that are fetched from the `.well-known` endpoint. - * - * @returns - A Promise that resolves with an object containing the OIDC service endpoints. - * - * @example - * ``` - * const endpoints = await auth.getOpenIDProviderEndpoints(); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getOpenIDProviderEndpoints} - * - * @preserve - */ - public async getOpenIDProviderEndpoints(): Promise> { - const oidcProviderMetaData: OIDCDiscoveryApiResponse = await this.oidcProviderMetaDataProvider(); - - return { - authorizationEndpoint: oidcProviderMetaData.authorization_endpoint ?? '', - checkSessionIframe: oidcProviderMetaData.check_session_iframe ?? '', - endSessionEndpoint: oidcProviderMetaData.end_session_endpoint ?? '', - introspectionEndpoint: oidcProviderMetaData.introspection_endpoint ?? '', - issuer: oidcProviderMetaData.issuer ?? '', - jwksUri: oidcProviderMetaData.jwks_uri ?? '', - registrationEndpoint: oidcProviderMetaData.registration_endpoint ?? '', - revocationEndpoint: oidcProviderMetaData.revocation_endpoint ?? '', - tokenEndpoint: oidcProviderMetaData.token_endpoint ?? '', - userinfoEndpoint: oidcProviderMetaData.userinfo_endpoint ?? '', - }; - } - - /** - * This method decodes a given JWT token and returns the payload. - * - * @param token - The token to be decoded. - * @returns - A Promise that resolves with the decoded token payload. - * - * @example - * ``` - * const decodedToken = await auth.decodeJwtToken(token); - * ``` - */ - public async decodeJwtToken>(token: string): Promise { - return this.cryptoHelper.decodeJwtToken(token); - } - - /** - * This method decodes the payload of the ID token and returns it. - * - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * @returns - A Promise that resolves with the decoded ID token payload. - * - * @example - * ``` - * const decodedIdToken = await auth.getDecodedIdToken(); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getDecodedIdToken} - * - * @preserve - */ - public async getDecodedIdToken(userId?: string, idToken?: string): Promise { - const storedIdToken: string = (await this.storageManager.getSessionData(userId)).id_token; - const payload: IdToken = this.cryptoHelper.decodeJwtToken(storedIdToken ?? idToken); - - return payload; - } - - /** - * This method returns the ID token. - * - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * @returns - A Promise that resolves with the ID token. - * - * @example - * ``` - * const idToken = await auth.getIdToken(); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getIdToken} - * - * @preserve - */ - public async getIdToken(userId?: string): Promise { - return (await this.storageManager.getSessionData(userId)).id_token; - } - - /** - * This method returns the basic user information obtained from the ID token. - * - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * @returns - A Promise that resolves with an object containing the basic user information. - * - * @example - * ``` - * const userInfo = await auth.getUser(); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getUser} - * - * @preserve - */ - public async getUser(userId?: string): Promise { - const sessionData: SessionData = await this.storageManager.getSessionData(userId); - const authenticatedUser: User = this.authHelper.getAuthenticatedUserInfo(sessionData?.id_token); - - Object.keys(authenticatedUser).forEach((key: string) => { - if (authenticatedUser[key] === undefined || authenticatedUser[key] === '' || authenticatedUser[key] === null) { - delete authenticatedUser[key]; - } - }); - - return authenticatedUser; - } - - public async getUserSession(userId?: string): Promise { - const sessionData: SessionData = await this.storageManager.getSessionData(userId); - - return { - scopes: sessionData?.scope?.split(' '), - sessionState: sessionData?.session_state ?? '', - }; - } - - /** - * This method returns the crypto helper object. - * - * @returns - A Promise that resolves with a IsomorphicCrypto object. - * - * @example - * ``` - * const cryptoHelper = await auth.IsomorphicCrypto(); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getCrypto} - * - * @preserve - */ - public async getCrypto(): Promise { - return this.cryptoHelper; - } - - /** - * This method revokes the access token. - * - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * **This method also clears the authentication data.** - * - * @returns - A Promise that returns the response of the revoke-access-token request. - * - * @example - * ``` - * auth.revokeAccessToken().then((response)=>{ - * // console.log(response); - * }).catch((error)=>{ - * // console.error(error); - * }); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#revokeAccessToken} - * - * @preserve - */ - public async revokeAccessToken(userId?: string): Promise { - const revokeTokenEndpoint: string | undefined = (await this.oidcProviderMetaDataProvider()).revocation_endpoint; - const configData: StrictAuthClientConfig = await this.configProvider(); - - if (!revokeTokenEndpoint || revokeTokenEndpoint.trim().length === 0) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RAT3-NF01', - 'No revoke access token endpoint found.', - 'No revoke access token endpoint was found in the OIDC provider meta data returned by ' + - 'the well-known endpoint or the revoke access token endpoint passed to the SDK is empty.', - ); - } - - const body: string[] = []; - - body.push(`client_id=${configData.clientId}`); - body.push(`token=${(await this.storageManager.getSessionData(userId)).access_token}`); - body.push('token_type_hint=access_token'); - - if (configData.clientSecret && configData.clientSecret.trim().length > 0) { - body.push(`client_secret=${configData.clientSecret}`); - } - - let response: Response; - - try { - response = await fetch(revokeTokenEndpoint, { - body: body.join('&'), - credentials: configData.sendCookiesInRequests ? 'include' : 'same-origin', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/x-www-form-urlencoded', - }, - method: 'POST', - }); - } catch (error: any) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RAT3-NE02', - 'The request to revoke access token failed.', - error ?? 'The request sent to revoke the access token failed.', - ); - } - - if (response.status !== 200 || !response.ok) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RAT3-HE03', - `Invalid response status received for revoke access token request (${response.statusText}).`, - (await response.json()) as string, - ); - } - - this.authHelper.clearSession(userId); - - return Promise.resolve(response); - } - - /** - * This method refreshes the access token and returns a Promise that resolves with the new access - * token and other relevant data. - * - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * @returns - A Promise that resolves with the token response. - * - * @example - * ``` - * auth.refreshAccessToken().then((response)=>{ - * // console.log(response); - * }).catch((error)=>{ - * // console.error(error); - * }); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#refreshAccessToken} - * - * @preserve - */ - public async refreshAccessToken(userId?: string): Promise { - const tokenEndpoint: string | undefined = (await this.oidcProviderMetaDataProvider()).token_endpoint; - const configData: StrictAuthClientConfig = await this.configProvider(); - const sessionData: SessionData = await this.storageManager.getSessionData(userId); - - if (!sessionData.refresh_token) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RAT2-NF01', - 'No refresh token found.', - "There was no refresh token found. Asgardeo doesn't return a " + - 'refresh token if the refresh token grant is not enabled.', - ); - } - - if (!tokenEndpoint || tokenEndpoint.trim().length === 0) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RAT2-NF02', - 'No refresh token endpoint found.', - 'No refresh token endpoint was in the OIDC provider meta data returned by the well-known ' + - 'endpoint or the refresh token endpoint passed to the SDK is empty.', - ); - } - - const body: string[] = []; - - body.push(`client_id=${configData.clientId}`); - body.push(`refresh_token=${sessionData.refresh_token}`); - body.push('grant_type=refresh_token'); - - if (configData.clientSecret && configData.clientSecret.trim().length > 0) { - body.push(`client_secret=${configData.clientSecret}`); - } - - let tokenResponse: Response; - - try { - tokenResponse = await fetch(tokenEndpoint, { - body: body.join('&'), - credentials: configData.sendCookiesInRequests ? 'include' : 'same-origin', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/x-www-form-urlencoded', - }, - method: 'POST', - }); - } catch (error: any) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RAT2-NR03', - 'Refresh access token request failed.', - error ?? 'The request to refresh the access token failed.', - ); - } - - if (!tokenResponse.ok) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RAT2-HE04', - `Refreshing access token failed with ${tokenResponse.statusText}`, - (await tokenResponse.json()) as string, - ); - } - - return this.authHelper.handleTokenResponse(tokenResponse, userId); - } - - /** - * This method returns the access token. - * - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * @returns - A Promise that resolves with the access token. - * - * @example - * ``` - * const accessToken = await auth.getAccessToken(); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getAccessToken} - * - * @preserve - */ - public async getAccessToken(userId?: string): Promise { - return (await this.storageManager.getSessionData(userId))?.access_token; - } - - /** - * This method sends a custom-grant request and returns a Promise that resolves with the response - * depending on the config passed. - * - * @param config - A config object containing the custom grant configurations. - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * @returns - A Promise that resolves with the response depending - * on your configurations. - * - * @example - * ``` - * const config = { - * attachToken: false, - * data: { - * client_id: "{{clientId}}", - * grant_type: "account_switch", - * scope: "{{scope}}", - * token: "{{token}}", - * }, - * id: "account-switch", - * returnResponse: true, - * returnsSession: true, - * signInRequired: true - * } - * - * auth.exchangeToken(config).then((response)=>{ - * // console.log(response); - * }).catch((error)=>{ - * // console.error(error); - * }); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#exchangeToken} - * - * @preserve - */ - public async exchangeToken(config: TokenExchangeRequestConfig, userId?: string): Promise { - if ( - !(await this.storageManager.getTemporaryDataParameter( - OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, - )) - ) { - await this.loadOpenIDProviderConfiguration(false); - } - - const oidcProviderMetadata: OIDCDiscoveryApiResponse = await this.oidcProviderMetaDataProvider(); - const configData: StrictAuthClientConfig = await this.configProvider(); - - let tokenEndpoint: string | undefined; - - if (config.tokenEndpoint && config.tokenEndpoint.trim().length !== 0) { - tokenEndpoint = config.tokenEndpoint; - } else { - tokenEndpoint = oidcProviderMetadata.token_endpoint; - } - - if (!tokenEndpoint || tokenEndpoint.trim().length === 0) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RCG-NF01', - 'Token endpoint not found.', - 'No token endpoint was found in the OIDC provider meta data returned by the well-known endpoint ' + - 'or the token endpoint passed to the SDK is empty.', - ); - } - - const data: string[] = await Promise.all( - Object.entries(config.data).map(async ([key, value]: [key: string, value: any]) => { - const newValue: string = await this.authHelper.replaceCustomGrantTemplateTags(value as string, userId); - - return `${key}=${newValue}`; - }), - ); - - let requestHeaders: Record = { - Accept: 'application/json', - 'Content-Type': 'application/x-www-form-urlencoded', - }; - - if (config.attachToken) { - requestHeaders = { - ...requestHeaders, - Authorization: `Bearer ${(await this.storageManager.getSessionData(userId)).access_token}`, - }; - } - - const requestConfig: RequestInit = { - body: data.join('&'), - credentials: configData.sendCookiesInRequests ? 'include' : 'same-origin', - headers: new Headers(requestHeaders), - method: 'POST', - }; - - let response: Response; - - try { - response = await fetch(tokenEndpoint, requestConfig); - } catch (error: any) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RCG-NE02', - 'The custom grant request failed.', - error ?? 'The request sent to get the custom grant failed.', - ); - } - - if (response.status !== 200 || !response.ok) { - throw new AsgardeoAuthException( - 'JS-AUTH_CORE-RCG-HE03', - `Invalid response status received for the custom grant request. (${response.statusText})`, - (await response.json()) as string, - ); - } - - if (config.returnsSession) { - return this.authHelper.handleTokenResponse(response, userId); - } - return Promise.resolve((await response.json()) as TokenResponse | Response); - } - - /** - * This method returns if the user is authenticated or not. - * - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * @returns - A Promise that resolves with `true` if the user is authenticated, `false` otherwise. - * - * @example - * ``` - * await auth.isSignedIn(); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#isSignedIn} - * - * @preserve - */ - public async isSignedIn(userId?: string): Promise { - const isAccessTokenAvailable: boolean = Boolean(await this.getAccessToken(userId)); - - // Check if the access token is expired. - const createdAt: number = (await this.storageManager.getSessionData(userId))?.created_at; - - // Get the expires in value. - const expiresInString: string = (await this.storageManager.getSessionData(userId))?.expires_in; - - // If the expires in value is not available, the token is invalid and the user is not authenticated. - if (!expiresInString) { - return false; - } - - // Convert to milliseconds. - const expiresIn: number = parseInt(expiresInString, 10) * 1000; - const currentTime: number = new Date().getTime(); - const isAccessTokenValid: boolean = createdAt + expiresIn > currentTime; - - const isSignedIn: boolean = isAccessTokenAvailable && isAccessTokenValid; - - return isSignedIn; - } - - /** - * This method returns the PKCE code generated during the generation of the authentication URL. - * - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * @param state - The state parameter that was passed in the authentication URL. - * - * @returns - A Promise that resolves with the PKCE code. - * - * @example - * ``` - * const pkce = await getPKCECode(); - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getPKCECode} - * - * @preserve - */ - public async getPKCECode(state: string, userId?: string): Promise { - return (await this.storageManager.getTemporaryDataParameter( - extractPkceStorageKeyFromState(state), - userId, - )) as string; - } - - /** - * This method sets the PKCE code to the data store. - * - * @param pkce - The PKCE code. - * @param state - The state parameter that was passed in the authentication URL. - * @param userId - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user - * scenarios where each user should be uniquely identified. - * - * @example - * ``` - * await auth.setPKCECode("pkce_code") - * ``` - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#setPKCECode} - * - * @preserve - */ - public async setPKCECode(pkce: string, state: string, userId?: string): Promise { - return this.storageManager.setTemporaryDataParameter(extractPkceStorageKeyFromState(state), pkce, userId); - } - - /** - * This method returns if the sign-out is successful or not. - * - * @param signOutRedirectUrl - The URL to which the user has been redirected to after signing-out. - * - * **The server appends path parameters to the `afterSignOutUrl` and these path parameters - * are required for this method to function.** - * - * @returns - `true` if successful, `false` otherwise. - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#isSignOutSuccessful} - * - * @preserve - */ - public static isSignOutSuccessful(afterSignOutUrl: string): boolean { - const url: URL = new URL(afterSignOutUrl); - const stateParam: string | null = url.searchParams.get(OIDCRequestConstants.Params.STATE); - const error: boolean = Boolean(url.searchParams.get('error')); - - return stateParam ? stateParam === OIDCRequestConstants.Params.SIGN_OUT_SUCCESS && !error : false; - } - - /** - * This method returns if the sign-out has failed or not. - * - * @param signOutRedirectUrl - The URL to which the user has been redirected to after signing-out. - * - * **The server appends path parameters to the `afterSignOutUrl` and these path parameters - * are required for this method to function.** - * - * @returns - `true` if successful, `false` otherwise. - * - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#didSignOutFail} - * - * @preserve - */ - public static didSignOutFail(afterSignOutUrl: string): boolean { - const url: URL = new URL(afterSignOutUrl); - const stateParam: string | null = url.searchParams.get(OIDCRequestConstants.Params.STATE); - const error: boolean = Boolean(url.searchParams.get('error')); - - return stateParam ? stateParam === OIDCRequestConstants.Params.SIGN_OUT_SUCCESS && error : false; - } - - /** - * This method updates the configuration that was passed into the constructor when instantiating this class. - * - * @param config - A config object to update the SDK configurations with. - * - * @example - * ``` - * const config = { - * afterSignInUrl: "http://localhost:3000/sign-in", - * clientId: "client ID", - * baseUrl: "https://localhost:9443" - * } - * - * await auth.reInitialize(config); - * ``` - * {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#reInitialize} - * - * @preserve - */ - public async reInitialize(config: Partial>): Promise { - const currentConfig: AuthClientConfig = this.storageManager.getConfigData() as unknown as AuthClientConfig; - const newConfig: AuthClientConfig = deepMerge(currentConfig, config); - - await this.storageManager.setConfigData(newConfig); - await this.loadOpenIDProviderConfiguration(true); - } - - public static async clearSession(userId?: string): Promise { - await this.authHelperInstance.clearSession(userId); - } -} diff --git a/packages/javascript/src/__legacy__/helpers/authentication-helper.ts b/packages/javascript/src/__legacy__/helpers/authentication-helper.ts deleted file mode 100644 index 63267eb5c..000000000 --- a/packages/javascript/src/__legacy__/helpers/authentication-helper.ts +++ /dev/null @@ -1,336 +0,0 @@ -/** - * Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import OIDCDiscoveryConstants from '../../constants/OIDCDiscoveryConstants'; -import TokenExchangeConstants from '../../constants/TokenExchangeConstants'; -import {AsgardeoAuthException} from '../../errors/exception'; -import {IsomorphicCrypto} from '../../IsomorphicCrypto'; -import {Config} from '../../models/config'; -import {JWKInterface} from '../../models/crypto'; -import {OIDCDiscoveryEndpointsApiResponse, OIDCDiscoveryApiResponse} from '../../models/oidc-discovery'; -import {Platform} from '../../models/platforms'; -import {SessionData} from '../../models/session'; -import {IdToken, TokenResponse, AccessTokenApiResponse} from '../../models/token'; -import {User} from '../../models/user'; -import StorageManager from '../../StorageManager'; -import extractUserClaimsFromIdToken from '../../utils/extractUserClaimsFromIdToken'; -import processOpenIDScopes from '../../utils/processOpenIDScopes'; -import {AuthClientConfig, StrictAuthClientConfig} from '../models'; - -export class AuthenticationHelper { - private storageManager: StorageManager; - - private config: () => Promise; - - private oidcProviderMetaData: () => Promise; - - private cryptoHelper: IsomorphicCrypto; - - public constructor(storageManagerInstance: StorageManager, cryptoHelperInstance: IsomorphicCrypto) { - this.storageManager = storageManagerInstance; - this.config = async (): Promise => this.storageManager.getConfigData(); - this.oidcProviderMetaData = async (): Promise => - this.storageManager.loadOpenIDProviderConfiguration(); - this.cryptoHelper = cryptoHelperInstance; - } - - public async resolveEndpoints(response: OIDCDiscoveryApiResponse): Promise { - const oidcProviderMetaData: OIDCDiscoveryApiResponse = {}; - const configData: StrictAuthClientConfig = await this.config(); - - if (configData.endpoints) { - Object.keys(configData.endpoints).forEach((endpointName: string) => { - const snakeCasedName: string = endpointName.replace(/[A-Z]/g, (letter: string) => `_${letter.toLowerCase()}`); - - oidcProviderMetaData[snakeCasedName] = configData?.endpoints ? configData.endpoints[endpointName] : ''; - }); - } - - return {...response, ...oidcProviderMetaData}; - } - - public async resolveEndpointsExplicitly(): Promise { - const oidcProviderMetaData: OIDCDiscoveryApiResponse = {}; - const configData: StrictAuthClientConfig = await this.config(); - - const requiredEndpoints: string[] = [ - OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.AUTHORIZATION, - OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.END_SESSION, - OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.JWKS, - OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.SESSION_IFRAME, - OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.REVOCATION, - OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.TOKEN, - OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.ISSUER, - OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.USERINFO, - ]; - - const isRequiredEndpointsContains: boolean = configData.endpoints - ? requiredEndpoints.every((reqEndpointName: string) => - configData.endpoints - ? Object.keys(configData.endpoints).some((endpointName: string) => { - const snakeCasedName: string = endpointName.replace( - /[A-Z]/g, - (letter: string) => `_${letter.toLowerCase()}`, - ); - - return snakeCasedName === reqEndpointName; - }) - : false, - ) - : false; - - if (!isRequiredEndpointsContains) { - throw new AsgardeoAuthException( - 'JS-AUTH_HELPER-REE-NF01', - 'Required endpoints missing', - 'Some or all of the required endpoints are missing in the object passed to the `endpoints` ' + - 'attribute of the`AuthConfig` object.', - ); - } - - if (configData.endpoints) { - Object.keys(configData.endpoints).forEach((endpointName: string) => { - const snakeCasedName: string = endpointName.replace(/[A-Z]/g, (letter: string) => `_${letter.toLowerCase()}`); - - oidcProviderMetaData[snakeCasedName] = configData?.endpoints ? configData.endpoints[endpointName] : ''; - }); - } - - return {...oidcProviderMetaData}; - } - - public async resolveEndpointsByBaseURL(): Promise { - const oidcProviderMetaData: OIDCDiscoveryEndpointsApiResponse = {}; - const configData: StrictAuthClientConfig = await this.config(); - - const {baseUrl} = configData as any; - - if (!baseUrl) { - throw new AsgardeoAuthException( - 'JS-AUTH_HELPER_REBO-NF01', - 'Base URL not defined.', - 'Base URL is not defined in AuthClient config.', - ); - } - - if (configData.endpoints) { - Object.keys(configData.endpoints).forEach((endpointName: string) => { - const snakeCasedName: string = endpointName.replace(/[A-Z]/g, (letter: string) => `_${letter.toLowerCase()}`); - - oidcProviderMetaData[snakeCasedName] = configData?.endpoints ? configData.endpoints[endpointName] : ''; - }); - } - - const endpointKeys: typeof OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints = - OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints; - const endpointPaths: typeof OIDCDiscoveryConstants.Endpoints = OIDCDiscoveryConstants.Endpoints; - - const defaultEndpoints: OIDCDiscoveryApiResponse = { - [endpointKeys.AUTHORIZATION]: `${baseUrl}${endpointPaths.AUTHORIZATION}`, - [endpointKeys.END_SESSION]: `${baseUrl}${endpointPaths.END_SESSION}`, - [endpointKeys.ISSUER]: `${baseUrl}${endpointPaths.ISSUER}`, - [endpointKeys.JWKS]: `${baseUrl}${endpointPaths.JWKS}`, - [endpointKeys.SESSION_IFRAME]: `${baseUrl}${endpointPaths.SESSION_IFRAME}`, - [endpointKeys.REVOCATION]: `${baseUrl}${endpointPaths.REVOCATION}`, - [endpointKeys.TOKEN]: `${baseUrl}${endpointPaths.TOKEN}`, - [endpointKeys.USERINFO]: `${baseUrl}${endpointPaths.USERINFO}`, - }; - - // For AsgardeoV2 (Thunder), the issuer must be the base URL (e.g., https://localhost:8090) - // to comply with RFC 8414 (Section 2 & 3) and OpenID Connect Discovery specs. - // The issuer should be a URL using "https" scheme with no query or fragment components. - // The well-known metadata endpoint is derived by inserting "/.well-known/oauth-authorization-server" - // between the host and path components of the issuer identifier. - // Reference: https://datatracker.ietf.org/doc/html/rfc8414#section-2 - // Trackers: - // - https://github.com/asgardeo/thunder/issues/815 - // - https://github.com/asgardeo/javascript/issues/322 - if ((configData as Config).platform === Platform.AsgardeoV2) { - defaultEndpoints[OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.ISSUER] = `${baseUrl}`; - } - - return {...defaultEndpoints, ...oidcProviderMetaData}; - } - - public async validateIdToken(idToken: string): Promise { - const jwksEndpoint: string | undefined = (await this.storageManager.loadOpenIDProviderConfiguration()).jwks_uri; - const configData: StrictAuthClientConfig = await this.config(); - - if (!jwksEndpoint || jwksEndpoint.trim().length === 0) { - throw new AsgardeoAuthException( - 'JS_AUTH_HELPER-VIT-NF01', - 'JWKS endpoint not found.', - 'No JWKS endpoint was found in the OIDC provider meta data returned by the well-known endpoint ' + - 'or the JWKS endpoint passed to the SDK is empty.', - ); - } - - let response: Response; - - try { - response = await fetch(jwksEndpoint, { - credentials: configData.sendCookiesInRequests ? 'include' : 'same-origin', - }); - } catch (error: any) { - throw new AsgardeoAuthException( - 'JS-AUTH_HELPER-VIT-NE02', - 'Request to jwks endpoint failed.', - error ?? 'The request sent to get the jwks from the server failed.', - ); - } - - if (response.status !== 200 || !response.ok) { - throw new AsgardeoAuthException( - 'JS-AUTH_HELPER-VIT-HE03', - `Invalid response status received for jwks request (${response.statusText}).`, - (await response.json()) as string, - ); - } - - const {issuer} = await this.oidcProviderMetaData(); - - const {keys}: {keys: JWKInterface[]} = (await response.json()) as { - keys: JWKInterface[]; - }; - - const jwk: any = await this.cryptoHelper.getJWKForTheIdToken(idToken.split('.')[0], keys); - - return this.cryptoHelper.isValidIdToken( - idToken, - jwk, - (await this.config()).clientId, - issuer ?? '', - this.cryptoHelper.decodeJwtToken(idToken).sub, - (await this.config()).tokenValidation?.idToken?.clockTolerance, - (await this.config()).tokenValidation?.idToken?.validateIssuer ?? true, - ); - } - - public getAuthenticatedUserInfo(idToken: string): User { - const payload: IdToken = this.cryptoHelper.decodeJwtToken(idToken); - const username: string = payload?.['username'] ?? ''; - const givenName: string = payload?.['given_name'] ?? ''; - const familyName: string = payload?.['family_name'] ?? ''; - const fullName: string = givenName && familyName ? `${givenName} ${familyName}` : givenName || familyName || ''; - const displayName: string = payload.preferred_username ?? fullName; - - return { - displayName, - username, - ...extractUserClaimsFromIdToken(payload), - }; - } - - public async replaceCustomGrantTemplateTags(text: string, userId?: string): Promise { - const configData: StrictAuthClientConfig = await this.config(); - - const sourceInstanceId: number | null = configData.organizationChain?.sourceInstanceId ?? null; - - let sessionData: SessionData; - - if (sourceInstanceId) { - const {clientId} = configData; - let instanceKey: string; - if (clientId) { - instanceKey = `instance_${sourceInstanceId}-${clientId}`; - } else { - instanceKey = `instance_${sourceInstanceId}`; - } - sessionData = await this.storageManager.getSessionData(userId, instanceKey); - - if (!sessionData || !sessionData.access_token) { - throw new AsgardeoAuthException( - 'JS-AUTH_HELPER-RCGTT-NE01', - 'No session data found for source instance.', - 'Failed to retrieve session data from the source organization context.', - ); - } - } else { - sessionData = await this.storageManager.getSessionData(userId); - } - - const scope: string = processOpenIDScopes(configData.scopes); - - if (typeof text !== 'string') { - return text; - } - - return text - .replace(TokenExchangeConstants.Placeholders.ACCESS_TOKEN, sessionData.access_token) - .replace( - TokenExchangeConstants.Placeholders.USERNAME, - this.getAuthenticatedUserInfo(sessionData.id_token).username, - ) - .replace(TokenExchangeConstants.Placeholders.SCOPES, scope) - .replace(TokenExchangeConstants.Placeholders.CLIENT_ID, configData.clientId) - .replace(TokenExchangeConstants.Placeholders.CLIENT_SECRET, configData.clientSecret ?? ''); - } - - public async clearSession(userId?: string): Promise { - await this.storageManager.removeTemporaryData(userId); - await this.storageManager.removeSessionData(userId); - } - - public async handleTokenResponse(response: Response, userId?: string): Promise { - if (response.status !== 200 || !response.ok) { - throw new AsgardeoAuthException( - 'JS-AUTH_HELPER-HTR-NE01', - `Invalid response status received for token request (${response.statusText}).`, - (await response.json()) as string, - ); - } - - // Get the response in JSON - const parsedResponse: AccessTokenApiResponse = (await response.json()) as AccessTokenApiResponse; - - parsedResponse.created_at = new Date().getTime(); - - const shouldValidateIdToken: boolean | undefined = (await this.config()).tokenValidation?.idToken?.validate; - - if (shouldValidateIdToken) { - return this.validateIdToken(parsedResponse.id_token).then(async () => { - await this.storageManager.setSessionData(parsedResponse, userId); - - const tokenResponse: TokenResponse = { - accessToken: parsedResponse.access_token, - createdAt: parsedResponse.created_at, - expiresIn: parsedResponse.expires_in, - idToken: parsedResponse.id_token, - refreshToken: parsedResponse.refresh_token, - scope: parsedResponse.scope, - tokenType: parsedResponse.token_type, - }; - - return Promise.resolve(tokenResponse); - }); - } - const tokenResponse: TokenResponse = { - accessToken: parsedResponse.access_token, - createdAt: parsedResponse.created_at, - expiresIn: parsedResponse.expires_in, - idToken: parsedResponse.id_token, - refreshToken: parsedResponse.refresh_token, - scope: parsedResponse.scope, - tokenType: parsedResponse.token_type, - }; - - await this.storageManager.setSessionData(parsedResponse, userId); - - return Promise.resolve(tokenResponse); - } -} diff --git a/packages/javascript/src/__legacy__/helpers/index.ts b/packages/javascript/src/__legacy__/helpers/index.ts deleted file mode 100644 index cc9eb3414..000000000 --- a/packages/javascript/src/__legacy__/helpers/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export * from './authentication-helper'; diff --git a/packages/javascript/src/api/exchangeToken.ts b/packages/javascript/src/api/exchangeToken.ts new file mode 100644 index 000000000..a355a2b4d --- /dev/null +++ b/packages/javascript/src/api/exchangeToken.ts @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {AsgardeoAuthException} from '../errors/exception'; +import OIDCDiscoveryConstants from '../constants/OIDCDiscoveryConstants'; +import {TokenResponse, TokenExchangeRequestConfig} from '../models/token'; +import {StrictAuthClientConfig} from '../models/auth-client-config'; +import StorageManager from '../StorageManager'; +import {IsomorphicCrypto} from '../IsomorphicCrypto'; +import loadOpenIDProviderConfiguration from './loadOpenIDProviderConfiguration'; +import replaceCustomGrantTemplateTags from '../utils/replaceCustomGrantTemplateTags'; +import handleTokenResponse from './handleTokenResponse'; + +export default async function exchangeToken( + storageManager: StorageManager, + cryptoHelper: IsomorphicCrypto, + config: TokenExchangeRequestConfig, + userId?: string, +): Promise { + if ( + !(await storageManager.getTemporaryDataParameter( + OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, + )) + ) { + await loadOpenIDProviderConfiguration(storageManager, cryptoHelper, false); + } + + const oidcProviderMetadata = await storageManager.loadOpenIDProviderConfiguration(); + const configData: StrictAuthClientConfig = await storageManager.getConfigData() as unknown as StrictAuthClientConfig; + + let tokenEndpoint: string | undefined; + + if (config.tokenEndpoint && config.tokenEndpoint.trim().length !== 0) { + tokenEndpoint = config.tokenEndpoint; + } else { + tokenEndpoint = oidcProviderMetadata.token_endpoint; + } + + if (!tokenEndpoint || tokenEndpoint.trim().length === 0) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RCG-NF01', + 'Token endpoint not found.', + 'No token endpoint was found in the OIDC provider meta data returned by the well-known endpoint ' + + 'or the token endpoint passed to the SDK is empty.', + ); + } + + const data: string[] = await Promise.all( + Object.entries(config.data).map(async ([key, value]: [key: string, value: any]) => { + const newValue: string = await replaceCustomGrantTemplateTags(storageManager, cryptoHelper, value as string, userId); + + return `${key}=${newValue}`; + }), + ); + + let requestHeaders: Record = { + Accept: 'application/json', + 'Content-Type': 'application/x-www-form-urlencoded', + }; + + if (config.attachToken) { + requestHeaders = { + ...requestHeaders, + Authorization: `Bearer ${(await storageManager.getSessionData(userId)).access_token}`, + }; + } + + const requestConfig: RequestInit = { + body: data.join('&'), + credentials: configData.sendCookiesInRequests ? 'include' : 'same-origin', + headers: new Headers(requestHeaders), + method: 'POST', + }; + + let response: Response; + + try { + response = await fetch(tokenEndpoint, requestConfig); + } catch (error: any) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RCG-NE02', + 'The custom grant request failed.', + error ?? 'The request sent to get the custom grant failed.', + ); + } + + if (response.status !== 200 || !response.ok) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RCG-HE03', + `Invalid response status received for the custom grant request. (${response.statusText})`, + (await response.json()) as string, + ); + } + + if (config.returnsSession) { + return handleTokenResponse(storageManager, cryptoHelper, response, userId); + } + return (await response.json()) as TokenResponse | Response; +} diff --git a/packages/javascript/src/api/handleTokenResponse.ts b/packages/javascript/src/api/handleTokenResponse.ts new file mode 100644 index 000000000..268203892 --- /dev/null +++ b/packages/javascript/src/api/handleTokenResponse.ts @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {AsgardeoAuthException} from '../errors/exception'; +import {TokenResponse, AccessTokenApiResponse} from '../models/token'; +import {StrictAuthClientConfig} from '../models/auth-client-config'; +import {IsomorphicCrypto} from '../IsomorphicCrypto'; +import StorageManager from '../StorageManager'; +import validateIdToken from './validateIdToken'; + +export default async function handleTokenResponse( + storageManager: StorageManager, + cryptoHelper: IsomorphicCrypto, + response: Response, + userId?: string, +): Promise { + if (response.status !== 200 || !response.ok) { + throw new AsgardeoAuthException( + 'JS-AUTH_HELPER-HTR-NE01', + `Invalid response status received for token request (${response.statusText}).`, + (await response.json()) as string, + ); + } + + // Get the response in JSON + const parsedResponse: AccessTokenApiResponse = (await response.json()) as AccessTokenApiResponse; + + parsedResponse.created_at = new Date().getTime(); + + const configData: StrictAuthClientConfig = await storageManager.getConfigData() as unknown as StrictAuthClientConfig; + const shouldValidateIdToken: boolean | undefined = configData.tokenValidation?.idToken?.validate; + + if (shouldValidateIdToken) { + await validateIdToken(storageManager, cryptoHelper, parsedResponse.id_token); + } + + await storageManager.setSessionData(parsedResponse, userId); + + const tokenResponse: TokenResponse = { + accessToken: parsedResponse.access_token, + createdAt: parsedResponse.created_at, + expiresIn: parsedResponse.expires_in, + idToken: parsedResponse.id_token, + refreshToken: parsedResponse.refresh_token, + scope: parsedResponse.scope, + tokenType: parsedResponse.token_type, + }; + + return tokenResponse; +} diff --git a/packages/javascript/src/api/loadOpenIDProviderConfiguration.ts b/packages/javascript/src/api/loadOpenIDProviderConfiguration.ts new file mode 100644 index 000000000..e77fa2bce --- /dev/null +++ b/packages/javascript/src/api/loadOpenIDProviderConfiguration.ts @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {AsgardeoAuthException} from '../errors/exception'; +import OIDCDiscoveryConstants from '../constants/OIDCDiscoveryConstants'; +import {StrictAuthClientConfig} from '../models/auth-client-config'; +import {Platform} from '../models/platforms'; +import StorageManager from '../StorageManager'; +import {IsomorphicCrypto} from '../IsomorphicCrypto'; +import resolveEndpoints from '../utils/resolveEndpoints'; +import resolveEndpointsByBaseURL from '../utils/resolveEndpointsByBaseURL'; +import resolveEndpointsExplicitly from '../utils/resolveEndpointsExplicitly'; + +export default async function loadOpenIDProviderConfiguration( + storageManager: StorageManager, + cryptoHelper: IsomorphicCrypto, + forceInit: boolean, +): Promise { + const configData: StrictAuthClientConfig = await storageManager.getConfigData() as unknown as StrictAuthClientConfig; + + if ( + !forceInit && + (await storageManager.getTemporaryDataParameter( + OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, + )) + ) { + return; + } + + const {wellKnownEndpoint, platform, discovery, baseUrl, endpoints} = configData as any; + + const resolvedWellKnownEndpoint: string | undefined = + wellKnownEndpoint || + (platform === Platform.AsgardeoV2 && discovery?.wellKnown?.enabled + ? `${baseUrl}${endpoints?.wellKnown ?? '/.well-known/openid-configuration'}` + : undefined); + + if (resolvedWellKnownEndpoint) { + let response: Response; + + try { + response = await fetch(resolvedWellKnownEndpoint); + if (response.status !== 200 || !response.ok) { + throw new Error(); + } + } catch { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-GOPMD-HE01', + 'Invalid well-known response', + 'The well known endpoint response has been failed with an error.', + ); + } + + await storageManager.setOIDCProviderMetaData( + await resolveEndpoints(storageManager, await response.json()), + ); + await storageManager.setTemporaryDataParameter( + OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, + true, + ); + + return; + } + + if ((configData as any).baseUrl) { + try { + await storageManager.setOIDCProviderMetaData(await resolveEndpointsByBaseURL(storageManager)); + } catch (error: any) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-GOPMD-IV02', + 'Resolving endpoints failed.', + error ?? 'Resolving endpoints by base url failed.', + ); + } + await storageManager.setTemporaryDataParameter( + OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, + true, + ); + + return; + } + + await storageManager.setOIDCProviderMetaData(await resolveEndpointsExplicitly(storageManager)); + + await storageManager.setTemporaryDataParameter( + OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, + true, + ); +} diff --git a/packages/javascript/src/api/refreshAccessToken.ts b/packages/javascript/src/api/refreshAccessToken.ts new file mode 100644 index 000000000..f95a372f0 --- /dev/null +++ b/packages/javascript/src/api/refreshAccessToken.ts @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {AsgardeoAuthException} from '../errors/exception'; +import {SessionData} from '../models/session'; +import {TokenResponse} from '../models/token'; +import {StrictAuthClientConfig} from '../models/auth-client-config'; +import StorageManager from '../StorageManager'; +import {IsomorphicCrypto} from '../IsomorphicCrypto'; +import handleTokenResponse from './handleTokenResponse'; + +export default async function refreshAccessToken( + storageManager: StorageManager, + cryptoHelper: IsomorphicCrypto, + userId?: string, +): Promise { + const tokenEndpoint: string | undefined = (await storageManager.loadOpenIDProviderConfiguration()).token_endpoint; + const configData: StrictAuthClientConfig = await storageManager.getConfigData() as unknown as StrictAuthClientConfig; + const sessionData: SessionData = await storageManager.getSessionData(userId); + + if (!sessionData.refresh_token) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RAT2-NF01', + 'No refresh token found.', + "There was no refresh token found. Asgardeo doesn't return a " + + 'refresh token if the refresh token grant is not enabled.', + ); + } + + if (!tokenEndpoint || tokenEndpoint.trim().length === 0) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RAT2-NF02', + 'No refresh token endpoint found.', + 'No refresh token endpoint was in the OIDC provider meta data returned by the well-known ' + + 'endpoint or the refresh token endpoint passed to the SDK is empty.', + ); + } + + const body: string[] = []; + + body.push(`client_id=${configData.clientId}`); + body.push(`refresh_token=${sessionData.refresh_token}`); + body.push('grant_type=refresh_token'); + + if (configData.clientSecret && configData.clientSecret.trim().length > 0) { + body.push(`client_secret=${configData.clientSecret}`); + } + + let tokenResponse: Response; + + try { + tokenResponse = await fetch(tokenEndpoint, { + body: body.join('&'), + credentials: configData.sendCookiesInRequests ? 'include' : 'same-origin', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/x-www-form-urlencoded', + }, + method: 'POST', + }); + } catch (error: any) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RAT2-NR03', + 'Refresh access token request failed.', + error ?? 'The request to refresh the access token failed.', + ); + } + + if (!tokenResponse.ok) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RAT2-HE04', + `Refreshing access token failed with ${tokenResponse.statusText}`, + (await tokenResponse.json()) as string, + ); + } + + return handleTokenResponse(storageManager, cryptoHelper, tokenResponse, userId); +} diff --git a/packages/javascript/src/api/requestAccessToken.ts b/packages/javascript/src/api/requestAccessToken.ts new file mode 100644 index 000000000..87e46cac6 --- /dev/null +++ b/packages/javascript/src/api/requestAccessToken.ts @@ -0,0 +1,146 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {AsgardeoAuthException} from '../errors/exception'; +import OIDCDiscoveryConstants from '../constants/OIDCDiscoveryConstants'; +import OIDCRequestConstants from '../constants/OIDCRequestConstants'; +import {SessionData} from '../models/session'; +import {TokenResponse} from '../models/token'; +import {StrictAuthClientConfig} from '../models/auth-client-config'; +import {Platform} from '../models/platforms'; +import {TokenEndpointAuthMethod} from '../models/token-endpoint-auth'; +import extractPkceStorageKeyFromState from '../utils/extractPkceStorageKeyFromState'; +import base64Encode from '../utils/base64Encode'; +import StorageManager from '../StorageManager'; +import {IsomorphicCrypto} from '../IsomorphicCrypto'; +import loadOpenIDProviderConfiguration from './loadOpenIDProviderConfiguration'; +import handleTokenResponse from './handleTokenResponse'; + +export default async function requestAccessToken( + storageManager: StorageManager, + cryptoHelper: IsomorphicCrypto, + authorizationCode: string, + sessionState: string, + state: string, + userId?: string, + tokenRequestConfig?: { + params: Record; + }, +): Promise { + if ( + !(await storageManager.getTemporaryDataParameter( + OIDCDiscoveryConstants.Storage.StorageKeys.OPENID_PROVIDER_CONFIG_INITIATED, + )) + ) { + await loadOpenIDProviderConfiguration(storageManager, cryptoHelper, false); + } + + const tokenEndpoint: string | undefined = (await storageManager.loadOpenIDProviderConfiguration()).token_endpoint; + const configData: StrictAuthClientConfig = await storageManager.getConfigData() as unknown as StrictAuthClientConfig; + + if (!tokenEndpoint || tokenEndpoint.trim().length === 0) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RAT1-NF01', + 'Token endpoint not found.', + 'No token endpoint was found in the OIDC provider meta data returned by the well-known endpoint ' + + 'or the token endpoint passed to the SDK is empty.', + ); + } + + if (sessionState) { + await storageManager.setSessionDataParameter( + OIDCRequestConstants.Params.SESSION_STATE as keyof SessionData, + sessionState, + userId, + ); + } + + const body: URLSearchParams = new URLSearchParams(); + + body.set('client_id', configData.clientId); + + const hasSecret: boolean = Boolean(configData.clientSecret && configData.clientSecret.trim().length > 0); + const tokenEndpointAuthMethod: TokenEndpointAuthMethod = + configData.tokenRequest?.authMethod ?? + ((configData as any).platform === Platform.AsgardeoV2 ? 'client_secret_basic' : 'client_secret_post'); + + if (hasSecret && tokenEndpointAuthMethod === 'client_secret_post') { + body.set('client_secret', configData.clientSecret); + } + + const code: string = authorizationCode; + + body.set('code', code); + + body.set('grant_type', 'authorization_code'); + body.set('redirect_uri', configData.afterSignInUrl); + + if (tokenRequestConfig?.params) { + Object.entries(tokenRequestConfig.params).forEach(([key, value]: [key: string, value: unknown]) => { + body.append(key, value as string); + }); + } + + if (configData.enablePKCE) { + body.set( + 'code_verifier', + `${await storageManager.getTemporaryDataParameter(extractPkceStorageKeyFromState(state), userId)}`, + ); + + await storageManager.removeTemporaryDataParameter(extractPkceStorageKeyFromState(state), userId); + } + + const tokenRequestHeaders: Record = { + Accept: 'application/json', + 'Content-Type': 'application/x-www-form-urlencoded', + }; + + if (hasSecret && tokenEndpointAuthMethod === 'client_secret_basic') { + const credential: string = `${encodeURIComponent(configData.clientId)}:${encodeURIComponent( + configData.clientSecret, + )}`; + tokenRequestHeaders['Authorization'] = `Basic ${base64Encode(credential)}`; + } + + let tokenResponse: Response; + + try { + tokenResponse = await fetch(tokenEndpoint, { + body, + credentials: configData.sendCookiesInRequests ? 'include' : 'same-origin', + headers: tokenRequestHeaders, + method: 'POST', + }); + } catch (error: any) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RAT1-NE02', + 'Requesting access token failed', + error ?? 'The request to get the access token from the server failed.', + ); + } + + if (!tokenResponse.ok) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RAT1-HE03', + `Requesting access token failed with ${tokenResponse.statusText}`, + (await tokenResponse.json()) as string, + ); + } + + return handleTokenResponse(storageManager, cryptoHelper, tokenResponse, userId); +} diff --git a/packages/javascript/src/api/revokeAccessToken.ts b/packages/javascript/src/api/revokeAccessToken.ts new file mode 100644 index 000000000..0c9312813 --- /dev/null +++ b/packages/javascript/src/api/revokeAccessToken.ts @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {AsgardeoAuthException} from '../errors/exception'; +import {StrictAuthClientConfig} from '../models/auth-client-config'; +import StorageManager from '../StorageManager'; +import clearSession from '../utils/clearSession'; + +export default async function revokeAccessToken( + storageManager: StorageManager, + userId?: string, +): Promise { + const revokeTokenEndpoint: string | undefined = (await storageManager.loadOpenIDProviderConfiguration()).revocation_endpoint; + const configData: StrictAuthClientConfig = await storageManager.getConfigData() as unknown as StrictAuthClientConfig; + + if (!revokeTokenEndpoint || revokeTokenEndpoint.trim().length === 0) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RAT3-NF01', + 'No revoke access token endpoint found.', + 'No revoke access token endpoint was found in the OIDC provider meta data returned by ' + + 'the well-known endpoint or the revoke access token endpoint passed to the SDK is empty.', + ); + } + + const body: string[] = []; + + body.push(`client_id=${configData.clientId}`); + body.push(`token=${(await storageManager.getSessionData(userId)).access_token}`); + body.push('token_type_hint=access_token'); + + if (configData.clientSecret && configData.clientSecret.trim().length > 0) { + body.push(`client_secret=${configData.clientSecret}`); + } + + let response: Response; + + try { + response = await fetch(revokeTokenEndpoint, { + body: body.join('&'), + credentials: configData.sendCookiesInRequests ? 'include' : 'same-origin', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/x-www-form-urlencoded', + }, + method: 'POST', + }); + } catch (error: any) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RAT3-NE02', + 'The request to revoke access token failed.', + error ?? 'The request sent to revoke the access token failed.', + ); + } + + if (response.status !== 200 || !response.ok) { + throw new AsgardeoAuthException( + 'JS-AUTH_CORE-RAT3-HE03', + `Invalid response status received for revoke access token request (${response.statusText}).`, + (await response.json()) as string, + ); + } + + await clearSession(storageManager, userId); + + return response; +} diff --git a/packages/javascript/src/api/validateIdToken.ts b/packages/javascript/src/api/validateIdToken.ts new file mode 100644 index 000000000..7f5b406c6 --- /dev/null +++ b/packages/javascript/src/api/validateIdToken.ts @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {AsgardeoAuthException} from '../errors/exception'; +import {JWKInterface} from '../models/crypto'; +import {IdToken} from '../models/token'; +import {StrictAuthClientConfig} from '../models/auth-client-config'; +import {IsomorphicCrypto} from '../IsomorphicCrypto'; +import StorageManager from '../StorageManager'; + +export default async function validateIdToken( + storageManager: StorageManager, + cryptoHelper: IsomorphicCrypto, + idToken: string, +): Promise { + const jwksEndpoint: string | undefined = (await storageManager.loadOpenIDProviderConfiguration()).jwks_uri; + const configData: StrictAuthClientConfig = await storageManager.getConfigData() as unknown as StrictAuthClientConfig; + + if (!jwksEndpoint || jwksEndpoint.trim().length === 0) { + throw new AsgardeoAuthException( + 'JS_AUTH_HELPER-VIT-NF01', + 'JWKS endpoint not found.', + 'No JWKS endpoint was found in the OIDC provider meta data returned by the well-known endpoint ' + + 'or the JWKS endpoint passed to the SDK is empty.', + ); + } + + let response: Response; + + try { + response = await fetch(jwksEndpoint, { + credentials: configData.sendCookiesInRequests ? 'include' : 'same-origin', + }); + } catch (error: any) { + throw new AsgardeoAuthException( + 'JS-AUTH_HELPER-VIT-NE02', + 'Request to jwks endpoint failed.', + error ?? 'The request sent to get the jwks from the server failed.', + ); + } + + if (response.status !== 200 || !response.ok) { + throw new AsgardeoAuthException( + 'JS-AUTH_HELPER-VIT-HE03', + `Invalid response status received for jwks request (${response.statusText}).`, + (await response.json()) as string, + ); + } + + const {issuer} = await storageManager.loadOpenIDProviderConfiguration(); + + const {keys}: {keys: JWKInterface[]} = (await response.json()) as { + keys: JWKInterface[]; + }; + + const jwk: any = await cryptoHelper.getJWKForTheIdToken(idToken.split('.')[0], keys); + + return cryptoHelper.isValidIdToken( + idToken, + jwk, + configData.clientId, + issuer ?? '', + cryptoHelper.decodeJwtToken(idToken).sub, + configData.tokenValidation?.idToken?.clockTolerance, + configData.tokenValidation?.idToken?.validateIssuer ?? true, + ); +} diff --git a/packages/javascript/src/index.ts b/packages/javascript/src/index.ts index ac913d7e7..aaa81a965 100644 --- a/packages/javascript/src/index.ts +++ b/packages/javascript/src/index.ts @@ -16,7 +16,7 @@ * under the License. */ -export {AsgardeoAuthClient} from './__legacy__/client'; +export {AsgardeoAuthClient} from './AsgardeoAuthClient'; export type { DefaultAuthClientConfig, WellKnownAuthClientConfig, @@ -24,7 +24,7 @@ export type { ExplicitAuthClientConfig, StrictAuthClientConfig, AuthClientConfig, -} from './__legacy__/models'; +} from './models/auth-client-config'; export {IsomorphicCrypto} from './IsomorphicCrypto'; diff --git a/packages/javascript/src/__legacy__/models/client-config.ts b/packages/javascript/src/models/auth-client-config.ts similarity index 93% rename from packages/javascript/src/__legacy__/models/client-config.ts rename to packages/javascript/src/models/auth-client-config.ts index 7f0a71b89..3c1087796 100644 --- a/packages/javascript/src/__legacy__/models/client-config.ts +++ b/packages/javascript/src/models/auth-client-config.ts @@ -16,10 +16,10 @@ * under the License. */ -import {OAuthResponseMode} from '../../models/oauth-response'; -import {OIDCEndpoints} from '../../models/oidc-endpoints'; -import {Platform} from '../../models/platforms'; -import {TokenEndpointAuthMethod} from '../../models/token-endpoint-auth'; +import {OAuthResponseMode} from './oauth-response'; +import {OIDCEndpoints} from './oidc-endpoints'; +import {Platform} from './platforms'; +import {TokenEndpointAuthMethod} from './token-endpoint-auth'; export interface DefaultAuthClientConfig { afterSignInUrl: string; diff --git a/packages/javascript/src/__legacy__/models/index.ts b/packages/javascript/src/utils/clearSession.ts similarity index 64% rename from packages/javascript/src/__legacy__/models/index.ts rename to packages/javascript/src/utils/clearSession.ts index 2d461ba29..ef07405cb 100644 --- a/packages/javascript/src/__legacy__/models/index.ts +++ b/packages/javascript/src/utils/clearSession.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -16,4 +16,12 @@ * under the License. */ -export * from './client-config'; +import StorageManager from '../StorageManager'; + +export default async function clearSession( + storageManager: StorageManager, + userId?: string, +): Promise { + await storageManager.removeTemporaryData(userId); + await storageManager.removeSessionData(userId); +} diff --git a/packages/javascript/src/utils/getAuthenticatedUserInfo.ts b/packages/javascript/src/utils/getAuthenticatedUserInfo.ts new file mode 100644 index 000000000..8d25c5738 --- /dev/null +++ b/packages/javascript/src/utils/getAuthenticatedUserInfo.ts @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {IdToken} from '../models/token'; +import {User} from '../models/user'; +import {IsomorphicCrypto} from '../IsomorphicCrypto'; +import extractUserClaimsFromIdToken from './extractUserClaimsFromIdToken'; + +export default function getAuthenticatedUserInfo( + cryptoHelper: IsomorphicCrypto, + idToken: string, +): User { + const payload: IdToken = cryptoHelper.decodeJwtToken(idToken); + const username: string = payload?.['username'] ?? ''; + const givenName: string = payload?.['given_name'] ?? ''; + const familyName: string = payload?.['family_name'] ?? ''; + const fullName: string = givenName && familyName ? `${givenName} ${familyName}` : givenName || familyName || ''; + const displayName: string = payload.preferred_username ?? fullName; + + return { + displayName, + username, + ...extractUserClaimsFromIdToken(payload), + }; +} diff --git a/packages/javascript/src/utils/replaceCustomGrantTemplateTags.ts b/packages/javascript/src/utils/replaceCustomGrantTemplateTags.ts new file mode 100644 index 000000000..f571a3b78 --- /dev/null +++ b/packages/javascript/src/utils/replaceCustomGrantTemplateTags.ts @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import TokenExchangeConstants from '../constants/TokenExchangeConstants'; +import {AsgardeoAuthException} from '../errors/exception'; +import {SessionData} from '../models/session'; +import {StrictAuthClientConfig} from '../models/auth-client-config'; +import processOpenIDScopes from './processOpenIDScopes'; +import getAuthenticatedUserInfo from './getAuthenticatedUserInfo'; +import {IsomorphicCrypto} from '../IsomorphicCrypto'; +import StorageManager from '../StorageManager'; + +export default async function replaceCustomGrantTemplateTags( + storageManager: StorageManager, + cryptoHelper: IsomorphicCrypto, + text: string, + userId?: string, +): Promise { + const configData: StrictAuthClientConfig = await storageManager.getConfigData() as unknown as StrictAuthClientConfig; + + const sourceInstanceId: number | null = configData.organizationChain?.sourceInstanceId ?? null; + + let sessionData: SessionData; + + if (sourceInstanceId) { + const {clientId} = configData; + let instanceKey: string; + if (clientId) { + instanceKey = `instance_${sourceInstanceId}-${clientId}`; + } else { + instanceKey = `instance_${sourceInstanceId}`; + } + sessionData = await storageManager.getSessionData(userId, instanceKey); + + if (!sessionData || !sessionData.access_token) { + throw new AsgardeoAuthException( + 'JS-AUTH_HELPER-RCGTT-NE01', + 'No session data found for source instance.', + 'Failed to retrieve session data from the source organization context.', + ); + } + } else { + sessionData = await storageManager.getSessionData(userId); + } + + const scope: string = processOpenIDScopes(configData.scopes); + + if (typeof text !== 'string') { + return text; + } + + return text + .replace(TokenExchangeConstants.Placeholders.ACCESS_TOKEN, sessionData.access_token) + .replace( + TokenExchangeConstants.Placeholders.USERNAME, + getAuthenticatedUserInfo(cryptoHelper, sessionData.id_token).username, + ) + .replace(TokenExchangeConstants.Placeholders.SCOPES, scope) + .replace(TokenExchangeConstants.Placeholders.CLIENT_ID, configData.clientId) + .replace(TokenExchangeConstants.Placeholders.CLIENT_SECRET, configData.clientSecret ?? ''); +} diff --git a/packages/javascript/src/utils/resolveEndpoints.ts b/packages/javascript/src/utils/resolveEndpoints.ts new file mode 100644 index 000000000..68e0b6426 --- /dev/null +++ b/packages/javascript/src/utils/resolveEndpoints.ts @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {OIDCDiscoveryApiResponse} from '../models/oidc-discovery'; +import {StrictAuthClientConfig} from '../models/auth-client-config'; +import StorageManager from '../StorageManager'; + +export default async function resolveEndpoints( + storageManager: StorageManager, + response: OIDCDiscoveryApiResponse, +): Promise { + const oidcProviderMetaData: OIDCDiscoveryApiResponse = {}; + const configData: StrictAuthClientConfig = await storageManager.getConfigData() as unknown as StrictAuthClientConfig; + + if (configData.endpoints) { + Object.keys(configData.endpoints).forEach((endpointName: string) => { + const snakeCasedName: string = endpointName.replace(/[A-Z]/g, (letter: string) => `_${letter.toLowerCase()}`); + + oidcProviderMetaData[snakeCasedName] = configData?.endpoints ? configData.endpoints[endpointName] : ''; + }); + } + + return {...response, ...oidcProviderMetaData}; +} diff --git a/packages/javascript/src/utils/resolveEndpointsByBaseURL.ts b/packages/javascript/src/utils/resolveEndpointsByBaseURL.ts new file mode 100644 index 000000000..21efa9f35 --- /dev/null +++ b/packages/javascript/src/utils/resolveEndpointsByBaseURL.ts @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import OIDCDiscoveryConstants from '../constants/OIDCDiscoveryConstants'; +import {AsgardeoAuthException} from '../errors/exception'; +import {OIDCDiscoveryEndpointsApiResponse, OIDCDiscoveryApiResponse} from '../models/oidc-discovery'; +import {StrictAuthClientConfig} from '../models/auth-client-config'; +import {Config} from '../models/config'; +import {Platform} from '../models/platforms'; +import StorageManager from '../StorageManager'; + +export default async function resolveEndpointsByBaseURL( + storageManager: StorageManager, +): Promise { + const oidcProviderMetaData: OIDCDiscoveryEndpointsApiResponse = {}; + const configData: StrictAuthClientConfig = await storageManager.getConfigData() as unknown as StrictAuthClientConfig; + + const {baseUrl} = configData as any; + + if (!baseUrl) { + throw new AsgardeoAuthException( + 'JS-AUTH_HELPER_REBO-NF01', + 'Base URL not defined.', + 'Base URL is not defined in AuthClient config.', + ); + } + + if (configData.endpoints) { + Object.keys(configData.endpoints).forEach((endpointName: string) => { + const snakeCasedName: string = endpointName.replace(/[A-Z]/g, (letter: string) => `_${letter.toLowerCase()}`); + + oidcProviderMetaData[snakeCasedName] = configData?.endpoints ? configData.endpoints[endpointName] : ''; + }); + } + + const endpointKeys: typeof OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints = + OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints; + const endpointPaths: typeof OIDCDiscoveryConstants.Endpoints = OIDCDiscoveryConstants.Endpoints; + + const defaultEndpoints: OIDCDiscoveryApiResponse = { + [endpointKeys.AUTHORIZATION]: `${baseUrl}${endpointPaths.AUTHORIZATION}`, + [endpointKeys.END_SESSION]: `${baseUrl}${endpointPaths.END_SESSION}`, + [endpointKeys.ISSUER]: `${baseUrl}${endpointPaths.ISSUER}`, + [endpointKeys.JWKS]: `${baseUrl}${endpointPaths.JWKS}`, + [endpointKeys.SESSION_IFRAME]: `${baseUrl}${endpointPaths.SESSION_IFRAME}`, + [endpointKeys.REVOCATION]: `${baseUrl}${endpointPaths.REVOCATION}`, + [endpointKeys.TOKEN]: `${baseUrl}${endpointPaths.TOKEN}`, + [endpointKeys.USERINFO]: `${baseUrl}${endpointPaths.USERINFO}`, + }; + + // For AsgardeoV2 (Thunder), the issuer must be the base URL (e.g., https://localhost:8090) + // to comply with RFC 8414 (Section 2 & 3) and OpenID Connect Discovery specs. + // The issuer should be a URL using "https" scheme with no query or fragment components. + // The well-known metadata endpoint is derived by inserting "/.well-known/oauth-authorization-server" + // between the host and path components of the issuer identifier. + // Reference: https://datatracker.ietf.org/doc/html/rfc8414#section-2 + // Trackers: + // - https://github.com/asgardeo/thunder/issues/815 + // - https://github.com/asgardeo/javascript/issues/322 + if ((configData as Config).platform === Platform.AsgardeoV2) { + defaultEndpoints[OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.ISSUER] = `${baseUrl}`; + } + + return {...defaultEndpoints, ...oidcProviderMetaData}; +} diff --git a/packages/javascript/src/utils/resolveEndpointsExplicitly.ts b/packages/javascript/src/utils/resolveEndpointsExplicitly.ts new file mode 100644 index 000000000..47ed91ccb --- /dev/null +++ b/packages/javascript/src/utils/resolveEndpointsExplicitly.ts @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import OIDCDiscoveryConstants from '../constants/OIDCDiscoveryConstants'; +import {AsgardeoAuthException} from '../errors/exception'; +import {OIDCDiscoveryEndpointsApiResponse} from '../models/oidc-discovery'; +import {StrictAuthClientConfig} from '../models/auth-client-config'; +import StorageManager from '../StorageManager'; + +export default async function resolveEndpointsExplicitly( + storageManager: StorageManager, +): Promise { + const oidcProviderMetaData: OIDCDiscoveryEndpointsApiResponse = {}; + const configData: StrictAuthClientConfig = await storageManager.getConfigData() as unknown as StrictAuthClientConfig; + + const requiredEndpoints: string[] = [ + OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.AUTHORIZATION, + OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.END_SESSION, + OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.JWKS, + OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.SESSION_IFRAME, + OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.REVOCATION, + OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.TOKEN, + OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.ISSUER, + OIDCDiscoveryConstants.Storage.StorageKeys.Endpoints.USERINFO, + ]; + + const isRequiredEndpointsContains: boolean = configData.endpoints + ? requiredEndpoints.every((reqEndpointName: string) => + configData.endpoints + ? Object.keys(configData.endpoints).some((endpointName: string) => { + const snakeCasedName: string = endpointName.replace( + /[A-Z]/g, + (letter: string) => `_${letter.toLowerCase()}`, + ); + + return snakeCasedName === reqEndpointName; + }) + : false, + ) + : false; + + if (!isRequiredEndpointsContains) { + throw new AsgardeoAuthException( + 'JS-AUTH_HELPER-REE-NF01', + 'Required endpoints missing', + 'Some or all of the required endpoints are missing in the object passed to the `endpoints` ' + + 'attribute of the`AuthConfig` object.', + ); + } + + if (configData.endpoints) { + Object.keys(configData.endpoints).forEach((endpointName: string) => { + const snakeCasedName: string = endpointName.replace(/[A-Z]/g, (letter: string) => `_${letter.toLowerCase()}`); + + oidcProviderMetaData[snakeCasedName] = configData?.endpoints ? configData.endpoints[endpointName] : ''; + }); + } + + return {...oidcProviderMetaData}; +} diff --git a/packages/node/src/__legacy__/client.ts b/packages/node/src/LegacyAsgardeoNodeClient.ts similarity index 100% rename from packages/node/src/__legacy__/client.ts rename to packages/node/src/LegacyAsgardeoNodeClient.ts diff --git a/packages/node/src/__legacy__/constants/index.ts b/packages/node/src/constants/index.ts similarity index 100% rename from packages/node/src/__legacy__/constants/index.ts rename to packages/node/src/constants/index.ts diff --git a/packages/node/src/__legacy__/constants/logger-config.ts b/packages/node/src/constants/logger-config.ts similarity index 100% rename from packages/node/src/__legacy__/constants/logger-config.ts rename to packages/node/src/constants/logger-config.ts diff --git a/packages/node/src/__legacy__/constants/uuid-config.ts b/packages/node/src/constants/uuid-config.ts similarity index 100% rename from packages/node/src/__legacy__/constants/uuid-config.ts rename to packages/node/src/constants/uuid-config.ts diff --git a/packages/node/src/__legacy__/core/authentication.ts b/packages/node/src/core/authentication.ts similarity index 100% rename from packages/node/src/__legacy__/core/authentication.ts rename to packages/node/src/core/authentication.ts diff --git a/packages/node/src/__legacy__/core/index.ts b/packages/node/src/core/index.ts similarity index 100% rename from packages/node/src/__legacy__/core/index.ts rename to packages/node/src/core/index.ts diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index f4ced8e8b..9018ec2ac 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -26,9 +26,9 @@ if (!globalThis.fetch) { globalThis.Response = Response; } -export {AsgardeoNodeClient as LegacyAsgardeoNodeClient} from './__legacy__/client'; -export * from './__legacy__/models'; -export * from './__legacy__/utils/logger-utils'; +export {AsgardeoNodeClient as LegacyAsgardeoNodeClient} from './LegacyAsgardeoNodeClient'; +export * from './models'; +export * from './utils/logger-utils'; export {default as CookieConfig} from './constants/CookieConfig'; diff --git a/packages/node/src/__legacy__/models/index.ts b/packages/node/src/models/index.ts similarity index 100% rename from packages/node/src/__legacy__/models/index.ts rename to packages/node/src/models/index.ts diff --git a/packages/node/src/__legacy__/models/session-data.ts b/packages/node/src/models/session-data.ts similarity index 100% rename from packages/node/src/__legacy__/models/session-data.ts rename to packages/node/src/models/session-data.ts diff --git a/packages/node/src/__legacy__/models/url-callback.ts b/packages/node/src/models/url-callback.ts similarity index 100% rename from packages/node/src/__legacy__/models/url-callback.ts rename to packages/node/src/models/url-callback.ts diff --git a/packages/node/src/__legacy__/stores/index.ts b/packages/node/src/stores/index.ts similarity index 100% rename from packages/node/src/__legacy__/stores/index.ts rename to packages/node/src/stores/index.ts diff --git a/packages/node/src/__legacy__/stores/memory-cache-store.ts b/packages/node/src/stores/memory-cache-store.ts similarity index 100% rename from packages/node/src/__legacy__/stores/memory-cache-store.ts rename to packages/node/src/stores/memory-cache-store.ts diff --git a/packages/node/src/__legacy__/utils/crypto-utils.ts b/packages/node/src/utils/crypto-utils.ts similarity index 100% rename from packages/node/src/__legacy__/utils/crypto-utils.ts rename to packages/node/src/utils/crypto-utils.ts diff --git a/packages/node/src/__legacy__/utils/index.ts b/packages/node/src/utils/index.ts similarity index 100% rename from packages/node/src/__legacy__/utils/index.ts rename to packages/node/src/utils/index.ts diff --git a/packages/node/src/__legacy__/utils/logger-utils.ts b/packages/node/src/utils/logger-utils.ts similarity index 100% rename from packages/node/src/__legacy__/utils/logger-utils.ts rename to packages/node/src/utils/logger-utils.ts diff --git a/packages/node/src/__legacy__/utils/session-utils.ts b/packages/node/src/utils/session-utils.ts similarity index 100% rename from packages/node/src/__legacy__/utils/session-utils.ts rename to packages/node/src/utils/session-utils.ts diff --git a/packages/vue/tsconfig.lib.json b/packages/vue/tsconfig.lib.json index e26d4cc9d..74c4b505e 100644 --- a/packages/vue/tsconfig.lib.json +++ b/packages/vue/tsconfig.lib.json @@ -8,7 +8,6 @@ "types": ["node"] }, "exclude": [ - "src/__legacy__/**", "**/*.spec.ts", "**/*.test.ts", "**/*.spec.tsx", diff --git a/scripts/aggregate-changelogs.js b/scripts/aggregate-changelogs.js index 44f280cf9..8d727d06b 100644 --- a/scripts/aggregate-changelogs.js +++ b/scripts/aggregate-changelogs.js @@ -27,7 +27,7 @@ const rootDir = process.cwd(); const outputFile = path.join(rootDir, 'CHANGELOG.md'); // List of package or directory names to skip when aggregating changelogs -const SKIP_PACKAGES = ['__legacy__', 'node_modules', 'dist', 'build', 'coverage', 'scripts', 'docs']; +const SKIP_PACKAGES = ['node_modules', 'dist', 'build', 'coverage', 'scripts', 'docs']; const findChangelogs = dir => { let changelogs = [];