diff --git a/frontend/pages/login.vue b/frontend/pages/login.vue index 823370e..19f5e9e 100644 --- a/frontend/pages/login.vue +++ b/frontend/pages/login.vue @@ -46,6 +46,15 @@ const doLogin = async (event: FormSubmitEvent) => {

+ + { }) }, - async onResponseError({ response }) { + async onResponseError({ response, request }) { // Toasts nur im Client anzeigen console.log(response) if (!process.client) return const status = response.status + const requestPath = String(request) let title = "Fehler" let description = "Ein unerwarteter Fehler ist aufgetreten." @@ -51,7 +52,10 @@ export default defineNuxtPlugin(() => { case 401: title = "Nicht angemeldet" description = "Deine Sitzung ist abgelaufen oder ungültig." - // Optional: useCookie('token').value = null + if (!requestPath.includes("/auth/login")) { + const auth = useAuthStore() + auth.expireSession() + } break case 403: title = "Zugriff verweigert" @@ -83,4 +87,4 @@ export default defineNuxtPlugin(() => { api } } -}) \ No newline at end of file +}) diff --git a/frontend/stores/auth.ts b/frontend/stores/auth.ts index b11e13e..fa7efc3 100644 --- a/frontend/stores/auth.ts +++ b/frontend/stores/auth.ts @@ -20,6 +20,7 @@ export const useAuthStore = defineStore("auth", { activeTenantData: null as any, loading: true as boolean, notLoggedIn: true, + sessionExpired: false, sessionWarningVisible: false, sessionWarningRemainingSeconds: 0, sessionWarningLeadMs: 5 * 60 * 1000, @@ -105,13 +106,12 @@ export const useAuthStore = defineStore("auth", { const msUntilLogout = expiresAtMs - now if (msUntilLogout <= 0) { - void this.logout() + this.expireSession() return } this.sessionLogoutTimer = setTimeout(() => { - this.sessionWarningVisible = false - void this.logout() + this.expireSession() }, msUntilLogout) const msUntilWarning = msUntilLogout - this.sessionWarningLeadMs @@ -152,12 +152,12 @@ export const useAuthStore = defineStore("auth", { // 1. Check: Haben wir überhaupt ein Token? const token = useCookie("token").value - /*if (!token) { + if (!token) { // Kein Token -> Wir sind fertig, User ist Gast. this.user = null this.loading = false return - }*/ + } // 2. Token existiert -> Versuche User zu laden await this.fetchMe(token) @@ -171,6 +171,8 @@ export const useAuthStore = defineStore("auth", { // Hier vorsichtig sein: Nicht navigieren, wenn der User auf eine Deep-Link URL will! // navigateTo("/") <-- Das würde ich hier evtl. sogar weglassen und der Middleware überlassen } + + this.loading = false }, async init(token=null) { @@ -199,6 +201,7 @@ export const useAuthStore = defineStore("auth", { // 1. WICHTIG: Token sofort ins Cookie schreiben, damit es persistiert wird this.setToken(token) + this.sessionExpired = false // 2. User Daten laden await this.fetchMe(token) @@ -241,6 +244,18 @@ export const useAuthStore = defineStore("auth", { navigateTo("/login") }, + expireSession() { + console.log("Auth session expired") + this.resetState() + this.sessionExpired = true + this.setToken(null) + this.loading = false + + if (process.client) { + navigateTo("/login") + } + }, + resetState() { this.clearSessionTimers() this.user = null @@ -249,8 +264,10 @@ export const useAuthStore = defineStore("auth", { this.activeTenant = null this.tenants = [] this.activeTenantData = null + this.sessionExpired = false this.sessionWarningVisible = false this.sessionWarningRemainingSeconds = 0 + this.loading = false }, async fetchMe(jwt= null) { @@ -260,6 +277,13 @@ export const useAuthStore = defineStore("auth", { // Token aus Argument oder Cookie holen const tokenToUse = jwt || useCookie("token").value + if (!tokenToUse) { + const wasSessionExpired = this.sessionExpired + this.resetState() + this.sessionExpired = wasSessionExpired + return + } + try { const me = await useNuxtApp().$api("/api/me", { headers: { @@ -296,9 +320,12 @@ export const useAuthStore = defineStore("auth", { // WICHTIG: Hier NICHT this.logout() aufrufen, weil das navigiert! console.log("fetchMe failed (Invalid Token or Network)", err) - // Stattdessen nur den State sauber machen und Token löschen - this.resetState() - this.setToken(null) + if (err?.response?.status === 401 || err?.status === 401 || err?.statusCode === 401) { + this.expireSession() + return + } + + this.loading = false // Wir werfen den Fehler nicht weiter, damit initStore normal durchläuft }