70 lines
2.2 KiB
JavaScript
Executable File
70 lines
2.2 KiB
JavaScript
Executable File
//File: frontend/app/_auth/drivers/cookieDriver.js
|
|
const API = process.env.NEXT_PUBLIC_API_BASE;
|
|
|
|
let accessToken = null;
|
|
let refreshToken = null;
|
|
|
|
function load() {
|
|
if (typeof window === 'undefined') return;
|
|
accessToken = localStorage.getItem('access_token');
|
|
refreshToken = localStorage.getItem('refresh_token');
|
|
}
|
|
function save(a, r) {
|
|
if (typeof window === 'undefined') return;
|
|
if (a) { accessToken = a; localStorage.setItem('access_token', a); }
|
|
if (r) { refreshToken = r; localStorage.setItem('refresh_token', r); }
|
|
}
|
|
function clear() {
|
|
if (typeof window === 'undefined') return;
|
|
accessToken = null; refreshToken = null;
|
|
localStorage.removeItem('access_token'); localStorage.removeItem('refresh_token');
|
|
}
|
|
|
|
export default {
|
|
mode: 'bearer',
|
|
async login({ username, password }) {
|
|
const r = await fetch(`${API}/api/auth/login`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ username, password })
|
|
});
|
|
if (!r.ok) throw new Error(`Login failed: ${r.status}`);
|
|
const j = await r.json();
|
|
if (!j?.access_token) throw new Error('No access_token');
|
|
save(j.access_token, j.refresh_token);
|
|
return true;
|
|
},
|
|
async me() {
|
|
load();
|
|
const headers = this.authHeaders();
|
|
const r = await fetch(`${API}/api/auth/me`, { headers });
|
|
if (r.status === 401 && await this.refresh()) {
|
|
const r2 = await fetch(`${API}/api/auth/me`, { headers: this.authHeaders() });
|
|
if (!r2.ok) return { ok: false };
|
|
return r2.json();
|
|
}
|
|
if (!r.ok) return { ok: false };
|
|
return r.json();
|
|
},
|
|
async refresh() {
|
|
load();
|
|
if (!refreshToken) return false;
|
|
const r = await fetch(`${API}/api/auth/refresh`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ refresh_token: refreshToken })
|
|
});
|
|
if (!r.ok) { clear(); return false; }
|
|
const j = await r.json();
|
|
if (!j?.access_token) return false;
|
|
save(j.access_token, j.refresh_token ?? refreshToken);
|
|
return true;
|
|
},
|
|
authHeaders(h = {}) {
|
|
load();
|
|
return accessToken ? { ...h, Authorization: `Bearer ${accessToken}` } : h;
|
|
},
|
|
credentials() { return 'omit'; },
|
|
async logout() { clear(); }
|
|
};
|