mirror of
https://github.com/R0m1k3/FlowReader.git
synced 2026-10-12 17:58:47 +02:00
- XSS stocké (critique) : sanitisation bluemonday sur tous les endpoints d'articles (List, ListByFeed, Favorites, Search, Get), pas seulement Get - SSRF (élevé) : nouveau utils/safehttp.go (ValidateExternalURL + client durci via Dialer.Control, bloque IP privées/loopback/link-local/metadata, anti-DNS-rebinding et limite de redirections) appliqué à l'extracteur et au parser - WebSocket CSWSH (élevé) : politique same-origin + override WS_ALLOWED_ORIGINS - rate-limiting (moyen) : token-bucket en mémoire sur /auth/* - token de session retiré du corps JSON (json:"-"), livré uniquement par le cookie HttpOnly - cookie Secure correct derrière un reverse-proxy (X-Forwarded-Proto + override COOKIE_SECURE) - admin : interdiction de supprimer son propre compte - en-têtes de sécurité (nosniff, X-Frame-Options, Referrer-Policy, Permissions-Policy) Note : backend non compilé localement (pas de toolchain Go) ; à valider via Docker. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
66 lines
1.7 KiB
TypeScript
66 lines
1.7 KiB
TypeScript
import { API_BASE, handleResponse } from './client';
|
|
|
|
export interface User {
|
|
id: string;
|
|
email: string;
|
|
is_admin: boolean;
|
|
}
|
|
|
|
export interface RegisterRequest {
|
|
email: string;
|
|
password: string;
|
|
}
|
|
|
|
export interface LoginRequest {
|
|
email: string;
|
|
password: string;
|
|
}
|
|
|
|
export interface LoginResponse {
|
|
// The session token is delivered via an HttpOnly cookie, not the JSON body.
|
|
expires_at: string;
|
|
user: User;
|
|
}
|
|
|
|
export interface RegisterResponse {
|
|
id: string;
|
|
email: string;
|
|
created_at: string;
|
|
}
|
|
|
|
export const authApi = {
|
|
async register(data: RegisterRequest): Promise<RegisterResponse> {
|
|
const response = await fetch(`${API_BASE}/auth/register`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
credentials: 'include',
|
|
body: JSON.stringify(data),
|
|
});
|
|
return handleResponse<RegisterResponse>(response);
|
|
},
|
|
|
|
async login(data: LoginRequest): Promise<LoginResponse> {
|
|
const response = await fetch(`${API_BASE}/auth/login`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
credentials: 'include',
|
|
body: JSON.stringify(data),
|
|
});
|
|
return handleResponse<LoginResponse>(response);
|
|
},
|
|
|
|
async logout(): Promise<void> {
|
|
await fetch(`${API_BASE}/auth/logout`, {
|
|
method: 'POST',
|
|
credentials: 'include',
|
|
});
|
|
},
|
|
|
|
async getMe(): Promise<User> {
|
|
const response = await fetch(`${API_BASE}/users/me`, {
|
|
credentials: 'include',
|
|
});
|
|
return handleResponse<User>(response);
|
|
},
|
|
};
|