From dbd242cb40da805762c2c7f9d04c95fc8435dda8 Mon Sep 17 00:00:00 2001 From: Brion Date: Fri, 24 Oct 2025 15:14:02 +0530 Subject: [PATCH 1/3] fix(react): update platform condition for Asgardeo V2 in authentication flow --- packages/react/src/AsgardeoReactClient.ts | 7 ++++++- packages/react/src/contexts/Asgardeo/AsgardeoProvider.tsx | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/react/src/AsgardeoReactClient.ts b/packages/react/src/AsgardeoReactClient.ts index 6f39bc00..ee584640 100644 --- a/packages/react/src/AsgardeoReactClient.ts +++ b/packages/react/src/AsgardeoReactClient.ts @@ -335,7 +335,12 @@ class AsgardeoReactClient e const config: AsgardeoReactConfig = (await this.asgardeo.getConfigData()) as AsgardeoReactConfig; - if (config.platform === Platform.AsgardeoV2 && typeof arg1 === 'object' && !isEmpty(arg1)) { + if ( + config.platform === Platform.AsgardeoV2 && + typeof arg1 === 'object' && + !isEmpty(arg1) && + ('flowId' in arg1 || 'applicationId' in arg1) + ) { const sessionDataKey: string = new URL(window.location.href).searchParams.get('sessionDataKey'); return executeEmbeddedSignInFlowV2({ diff --git a/packages/react/src/contexts/Asgardeo/AsgardeoProvider.tsx b/packages/react/src/contexts/Asgardeo/AsgardeoProvider.tsx index 190acf59..aa33c9ca 100644 --- a/packages/react/src/contexts/Asgardeo/AsgardeoProvider.tsx +++ b/packages/react/src/contexts/Asgardeo/AsgardeoProvider.tsx @@ -257,7 +257,7 @@ const AsgardeoProvider: FC> = ({ // TEMPORARY: Asgardeo V2 platform does not support SCIM2, Organizations endpoints yet. // Tracker: https://github.com/asgardeo/javascript/issues/212 - if (config.platform !== Platform.AsgardeoV2) { + if (config.platform === Platform.AsgardeoV2) { setUser(extractUserClaimsFromIdToken(decodedToken)); } else { try { From a027f8a68a061dd26c78eb9cd92686e5fcbf7540 Mon Sep 17 00:00:00 2001 From: Brion Date: Fri, 24 Oct 2025 16:25:55 +0530 Subject: [PATCH 2/3] fix: protected route should work without any props --- .../src/components/ProtectedRoute.tsx | 104 +++++++++++++++++- packages/react/src/index.ts | 2 +- 2 files changed, 99 insertions(+), 7 deletions(-) diff --git a/packages/react-router/src/components/ProtectedRoute.tsx b/packages/react-router/src/components/ProtectedRoute.tsx index 0b8a2521..3e70ca7d 100644 --- a/packages/react-router/src/components/ProtectedRoute.tsx +++ b/packages/react-router/src/components/ProtectedRoute.tsx @@ -21,7 +21,7 @@ import {AsgardeoRuntimeError} from '@asgardeo/browser';2025, WSO2 LLC. (https:// import {FC, ReactElement, ReactNode} from 'react'; import {Navigate} from 'react-router'; -import {useAsgardeo, AsgardeoRuntimeError} from '@asgardeo/react'; +import {useAsgardeo, AsgardeoRuntimeError, navigate} from '@asgardeo/react'; /** * Props for the ProtectedRoute component. @@ -45,6 +45,37 @@ export interface ProtectedRouteProps { * Custom loading element to render while authentication status is being determined. */ loader?: ReactNode; + /** + * Custom sign-in function to override the default behavior. + * If provided, this function will be called instead of the default signIn method + * when the user is not authenticated and no fallback or redirectTo is specified. + * This allows you to pass additional parameters or implement custom sign-in logic. + * + * @param defaultSignIn - The default signIn method from useAsgardeo hook + * @param signInOptions - Merged sign-in options (context + component props) + */ + onSignIn?: (defaultSignIn: (options?: Record) => void, signInOptions?: Record) => void; + /** + * Additional parameters to pass to the authorize request. + * These will be merged with the default signInOptions from the Asgardeo context. + * Common options include: + * - prompt: "login" | "none" | "consent" | "select_account" + * - fidp: Federation Identity Provider identifier + * - kc_idp_hint: Keycloak identity provider hint + * - login_hint: Hint to help with the username/identifier in the login form + * - max_age: Maximum authentication age in seconds + * - ui_locales: End-user's preferred languages and scripts for the user interface + * + * @example + * ```tsx + * signInOptions={{ + * prompt: "login", + * fidp: "OrganizationSSO", + * login_hint: "user@example.com" + * }} + * ``` + */ + signInOptions?: Record; } /** @@ -80,9 +111,47 @@ export interface ProtectedRouteProps { * } * /> * ``` + * + * @example With custom sign-in parameters + * ```tsx + * + * + * + * } + * /> + * ``` + * + * @example With custom sign-in handler + * ```tsx + * { + * // Custom logic before sign-in + * console.log('Initiating custom sign-in'); + * defaultSignIn({ ...options, prompt: "login" }); + * }} + * signInOptions={{ fidp: "CustomIDP" }} + * > + * + * + * } + * /> + * ``` */ -const ProtectedRoute: FC = ({children, fallback, redirectTo, loader = null}) => { - const {isSignedIn, isLoading} = useAsgardeo(); +const ProtectedRoute: FC = ({ + children, + fallback, + redirectTo, + loader = null, + onSignIn, + signInOptions: overriddenSignInOptions = {}, +}) => { + const {isSignedIn, isLoading, signIn, signInOptions, signInUrl} = useAsgardeo(); // Always wait for loading to finish before making authentication decisions if (isLoading) { @@ -101,11 +170,34 @@ const ProtectedRoute: FC = ({children, fallback, redirectTo return ; } + if (!isSignedIn) { + if (signInUrl) { + navigate(signInUrl); + } else { + if (onSignIn) { + onSignIn(signIn, overriddenSignInOptions); + } else { + (async () => { + try { + await signIn(overriddenSignInOptions ?? signInOptions); + } catch (error) { + throw new AsgardeoRuntimeError( + 'Sign-in failed in ProtectedRoute.', + 'ProtectedRoute-SignInError-001', + 'react-router', + `An error occurred during sign-in: ${(error as Error).message}`, + ); + } + })(); + } + } + } + throw new AsgardeoRuntimeError( - '"fallback" or "redirectTo" prop is required.', - 'ProtectedRoute-ValidationError-001', + 'ProtectedRoute misconfiguration.', + 'ProtectedRoute-Misconfiguration-001', 'react-router', - 'Either "fallback" or "redirectTo" prop must be provided to handle unauthenticated users.', + 'The internal handler failed to process the state. Please try with a fallback or redirectTo prop.', ); }; diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 01f68131..64a9ff6d 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -273,4 +273,4 @@ export {default as updateMeProfile, UpdateMeProfileConfig} from './api/updateMeP export {default as getMeProfile} from './api/getScim2Me'; export * from './api/getScim2Me'; -export {AsgardeoRuntimeError, http, getActiveTheme} from '@asgardeo/browser'; +export {AsgardeoRuntimeError, http, getActiveTheme, navigate} from '@asgardeo/browser'; From 2bf7be42f298273fb6888bd55cf55e5eba3476a9 Mon Sep 17 00:00:00 2001 From: Brion Date: Fri, 24 Oct 2025 16:27:13 +0530 Subject: [PATCH 3/3] =?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/huge-beds-push.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/huge-beds-push.md diff --git a/.changeset/huge-beds-push.md b/.changeset/huge-beds-push.md new file mode 100644 index 00000000..9dd53f4d --- /dev/null +++ b/.changeset/huge-beds-push.md @@ -0,0 +1,6 @@ +--- +'@asgardeo/react-router': patch +'@asgardeo/react': patch +--- + +`ProtectedRoute` should work without any props