From 960e91c38a7cd1d67a4f94248913804a55ef4d7e Mon Sep 17 00:00:00 2001 From: Theis Gaedigk Date: Fri, 24 Oct 2025 20:45:37 +0200 Subject: [PATCH] feat: Implement authentication flow with token verification and protected routes --- FrontendV2/src/App.tsx | 27 +++++++++++++++++++- FrontendV2/src/pages/HomePage.tsx | 6 +++++ FrontendV2/src/pages/LoginPage.tsx | 27 ++++++++++++-------- FrontendV2/src/utils/ProtectedRoutes.tsx | 32 ++---------------------- 4 files changed, 50 insertions(+), 42 deletions(-) diff --git a/FrontendV2/src/App.tsx b/FrontendV2/src/App.tsx index 5848cc6..f4f5a62 100644 --- a/FrontendV2/src/App.tsx +++ b/FrontendV2/src/App.tsx @@ -3,6 +3,10 @@ import { LoginPage } from "@/pages/LoginPage"; import { BrowserRouter, Route, Routes } from "react-router-dom"; import { HomePage } from "@/pages/HomePage"; import { ProtectedRoutes } from "./utils/ProtectedRoutes"; +import { useEffect } from "react"; +import Cookies from "js-cookie"; +import { useAtom } from "jotai"; +import { setIsLoggedInAtom } from "@/states/Atoms"; const API_BASE = (import.meta as any).env?.VITE_BACKEND_URL || @@ -10,9 +14,30 @@ const API_BASE = "http://localhost:8002"; function App() { + const [, setIsLoggedIn] = useAtom(setIsLoggedInAtom); + useEffect(() => { + if (Cookies.get("token")) { + const verifyToken = async () => { + const response = await fetch(`${API_BASE}/api/verifyToken`, { + method: "GET", + headers: { + Authorization: `Bearer ${Cookies.get("token")}`, + }, + }); + if (response.ok) { + setIsLoggedIn(true); + } else { + Cookies.remove("token"); + setIsLoggedIn(false); + window.location.reload(); + } + }; + verifyToken(); + } + }, []); + return ( <> -
Layout Component
}> diff --git a/FrontendV2/src/pages/HomePage.tsx b/FrontendV2/src/pages/HomePage.tsx index 17fc087..b0bbf98 100644 --- a/FrontendV2/src/pages/HomePage.tsx +++ b/FrontendV2/src/pages/HomePage.tsx @@ -1,4 +1,10 @@ +import { setIsLoggedInAtom } from "@/states/Atoms"; +import { useAtom } from "jotai"; + export const HomePage = () => { + const [isLoggedIn] = useAtom(setIsLoggedInAtom); + console.log(isLoggedIn); + return (

Home Page

diff --git a/FrontendV2/src/pages/LoginPage.tsx b/FrontendV2/src/pages/LoginPage.tsx index c453322..e70306a 100644 --- a/FrontendV2/src/pages/LoginPage.tsx +++ b/FrontendV2/src/pages/LoginPage.tsx @@ -1,10 +1,10 @@ -import { useState } from "react"; +import { useState, useEffect } from "react"; import MyAlert from "../components/myChakra/MyAlert"; import { Button, Card, Field, Input, Stack } from "@chakra-ui/react"; import { setIsLoggedInAtom } from "@/states/Atoms"; import { useAtom } from "jotai"; -import { useEffect } from "react"; import Cookies from "js-cookie"; +import { Navigate, useNavigate } from "react-router-dom"; const API_BASE = (import.meta as any).env?.VITE_BACKEND_URL || @@ -13,29 +13,29 @@ const API_BASE = export const LoginPage = () => { const [isLoggedIn, setIsLoggedIn] = useAtom(setIsLoggedInAtom); + const navigate = useNavigate(); + console.log(isLoggedIn); useEffect(() => { if (isLoggedIn) { - window.location.href = "/"; + navigate("/", { replace: true }); } - }, [isLoggedIn]); + }, [isLoggedIn, navigate]); const loginFnc = async (username: string, password: string) => { const response = await fetch(`${API_BASE}/api/login`, { method: "POST", - headers: { - "Content-Type": "application/json", - }, + headers: { "Content-Type": "application/json" }, body: JSON.stringify({ username, password }), }); + const data = await response.json(); if (!response.ok) { - const errorData = await response.json(); return { success: false, - message: errorData.message, - description: errorData.description, + message: data.message ?? "Login fehlgeschlagen", + description: data.description ?? "", }; } @@ -58,8 +58,13 @@ export const LoginPage = () => { setIsError(true); return; } + navigate("/", { replace: true }); }; + if (isLoggedIn) { + return ; + } + return (
e.preventDefault()}> @@ -94,7 +99,7 @@ export const LoginPage = () => { )} diff --git a/FrontendV2/src/utils/ProtectedRoutes.tsx b/FrontendV2/src/utils/ProtectedRoutes.tsx index ce436f9..d152733 100644 --- a/FrontendV2/src/utils/ProtectedRoutes.tsx +++ b/FrontendV2/src/utils/ProtectedRoutes.tsx @@ -1,37 +1,9 @@ -import { Outlet, Navigate } from "react-router-dom"; +import { Navigate, Outlet } from "react-router-dom"; import { useAtom } from "jotai"; import { setIsLoggedInAtom } from "@/states/Atoms"; -import { useEffect } from "react"; -import Cookies from "js-cookie"; - -const API_BASE = - (import.meta as any).env?.VITE_BACKEND_URL || - import.meta.env.VITE_BACKEND_URL || - "http://localhost:8002"; export const ProtectedRoutes = () => { - const [isLoggedIn, setIsLoggedIn] = useAtom(setIsLoggedInAtom); - - useEffect(() => { - if (Cookies.get("token")) { - const verifyToken = async () => { - const response = await fetch(`${API_BASE}/api/verifyToken`, { - method: "GET", - headers: { - Authorization: `Bearer ${Cookies.get("token")}`, - }, - }); - if (response.ok) { - setIsLoggedIn(true); - } else { - Cookies.remove("token"); - setIsLoggedIn(false); - window.location.reload(); - } - }; - verifyToken(); - } - }, []); + const [isLoggedIn] = useAtom(setIsLoggedInAtom); return isLoggedIn ? : ; };