refactor: make authentication truly transparent proxy

- Pass through ALL Jellyfin responses (success and error) without modification
- Move session capabilities posting to background task (don't block auth response)
- Remove generic error fallbacks - always return Jellyfin's actual response
- Simplify logic: if Jellyfin returns a response, pass it through; if not, return status code only
This commit is contained in:
2026-02-07 11:45:16 -05:00
parent d88ed64e37
commit da8cb29e08

View File

@@ -1830,61 +1830,64 @@ public class JellyfinController : ControllerBase
_logger.LogInformation("Authentication request received"); _logger.LogInformation("Authentication request received");
// DO NOT log request body or detailed headers - contains password // DO NOT log request body or detailed headers - contains password
// Forward to Jellyfin server with client headers // Forward to Jellyfin server with client headers - completely transparent proxy
var (result, statusCode) = await _proxyService.PostJsonAsync("Users/AuthenticateByName", body, Request.Headers); var (result, statusCode) = await _proxyService.PostJsonAsync("Users/AuthenticateByName", body, Request.Headers);
if (statusCode != 200) // Pass through Jellyfin's response exactly as-is (transparent proxy)
if (result != null)
{ {
_logger.LogWarning("Authentication failed - status {StatusCode}", statusCode); var responseJson = result.RootElement.GetRawText();
// Pass through Jellyfin's error response if available // On successful auth, post session capabilities in background
if (result != null) if (statusCode == 200)
{ {
return StatusCode(statusCode, result.RootElement.GetRawText()); _logger.LogInformation("Authentication successful, posting session capabilities in background");
}
// Fallback to generic error if no response body // Don't await - do this in background so we return auth response immediately
if (statusCode == 401) _ = Task.Run(async () =>
{ {
return Unauthorized(new { error = "Invalid username or password" }); try
} {
return StatusCode(statusCode, new { error = "Authentication failed" }); _logger.LogInformation("🔧 Posting session capabilities after authentication");
} var capabilities = new
{
PlayableMediaTypes = new[] { "Audio" },
SupportedCommands = Array.Empty<string>(),
SupportsMediaControl = false,
SupportsPersistentIdentifier = true,
SupportsSync = false
};
_logger.LogInformation("Authentication successful"); var capabilitiesJson = JsonSerializer.Serialize(capabilities);
var (capResult, capStatus) = await _proxyService.PostJsonAsync("Sessions/Capabilities/Full", capabilitiesJson, Request.Headers);
// Post session capabilities immediately after authentication if (capStatus == 204 || capStatus == 200)
// This ensures Jellyfin creates a session that will show up in the dashboard {
try _logger.LogInformation("✓ Session capabilities posted after auth ({StatusCode})", capStatus);
{ }
_logger.LogInformation("🔧 Posting session capabilities after authentication"); else
var capabilities = new {
{ _logger.LogWarning("⚠ Session capabilities returned {StatusCode} after auth", capStatus);
PlayableMediaTypes = new[] { "Audio" }, }
SupportedCommands = Array.Empty<string>(), }
SupportsMediaControl = false, catch (Exception ex)
SupportsPersistentIdentifier = true, {
SupportsSync = false _logger.LogWarning(ex, "Failed to post session capabilities after auth");
}; }
});
var capabilitiesJson = JsonSerializer.Serialize(capabilities);
var (capResult, capStatus) = await _proxyService.PostJsonAsync("Sessions/Capabilities/Full", capabilitiesJson, Request.Headers);
if (capStatus == 204 || capStatus == 200)
{
_logger.LogInformation("✓ Session capabilities posted after auth ({StatusCode})", capStatus);
} }
else else
{ {
_logger.LogWarning("⚠ Session capabilities returned {StatusCode} after auth", capStatus); _logger.LogWarning("Authentication failed - status {StatusCode}", statusCode);
} }
}
catch (Exception ex) // Return Jellyfin's exact response
{ return Content(responseJson, "application/json");
_logger.LogWarning(ex, "Failed to post session capabilities after auth, continuing anyway");
} }
return Content(result.RootElement.GetRawText(), "application/json"); // No response body from Jellyfin - return status code only
_logger.LogWarning("Authentication request returned {StatusCode} with no response body", statusCode);
return StatusCode(statusCode);
} }
catch (Exception ex) catch (Exception ex)
{ {