mirror of https://github.com/usememos/memos.git
fix(web): skip GetCurrentUser on init when no token is stored
When no token exists in sessionStorage, AuthContext.initialize() was still calling GetCurrentUser, triggering the auth interceptor to attempt RefreshToken and retry — producing a burst of 5+ auth API calls in under a second that reverse proxies with rate limiting (e.g. CrowdSec) flag as brute force. Add hasStoredToken() to auth-state and bail out of initialize() early when there is definitively no session to restore. The refresh flow for expired tokens is preserved since hasStoredToken() checks for presence regardless of expiry. Fixes #5647
This commit is contained in:
parent
b8bca6bacf
commit
4aaebc507e
|
|
@ -62,6 +62,19 @@ export const isTokenExpired = (bufferMs: number = 30000): boolean => {
|
|||
return new Date() >= new Date(tokenExpiresAt.getTime() - bufferMs);
|
||||
};
|
||||
|
||||
// Returns true if a token exists in sessionStorage, even if it is expired.
|
||||
// Used to decide whether to attempt GetCurrentUser on app init — if no token
|
||||
// was ever stored, the user is definitively not logged in and there is nothing
|
||||
// to refresh, so we can skip the network round-trip entirely.
|
||||
export const hasStoredToken = (): boolean => {
|
||||
if (accessToken) return true;
|
||||
try {
|
||||
return !!sessionStorage.getItem(SESSION_TOKEN_KEY);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const clearAccessToken = (): void => {
|
||||
accessToken = null;
|
||||
tokenExpiresAt = null;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { createContext, type ReactNode, useCallback, useContext, useMemo, useState } from "react";
|
||||
import { clearAccessToken } from "@/auth-state";
|
||||
import { clearAccessToken, hasStoredToken } from "@/auth-state";
|
||||
import { authServiceClient, shortcutServiceClient, userServiceClient } from "@/connect";
|
||||
import { userKeys } from "@/hooks/useUserQueries";
|
||||
import type { Shortcut } from "@/types/proto/api/v1/shortcut_service_pb";
|
||||
|
|
@ -52,6 +52,21 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
|||
|
||||
const initialize = useCallback(async () => {
|
||||
setState((prev) => ({ ...prev, isLoading: true }));
|
||||
|
||||
// If there is no stored token at all, the user is not authenticated.
|
||||
// Skip the network call — there is nothing to refresh and no session to restore.
|
||||
if (!hasStoredToken()) {
|
||||
setState({
|
||||
currentUser: undefined,
|
||||
userGeneralSetting: undefined,
|
||||
userWebhooksSetting: undefined,
|
||||
shortcuts: [],
|
||||
isInitialized: true,
|
||||
isLoading: false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { user: currentUser } = await authServiceClient.getCurrentUser({});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue