Use safe redirections

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-02-11 22:34:04 +04:00
parent e46c1d4894
commit 4f7274d50b
2 changed files with 28 additions and 7 deletions

View File

@@ -36,6 +36,20 @@ export default function PasswordSignInPage() {
if (!emailValue || !passwordValue) return; if (!emailValue || !passwordValue) return;
const continueUrlParam = searchParams.get("continue");
let safeContinueUrl: string;
if (continueUrlParam) {
let continueUrl: URL;
try {
continueUrl = new URL(continueUrlParam, window.location.origin);
} catch {
continueUrl = new URL(window.location.origin);
}
safeContinueUrl = window.location.origin + continueUrl.pathname + continueUrl.search;
} else {
safeContinueUrl = window.location.origin;
}
signIn({ signIn({
variables: { variables: {
input: { input: {
@@ -59,7 +73,7 @@ export default function PasswordSignInPage() {
return; return;
} }
window.location.href = searchParams.get("continue") ?? window.location.origin; window.location.href = safeContinueUrl;
}, },
onError: (e) => { onError: (e) => {
toast({ toast({

View File

@@ -38,18 +38,25 @@ function AssumePageInner() {
const [assumeOrganizationSession] = useMutation<AssumePageMutation>(assumeMutation); const [assumeOrganizationSession] = useMutation<AssumePageMutation>(assumeMutation);
const continueUrl = searchParams.get("continue") ?? new URL(`/organizations/${organizationId}`, window.location.origin).toString(); const continueUrlParam = searchParams.get("continue");
let safeContinueUrl: string;
if (continueUrlParam) {
const continueUrl = new URL(continueUrlParam);
safeContinueUrl = window.location.origin + continueUrl.pathname + continueUrl.search;
} else {
safeContinueUrl = window.location.origin + `/organizations/${organizationId}`;
}
useEffect(() => { useEffect(() => {
assumeOrganizationSession({ assumeOrganizationSession({
variables: { variables: {
input: { organizationId, continue: continueUrl }, input: { organizationId, continue: safeContinueUrl },
}, },
onError: (error) => { onError: (error) => {
if (error instanceof UnAuthenticatedError) { if (error instanceof UnAuthenticatedError) {
const search = new URLSearchParams([ const search = new URLSearchParams([
["organization-id", organizationId], ["organization-id", organizationId],
["continue", continueUrl], ["continue", safeContinueUrl],
]); ]);
void navigate({ pathname: "/auth/login", search: "?" + search.toString() }); void navigate({ pathname: "/auth/login", search: "?" + search.toString() });
@@ -68,7 +75,7 @@ function AssumePageInner() {
switch (result.__typename) { switch (result.__typename) {
case "PasswordRequired": case "PasswordRequired":
search.set("organization-id", organizationId); search.set("organization-id", organizationId);
search.set("continue", continueUrl); search.set("continue", safeContinueUrl);
void navigate({ pathname: "/auth/password-login", search: "?" + search.toString() }); void navigate({ pathname: "/auth/password-login", search: "?" + search.toString() });
break; break;
@@ -79,11 +86,11 @@ function AssumePageInner() {
window.location.href = samlSSOLoginURL.toString(); window.location.href = samlSSOLoginURL.toString();
break; break;
default: default:
window.location.href = continueUrl; window.location.href = safeContinueUrl;
} }
}, },
}); });
}, [organizationId, navigate, assumeOrganizationSession, continueUrl, searchParams]); }, [organizationId, navigate, assumeOrganizationSession, safeContinueUrl, searchParams]);
return ( return (
<AuthLayout> <AuthLayout>