fix(auth): preserve session on reload and correct 401 redirect flow

- Save PKCE params to sessionStorage.redirectState on 401 instead of overwriting tokenSet

- Persist userData in sessionStorage after OIDC callback for later hydration

- Hydrate Redux (tokens + userData) from sessionStorage on app start to avoid forced re-login

- Keep SPA single route '/' behavior unchanged; only improves auth robustness

Files: src/utils/apiUtils.ts, src/features/User/LoginCallback.tsx, src/features/User/HandleLogin.tsx
This commit is contained in:
lenhanphung
2025-09-15 11:46:20 +07:00
parent d76775c7d2
commit a4394e6a25
3 changed files with 18 additions and 2 deletions
+16 -1
View File
@@ -5,6 +5,7 @@ import { Loading } from "../../components/Loading/Loading";
import { Error } from "../../components/Error/Error";
import { push } from "redux-first-history";
import { redirectTo } from "../../utils/apiUtils";
import { setTokens, setUserData } from "./userSlice";
export function HandleLogin() {
const userData = useAppSelector((state) => state.user);
@@ -13,6 +14,20 @@ export function HandleLogin() {
useEffect(() => {
const initiateLogin = async () => {
if (!userData.userData) {
const savedToken = sessionStorage.getItem("tokenSet")
? JSON.parse(sessionStorage.getItem("tokenSet")!)
: null;
const savedUser = sessionStorage.getItem("userData")
? JSON.parse(sessionStorage.getItem("userData")!)
: null;
if (savedToken && savedUser) {
dispatch(setTokens(savedToken));
dispatch(setUserData(savedUser));
dispatch(push("/"));
return;
}
const loginurl = await Auth();
sessionStorage.setItem(
@@ -28,7 +43,7 @@ export function HandleLogin() {
};
initiateLogin();
}, [userData]);
}, [userData, dispatch]);
if (!calendars.pending && !userData.loading) {
dispatch(push("/error"));
+1
View File
@@ -27,6 +27,7 @@ export function CallbackResume() {
sessionStorage.removeItem("redirectState");
sessionStorage.setItem("tokenSet", JSON.stringify(data?.tokenSet));
sessionStorage.setItem("userData", JSON.stringify(data?.userinfo));
// Redirect to main page after successful callback
dispatch(push("/"));
} catch (e) {
+1 -1
View File
@@ -23,7 +23,7 @@ export const api = ky.extend({
const loginurl = await Auth();
sessionStorage.setItem(
"tokenSet",
"redirectState",
JSON.stringify({
code_verifier: loginurl.code_verifier,
state: loginurl.state,