feat(security): HttpOnly cookies + CSP headers + CSRF double-submit protection

- Migrate auth tokens from localStorage to HttpOnly SameSite=Lax cookies
- Add cookie_auth.rs: helpers for setting/clearing auth + CSRF cookies
- Update auth middleware: 3-method auth (Bearer → Basic → Cookie)
- Add 5 security headers: CSP, X-Content-Type-Options, X-Frame-Options,
  Referrer-Policy, Permissions-Policy
- Implement CSRF double-submit cookie pattern (csrf.rs middleware)
- Set CSRF cookie on login/refresh/oidc-exchange, clear on logout
- CookieAuthenticated marker skips CSRF for Bearer/Basic clients
- Frontend: strip all localStorage token refs from 14 JS files
- Frontend: csrf.js utility + all 52 mutating fetch/XHR calls protected
- 121 tests passing, 0 warnings
This commit is contained in:
Dionisio
2026-03-03 01:10:50 +01:00
parent 7b2a8577a9
commit d2c08d31ba
27 changed files with 579 additions and 455 deletions
+8 -11
View File
@@ -4,16 +4,12 @@
*/
/**
* Get authorization headers for API requests
* @returns {Object} Headers object with Authorization bearer token
* Get authorization headers for API requests.
* Tokens are now in HttpOnly cookies — no explicit Authorization header needed.
* @returns {Object} Headers object
*/
function getAuthHeaders() {
const token = localStorage.getItem('oxicloud_token');
const headers = {};
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
return headers;
return { ...getCsrfHeaders() };
}
// File Operations Module
@@ -177,10 +173,11 @@ const fileOps = {
xhr.open('POST', '/api/files/upload');
// Set auth header
const token = localStorage.getItem('oxicloud_token');
if (token) xhr.setRequestHeader('Authorization', `Bearer ${token}`);
// Auth is handled by HttpOnly cookies — no explicit header needed
xhr.setRequestHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
// CSRF double-submit: echo the CSRF cookie as a request header
const _csrfTok = getCsrfToken();
if (_csrfTok) xhr.setRequestHeader('X-CSRF-Token', _csrfTok);
try {
xhr.send(formData);