From b37f3173b81d032bda7325efab194855c201c0c8 Mon Sep 17 00:00:00 2001 From: Brion Date: Thu, 4 Sep 2025 11:37:09 +0530 Subject: [PATCH 1/4] chore(react): add getAccessToken method to AsgardeoContextProps --- packages/react/src/contexts/Asgardeo/AsgardeoContext.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/react/src/contexts/Asgardeo/AsgardeoContext.ts b/packages/react/src/contexts/Asgardeo/AsgardeoContext.ts index 0f8f6e94..c0def2ab 100644 --- a/packages/react/src/contexts/Asgardeo/AsgardeoContext.ts +++ b/packages/react/src/contexts/Asgardeo/AsgardeoContext.ts @@ -97,6 +97,14 @@ export type AsgardeoContextProps = { * @returns A promise that resolves to the decoded ID token payload. */ getDecodedIdToken?: () => Promise; + + /** + * Function to retrieve the access token. + * This function retrieves the access token and returns it. + * @remarks This does not work in the `webWorker` or any other worker environment. + * @returns A promise that resolves to the access token. + */ + getAccessToken?: () => Promise; }; /** @@ -124,6 +132,7 @@ const AsgardeoContext: Context = createContext Date: Thu, 4 Sep 2025 11:48:45 +0530 Subject: [PATCH 2/4] fix(nextjs): improve error handling for access token retrieval in AsgardeoNextClient --- packages/nextjs/src/AsgardeoNextClient.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/nextjs/src/AsgardeoNextClient.ts b/packages/nextjs/src/AsgardeoNextClient.ts index 6adcde8d..3bec499a 100644 --- a/packages/nextjs/src/AsgardeoNextClient.ts +++ b/packages/nextjs/src/AsgardeoNextClient.ts @@ -390,7 +390,6 @@ class AsgardeoNextClient exte const token = await getAccessToken(); if (typeof token !== 'string' || !token) { - throw new Error('Access token not found'); throw new AsgardeoRuntimeError( 'Failed to get access token.', 'AsgardeoNextClient-getAccessToken-RuntimeError-003', From 6bc940bc6d11fc29fc805fb68951418fab24a58a Mon Sep 17 00:00:00 2001 From: Brion Date: Thu, 4 Sep 2025 11:58:54 +0530 Subject: [PATCH 3/4] feat: add exchangeToken method for token exchange functionality across clients --- .../src/AsgardeoJavaScriptClient.ts | 4 +++- packages/javascript/src/models/client.ts | 9 ++++++++- packages/nextjs/src/AsgardeoNextClient.ts | 5 +++++ packages/nextjs/src/server/asgardeo.ts | 11 ++++++++-- packages/react/src/AsgardeoReactClient.ts | 10 ++++++++++ .../src/contexts/Asgardeo/AsgardeoContext.ts | 20 +++++++++++++++++-- .../contexts/Asgardeo/AsgardeoProvider.tsx | 1 + 7 files changed, 54 insertions(+), 6 deletions(-) diff --git a/packages/javascript/src/AsgardeoJavaScriptClient.ts b/packages/javascript/src/AsgardeoJavaScriptClient.ts index 9d571717..a732607e 100644 --- a/packages/javascript/src/AsgardeoJavaScriptClient.ts +++ b/packages/javascript/src/AsgardeoJavaScriptClient.ts @@ -22,7 +22,7 @@ import {Config, SignInOptions, SignOutOptions, SignUpOptions} from './models/con import {Storage} from './models/store'; import {EmbeddedFlowExecuteRequestPayload, EmbeddedFlowExecuteResponse} from './models/embedded-flow'; import {EmbeddedSignInFlowHandleRequestPayload} from './models/embedded-signin-flow'; -import {TokenResponse} from './models/token'; +import {TokenExchangeRequestConfig, TokenResponse} from './models/token'; import {Organization} from './models/organization'; import {User, UserProfile} from './models/user'; @@ -55,6 +55,8 @@ abstract class AsgardeoJavaScriptClient implements AsgardeoClient abstract getConfiguration(): T; + abstract exchangeToken(config: TokenExchangeRequestConfig, sessionId?: string): Promise; + abstract signIn( options?: SignInOptions, sessionId?: string, diff --git a/packages/javascript/src/models/client.ts b/packages/javascript/src/models/client.ts index b5f8ec55..1ee1dfb8 100644 --- a/packages/javascript/src/models/client.ts +++ b/packages/javascript/src/models/client.ts @@ -25,7 +25,7 @@ import { import {EmbeddedSignInFlowHandleRequestPayload} from './embedded-signin-flow'; import {Organization} from './organization'; import {User, UserProfile} from './user'; -import {TokenResponse} from './token'; +import {TokenExchangeRequestConfig, TokenResponse} from './token'; import {Storage} from './store'; import {SignInOptions, SignOutOptions, SignUpOptions} from './config'; @@ -65,6 +65,13 @@ export interface AsgardeoClient { getConfiguration(): T; + /** + * Swaps the current access token with a new one based on the provided configuration (with a grant type). + * @param config - Configuration for the token exchange request. + * @param sessionId - Optional session ID to be used for the token exchange. + */ + exchangeToken(config: TokenExchangeRequestConfig, sessionId?: string): Promise; + updateUserProfile(payload: any, userId?: string): Promise; /** diff --git a/packages/nextjs/src/AsgardeoNextClient.ts b/packages/nextjs/src/AsgardeoNextClient.ts index 3bec499a..d31343bb 100644 --- a/packages/nextjs/src/AsgardeoNextClient.ts +++ b/packages/nextjs/src/AsgardeoNextClient.ts @@ -52,6 +52,7 @@ import { extractUserClaimsFromIdToken, TokenResponse, Storage, + TokenExchangeRequestConfig, } from '@asgardeo/node'; import {AsgardeoNextConfig} from './models/config'; import getSessionId from './server/actions/getSessionId'; @@ -381,6 +382,10 @@ class AsgardeoNextClient exte return this.asgardeo.isSignedIn(sessionId as string); } + override exchangeToken(config: TokenExchangeRequestConfig, sessionId?: string): Promise { + return this.asgardeo.exchangeToken(config, sessionId); + } + /** * Gets the access token from the session cookie if no sessionId is provided, * otherwise falls back to legacy client method. diff --git a/packages/nextjs/src/server/asgardeo.ts b/packages/nextjs/src/server/asgardeo.ts index 4fbc797b..063c32c5 100644 --- a/packages/nextjs/src/server/asgardeo.ts +++ b/packages/nextjs/src/server/asgardeo.ts @@ -16,22 +16,29 @@ * under the License. */ +import {TokenExchangeRequestConfig} from '@asgardeo/node'; import AsgardeoNextClient from '../AsgardeoNextClient'; import getSessionIdAction from './actions/getSessionId'; const asgardeo = async () => { - const getAccessToken = async (id: string) => { + const getAccessToken = async (sessionId: string) => { const client: AsgardeoNextClient = AsgardeoNextClient.getInstance(); - return await client.getAccessToken(id); + return await client.getAccessToken(sessionId); }; const getSessionId = async () => { return await getSessionIdAction(); }; + const exchangeToken = async (config: TokenExchangeRequestConfig, sessionId: string) => { + const client: AsgardeoNextClient = AsgardeoNextClient.getInstance(); + return await client.exchangeToken(config, sessionId); + }; + return { getAccessToken, getSessionId, + exchangeToken, }; }; diff --git a/packages/react/src/AsgardeoReactClient.ts b/packages/react/src/AsgardeoReactClient.ts index 6ca76f1b..07b533e5 100644 --- a/packages/react/src/AsgardeoReactClient.ts +++ b/packages/react/src/AsgardeoReactClient.ts @@ -42,6 +42,7 @@ import { HttpRequestConfig, HttpResponse, Storage, + TokenExchangeRequestConfig, } from '@asgardeo/browser'; import AuthAPI from './__temp__/api'; import getMeOrganizations from './api/getMeOrganizations'; @@ -271,6 +272,15 @@ class AsgardeoReactClient e return this.asgardeo.getConfigData() as unknown as T; } + override async exchangeToken( + config: TokenExchangeRequestConfig, + sessionId?: string, + ): Promise { + return this.withLoading(async () => { + return this.asgardeo.exchangeToken(config, (user: User) => {}) as unknown as TokenResponse | Response; + }); + } + override signIn( options?: SignInOptions, sessionId?: string, diff --git a/packages/react/src/contexts/Asgardeo/AsgardeoContext.ts b/packages/react/src/contexts/Asgardeo/AsgardeoContext.ts index c0def2ab..c5dcdba1 100644 --- a/packages/react/src/contexts/Asgardeo/AsgardeoContext.ts +++ b/packages/react/src/contexts/Asgardeo/AsgardeoContext.ts @@ -17,7 +17,15 @@ */ import {Context, createContext} from 'react'; -import {HttpRequestConfig, HttpResponse, IdToken, Organization, SignInOptions} from '@asgardeo/browser'; +import { + HttpRequestConfig, + HttpResponse, + IdToken, + Organization, + SignInOptions, + TokenExchangeRequestConfig, + TokenResponse, +} from '@asgardeo/browser'; import AsgardeoReactClient from '../../AsgardeoReactClient'; /** @@ -99,12 +107,19 @@ export type AsgardeoContextProps = { getDecodedIdToken?: () => Promise; /** - * Function to retrieve the access token. + * Retrieves the access token stored in the storage. * This function retrieves the access token and returns it. * @remarks This does not work in the `webWorker` or any other worker environment. * @returns A promise that resolves to the access token. */ getAccessToken?: () => Promise; + + /** + * Swaps the current access token with a new one based on the provided configuration (with a grant type). + * @param config - Configuration for the token exchange request. + * @returns A promise that resolves to the token response or the raw response. + */ + exchangeToken?: (config: TokenExchangeRequestConfig) => Promise; }; /** @@ -133,6 +148,7 @@ const AsgardeoContext: Context = createContext> = ({ }, signInOptions, getDecodedIdToken: asgardeo.getDecodedIdToken.bind(asgardeo), + exchangeToken: asgardeo.exchangeToken.bind(asgardeo), syncSession, }), [ From a9f72798c59a077eb58c56d40718ec529e76fec3 Mon Sep 17 00:00:00 2001 From: Brion Date: Thu, 4 Sep 2025 13:22:46 +0530 Subject: [PATCH 4/4] =?UTF-8?q?chore:=20add=20changeset=20=F0=9F=A6=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .changeset/some-moons-show.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/some-moons-show.md diff --git a/.changeset/some-moons-show.md b/.changeset/some-moons-show.md new file mode 100644 index 00000000..77016312 --- /dev/null +++ b/.changeset/some-moons-show.md @@ -0,0 +1,7 @@ +--- +'@asgardeo/javascript': patch +'@asgardeo/nextjs': patch +'@asgardeo/react': patch +--- + +Expose `getAccessToken` & `exchangeToken` from `useAsgardeo`