Skip to content

Commit a44880b

Browse files
authored
Fix 401 bug (#2309)
1 parent 85b8d3b commit a44880b

File tree

2 files changed

+57
-2
lines changed

2 files changed

+57
-2
lines changed

web/src/components/wizard/SetupStep.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { ChevronLeft, ChevronRight } from "lucide-react";
77
import LinuxSetup from "./setup/LinuxSetup";
88
import { useQuery, useMutation } from "@tanstack/react-query";
99
import { useAuth } from "../../contexts/AuthContext";
10+
import { handleUnauthorized } from "../../utils/auth";
1011

1112
interface SetupStepProps {
1213
onNext: () => void;
@@ -39,7 +40,12 @@ const SetupStep: React.FC<SetupStepProps> = ({ onNext, onBack }) => {
3940
},
4041
});
4142
if (!response.ok) {
42-
throw new Error("Failed to fetch install configuration");
43+
const errorData = await response.json().catch(() => ({}));
44+
if (response.status === 401) {
45+
handleUnauthorized(errorData);
46+
throw new Error("Session expired. Please log in again.");
47+
}
48+
throw new Error(errorData.message || "Failed to fetch install configuration");
4349
}
4450
const config = await response.json();
4551
updateConfig(config);
@@ -57,7 +63,12 @@ const SetupStep: React.FC<SetupStepProps> = ({ onNext, onBack }) => {
5763
},
5864
});
5965
if (!response.ok) {
60-
throw new Error("Failed to fetch network interfaces");
66+
const errorData = await response.json().catch(() => ({}));
67+
if (response.status === 401) {
68+
handleUnauthorized(errorData);
69+
throw new Error("Session expired. Please log in again.");
70+
}
71+
throw new Error(errorData.message || "Failed to fetch network interfaces");
6172
}
6273
return response.json();
6374
},
@@ -77,6 +88,10 @@ const SetupStep: React.FC<SetupStepProps> = ({ onNext, onBack }) => {
7788

7889
if (!response.ok) {
7990
const errorData = await response.json().catch(() => ({}));
91+
if (response.status === 401) {
92+
handleUnauthorized(errorData);
93+
throw new Error("Session expired. Please log in again.");
94+
}
8095
throw errorData;
8196
}
8297
return response.json();

web/src/contexts/AuthContext.tsx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import React, { createContext, useContext, useState, useEffect } from "react";
2+
import { handleUnauthorized } from "../utils/auth";
23

34
interface AuthContextType {
45
token: string | null;
56
setToken: (token: string | null) => void;
67
isAuthenticated: boolean;
8+
isLoading: boolean;
79
}
810

911
export const AuthContext = createContext<AuthContextType | undefined>(undefined);
@@ -20,6 +22,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
2022
const [token, setTokenState] = useState<string | null>(() => {
2123
return localStorage.getItem("auth");
2224
});
25+
const [isLoading, setIsLoading] = useState(true);
2326

2427
const setToken = (newToken: string | null) => {
2528
if (newToken) {
@@ -30,6 +33,38 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
3033
setTokenState(newToken);
3134
};
3235

36+
// Check token validity on mount and when token changes
37+
useEffect(() => {
38+
if (token) {
39+
// Make a request to any authenticated endpoint to check token validity
40+
fetch("/api/install/installation/config", {
41+
headers: {
42+
Authorization: `Bearer ${token}`,
43+
},
44+
})
45+
.then((response) => {
46+
if (!response.ok) {
47+
// If we get a 401, handle it
48+
if (response.status === 401) {
49+
const error = new Error("Unauthorized");
50+
(error as Error & { status?: number }).status = 401;
51+
handleUnauthorized(error);
52+
}
53+
}
54+
setIsLoading(false);
55+
})
56+
.catch(() => {
57+
// If the request fails, assume the token is invalid
58+
const err = new Error("Request failed");
59+
(err as Error & { status?: number }).status = 401;
60+
handleUnauthorized(err);
61+
setIsLoading(false);
62+
});
63+
} else {
64+
setIsLoading(false);
65+
}
66+
}, [token]);
67+
3368
useEffect(() => {
3469
// Listen for storage events to sync token state across tabs
3570
const handleStorageChange = (e: StorageEvent) => {
@@ -48,7 +83,12 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
4883
token,
4984
setToken,
5085
isAuthenticated: !!token,
86+
isLoading,
5187
};
5288

89+
if (isLoading) {
90+
return null; // Don't render anything while checking token validity
91+
}
92+
5393
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
5494
};

0 commit comments

Comments
 (0)