mirror of https://github.com/usememos/memos.git
fix(web): redirect to auth page instead of explore on session expiry
Fixes #5617
This commit is contained in:
parent
27063d4850
commit
47e2ace690
|
|
@ -67,7 +67,7 @@ const refreshTransport = createConnectTransport({
|
|||
|
||||
const refreshAuthClient = createClient(AuthService, refreshTransport);
|
||||
|
||||
export async function refreshAccessToken(): Promise<void> {
|
||||
async function doRefreshAccessToken(): Promise<void> {
|
||||
const response = await refreshAuthClient.refreshToken({});
|
||||
|
||||
if (!response.accessToken) {
|
||||
|
|
@ -78,6 +78,14 @@ export async function refreshAccessToken(): Promise<void> {
|
|||
setAccessToken(response.accessToken, expiresAt);
|
||||
}
|
||||
|
||||
// All callers go through the manager to deduplicate concurrent refresh requests.
|
||||
// This prevents race conditions between useTokenRefreshOnFocus (proactive refresh
|
||||
// on tab focus) and the auth interceptor (reactive refresh on 401), which could
|
||||
// otherwise send duplicate requests that conflict with server-side token rotation.
|
||||
export async function refreshAccessToken(): Promise<void> {
|
||||
return tokenRefreshManager.refresh(doRefreshAccessToken);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Authentication Interceptor
|
||||
// ============================================================================
|
||||
|
|
@ -104,7 +112,7 @@ const authInterceptor: Interceptor = (next) => async (req) => {
|
|||
}
|
||||
|
||||
try {
|
||||
await tokenRefreshManager.refresh(refreshAccessToken);
|
||||
await refreshAccessToken();
|
||||
|
||||
const newToken = getAccessToken();
|
||||
if (!newToken) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import { useEffect, useMemo } from "react";
|
|||
import { Outlet, useLocation, useSearchParams } from "react-router-dom";
|
||||
import usePrevious from "react-use/lib/usePrevious";
|
||||
import Navigation from "@/components/Navigation";
|
||||
import { useInstance } from "@/contexts/InstanceContext";
|
||||
import { useMemoFilterContext } from "@/contexts/MemoFilterContext";
|
||||
import useCurrentUser from "@/hooks/useCurrentUser";
|
||||
import useMediaQuery from "@/hooks/useMediaQuery";
|
||||
|
|
@ -14,16 +13,15 @@ const RootLayout = () => {
|
|||
const [searchParams] = useSearchParams();
|
||||
const sm = useMediaQuery("sm");
|
||||
const currentUser = useCurrentUser();
|
||||
const { memoRelatedSetting } = useInstance();
|
||||
const { removeFilter } = useMemoFilterContext();
|
||||
const pathname = useMemo(() => location.pathname, [location.pathname]);
|
||||
const prevPathname = usePrevious(pathname);
|
||||
|
||||
useEffect(() => {
|
||||
if (!currentUser && memoRelatedSetting.disallowPublicVisibility) {
|
||||
if (!currentUser) {
|
||||
redirectOnAuthFailure();
|
||||
}
|
||||
}, [currentUser, memoRelatedSetting.disallowPublicVisibility]);
|
||||
}, [currentUser]);
|
||||
|
||||
useEffect(() => {
|
||||
// When the route changes and there is no filter in the search params, remove all filters
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { clearAccessToken } from "@/auth-state";
|
||||
import { getInstanceConfig } from "@/instance-config";
|
||||
import { ROUTES } from "@/router/routes";
|
||||
|
||||
const PUBLIC_ROUTES = [
|
||||
|
|
@ -27,15 +26,10 @@ export function redirectOnAuthFailure(): void {
|
|||
return;
|
||||
}
|
||||
|
||||
const disallowPublicVisibility = getInstanceConfig().memoRelatedSetting.disallowPublicVisibility;
|
||||
const target = disallowPublicVisibility ? ROUTES.AUTH : ROUTES.EXPLORE;
|
||||
|
||||
// Only redirect if it's a private route or disallowPublicVisibility is enabled
|
||||
if (disallowPublicVisibility || isPrivateRoute(currentPath)) {
|
||||
// Clear access token to ensure user is fully logged out
|
||||
// This prevents the issue where user appears logged in but sees only public memos
|
||||
// See: https://github.com/usememos/memos/issues/5565
|
||||
// Always redirect to auth page on auth failure - the user's session expired
|
||||
// and they should re-authenticate rather than being sent to explore.
|
||||
if (isPrivateRoute(currentPath)) {
|
||||
clearAccessToken();
|
||||
window.location.replace(target);
|
||||
window.location.replace(ROUTES.AUTH);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue