Add JSON config, DB-backed library options, and docs

- Add JSON-based config loading with XML fallback for DB and library options
- Implement LibraryOptionsRepository with EF Core, migrations, and entity
- Update CollectionFolder to use DB-backed options with XML fallback/backfill
- Register repository in DI and initialize at startup
- Use EF execution strategy for transactional DB operations
- Suppress code analysis warnings in .csproj and test files
- Add DATABASE_MIGRATION.md, LIBRARY_OPTIONS_DB_DESIGN.md, and WEBSOCKET_AUTHENTICATION.md
- Add database.json.example and improve migration docs
- Add tests for JSON config loader and update test naming warnings
This commit is contained in:
2026-04-30 12:25:24 -04:00
parent bad167656a
commit e81c127514
80 changed files with 2039 additions and 140 deletions
+167
View File
@@ -0,0 +1,167 @@
# WebSocket Authentication Guide
## Overview
WebSocket connections to Jellyfin servers require authentication. This guide explains how to properly authenticate WebSocket connections using API tokens.
## Authentication Methods
### 1. Query String Parameter (Recommended for WebSocket)
The simplest and most compatible method for WebSocket connections.
**URL Format:**
```
ws://jellyfin-server:8096/socket?api_key=YOUR_API_TOKEN
wss://jellyfin-server:8096/socket?api_key=YOUR_API_TOKEN (for HTTPS)
```
**JavaScript Example:**
```javascript
const token = "YOUR_API_KEY";
const ws = new WebSocket(`ws://jellyfin-server:8096/socket?api_key=${token}`);
ws.onopen = function(event) {
console.log("WebSocket connection established with authentication");
};
ws.onerror = function(event) {
console.error("WebSocket error:", event);
};
ws.onmessage = function(event) {
const message = JSON.parse(event.data);
console.log("Received message:", message);
};
ws.onclose = function(event) {
console.log("WebSocket connection closed");
};
```
**Python Example:**
```python
import asyncio
import websockets
import json
async def connect_with_token():
token = "YOUR_API_KEY"
uri = f"ws://jellyfin-server:8096/socket?api_key={token}"
async with websockets.connect(uri) as websocket:
print("Connected to Jellyfin WebSocket")
# Receive messages
async for message in websocket:
data = json.loads(message)
print(f"Received: {data}")
asyncio.run(connect_with_token())
```
**C# Example:**
```csharp
using System;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
public class JellyfinWebSocketClient
{
public async Task ConnectAsync(string serverUrl, string token)
{
var uri = new Uri($"ws://{serverUrl}:8096/socket?api_key={token}");
using (var client = new ClientWebSocket())
{
await client.ConnectAsync(uri, CancellationToken.None);
Console.WriteLine("Connected to Jellyfin WebSocket");
// Receive messages
var buffer = new byte[1024 * 4];
while (client.State == WebSocketState.Open)
{
var result = await client.ReceiveAsync(
new ArraySegment<byte>(buffer),
CancellationToken.None);
if (result.MessageType == WebSocketMessageType.Text)
{
var message = System.Text.Encoding.UTF8.GetString(
buffer, 0, result.Count);
Console.WriteLine($"Received: {message}");
}
}
}
}
}
```
### 2. Authorization Header (Alternative)
For advanced use cases, you can also use the Authorization header.
**Header Format:**
```
Authorization: MediaBrowser Device="ClientName", DeviceId="unique-id", Version="1.0", Token="YOUR_API_TOKEN"
```
**Note:** Some WebSocket implementations may not support custom headers during the upgrade handshake. Query parameters are recommended.
## Obtaining an API Token
### Via Server UI
1. Navigate to your Jellyfin server dashboard
2. Go to Settings → API Keys (or similar, depending on version)
3. Create a new API key
4. Copy the token to use in your WebSocket connection
### Programmatically
Use the REST API to create API keys:
```bash
curl -X POST "http://jellyfin-server:8096/Auth/Keys" \
-H "Authorization: MediaBrowser Token=existing_token" \
-H "Content-Type: application/json" \
-d '{"AppName": "My WebSocket Client"}'
```
## Common Issues
### Connection Refused / 401 Unauthorized
- Verify the API token is correct
- Ensure the token hasn't expired
- Check that the WebSocket endpoint path is correct (`/socket`)
### Token Not Found
- Verify the query parameter is URL-encoded properly
- Ensure the parameter name is correct: `api_key` (lowercase)
- Check server logs for authentication errors
### WebSocket Connection Fails Immediately
- Confirm the server is reachable
- Check firewall rules allow WebSocket connections
- Try with `wss://` (secure WebSocket) if using HTTPS
## Server Configuration
The server automatically extracts tokens from:
1. Authorization header (MediaBrowser Token parameter)
2. Query string `api_key` parameter
3. Query string `ApiKey` parameter
4. Legacy headers (if enabled in config)
No special server configuration is required for WebSocket authentication to work.
## Security Considerations
- Always use `wss://` (secure WebSocket) when connecting over untrusted networks
- Keep API tokens secure and rotate them periodically
- Use separate tokens for different clients/applications
- Consider implementing token expiration in your server configuration
## See Also
- [Jellyfin API Documentation](https://api.jellyfin.org/)
- [WebSocket Protocol (RFC 6455)](https://tools.ietf.org/html/rfc6455)