feat: handle redirectTo query parameter in middleware

This commit is contained in:
Ephraim Atta-Duncan
2025-05-21 11:31:00 +00:00
parent 44bc769e60
commit d213b378b8
2 changed files with 32 additions and 4 deletions

View File

@ -1,6 +1,7 @@
import { Trans } from '@lingui/react/macro'; import { Trans } from '@lingui/react/macro';
import { Link, redirect } from 'react-router'; import { Link, redirect } from 'react-router';
import { extractCookieFromHeaders } from '@documenso/auth/server/lib/utils/cookies';
import { getOptionalSession } from '@documenso/auth/server/lib/utils/get-session'; import { getOptionalSession } from '@documenso/auth/server/lib/utils/get-session';
import { import {
IS_GOOGLE_SSO_ENABLED, IS_GOOGLE_SSO_ENABLED,
@ -20,13 +21,18 @@ export function meta() {
export async function loader({ request }: Route.LoaderArgs) { export async function loader({ request }: Route.LoaderArgs) {
const { isAuthenticated } = await getOptionalSession(request); const { isAuthenticated } = await getOptionalSession(request);
const redirectToCookie = extractCookieFromHeaders('redirectTo', request.headers);
const redirectToAfterLogin = redirectToCookie ? decodeURIComponent(redirectToCookie) : '';
// SSR env variables.
const isGoogleSSOEnabled = IS_GOOGLE_SSO_ENABLED; const isGoogleSSOEnabled = IS_GOOGLE_SSO_ENABLED;
const isOIDCSSOEnabled = IS_OIDC_SSO_ENABLED; const isOIDCSSOEnabled = IS_OIDC_SSO_ENABLED;
const oidcProviderLabel = OIDC_PROVIDER_LABEL; const oidcProviderLabel = OIDC_PROVIDER_LABEL;
if (isAuthenticated) { if (isAuthenticated) {
if (redirectToAfterLogin) {
throw redirect(redirectToAfterLogin);
}
throw redirect('/documents'); throw redirect('/documents');
} }
@ -34,11 +40,13 @@ export async function loader({ request }: Route.LoaderArgs) {
isGoogleSSOEnabled, isGoogleSSOEnabled,
isOIDCSSOEnabled, isOIDCSSOEnabled,
oidcProviderLabel, oidcProviderLabel,
redirectToAfterLogin,
}; };
} }
export default function SignIn({ loaderData }: Route.ComponentProps) { export default function SignIn({ loaderData }: Route.ComponentProps) {
const { isGoogleSSOEnabled, isOIDCSSOEnabled, oidcProviderLabel } = loaderData; const { isGoogleSSOEnabled, isOIDCSSOEnabled, oidcProviderLabel, redirectToAfterLogin } =
loaderData;
return ( return (
<div className="w-screen max-w-lg px-4"> <div className="w-screen max-w-lg px-4">
@ -56,6 +64,7 @@ export default function SignIn({ loaderData }: Route.ComponentProps) {
isGoogleSSOEnabled={isGoogleSSOEnabled} isGoogleSSOEnabled={isGoogleSSOEnabled}
isOIDCSSOEnabled={isOIDCSSOEnabled} isOIDCSSOEnabled={isOIDCSSOEnabled}
oidcProviderLabel={oidcProviderLabel} oidcProviderLabel={oidcProviderLabel}
returnTo={redirectToAfterLogin ?? undefined}
/> />
{env('NEXT_PUBLIC_DISABLE_SIGNUP') !== 'true' && ( {env('NEXT_PUBLIC_DISABLE_SIGNUP') !== 'true' && (

View File

@ -18,13 +18,32 @@ export const appMiddleware = async (c: Context, next: Next) => {
const { req } = c; const { req } = c;
const { path } = req; const { path } = req;
// PRE-HANDLER CODE: Place code here to execute BEFORE the route handler runs.
const redirectTo = req.query('redirectTo');
if (redirectTo) {
if (redirectTo.startsWith('/') && !redirectTo.startsWith('//') && !redirectTo.includes('..')) {
debug.log('Setting redirectTo cookie to:', redirectTo);
setCookie(c, 'redirectTo', redirectTo, {
path: '/',
httpOnly: true,
sameSite: 'Lax',
maxAge: 150,
// secure: process.env.NODE_ENV === 'production'
});
debug.log('Redirecting to (from param):', redirectTo);
return c.redirect(redirectTo, 307);
} else {
debug.log('Invalid redirectTo parameter encountered:', redirectTo);
}
}
// Paths to ignore. // Paths to ignore.
if (nonPagePathRegex.test(path)) { if (nonPagePathRegex.test(path)) {
return next(); return next();
} }
// PRE-HANDLER CODE: Place code here to execute BEFORE the route handler runs.
await next(); await next();
// POST-HANDLER CODE: Place code here to execute AFTER the route handler completes. // POST-HANDLER CODE: Place code here to execute AFTER the route handler completes.