diff --git a/frontend/src/component/common/ProtectedRoute/ProtectedRoute.jsx b/frontend/src/component/common/ProtectedRoute/ProtectedRoute.jsx index 2ab6d65e4c..7f0e538d29 100644 --- a/frontend/src/component/common/ProtectedRoute/ProtectedRoute.jsx +++ b/frontend/src/component/common/ProtectedRoute/ProtectedRoute.jsx @@ -6,9 +6,10 @@ const ProtectedRoute = ({ renderProps = {}, ...rest }) => { - const { pathname } = useLocation(); - const loginLink = - pathname.length > 1 ? `/login?redirect=${pathname}` : '/login'; + const { pathname, search } = useLocation(); + const redirect = encodeURIComponent(pathname + search); + const loginLink = `/login?redirect=${redirect}`; + return ( { const styles = useStyles(); @@ -18,7 +19,7 @@ const Login = () => { const redirect = query.get('redirect') || '/'; if (user) { - return ; + return ; } return ( diff --git a/frontend/src/component/user/Login/parseRedirectParam.test.ts b/frontend/src/component/user/Login/parseRedirectParam.test.ts new file mode 100644 index 0000000000..b38e6a7245 --- /dev/null +++ b/frontend/src/component/user/Login/parseRedirectParam.test.ts @@ -0,0 +1,33 @@ +import { parseRedirectParam } from 'component/user/Login/parseRedirectParam'; + +test('parseRedirectParam should parse an empty redirect param', async () => { + expect(parseRedirectParam('')).toEqual({ + pathname: '/', + search: '', + }); +}); + +test('parseRedirectParam should parse the pathname', async () => { + expect(parseRedirectParam(encodeURIComponent('/foo'))).toEqual({ + pathname: '/foo', + search: '', + }); +}); + +test('parseRedirectParam should parse the search query', async () => { + expect(parseRedirectParam(encodeURIComponent('/foo?a=1&b=2'))).toEqual({ + pathname: '/foo', + search: '?a=1&b=2', + }); +}); + +test('parseRedirectParam should ignore external domains', async () => { + expect( + parseRedirectParam( + encodeURIComponent('https://example.com/foo?a=1&b=2') + ) + ).toEqual({ + pathname: '/foo', + search: '?a=1&b=2', + }); +}); diff --git a/frontend/src/component/user/Login/parseRedirectParam.ts b/frontend/src/component/user/Login/parseRedirectParam.ts new file mode 100644 index 0000000000..3cd83c8914 --- /dev/null +++ b/frontend/src/component/user/Login/parseRedirectParam.ts @@ -0,0 +1,16 @@ +interface IRedirectParam { + pathname: string; + search: string; +} + +export const parseRedirectParam = (redirect: string): IRedirectParam => { + const url = new URL( + decodeURIComponent(redirect), + window.location.protocol + '//' + window.location.host + ); + + return { + pathname: url.pathname, + search: url.search, + }; +};