Login bei abgelaufener Sitzung korrigieren

This commit is contained in:
2026-05-26 16:27:08 +02:00
parent cb09651d8d
commit f002ad867a
3 changed files with 51 additions and 11 deletions

View File

@@ -46,6 +46,15 @@ const doLogin = async (event: FormSubmitEvent<typeof state>) => {
</p> </p>
</div> </div>
<UAlert
v-if="auth.sessionExpired"
color="warning"
variant="soft"
icon="i-heroicons-clock"
title="Deine Sitzung ist abgelaufen"
description="Bitte melde dich erneut an, um weiterzuarbeiten."
/>
<UForm :state="state" class="space-y-4" @submit="doLogin"> <UForm :state="state" class="space-y-4" @submit="doLogin">
<UFormField label="E-Mail" name="email"> <UFormField label="E-Mail" name="email">
<UInput <UInput

View File

@@ -34,12 +34,13 @@ export default defineNuxtPlugin(() => {
}) })
}, },
async onResponseError({ response }) { async onResponseError({ response, request }) {
// Toasts nur im Client anzeigen // Toasts nur im Client anzeigen
console.log(response) console.log(response)
if (!process.client) return if (!process.client) return
const status = response.status const status = response.status
const requestPath = String(request)
let title = "Fehler" let title = "Fehler"
let description = "Ein unerwarteter Fehler ist aufgetreten." let description = "Ein unerwarteter Fehler ist aufgetreten."
@@ -51,7 +52,10 @@ export default defineNuxtPlugin(() => {
case 401: case 401:
title = "Nicht angemeldet" title = "Nicht angemeldet"
description = "Deine Sitzung ist abgelaufen oder ungültig." description = "Deine Sitzung ist abgelaufen oder ungültig."
// Optional: useCookie('token').value = null if (!requestPath.includes("/auth/login")) {
const auth = useAuthStore()
auth.expireSession()
}
break break
case 403: case 403:
title = "Zugriff verweigert" title = "Zugriff verweigert"

View File

@@ -20,6 +20,7 @@ export const useAuthStore = defineStore("auth", {
activeTenantData: null as any, activeTenantData: null as any,
loading: true as boolean, loading: true as boolean,
notLoggedIn: true, notLoggedIn: true,
sessionExpired: false,
sessionWarningVisible: false, sessionWarningVisible: false,
sessionWarningRemainingSeconds: 0, sessionWarningRemainingSeconds: 0,
sessionWarningLeadMs: 5 * 60 * 1000, sessionWarningLeadMs: 5 * 60 * 1000,
@@ -105,13 +106,12 @@ export const useAuthStore = defineStore("auth", {
const msUntilLogout = expiresAtMs - now const msUntilLogout = expiresAtMs - now
if (msUntilLogout <= 0) { if (msUntilLogout <= 0) {
void this.logout() this.expireSession()
return return
} }
this.sessionLogoutTimer = setTimeout(() => { this.sessionLogoutTimer = setTimeout(() => {
this.sessionWarningVisible = false this.expireSession()
void this.logout()
}, msUntilLogout) }, msUntilLogout)
const msUntilWarning = msUntilLogout - this.sessionWarningLeadMs const msUntilWarning = msUntilLogout - this.sessionWarningLeadMs
@@ -152,12 +152,12 @@ export const useAuthStore = defineStore("auth", {
// 1. Check: Haben wir überhaupt ein Token? // 1. Check: Haben wir überhaupt ein Token?
const token = useCookie("token").value const token = useCookie("token").value
/*if (!token) { if (!token) {
// Kein Token -> Wir sind fertig, User ist Gast. // Kein Token -> Wir sind fertig, User ist Gast.
this.user = null this.user = null
this.loading = false this.loading = false
return return
}*/ }
// 2. Token existiert -> Versuche User zu laden // 2. Token existiert -> Versuche User zu laden
await this.fetchMe(token) 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! // 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 // navigateTo("/") <-- Das würde ich hier evtl. sogar weglassen und der Middleware überlassen
} }
this.loading = false
}, },
async init(token=null) { async init(token=null) {
@@ -199,6 +201,7 @@ export const useAuthStore = defineStore("auth", {
// 1. WICHTIG: Token sofort ins Cookie schreiben, damit es persistiert wird // 1. WICHTIG: Token sofort ins Cookie schreiben, damit es persistiert wird
this.setToken(token) this.setToken(token)
this.sessionExpired = false
// 2. User Daten laden // 2. User Daten laden
await this.fetchMe(token) await this.fetchMe(token)
@@ -241,6 +244,18 @@ export const useAuthStore = defineStore("auth", {
navigateTo("/login") 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() { resetState() {
this.clearSessionTimers() this.clearSessionTimers()
this.user = null this.user = null
@@ -249,8 +264,10 @@ export const useAuthStore = defineStore("auth", {
this.activeTenant = null this.activeTenant = null
this.tenants = [] this.tenants = []
this.activeTenantData = null this.activeTenantData = null
this.sessionExpired = false
this.sessionWarningVisible = false this.sessionWarningVisible = false
this.sessionWarningRemainingSeconds = 0 this.sessionWarningRemainingSeconds = 0
this.loading = false
}, },
async fetchMe(jwt= null) { async fetchMe(jwt= null) {
@@ -260,6 +277,13 @@ export const useAuthStore = defineStore("auth", {
// Token aus Argument oder Cookie holen // Token aus Argument oder Cookie holen
const tokenToUse = jwt || useCookie("token").value const tokenToUse = jwt || useCookie("token").value
if (!tokenToUse) {
const wasSessionExpired = this.sessionExpired
this.resetState()
this.sessionExpired = wasSessionExpired
return
}
try { try {
const me = await useNuxtApp().$api("/api/me", { const me = await useNuxtApp().$api("/api/me", {
headers: { headers: {
@@ -296,9 +320,12 @@ export const useAuthStore = defineStore("auth", {
// WICHTIG: Hier NICHT this.logout() aufrufen, weil das navigiert! // WICHTIG: Hier NICHT this.logout() aufrufen, weil das navigiert!
console.log("fetchMe failed (Invalid Token or Network)", err) console.log("fetchMe failed (Invalid Token or Network)", err)
// Stattdessen nur den State sauber machen und Token löschen if (err?.response?.status === 401 || err?.status === 401 || err?.statusCode === 401) {
this.resetState() this.expireSession()
this.setToken(null) return
}
this.loading = false
// Wir werfen den Fehler nicht weiter, damit initStore normal durchläuft // Wir werfen den Fehler nicht weiter, damit initStore normal durchläuft
} }