fix: use bearer tokens instead of cookies for cross-origin auth
This commit is contained in:
@@ -8,10 +8,30 @@ const AUTH_BASE = import.meta.env.PROD
|
|||||||
? 'https://api.thenetwork.donovankelly.xyz'
|
? 'https://api.thenetwork.donovankelly.xyz'
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
|
const TOKEN_KEY = 'network-auth-token';
|
||||||
|
|
||||||
class ApiClient {
|
class ApiClient {
|
||||||
|
private getToken(): string | null {
|
||||||
|
return localStorage.getItem(TOKEN_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
setToken(token: string | null) {
|
||||||
|
if (token) {
|
||||||
|
localStorage.setItem(TOKEN_KEY, token);
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem(TOKEN_KEY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private authHeaders(): HeadersInit {
|
||||||
|
const token = this.getToken();
|
||||||
|
return token ? { Authorization: `Bearer ${token}` } : {};
|
||||||
|
}
|
||||||
|
|
||||||
private async fetch<T>(path: string, options: RequestInit = {}): Promise<T> {
|
private async fetch<T>(path: string, options: RequestInit = {}): Promise<T> {
|
||||||
const headers: HeadersInit = {
|
const headers: HeadersInit = {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
...this.authHeaders(),
|
||||||
...options.headers,
|
...options.headers,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -43,23 +63,33 @@ class ApiClient {
|
|||||||
const error = await response.json().catch(() => ({ message: 'Login failed' }));
|
const error = await response.json().catch(() => ({ message: 'Login failed' }));
|
||||||
throw new Error(error.message || 'Login failed');
|
throw new Error(error.message || 'Login failed');
|
||||||
}
|
}
|
||||||
|
// Capture bearer token from response header
|
||||||
|
const authToken = response.headers.get('set-auth-token');
|
||||||
|
if (authToken) {
|
||||||
|
this.setToken(authToken);
|
||||||
|
}
|
||||||
return response.json();
|
return response.json();
|
||||||
}
|
}
|
||||||
|
|
||||||
async logout() {
|
async logout() {
|
||||||
await fetch(`${AUTH_BASE}/api/auth/sign-out`, {
|
await fetch(`${AUTH_BASE}/api/auth/sign-out`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
headers: this.authHeaders(),
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
});
|
});
|
||||||
|
this.setToken(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getSession(): Promise<{ user: User } | null> {
|
async getSession(): Promise<{ user: User } | null> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${AUTH_BASE}/api/auth/get-session`, {
|
const response = await fetch(`${AUTH_BASE}/api/auth/get-session`, {
|
||||||
|
headers: this.authHeaders(),
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
});
|
});
|
||||||
if (!response.ok) return null;
|
if (!response.ok) return null;
|
||||||
return response.json();
|
const data = await response.json();
|
||||||
|
if (!data || !data.user) return null;
|
||||||
|
return data;
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ export const useAuthStore = create<AuthState>()(
|
|||||||
try {
|
try {
|
||||||
await api.logout();
|
await api.logout();
|
||||||
} finally {
|
} finally {
|
||||||
|
api.setToken(null);
|
||||||
set({ user: null, isAuthenticated: false });
|
set({ user: null, isAuthenticated: false });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user