Authenticate browser media with durable HttpOnly login cookies

Adapted cookie, origin, URL validation and secret handling from MikaelKW/nodecast-tv-plus. Protect API roles, revoke logins across restart, preserve existing accounts, and isolate transcode sessions by account.

Co-authored-by: Mikael <mikaelkwessel@gmail.com>
This commit is contained in:
Technomancer702
2026-10-12 16:53:15 -07:00
parent 2999d6542f
commit 1f665dcb11
24 changed files with 553 additions and 111 deletions

View File

@ -28,7 +28,7 @@ class App {
async init() {
// Check authentication first
await this.checkAuth();
if (!await this.checkAuth()) return;
// Mobile menu toggle
const mobileMenuToggle = document.getElementById('mobile-menu-toggle');
@ -167,19 +167,14 @@ class App {
async checkAuth() {
const token = localStorage.getItem('authToken');
if (!token) {
// No token, redirect to login (replace to avoid back button issues)
window.location.replace('/login.html');
return;
}
try {
// Verify token with server
const response = await fetch('/api/auth/me', {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (token) {
const migrated = await fetch('/api/auth/session', { method: 'POST',
headers: { Authorization: `Bearer ${token}` } });
localStorage.removeItem('authToken');
if (!migrated.ok) throw new Error('Please sign in again');
}
const response = await fetch('/api/auth/me', { credentials: 'same-origin' });
if (!response.ok) {
throw new Error('Invalid token');
@ -197,11 +192,13 @@ class App {
// Add logout button to navbar
this.addLogoutButton();
return true;
} catch (err) {
console.error('Authentication error:', err);
localStorage.removeItem('authToken');
window.location.replace('/login.html');
return false;
}
}
@ -223,15 +220,7 @@ class App {
logoutLink.addEventListener('click', async (e) => {
e.preventDefault();
const token = localStorage.getItem('authToken');
if (token) {
await fetch('/api/auth/logout', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`
}
});
}
await fetch('/api/auth/logout', { method: 'POST', credentials: 'same-origin' });
localStorage.removeItem('authToken');
window.location.replace('/login.html');