feat(auth): implement hybrid session model with HTTP-only cookies
Add HTTP-only cookie session support to backend for SSR compatibility Update frontend fetch calls to include credentials Maintain legacy bearer token support for SPA transition
This commit is contained in:
@@ -112,17 +112,14 @@ const navItems = computed<NavItem[]>(() => {
|
||||
});
|
||||
|
||||
async function loadCurrentUser() {
|
||||
if (!getAuthToken()) {
|
||||
currentUser.value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await api.me();
|
||||
currentUser.value = response.user;
|
||||
} catch {
|
||||
currentUser.value = null;
|
||||
setAuthToken(null);
|
||||
if (getAuthToken()) {
|
||||
setAuthToken(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { api, getAuthToken, setAuthToken } from '../src/services/api';
|
||||
import { api, setAuthToken } from '../src/services/api';
|
||||
|
||||
export default defineNuxtRouteMiddleware(async (to) => {
|
||||
const requiredPermissions = to.matched
|
||||
@@ -16,10 +16,6 @@ export default defineNuxtRouteMiddleware(async (to) => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!getAuthToken()) {
|
||||
return navigateTo({ path: '/login', query: { redirect: to.fullPath } });
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await api.me();
|
||||
if (requiresVerified && !response.user.emailVerified) {
|
||||
|
||||
@@ -1136,6 +1136,7 @@ async function getErrorMessage(response: Response): Promise<string> {
|
||||
|
||||
async function getJson<T>(path: string, signal?: AbortSignal): Promise<T> {
|
||||
const response = await fetch(apiUrl(path), {
|
||||
credentials: 'include',
|
||||
headers: requestHeaders(),
|
||||
signal
|
||||
});
|
||||
@@ -1149,6 +1150,7 @@ async function getJson<T>(path: string, signal?: AbortSignal): Promise<T> {
|
||||
|
||||
async function sendJson<T>(path: string, method: 'PATCH' | 'POST' | 'PUT', body: unknown): Promise<T> {
|
||||
const response = await fetch(apiUrl(path), {
|
||||
credentials: 'include',
|
||||
method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -1166,6 +1168,7 @@ async function sendJson<T>(path: string, method: 'PATCH' | 'POST' | 'PUT', body:
|
||||
|
||||
async function sendFormData<T>(path: string, body: FormData): Promise<T> {
|
||||
const response = await fetch(apiUrl(path), {
|
||||
credentials: 'include',
|
||||
method: 'POST',
|
||||
headers: requestHeaders(),
|
||||
body
|
||||
@@ -1180,6 +1183,7 @@ async function sendFormData<T>(path: string, body: FormData): Promise<T> {
|
||||
|
||||
async function postEmpty(path: string): Promise<void> {
|
||||
const response = await fetch(apiUrl(path), {
|
||||
credentials: 'include',
|
||||
method: 'POST',
|
||||
headers: requestHeaders()
|
||||
});
|
||||
@@ -1191,6 +1195,7 @@ async function postEmpty(path: string): Promise<void> {
|
||||
|
||||
async function deleteJson(path: string): Promise<void> {
|
||||
const response = await fetch(apiUrl(path), {
|
||||
credentials: 'include',
|
||||
method: 'DELETE',
|
||||
headers: requestHeaders()
|
||||
});
|
||||
@@ -1202,6 +1207,7 @@ async function deleteJson(path: string): Promise<void> {
|
||||
|
||||
async function deleteAndGetJson<T>(path: string): Promise<T> {
|
||||
const response = await fetch(apiUrl(path), {
|
||||
credentials: 'include',
|
||||
method: 'DELETE',
|
||||
headers: requestHeaders()
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user