yangdx
commited on
Commit
·
578ed1a
1
Parent(s):
a796e61
Added authentication checks and token validation
Browse files- Added auth checks in health check logic
- Protected routes require authentication
- Validated token on app startup
- Added auth check in API interceptor
- Clear token on 401 unauthorized error
lightrag_webui/src/App.tsx
CHANGED
@@ -5,7 +5,7 @@ import MessageAlert from '@/components/MessageAlert'
|
|
5 |
import ApiKeyAlert from '@/components/ApiKeyAlert'
|
6 |
import StatusIndicator from '@/components/graph/StatusIndicator'
|
7 |
import { healthCheckInterval } from '@/lib/constants'
|
8 |
-
import { useBackendState } from '@/stores/state'
|
9 |
import { useSettingsStore } from '@/stores/settings'
|
10 |
import { useEffect } from 'react'
|
11 |
import SiteHeader from '@/features/SiteHeader'
|
@@ -26,7 +26,8 @@ function App() {
|
|
26 |
|
27 |
// Health check
|
28 |
useEffect(() => {
|
29 |
-
|
|
|
30 |
|
31 |
// Check immediately
|
32 |
useBackendState.getState().check()
|
|
|
5 |
import ApiKeyAlert from '@/components/ApiKeyAlert'
|
6 |
import StatusIndicator from '@/components/graph/StatusIndicator'
|
7 |
import { healthCheckInterval } from '@/lib/constants'
|
8 |
+
import { useBackendState, useAuthStore } from '@/stores/state'
|
9 |
import { useSettingsStore } from '@/stores/settings'
|
10 |
import { useEffect } from 'react'
|
11 |
import SiteHeader from '@/features/SiteHeader'
|
|
|
26 |
|
27 |
// Health check
|
28 |
useEffect(() => {
|
29 |
+
const { isAuthenticated } = useAuthStore.getState();
|
30 |
+
if (!enableHealthCheck || !isAuthenticated) return
|
31 |
|
32 |
// Check immediately
|
33 |
useBackendState.getState().check()
|
lightrag_webui/src/AppRouter.tsx
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
-
import { HashRouter as Router, Routes, Route } from 'react-router-dom'
|
2 |
-
|
|
|
3 |
import { Toaster } from 'sonner'
|
4 |
import App from './App'
|
5 |
import LoginPage from '@/features/LoginPage'
|
@@ -10,16 +11,24 @@ interface ProtectedRouteProps {
|
|
10 |
}
|
11 |
|
12 |
const ProtectedRoute = ({ children }: ProtectedRouteProps) => {
|
13 |
-
|
14 |
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
|
19 |
return <>{children}</>
|
20 |
}
|
21 |
|
22 |
const AppRouter = () => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
return (
|
24 |
<ThemeProvider>
|
25 |
<Router>
|
|
|
1 |
+
import { HashRouter as Router, Routes, Route, Navigate } from 'react-router-dom'
|
2 |
+
import { useEffect } from 'react'
|
3 |
+
import { useAuthStore } from '@/stores/state'
|
4 |
import { Toaster } from 'sonner'
|
5 |
import App from './App'
|
6 |
import LoginPage from '@/features/LoginPage'
|
|
|
11 |
}
|
12 |
|
13 |
const ProtectedRoute = ({ children }: ProtectedRouteProps) => {
|
14 |
+
const { isAuthenticated } = useAuthStore()
|
15 |
|
16 |
+
if (!isAuthenticated) {
|
17 |
+
return <Navigate to="/login" replace />
|
18 |
+
}
|
19 |
|
20 |
return <>{children}</>
|
21 |
}
|
22 |
|
23 |
const AppRouter = () => {
|
24 |
+
// Check login at befor startup
|
25 |
+
useEffect(() => {
|
26 |
+
const token = localStorage.getItem('LIGHTRAG-API-TOKEN');
|
27 |
+
if (!token) {
|
28 |
+
useAuthStore.getState().logout();
|
29 |
+
}
|
30 |
+
}, []);
|
31 |
+
|
32 |
return (
|
33 |
<ThemeProvider>
|
34 |
<Router>
|
lightrag_webui/src/api/lightrag.ts
CHANGED
@@ -142,10 +142,20 @@ const axiosInstance = axios.create({
|
|
142 |
}
|
143 |
})
|
144 |
|
145 |
-
// Interceptor
|
146 |
axiosInstance.interceptors.request.use((config) => {
|
147 |
const apiKey = useSettingsStore.getState().apiKey
|
148 |
const token = localStorage.getItem('LIGHTRAG-API-TOKEN');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
149 |
if (apiKey) {
|
150 |
config.headers['X-API-Key'] = apiKey
|
151 |
}
|
@@ -160,10 +170,6 @@ axiosInstance.interceptors.response.use(
|
|
160 |
(response) => response,
|
161 |
(error: AxiosError) => {
|
162 |
if (error.response) {
|
163 |
-
interface ErrorResponse {
|
164 |
-
detail: string;
|
165 |
-
}
|
166 |
-
|
167 |
if (error.response?.status === 401) {
|
168 |
localStorage.removeItem('LIGHTRAG-API-TOKEN');
|
169 |
sessionStorage.clear();
|
|
|
142 |
}
|
143 |
})
|
144 |
|
145 |
+
// Interceptor: add api key and check authentication
|
146 |
axiosInstance.interceptors.request.use((config) => {
|
147 |
const apiKey = useSettingsStore.getState().apiKey
|
148 |
const token = localStorage.getItem('LIGHTRAG-API-TOKEN');
|
149 |
+
|
150 |
+
// Check authentication status for paths that require authentication
|
151 |
+
const authRequiredPaths = ['/documents', '/graphs', '/query', '/health']; // Add all paths that require authentication
|
152 |
+
const isAuthRequired = authRequiredPaths.some(path => config.url?.includes(path));
|
153 |
+
|
154 |
+
if (isAuthRequired && !token && config.url !== '/login') {
|
155 |
+
// Cancel the request and return a rejected Promise
|
156 |
+
return Promise.reject(new Error('Authentication required'));
|
157 |
+
}
|
158 |
+
|
159 |
if (apiKey) {
|
160 |
config.headers['X-API-Key'] = apiKey
|
161 |
}
|
|
|
170 |
(response) => response,
|
171 |
(error: AxiosError) => {
|
172 |
if (error.response) {
|
|
|
|
|
|
|
|
|
173 |
if (error.response?.status === 401) {
|
174 |
localStorage.removeItem('LIGHTRAG-API-TOKEN');
|
175 |
sessionStorage.clear();
|