Return to the requested URL after logging in (#24637)

When an unauthenticated user opens a deep link, carry the requested
path through the login page in a redirect query param and return to it
after a successful login instead of always going to the home page.
Only same-origin targets are honored.


Claude-Session: https://claude.ai/code/session_011CFGjgYURSRTpXBaxp1Dq7

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ljlongwing
2026-10-11 17:59:13 -06:00
committed by GitHub
co-authored by Claude Opus 5.5
parent 135a95d8f2
commit e7164882f5
5 changed files with 125 additions and 8 deletions
+45
View File
@@ -1,3 +1,5 @@
import { baseUrl } from "./baseUrl";
// Module-level flag to prevent multiple simultaneous redirects
// (eg, when multiple SWR queries fail with 401 at once, or when
// both ApiProvider and ProtectedRoute try to redirect)
@@ -10,3 +12,46 @@ export function isRedirectingToLogin(): boolean {
export function setRedirectingToLogin(value: boolean): void {
_isRedirectingToLogin = value;
}
const REDIRECT_PARAM = "redirect";
// Build the login page url, carrying the current location along
// so the user can be returned to it after logging in
export function getLoginUrl(loginPage: string = `${baseUrl}login`): string {
const url = new URL(loginPage, window.location.href);
// an external login page (eg, an auth proxy) handles its own return url
if (url.origin !== window.location.origin) {
return loginPage;
}
const { pathname, search, hash } = window.location;
const current = `${pathname}${search}${hash}`;
// no need to carry the home page, it is the default after logging in
if (current !== new URL(baseUrl).pathname) {
url.searchParams.set(REDIRECT_PARAM, current);
}
return url.href;
}
// Resolve where to send the user after a successful login
export function getPostLoginUrl(): string {
const target = new URLSearchParams(window.location.search).get(
REDIRECT_PARAM,
);
if (!target) {
return baseUrl;
}
// only return to urls on this origin so the param can't be used
// to send the user to another site
try {
const url = new URL(target, window.location.origin);
return url.origin === window.location.origin ? url.href : baseUrl;
} catch {
return baseUrl;
}
}
+6 -2
View File
@@ -3,7 +3,11 @@ import { SWRConfig } from "swr";
import { WsProvider } from "./WsProvider";
import axios from "axios";
import { ReactNode } from "react";
import { isRedirectingToLogin, setRedirectingToLogin } from "./auth-redirect";
import {
getLoginUrl,
isRedirectingToLogin,
setRedirectingToLogin,
} from "./auth-redirect";
axios.defaults.baseURL = `${baseUrl}api/`;
@@ -34,7 +38,7 @@ export function ApiProvider({ children, options }: ApiProviderType) {
const loginPage = error.response.headers.get("location") ?? "login";
if (window.location.href !== loginPage && !isRedirectingToLogin()) {
setRedirectingToLogin(true);
window.location.href = loginPage;
window.location.href = getLoginUrl(loginPage);
}
}
},