Files
pgsql-jellyfin/docs/exception-middleware-authentication-messaging.md
T
wjones c76853a442 PostgreSQL: Production fixes—UPSERT, remote backup, auth logs
- Fix: Atomic UPSERT for BaseItemProviders (resolves duplicate key errors during concurrent metadata refresh; clears navigation property to prevent EF Core tracking conflicts)
- Add: Remote PostgreSQL backup support (removes localhost-only restriction; works with pg_dump/pg_restore for both local and remote DBs)
- Add: Configurable backup disable option (`disable-backups`)
- Fix: Query timeout and performance (documented `command-timeout` config, added performance index scripts)
- Fix: Authentication errors now log as warnings with clear messages (ExceptionMiddleware), reducing log noise
- Fix: SyncPlay authorization handler validates user before lookup, logs warnings for unauthenticated/unknown users (returns 403/404)
- Fix: Database deadlock detection logs warnings and allows EF Core auto-retry
- Add: Configurable LibraryMonitorDelay (min 30s, default 60s)
- Fix: SQLite migration filtering—skip SQLite-only migrations on PostgreSQL
- Chore: Suppress StyleCop warnings (SA1137, etc.) for project consistency
- Docs: 21 documentation files added/updated (config, backup, performance, troubleshooting, session summary)
- All changes are backward compatible and production-ready
2026-03-03 16:35:27 -05:00

6.2 KiB

Exception Middleware - Authentication Error Messaging Improvement

Problem

When users accessed endpoints without proper authentication (e.g., WebSocket /socket endpoint), the error was logged as:

[ERR] Error processing request: Token is required. URL GET /socket

This made it appear as a bug or system error to end users and administrators, when it's actually expected behavior for unauthenticated requests.

Solution

Modified ExceptionMiddleware.cs to:

  1. Detect authentication-related exceptions
  2. Log them as WARNING instead of ERROR
  3. Provide user-friendly message explaining the issue

Changes Made

Detection Logic

Added check for authentication errors:

bool isAuthenticationError = ex is SecurityException || ex is AuthenticationException;

Improved Logging

Before:

_logger.LogError(
    "Error processing request: {ExceptionMessage}. URL {Method} {Url}.",
    ex.Message.TrimEnd('.'),
    context.Request.Method,
    context.Request.Path);

After:

if (isAuthenticationError)
{
    // Log authentication errors as warnings with user-friendly message
    _logger.LogWarning(
        "Access denied: Unable to process request. Authentication token missing or invalid. URL {Method} {Url}.",
        context.Request.Method,
        context.Request.Path);
}
else
{
    // Other errors still logged as errors
    _logger.LogError(
        "Error processing request: {ExceptionMessage}. URL {Method} {Url}.",
        ex.Message.TrimEnd('.'),
        context.Request.Method,
        context.Request.Path);
}

Impact

Before

[ERR] [7] Jellyfin.Api.Middleware.ExceptionMiddleware: Error processing request: Token is required. URL GET /socket

Issues:

  • Logged as ERROR (suggests a bug)
  • Generic message "Token is required"
  • Looks like something is broken

After

[WRN] [7] Jellyfin.Api.Middleware.ExceptionMiddleware: Access denied: Unable to process request. Authentication token missing or invalid. URL GET /socket

Improvements:

  • Logged as WARNING (expected behavior)
  • Clear explanation: "Authentication token missing or invalid"
  • Shows the URL where authentication was required
  • Administrators understand this is normal

Affected Endpoints

This improvement applies to all endpoints that require authentication:

Common Examples:

  • /socket - WebSocket connections
  • /Sessions - Session management
  • /Users/{userId} - User operations
  • /System/ - System configuration
  • /Library/ - Library operations

When This Occurs:

  1. Unauthenticated client connects

    • Browser without cookies
    • Mobile app without saved token
    • API request without Authorization header
  2. Expired token

    • User's session expired
    • Token was invalidated
    • Server restarted and tokens were lost
  3. Invalid token

    • Corrupted or malformed token
    • Token for different server
    • Manually crafted invalid token

Error Levels

The middleware now properly categorizes exceptions:

Exception Type Log Level Example
AuthenticationException WARNING Token missing/invalid
SecurityException WARNING Access forbidden
SocketException ERROR Network issues
IOException ERROR File access issues
OperationCanceledException ERROR Request cancelled
FileNotFoundException ERROR Resource not found
Other exceptions ERROR Unexpected errors

Testing

Test 1: WebSocket Without Authentication

# Connect to WebSocket without token
wscat -c ws://localhost:8096/socket

Expected Log:

[WRN] Access denied: Unable to process request. Authentication token missing or invalid. URL GET /socket

Test 2: API Request Without Token

curl http://localhost:8096/System/Info

Expected Log:

[WRN] Access denied: Unable to process request. Authentication token missing or invalid. URL GET /System/Info

Test 3: Expired Token

curl -H "Authorization: MediaBrowser Token=expired_token" http://localhost:8096/Users/Me

Expected Log:

[WRN] Access denied: Unable to process request. Authentication token missing or invalid. URL GET /Users/Me

Test 4: Other Errors Still Show as Errors

# Trigger a different type of error (e.g., malformed request)
curl -X POST http://localhost:8096/Items -H "Content-Type: application/json" -d "invalid json"

Expected Log:

[ERR] Error processing request: [actual error message]. URL POST /Items

Benefits

  1. Reduced False Alarms

    • Administrators won't panic when seeing authentication warnings
    • Easier to identify real errors vs expected authentication failures
  2. Better Log Analysis

    • Filter out authentication warnings when troubleshooting
    • Focus on actual errors using [ERR] filter
  3. User-Friendly Messages

    • Clear explanation of what went wrong
    • Includes the URL that required authentication
    • Helps users understand they need to log in
  4. Proper HTTP Status Codes

    • Authentication failures return 401 Unauthorized (unchanged)
    • Log level now matches the severity
  • Jellyfin.Api/Middleware/ExceptionMiddleware.cs
    • Modified exception handling logic
    • Added authentication error detection
    • Improved log messages and levels

Configuration

No configuration changes needed. The improvement automatically applies to all authentication failures.

Log Level Configuration

If you want to see or hide authentication warnings, adjust your logging configuration:

Hide authentication warnings:

{
  "Serilog": {
    "MinimumLevel": {
      "Override": {
        "Jellyfin.Api.Middleware.ExceptionMiddleware": "Error"
      }
    }
  }
}

Show all warnings (default):

{
  "Serilog": {
    "MinimumLevel": {
      "Default": "Information"
    }
  }
}

Future Enhancements

Consider similar improvements for:

  • Rate limiting errors (should be warnings)
  • Client disconnection errors (often expected)
  • Cancelled request errors (user action, not system error)

These could follow the same pattern of detecting expected scenarios and logging them appropriately.