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(); }
 | |
| };
 |