diff --git a/src/api/axiosInstance.js b/src/api/axiosInstance.js index 418dcf5..814e6e5 100644 --- a/src/api/axiosInstance.js +++ b/src/api/axiosInstance.js @@ -1,30 +1,18 @@ import axios from 'axios'; -/* -const axiosInstance = axios.create({ - baseURL: '/api', - headers: { 'Content-Type': 'application/json' }, -}); -*/ const axiosInstance = axios.create({ baseURL: 'https://api.testsite.deinedorfapp.de/api', - //baseURL: 'http://localhost:5173/api', headers: { 'Content-Type': 'application/json' }, -}); - -axiosInstance.interceptors.request.use((config) => { - const token = localStorage.getItem('jwt_token'); - if (token) { - config.headers.Authorization = `Bearer ${token}`; - } - return config; + withCredentials: true }); axiosInstance.interceptors.response.use( (response) => response, (error) => { - if (error.response?.status === 401) { - localStorage.removeItem('jwt_token'); + const isAuthCheck = error.config?.url?.includes('/auth/me'); + const isLogin = error.config?.url?.includes('/auth/login'); + + if (error.response?.status === 401 && !isAuthCheck && !isLogin) { window.location.href = '/login'; } return Promise.reject(error); diff --git a/src/components/PrivateRoute.jsx b/src/components/PrivateRoute.jsx index b9a140e..b30d197 100644 --- a/src/components/PrivateRoute.jsx +++ b/src/components/PrivateRoute.jsx @@ -1,8 +1,15 @@ import { Navigate } from 'react-router-dom'; import { useAuth } from '../context/AuthContext'; +import { CircularProgress, Box } from '@mui/material'; export default function PrivateRoute({ children, allowedRoles }) { - const { isAuthenticated, role } = useAuth(); + const { isAuthenticated, role, loading } = useAuth(); + + if (loading) return ( + + + + ); if (!isAuthenticated) return ; if (allowedRoles && !allowedRoles.includes(role)) return ; diff --git a/src/context/AuthContext.jsx b/src/context/AuthContext.jsx index 6810529..e310947 100644 --- a/src/context/AuthContext.jsx +++ b/src/context/AuthContext.jsx @@ -1,37 +1,50 @@ -import { createContext, useContext, useState } from 'react'; +import { createContext, useContext, useState, useEffect } from 'react'; import axiosInstance from '../api/axiosInstance'; -import { jwtDecode } from 'jwt-decode'; -import { SettingsRemoteOutlined } from '@mui/icons-material'; const AuthContext = createContext(null); export function AuthProvider({ children }) { - const [token, setToken] = useState(() => localStorage.getItem('jwt_token')); - const [role, setRole] = useState(() => { - const t = localStorage.getItem('jwt_token'); - return t ? jwtDecode(t).role : null; - }); + const [role, setRole] = useState(null); + const [isAuthenticated, setIsAuthenticated] = useState(false); + const [loading, setLoading] = useState(true); + + useEffect(() => { + axiosInstance.get('/auth/me') + .then(({ data }) => { + setRole(data.role.replace('ROLE_', '')); + setIsAuthenticated(true); + }) + .catch(() => { + setRole(null); + setIsAuthenticated(false); + }) + .finally(() => setLoading(false)); + }, []); const login = async (email, password) => { - // Endpunkt ggf. anpassen const { data } = await axiosInstance.post('/auth/login', { email, password }); - localStorage.setItem('jwt_token', data.token); - const decoded = jwtDecode(data.token); - setToken(data.token); - setRole(decoded.role) + setRole(data.role.replace('ROLE_', '')); + setIsAuthenticated(true); }; - const logout = () => { - localStorage.removeItem('jwt_token'); - setToken(null); - setRole(null) + const logout = async () => { + try { + await axiosInstance.post('/auth/logout'); + } finally { + setRole(null); + setIsAuthenticated(false); + } }; return ( - - {children} - + + {children} + ); } -export const useAuth = () => useContext(AuthContext); +export const useAuth = () => { + const context = useContext(AuthContext); + if (!context) throw new Error('useAuth muss innerhalb eines AuthProviders verwendet werden'); + return context; +}; \ No newline at end of file