75 lines
No EOL
2.2 KiB
TypeScript
75 lines
No EOL
2.2 KiB
TypeScript
import { useMsal } from "@azure/msal-react";
|
|
import { Navigate, useLocation } from "react-router-dom";
|
|
import { ReactNode, useEffect, useState } from "react";
|
|
|
|
interface ProtectedRouteProps {
|
|
children: ReactNode;
|
|
redirectPath?: string;
|
|
}
|
|
|
|
export const ProtectedRoute = ({
|
|
children,
|
|
redirectPath = "/login"
|
|
}: ProtectedRouteProps) => {
|
|
const { accounts } = useMsal();
|
|
const location = useLocation();
|
|
const [isChecking, setIsChecking] = useState(true);
|
|
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
|
|
|
useEffect(() => {
|
|
const checkAuthentication = async () => {
|
|
try {
|
|
// Check for MSAL authentication
|
|
const hasMsalAccount = accounts.length > 0;
|
|
|
|
// Check for backend token
|
|
const authData = localStorage.getItem('auth_data');
|
|
let hasBackendToken = false;
|
|
|
|
if (authData) {
|
|
try {
|
|
const parsedAuthData = JSON.parse(authData);
|
|
hasBackendToken = !!parsedAuthData.accessToken;
|
|
} catch (e) {
|
|
console.error('Error parsing auth data:', e);
|
|
}
|
|
}
|
|
|
|
// User is authenticated if either method is valid
|
|
setIsAuthenticated(hasMsalAccount || hasBackendToken);
|
|
|
|
if (hasBackendToken) {
|
|
console.log('Authenticated with backend token');
|
|
} else if (hasMsalAccount) {
|
|
console.log('Authenticated with MSAL');
|
|
}
|
|
} catch (error) {
|
|
console.error('Error checking authentication:', error);
|
|
setIsAuthenticated(false);
|
|
} finally {
|
|
setIsChecking(false);
|
|
}
|
|
};
|
|
|
|
// Small delay to ensure MSAL is initialized
|
|
const timer = setTimeout(() => {
|
|
checkAuthentication();
|
|
}, 100);
|
|
|
|
return () => clearTimeout(timer);
|
|
}, [accounts]);
|
|
|
|
// If still checking, show loading
|
|
if (isChecking) {
|
|
return <div>Checking authentication...</div>;
|
|
}
|
|
|
|
// Check if user is authenticated through either method
|
|
if (!isAuthenticated) {
|
|
console.log("No valid authentication found, redirecting to login");
|
|
return <Navigate to={redirectPath} state={{ from: location }} replace />;
|
|
}
|
|
|
|
console.log("User is authenticated, rendering protected content");
|
|
return <>{children}</>;
|
|
}; |