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` 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 6adcde8d..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. @@ -390,7 +395,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', 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 0f8f6e94..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'; /** @@ -97,6 +105,21 @@ export type AsgardeoContextProps = { * @returns A promise that resolves to the decoded ID token payload. */ getDecodedIdToken?: () => Promise; + + /** + * 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; }; /** @@ -124,6 +147,8 @@ const AsgardeoContext: Context = createContext> = ({ }, signInOptions, getDecodedIdToken: asgardeo.getDecodedIdToken.bind(asgardeo), + exchangeToken: asgardeo.exchangeToken.bind(asgardeo), syncSession, }), [