Enable EF Core SplitQuery for PostgreSQL provider
Configured QuerySplittingBehavior.SplitQuery in PostgresDatabaseProvider to optimize performance for queries with multiple Include() statements. This prevents cartesian explosion, eliminates EF Core warnings, and aligns with best practices for handling related collections in PostgreSQL.
This commit is contained in:
@@ -0,0 +1,499 @@
|
||||
# WebSocket "Token is required" Error - Not a Bug!
|
||||
|
||||
**Error Message:** `Token is required. URL GET /socket`
|
||||
**Location:** `Jellyfin.Api.Middleware.ExceptionMiddleware`
|
||||
**Status:** ✅ Expected Behavior (Not a Bug)
|
||||
|
||||
---
|
||||
|
||||
## What This Error Means
|
||||
|
||||
### The Message
|
||||
|
||||
```
|
||||
[WRN] Jellyfin.Api.Middleware.ExceptionMiddleware: Error processing request:
|
||||
Token is required. URL GET /socket
|
||||
```
|
||||
|
||||
### What's Happening
|
||||
|
||||
1. A client (web browser, mobile app, etc.) is trying to connect to the WebSocket endpoint
|
||||
2. The WebSocket endpoint `/socket` **requires authentication**
|
||||
3. The client didn't provide a valid authentication token
|
||||
4. Jellyfin correctly rejects the connection
|
||||
|
||||
**This is SECURITY WORKING AS INTENDED** ✅
|
||||
|
||||
---
|
||||
|
||||
## Why WebSockets Require Authentication
|
||||
|
||||
### Code Location
|
||||
|
||||
**File:** `Emby.Server.Implementations/HttpServer/WebSocketManager.cs`
|
||||
**Method:** `WebSocketRequestHandler()`
|
||||
|
||||
```csharp
|
||||
public async Task WebSocketRequestHandler(HttpContext context)
|
||||
{
|
||||
// Authenticate the request
|
||||
var authorizationInfo = await _authService.Authenticate(context.Request).ConfigureAwait(false);
|
||||
|
||||
// Reject if not authenticated
|
||||
if (!authorizationInfo.IsAuthenticated)
|
||||
{
|
||||
throw new SecurityException("Token is required");
|
||||
}
|
||||
|
||||
// Continue with WebSocket connection...
|
||||
}
|
||||
```
|
||||
|
||||
### Why Authentication Is Required
|
||||
|
||||
1. **Real-Time Updates** - WebSockets send real-time events about:
|
||||
- Library changes
|
||||
- Playback status
|
||||
- User activities
|
||||
- System notifications
|
||||
|
||||
2. **Personal Data** - WebSocket messages contain:
|
||||
- User-specific information
|
||||
- Viewing history
|
||||
- Preferences
|
||||
- Session data
|
||||
|
||||
3. **Security** - Without authentication:
|
||||
- Anyone could listen to events
|
||||
- Privacy violation
|
||||
- Potential data leak
|
||||
|
||||
---
|
||||
|
||||
## Common Causes
|
||||
|
||||
### 1. Browser Extension or Developer Tools ⚠️
|
||||
|
||||
**Scenario:** Browser trying to auto-connect WebSocket
|
||||
|
||||
```javascript
|
||||
// Browser dev tools or extension
|
||||
var ws = new WebSocket('ws://localhost:8096/socket');
|
||||
// ❌ No token provided → "Token is required" error
|
||||
```
|
||||
|
||||
**Solution:** Ignore - this is external tools testing
|
||||
|
||||
### 2. Web Client Not Sending Token
|
||||
|
||||
**Scenario:** Jellyfin web client not properly authenticated
|
||||
|
||||
**Possible causes:**
|
||||
- Session expired
|
||||
- Cookie cleared
|
||||
- Fresh installation without login
|
||||
|
||||
**Solution:** Log in to web UI at http://localhost:8096
|
||||
|
||||
### 3. Third-Party Client Issues
|
||||
|
||||
**Scenario:** Mobile app or third-party client with authentication issues
|
||||
|
||||
**Solution:**
|
||||
- Re-authenticate in the client
|
||||
- Check client API token configuration
|
||||
- Update client to latest version
|
||||
|
||||
### 4. Development/Testing Scripts
|
||||
|
||||
**Scenario:** Testing WebSocket without authentication
|
||||
|
||||
**Solution:** Add proper authentication:
|
||||
|
||||
```javascript
|
||||
// Correct WebSocket connection with token
|
||||
const accessToken = 'your-jellyfin-api-token';
|
||||
const ws = new WebSocket(`ws://localhost:8096/socket?api_key=${accessToken}`);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## How to Fix (If Needed)
|
||||
|
||||
### Option 1: Ignore the Error (Recommended) ✅
|
||||
|
||||
**When:** Error appears occasionally and doesn't affect functionality
|
||||
|
||||
**Action:** Nothing - this is normal
|
||||
|
||||
**Reason:**
|
||||
- Browsers test WebSocket connections
|
||||
- Extensions probe endpoints
|
||||
- Development tools auto-connect
|
||||
- These are expected failed attempts
|
||||
|
||||
**In startup.json or appsettings.json:**
|
||||
```json
|
||||
{
|
||||
"Serilog": {
|
||||
"MinimumLevel": {
|
||||
"Override": {
|
||||
"Jellyfin.Api.Middleware.ExceptionMiddleware": "Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This reduces warning noise while keeping actual errors visible.
|
||||
|
||||
---
|
||||
|
||||
### Option 2: Check Web Client Authentication
|
||||
|
||||
**When:** Error happens every time you load web UI
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. **Clear browser cache and cookies**
|
||||
```
|
||||
Chrome: Settings → Privacy → Clear browsing data
|
||||
Firefox: Settings → Privacy → Clear Data
|
||||
```
|
||||
|
||||
2. **Access web UI**
|
||||
```
|
||||
http://localhost:8096
|
||||
```
|
||||
|
||||
3. **Log in again**
|
||||
- Enter username/password
|
||||
- Client will get new token
|
||||
- WebSocket should connect successfully
|
||||
|
||||
4. **Verify in browser console**
|
||||
```javascript
|
||||
// F12 → Console
|
||||
// Should see: "WebSocket connection established"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Option 3: Check Startup Configuration
|
||||
|
||||
**File:** `startup.json` or environment configuration
|
||||
|
||||
**Verify:**
|
||||
```json
|
||||
{
|
||||
"EnableRemoteAccess": true,
|
||||
"RequireHttps": false, // For local development
|
||||
"BaseUrl": "",
|
||||
"HttpServerPortNumber": 8096
|
||||
}
|
||||
```
|
||||
|
||||
**Common issues:**
|
||||
- BaseUrl misconfigured
|
||||
- RequireHttps forcing HTTP redirect
|
||||
- Port conflicts
|
||||
|
||||
---
|
||||
|
||||
## Debugging WebSocket Connections
|
||||
|
||||
### Check Browser Console
|
||||
|
||||
**Open Developer Tools (F12):**
|
||||
|
||||
```javascript
|
||||
// Console tab - look for:
|
||||
WebSocket connection to 'ws://localhost:8096/socket' failed:
|
||||
Error during WebSocket handshake: Unexpected response code: 401
|
||||
```
|
||||
|
||||
**Network tab:**
|
||||
- Look for `/socket` request
|
||||
- Check status code
|
||||
- Check headers (should have Authorization or api_key)
|
||||
|
||||
### Check Jellyfin Logs
|
||||
|
||||
**File:** `log/log_*.txt`
|
||||
|
||||
**Good connection:**
|
||||
```
|
||||
[INF] WS 127.0.0.1 request
|
||||
[INF] WS 127.0.0.1 closed
|
||||
```
|
||||
|
||||
**Failed connection:**
|
||||
```
|
||||
[WRN] Error processing request: Token is required. URL GET /socket
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## When to Worry
|
||||
|
||||
### ⚠️ Investigate If:
|
||||
|
||||
1. **Constant errors** - Every few seconds
|
||||
2. **Affects functionality** - Real-time updates not working
|
||||
3. **After fresh install** - Can't connect at all
|
||||
4. **All clients failing** - Not just one browser
|
||||
|
||||
### ✅ Ignore If:
|
||||
|
||||
1. **Occasional** - Happens rarely
|
||||
2. **No impact** - Everything works fine
|
||||
3. **Development only** - Testing/debugging
|
||||
4. **Browser extensions** - External tools probing
|
||||
|
||||
---
|
||||
|
||||
## Security Implications
|
||||
|
||||
### ✅ Good Security Practice
|
||||
|
||||
The "Token is required" error shows that:
|
||||
- ✅ Authentication is enforced
|
||||
- ✅ Unauthorized access is blocked
|
||||
- ✅ Security middleware is working
|
||||
- ✅ WebSocket endpoints are protected
|
||||
|
||||
### If You Disable Authentication (DON'T!)
|
||||
|
||||
**Never do this:**
|
||||
```csharp
|
||||
// BAD - Don't remove authentication check
|
||||
if (!authorizationInfo.IsAuthenticated)
|
||||
{
|
||||
// Don't comment this out!
|
||||
// throw new SecurityException("Token is required");
|
||||
}
|
||||
```
|
||||
|
||||
**Why not:**
|
||||
- Anyone can connect to WebSocket
|
||||
- Privacy violation
|
||||
- Data leak
|
||||
- Security vulnerability
|
||||
|
||||
---
|
||||
|
||||
## Client Integration Guide
|
||||
|
||||
### For Developers Building Jellyfin Clients
|
||||
|
||||
**Correct WebSocket connection:**
|
||||
|
||||
```javascript
|
||||
// Step 1: Get API token (after login)
|
||||
const accessToken = jellyfinApi.getAccessToken();
|
||||
|
||||
// Step 2: Connect with token
|
||||
const wsUrl = `ws://server:8096/socket?api_key=${accessToken}`;
|
||||
const ws = new WebSocket(wsUrl);
|
||||
|
||||
// Step 3: Handle connection
|
||||
ws.onopen = () => console.log('Connected');
|
||||
ws.onmessage = (event) => console.log('Message:', event.data);
|
||||
ws.onerror = (error) => console.error('Error:', error);
|
||||
```
|
||||
|
||||
**Alternative (Authorization header):**
|
||||
|
||||
```javascript
|
||||
const ws = new WebSocket('ws://server:8096/socket');
|
||||
ws.onopen = () => {
|
||||
// Send authentication message
|
||||
ws.send(JSON.stringify({
|
||||
MessageType: 'Authenticate',
|
||||
Data: accessToken
|
||||
}));
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### Option A: Log Level Adjustment (Recommended)
|
||||
|
||||
**Reduce noise from failed connection attempts:**
|
||||
|
||||
**File:** `Jellyfin.Server/appsettings.json` or `startup.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"Serilog": {
|
||||
"MinimumLevel": {
|
||||
"Default": "Information",
|
||||
"Override": {
|
||||
"Jellyfin.Api.Middleware.ExceptionMiddleware": "Error",
|
||||
"Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware": "Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Effect:**
|
||||
- Security exceptions logged at Error level only
|
||||
- Reduces log noise
|
||||
- Still captures important errors
|
||||
|
||||
### Option B: Custom WebSocket Authentication
|
||||
|
||||
**If you need different auth logic (not recommended):**
|
||||
|
||||
Modify `WebSocketManager.cs`:
|
||||
```csharp
|
||||
// Allow anonymous for specific scenarios (NOT RECOMMENDED)
|
||||
if (context.Request.Path == "/socket/anonymous")
|
||||
{
|
||||
// Skip authentication
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Scenarios
|
||||
|
||||
### Scenario 1: Browser Dev Tools
|
||||
|
||||
**What happens:**
|
||||
- Open F12 dev tools
|
||||
- Browser auto-tests WebSocket endpoint
|
||||
- No token provided
|
||||
- Error logged
|
||||
|
||||
**Solution:** Ignore - normal browser behavior
|
||||
|
||||
---
|
||||
|
||||
### Scenario 2: Fresh Installation
|
||||
|
||||
**What happens:**
|
||||
- First run of Jellyfin
|
||||
- No users logged in yet
|
||||
- Web UI tries to connect WebSocket
|
||||
- Error logged until first login
|
||||
|
||||
**Solution:** Complete setup wizard and log in
|
||||
|
||||
---
|
||||
|
||||
### Scenario 3: Session Timeout
|
||||
|
||||
**What happens:**
|
||||
- User logged in previously
|
||||
- Session expired (default: 24 hours)
|
||||
- WebSocket reconnect fails
|
||||
- Error logged
|
||||
|
||||
**Solution:** User re-authenticates automatically or manually
|
||||
|
||||
---
|
||||
|
||||
### Scenario 4: Reverse Proxy Issues
|
||||
|
||||
**What happens:**
|
||||
- Jellyfin behind reverse proxy (nginx, Apache)
|
||||
- WebSocket headers not forwarded correctly
|
||||
- Token not reaching Jellyfin
|
||||
- Error logged
|
||||
|
||||
**Solution:** Configure reverse proxy to forward WebSocket headers
|
||||
|
||||
**nginx example:**
|
||||
```nginx
|
||||
location /socket {
|
||||
proxy_pass http://jellyfin:8096;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "Upgrade";
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Monitoring
|
||||
|
||||
### Normal Operation
|
||||
|
||||
**Expected log pattern:**
|
||||
```
|
||||
[INF] WS 192.168.1.100 request
|
||||
[INF] WS 192.168.1.100 closed
|
||||
[INF] WS 192.168.1.101 request
|
||||
```
|
||||
|
||||
**Occasional failed attempts:**
|
||||
```
|
||||
[WRN] Error processing request: Token is required. URL GET /socket
|
||||
```
|
||||
↑ This is fine if occasional
|
||||
|
||||
### Problem Indicators
|
||||
|
||||
**Constant errors (every few seconds):**
|
||||
```
|
||||
[WRN] Error processing request: Token is required. URL GET /socket
|
||||
[WRN] Error processing request: Token is required. URL GET /socket
|
||||
[WRN] Error processing request: Token is required. URL GET /socket
|
||||
...
|
||||
```
|
||||
↑ Investigate client authentication
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
**Error:** `Token is required. URL GET /socket`
|
||||
**Cause:** Unauthenticated WebSocket connection attempt
|
||||
**Status:** ✅ Expected behavior (security working)
|
||||
**Action Required:** None (unless affecting functionality)
|
||||
|
||||
### When to Ignore ✅
|
||||
- Occasional occurrence
|
||||
- No functionality impact
|
||||
- Normal operation otherwise
|
||||
|
||||
### When to Investigate ⚠️
|
||||
- Constant/frequent errors
|
||||
- Real-time updates not working
|
||||
- After fresh install or configuration change
|
||||
|
||||
---
|
||||
|
||||
## Related Files
|
||||
|
||||
- `WebSocketHandlerMiddleware.cs` - Middleware entry point
|
||||
- `WebSocketManager.cs` - Authentication check
|
||||
- `ExceptionMiddleware.cs` - Error logging
|
||||
|
||||
---
|
||||
|
||||
## Quick Checklist
|
||||
|
||||
If this error concerns you, check:
|
||||
|
||||
- [ ] Can you access web UI? (http://localhost:8096)
|
||||
- [ ] Can you log in?
|
||||
- [ ] Do real-time updates work?
|
||||
- [ ] Is this happening constantly or occasionally?
|
||||
- [ ] Any reverse proxy in use?
|
||||
|
||||
If all above are OK → **Ignore the error** ✅
|
||||
|
||||
---
|
||||
|
||||
**Conclusion:** This is a security feature working correctly. The error logs unauthenticated connection attempts, which is expected and normal in web environments.
|
||||
|
||||
✅ **No fix needed - security is working as designed!**
|
||||
Reference in New Issue
Block a user