diff --git a/Seasoned.Backend/Program.cs b/Seasoned.Backend/Program.cs index a0e56e4..846208b 100644 --- a/Seasoned.Backend/Program.cs +++ b/Seasoned.Backend/Program.cs @@ -23,6 +23,22 @@ builder.Services.AddIdentityApiEndpoints( options => { }) .AddEntityFrameworkStores(); +builder.Services.ConfigureApplicationCookie(options => +{ + options.Cookie.Name = "Seasoned.Session"; + options.Cookie.HttpOnly = true; + options.Cookie.SameSite = SameSiteMode.None; + options.Cookie.SecurePolicy = CookieSecurePolicy.Always; + + options.ExpireTimeSpan = TimeSpan.FromMinutes(30); + options.SlidingExpiration = true; + options.Events.OnRedirectToLogin = context => + { + context.Response.StatusCode = StatusCodes.Status401Unauthorized; + return Task.CompletedTask; + }; +}); + builder.Services.AddAuthorization(); builder.Services.AddControllers() diff --git a/Seasoned.Frontend/app/app.vue b/Seasoned.Frontend/app/app.vue index e6c94ec..b4d011a 100644 --- a/Seasoned.Frontend/app/app.vue +++ b/Seasoned.Frontend/app/app.vue @@ -43,6 +43,7 @@ + @@ -50,6 +51,7 @@ \ No newline at end of file diff --git a/Seasoned.Frontend/app/pages/login.vue b/Seasoned.Frontend/app/pages/login.vue index 51ea5dc..d7e28da 100644 --- a/Seasoned.Frontend/app/pages/login.vue +++ b/Seasoned.Frontend/app/pages/login.vue @@ -127,6 +127,8 @@ const errorMessage = ref('') const authLoading = ref(false) const config = useRuntimeConfig() +const isLoggedIn = useState('isLoggedIn', () => false) + const toggleMode = () => { isLogin.value = !isLogin.value errorMessage.value = '' @@ -144,7 +146,7 @@ const handleAuth = async () => { const endpoint = isLogin.value ? 'api/auth/login' : 'api/auth/register' const url = isLogin.value - ? `${config.public.apiBase}${endpoint}?useCookies=true` + ? `${config.public.apiBase}${endpoint}?useCookies=true&useSessionCookies=false` : `${config.public.apiBase}${endpoint}` try { @@ -153,28 +155,31 @@ const handleAuth = async () => { body: { email: email.value, password: password.value - } + }, + credentials: 'include' }) if (isLogin.value) { - const isLoggedIn = useState('isLoggedIn') isLoggedIn.value = true navigateTo('/') } else { isLogin.value = true authLoading.value = false errorMessage.value = "Account created! Please sign in." + password.value = '' + confirmPassword.value = '' } } catch (err) { authLoading.value = false if (err.status === 401) { errorMessage.value = "Invalid email or password. Please try again." + } else if (err.status === 400) { + errorMessage.value = "Registration failed. Check your password length." } else if (err.status === 404) { errorMessage.value = "Account not found. Would you like to register?" } else { - errorMessage.value = "Something went wrong. Please check your connection." + errorMessage.value = "Something went wrong." } - console.error('Auth error:', err) } } diff --git a/Seasoned.Frontend/app/plugins/auth-watch.ts b/Seasoned.Frontend/app/plugins/auth-watch.ts new file mode 100644 index 0000000..4687746 --- /dev/null +++ b/Seasoned.Frontend/app/plugins/auth-watch.ts @@ -0,0 +1,15 @@ +export default defineNuxtPlugin((nuxtApp) => { + const showTimeout = useState('showSessionTimeout', () => false); + const isLoggedIn = useState('isLoggedIn'); + + nuxtApp.hooks.hook('app:suspense:resolve', () => { + globalThis.$fetch = $fetch.create({ + onResponseError({ response }) { + if (response.status === 401 && isLoggedIn.value) { + isLoggedIn.value = false; + showTimeout.value = true; + } + } + }); + }); +}); \ No newline at end of file