diff --git a/apps/console/src/components/OrganizationErrorBoundary.tsx b/apps/console/src/components/OrganizationErrorBoundary.tsx
index 4adb762ba..765f73ed4 100644
--- a/apps/console/src/components/OrganizationErrorBoundary.tsx
+++ b/apps/console/src/components/OrganizationErrorBoundary.tsx
@@ -1,5 +1,5 @@
import { AssumptionRequiredError, UnAuthenticatedError } from "@probo/relay";
-import { Navigate, useLocation, useRouteError } from "react-router";
+import { Navigate, useRouteError } from "react-router";
import { useOrganizationId } from "#/hooks/useOrganizationId";
@@ -7,15 +7,26 @@ import { PageError } from "./PageError";
export function OrganizationErrorBoundary() {
const error = useRouteError();
- const location = useLocation();
const organizationId = useOrganizationId();
+ const search = new URLSearchParams([
+ ["organization-id", organizationId],
+ ["redirect-path", window.location.href],
+ ]);
+
if (error instanceof UnAuthenticatedError) {
- return ;
+ return ;
}
if (error instanceof AssumptionRequiredError) {
- return ;
+ return (
+
+ );
}
return ;
diff --git a/apps/console/src/components/RootErrorBoundary.tsx b/apps/console/src/components/RootErrorBoundary.tsx
index a6f698230..fc34d0cd1 100644
--- a/apps/console/src/components/RootErrorBoundary.tsx
+++ b/apps/console/src/components/RootErrorBoundary.tsx
@@ -1,14 +1,15 @@
import { UnAuthenticatedError } from "@probo/relay";
-import { Navigate, useLocation, useRouteError } from "react-router";
+import { Navigate, useRouteError } from "react-router";
import { PageError } from "./PageError";
export function RootErrorBoundary() {
const error = useRouteError();
- const location = useLocation();
+
+ const search = new URLSearchParams([["redirect-path", window.location.href]]);
if (error instanceof UnAuthenticatedError) {
- return ;
+ return ;
}
return ;
diff --git a/apps/console/src/hooks/iam/useAssume.ts b/apps/console/src/hooks/iam/useAssume.ts
index b9d8fa3b4..4999004ad 100644
--- a/apps/console/src/hooks/iam/useAssume.ts
+++ b/apps/console/src/hooks/iam/useAssume.ts
@@ -9,6 +9,7 @@ import type { useAssumeMutation } from "#/__generated__/iam/useAssumeMutation.gr
import { useOrganizationId } from "../useOrganizationId";
interface UseAssumeParameters {
+ afterAssumePath: string;
onSuccess: () => void;
}
@@ -41,7 +42,7 @@ const assumeMutation = graphql`
`;
export function useAssume(params: UseAssumeParameters) {
- const { onSuccess } = params;
+ const { afterAssumePath, onSuccess } = params;
const organizationId = useOrganizationId();
const navigate = useNavigate();
@@ -55,7 +56,12 @@ export function useAssume(params: UseAssumeParameters) {
},
onError: (error) => {
if (error instanceof UnAuthenticatedError) {
- void navigate("/auth/login");
+ const search = new URLSearchParams([
+ ["organization-id", organizationId],
+ ["redirect-path", afterAssumePath],
+ ]);
+
+ void navigate({ pathname: "/auth/login", search: "?" + search.toString() });
return;
}
},
@@ -69,7 +75,9 @@ export function useAssume(params: UseAssumeParameters) {
switch (result.__typename) {
case "PasswordRequired":
- search.set("organizationId", organizationId);
+ search.set("organization-id", organizationId);
+ search.set("redirect-path", afterAssumePath);
+
void navigate({ pathname: "/auth/passord-login", search: "?" + search.toString() });
break;
case "SAMLAuthenticationRequired":
@@ -80,7 +88,7 @@ export function useAssume(params: UseAssumeParameters) {
}
},
});
- }, [onSuccess, navigate, assumeOrganizationSession, organizationId]);
+ }, [afterAssumePath, organizationId, onSuccess, navigate, assumeOrganizationSession]);
return;
}
diff --git a/apps/console/src/pages/iam/auth/sign-in/PasswordSignInPage.tsx b/apps/console/src/pages/iam/auth/sign-in/PasswordSignInPage.tsx
index aca2b92f7..838a24e58 100644
--- a/apps/console/src/pages/iam/auth/sign-in/PasswordSignInPage.tsx
+++ b/apps/console/src/pages/iam/auth/sign-in/PasswordSignInPage.tsx
@@ -41,7 +41,7 @@ export default function PasswordSignInPage() {
email: emailValue,
password: passwordValue,
// Assume when signing in
- organizationId: searchParams.get("organizationId"),
+ organizationId: searchParams.get("organization-id"),
},
},
onCompleted: (_, error) => {
@@ -57,7 +57,7 @@ export default function PasswordSignInPage() {
return;
}
- window.location.href = "/";
+ window.location.href = searchParams.get("redirect-path") ?? "/";
},
onError: (e) => {
toast({
diff --git a/apps/console/src/pages/iam/auth/sign-in/SignInPage.tsx b/apps/console/src/pages/iam/auth/sign-in/SignInPage.tsx
index cbc9dbe8f..f3bbdea82 100644
--- a/apps/console/src/pages/iam/auth/sign-in/SignInPage.tsx
+++ b/apps/console/src/pages/iam/auth/sign-in/SignInPage.tsx
@@ -1,10 +1,12 @@
import { useTranslate } from "@probo/i18n";
import { Button } from "@probo/ui";
-import { Link } from "react-router";
+import { Link, useLocation } from "react-router";
export default function SignInPage() {
const { __ } = useTranslate();
+ const location = useLocation();
+
return (
@@ -14,7 +16,10 @@ export default function SignInPage() {
{__("Choose your login method")}
-
-
+
{__("Login with SSO")}
{__("Don't have an account ?")}
{" "}
-
+
{__("Register")}
diff --git a/apps/console/src/pages/iam/organizations/AssumePage.tsx b/apps/console/src/pages/iam/organizations/AssumePage.tsx
index 5da6f9909..e2a7c1939 100644
--- a/apps/console/src/pages/iam/organizations/AssumePage.tsx
+++ b/apps/console/src/pages/iam/organizations/AssumePage.tsx
@@ -1,23 +1,19 @@
import { useTranslate } from "@probo/i18n";
-import { useLocation, useNavigate } from "react-router";
+import { useNavigate, useSearchParams } from "react-router";
import { useAssume } from "#/hooks/iam/useAssume";
+import { IAMRelayProvider } from "#/providers/IAMRelayProvider";
import AuthLayout from "../auth/AuthLayout";
-interface State {
- from: string;
-}
-
-export default function AssumePage() {
+function AssumePageInner() {
const navigate = useNavigate();
- const location = useLocation();
- const state = location.state as State;
-
+ const [searchParams] = useSearchParams();
const { __ } = useTranslate();
useAssume({
- onSuccess: () => void navigate(state.from),
+ afterAssumePath: searchParams.get("redirect-path") ?? "/",
+ onSuccess: () => void navigate(searchParams.get("redirect-path") ?? "/"),
});
return (
@@ -33,3 +29,11 @@ export default function AssumePage() {
);
}
+
+export default function AssumePage() {
+ return (
+
+
+
+ );
+}
diff --git a/apps/console/src/pages/iam/organizations/ViewerMembershipLayoutLoader.tsx b/apps/console/src/pages/iam/organizations/ViewerMembershipLayoutLoader.tsx
index 16eb3d155..ca4f956f2 100644
--- a/apps/console/src/pages/iam/organizations/ViewerMembershipLayoutLoader.tsx
+++ b/apps/console/src/pages/iam/organizations/ViewerMembershipLayoutLoader.tsx
@@ -1,6 +1,7 @@
import { Skeleton } from "@probo/ui";
import { Suspense, useCallback } from "react";
import { useQueryLoader } from "react-relay";
+import { useLocation } from "react-router";
import type { ViewerMembershipLayoutQuery } from "#/__generated__/iam/ViewerMembershipLayoutQuery.graphql";
import { useAssume } from "#/hooks/iam/useAssume";
@@ -14,6 +15,7 @@ import {
function ViewerMembershipLayoutQueryLoader() {
const organizationId = useOrganizationId();
+ const location = useLocation();
const [queryRef, loadQuery] = useQueryLoader(
viewerMembershipLayoutQuery,
@@ -28,7 +30,10 @@ function ViewerMembershipLayoutQueryLoader() {
[loadQuery, organizationId],
);
- useAssume({ onSuccess: onAssumeSuccess });
+ useAssume({
+ afterAssumePath: location.pathname,
+ onSuccess: onAssumeSuccess,
+ });
if (!queryRef) {
return ;
diff --git a/apps/console/src/pages/organizations/employee/EmployeeLayoutLoader.tsx b/apps/console/src/pages/organizations/employee/EmployeeLayoutLoader.tsx
index b23446765..066d8574c 100644
--- a/apps/console/src/pages/organizations/employee/EmployeeLayoutLoader.tsx
+++ b/apps/console/src/pages/organizations/employee/EmployeeLayoutLoader.tsx
@@ -1,6 +1,7 @@
import { Skeleton } from "@probo/ui";
import { Suspense, useCallback } from "react";
import { useQueryLoader } from "react-relay";
+import { useLocation } from "react-router";
import type { ViewerMembershipLayoutQuery } from "#/__generated__/iam/ViewerMembershipLayoutQuery.graphql";
import { useAssume } from "#/hooks/iam/useAssume";
@@ -17,6 +18,7 @@ function EmployeeLayoutQueryLoader() {
const [queryRef, loadQuery] = useQueryLoader(
viewerMembershipLayoutQuery,
);
+ const location = useLocation();
const onAssumeSuccess = useCallback(
() =>
@@ -27,7 +29,10 @@ function EmployeeLayoutQueryLoader() {
[loadQuery, organizationId],
);
- useAssume({ onSuccess: onAssumeSuccess });
+ useAssume({
+ afterAssumePath: location.pathname,
+ onSuccess: onAssumeSuccess,
+ });
if (!queryRef) {
return ;
diff --git a/apps/console/src/routes.tsx b/apps/console/src/routes.tsx
index 367bfe9ff..c801b9a05 100644
--- a/apps/console/src/routes.tsx
+++ b/apps/console/src/routes.tsx
@@ -122,6 +122,7 @@ const routes = [
},
{
path: "/organizations/:organizationId",
+ ErrorBoundary: OrganizationErrorBoundary,
children: [
{
path: "assume",
@@ -132,7 +133,6 @@ const routes = [
Component: lazy(
() => import("./pages/organizations/employee/EmployeeLayoutLoader"),
),
- ErrorBoundary: OrganizationErrorBoundary,
children: [
{
index: true,
@@ -154,9 +154,9 @@ const routes = [
Component: lazy(
() => import("./pages/iam/organizations/ViewerMembershipLayoutLoader"),
),
- ErrorBoundary: OrganizationErrorBoundary,
children: [
{
+ path: "",
Component: () => {
const { role } = use(CurrentUser);
switch (role) {
diff --git a/packages/ui/src/Atoms/Button/Button.tsx b/packages/ui/src/Atoms/Button/Button.tsx
index 5488a8e5c..6e927d980 100644
--- a/packages/ui/src/Atoms/Button/Button.tsx
+++ b/packages/ui/src/Atoms/Button/Button.tsx
@@ -4,7 +4,7 @@ import type {
FC,
PropsWithChildren,
} from "react";
-import { Link } from "react-router";
+import { Link, type To } from "react-router";
import { tv, type VariantProps } from "tailwind-variants";
import { Slot } from "../Slot";
@@ -49,7 +49,7 @@ type Props = PropsWithChildren<
| "tertiary"
| "quaternary"
| "danger";
- to?: string;
+ to?: To;
asChild?: boolean;
} & VariantProps
>
diff --git a/pkg/iam/session_service.go b/pkg/iam/session_service.go
index b720c1f2f..77ebd876e 100644
--- a/pkg/iam/session_service.go
+++ b/pkg/iam/session_service.go
@@ -321,12 +321,11 @@ func (s SessionService) OpenPasswordChildSessionForOrganization(
organizationID gid.GID,
) (*coredata.Session, *coredata.Membership, error) {
var (
- now = time.Now()
- rootSession = &coredata.Session{}
- identity = &coredata.Identity{}
- membership = &coredata.Membership{}
- childSession = &coredata.Session{}
- scope = coredata.NewScopeFromObjectID(organizationID)
+ now = time.Now()
+ rootSession = &coredata.Session{}
+ identity = &coredata.Identity{}
+ membership = &coredata.Membership{}
+ scope = coredata.NewScopeFromObjectID(organizationID)
)
err := s.pg.WithTx(
@@ -366,7 +365,7 @@ func (s SessionService) OpenPasswordChildSessionForOrganization(
}
tenantID := scope.GetTenantID()
- childSession = &coredata.Session{
+ childSession := &coredata.Session{
ID: gid.New(tenantID, coredata.SessionEntityType),
IdentityID: rootSession.IdentityID,
TenantID: &tenantID,
@@ -399,7 +398,7 @@ func (s SessionService) OpenPasswordChildSessionForOrganization(
return nil, nil, err
}
- return childSession, membership, nil
+ return rootSession, membership, nil
}
// OpenSAMLChildSessionForOrganization creates a SAML-authenticated child session for the given