Summary
Adds an HttpOnly session cookie on login so browsers can authenticate image requests and resource loads without JavaScript workarounds.
Problem
When auth is enabled, <img src="/api/v1/images/..."> can't attach an Authorization header since browsers don't support custom headers on resource loads. The frontend works around this with a composable that fetches each image via JS, converts it to a blob URL, manages cache maps per component, and revokes blob URLs on unmount. It works but it adds a lot of complexity and a visible placeholder flash on every image.
Added
- Session cookie (
listenarr_session) set on login for browser-native image authentication (HttpOnly, SameSite=Strict, Secure on HTTPS) - Cookie fallback in
SessionAuthenticationMiddlewareafter Bearer, X-Session-Token, and SignalR query param - Cookie deletion and token extraction from cookie on logout
- 7 integration tests for cookie auth, revocation, Bearer priority, API key regression, and auth-disabled mode
- Shared
TestHelpers.csfor common test utilities
Changed
- Session duration constants in
SessionServiceconsolidated as public static fields so cookie expiry stays in sync with DB session expiry TestStartupConfigServicemoved fromAuthenticationMiddlewareTests.csinto sharedTestHelpers.cs
Existing Bearer token and API key auth are completely unaffected. The cookie is only used when no header is present.
Security
- HttpOnly, SameSite=Strict, Secure on HTTPS
- Same opaque token and DB hash validation as Bearer
- Server-side revocation works instantly
- Image endpoints are GET-only, no CSRF risk
Tests
7 new integration tests covering cookie auth, invalid/revoked tokens, Bearer priority, API key regression, and auth-disabled mode. 602 total tests pass.
Next Steps
With this in place a follow-up PR can simplify the frontend by replacing the blob URL fetching in useProtectedImages ...
Automated canary build