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:
@@ -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)
|
||||
Reference in New Issue
Block a user