Refactor authentication flows and improve logout handling
Split authentication logic into a reusable `MainLayout` component for better structure and consistency. Enhanced logout functionality to ensure proper state resetting and added minor delays for reliable redirect behavior. Improved safeguards for unauthenticated access, reducing potential edge case errors.
This commit is contained in:
41
frontend/src/app/(main)/dashboard/layout.tsx
Normal file
41
frontend/src/app/(main)/dashboard/layout.tsx
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useAuth } from "@/context/auth-context";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
|
export default function MainLayout({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
const { isAuthenticated, isLoading } = useAuth();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isLoading && !isAuthenticated) {
|
||||||
|
router.push("/login");
|
||||||
|
}
|
||||||
|
}, [isAuthenticated, isLoading, router]);
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen flex items-center justify-center">
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="h-8 w-8 mx-auto border-4 border-t-blue-500 border-blue-200 rounded-full animate-spin"></div>
|
||||||
|
<p className="mt-2">Loading...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isAuthenticated) {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen flex items-center justify-center">
|
||||||
|
Redirecting to login...
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <>{children}</>;
|
||||||
|
}
|
||||||
@@ -6,16 +6,29 @@ import { useRouter } from "next/navigation";
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
|
||||||
export default function DashboardPage() {
|
export default function DashboardPage() {
|
||||||
const { user, isLoading, isAuthenticated } = useAuth();
|
const { user, isLoading, isAuthenticated, logout } = useAuth();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
// Redirect to login if not authenticated
|
// Redirect to login if not authenticated
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// Add a small delay to ensure context is fully updated
|
||||||
|
const checkAuth = setTimeout(() => {
|
||||||
if (!isLoading && !isAuthenticated) {
|
if (!isLoading && !isAuthenticated) {
|
||||||
|
console.log("Not authenticated, redirecting to login");
|
||||||
router.push("/login");
|
router.push("/login");
|
||||||
}
|
}
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
return () => clearTimeout(checkAuth);
|
||||||
}, [isLoading, isAuthenticated, router]);
|
}, [isLoading, isAuthenticated, router]);
|
||||||
|
|
||||||
|
// Handle logout with explicit redirect
|
||||||
|
const handleLogout = () => {
|
||||||
|
logout();
|
||||||
|
// Force redirection to login
|
||||||
|
router.push("/login");
|
||||||
|
};
|
||||||
|
|
||||||
// Show loading state
|
// Show loading state
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
@@ -28,6 +41,12 @@ export default function DashboardPage() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extra safeguard - if we somehow get here without authentication, redirect
|
||||||
|
if (!isAuthenticated) {
|
||||||
|
router.push("/login");
|
||||||
|
return <div>Redirecting...</div>;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container mx-auto px-4 py-12">
|
<div className="container mx-auto px-4 py-12">
|
||||||
<div className="max-w-7xl mx-auto">
|
<div className="max-w-7xl mx-auto">
|
||||||
@@ -57,10 +76,7 @@ export default function DashboardPage() {
|
|||||||
<div className="mt-8">
|
<div className="mt-8">
|
||||||
<button
|
<button
|
||||||
className="px-4 py-2 bg-red-100 text-red-600 rounded hover:bg-red-200 transition-colors"
|
className="px-4 py-2 bg-red-100 text-red-600 rounded hover:bg-red-200 transition-colors"
|
||||||
onClick={() => {
|
onClick={handleLogout}
|
||||||
const auth = useAuth();
|
|
||||||
auth.logout();
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Sign Out
|
Sign Out
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -189,23 +189,27 @@ export const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {
|
|||||||
|
|
||||||
// Logout function
|
// Logout function
|
||||||
const logout = useCallback((): void => {
|
const logout = useCallback((): void => {
|
||||||
// Clear tokens
|
// Clear tokens first
|
||||||
storeToken(null);
|
storeToken(null);
|
||||||
|
|
||||||
// Remove auth headers
|
// Remove auth headers from client
|
||||||
client.setConfig({
|
client.setConfig({
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: undefined,
|
Authorization: undefined,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Clear user from cache
|
// Properly reset the cache - use null instead of undefined
|
||||||
queryClient.invalidateQueries({
|
queryClient.setQueryData(getCurrentUserInfoOptions().queryKey, undefined);
|
||||||
queryKey: getCurrentUserInfoOptions().queryKey,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
// Reset the entire cache to be safe
|
||||||
|
queryClient.clear();
|
||||||
|
|
||||||
|
// Wait for all state updates to process
|
||||||
|
setTimeout(() => {
|
||||||
// Redirect to login page
|
// Redirect to login page
|
||||||
router.push("/login");
|
router.push("/login");
|
||||||
|
}, 100);
|
||||||
}, [router, queryClient]);
|
}, [router, queryClient]);
|
||||||
|
|
||||||
// Refresh token function
|
// Refresh token function
|
||||||
|
|||||||
Reference in New Issue
Block a user