Skip to content

Fix/qbittorrent v5 referer auth#616

Closed
statte wants to merge 3 commits into
vavallee:mainfrom
statte:fix/qbittorrent-v5-referer-auth
Closed

Fix/qbittorrent v5 referer auth#616
statte wants to merge 3 commits into
vavallee:mainfrom
statte:fix/qbittorrent-v5-referer-auth

Conversation

@statte
Copy link
Copy Markdown
Contributor

@statte statte commented May 12, 2026

Fix qBittorrent v5.x login compatibility

Problem

qBittorrent v5.x introduced two breaking changes to the /api/v2/auth/login endpoint that caused the connection test to fail with an empty error body:

  1. CSRF protection ; the login endpoint now requires Origin and Referer headers matching the server URL. Requests without them are rejected silently.
  2. Success response changed ; v5.x returns 204 No Content on successful login instead of 200 Ok. The old check treated 204 as a failure.

Changes

  • internal/downloader/qbittorrent/client.go
    send Origin and Referer headers on the login request; accept 204 No Content as a successful login response alongside the
    existing 200 Ok. path
    include the HTTP status code in login failure errors to aid diagnosis.
  • internal/downloader/qbittorrent/client_test.go
    add TestLogin_V5_NoContent and TestLogin_SendsCSRFHeaders to cover the new behaviour.

Testing

Verified against a live qBittorrent v5 instance behind a reverse proxy. All existing unit tests pass.

statte and others added 3 commits May 12, 2026 20:19
…ibility

qBittorrent v5.x enforces CSRF protection on the login endpoint and rejects
POST requests that don't include a Referer or Origin header matching the
target host. The previous implementation omitted this header, causing
authentication to fail silently against any qBittorrent 5.x instance.

Fix: set Referer to c.baseURL (scheme://host:port[/urlBase]) on the login
request, which already contains the correct value for all configurations
including reverse-proxy subpath deployments.
qBittorrent v5.x made two breaking changes to the login endpoint:
- Requires Origin and Referer headers for CSRF protection
- Returns 204 No Content on success instead of 200 Ok.

Also improves the login failure error message to include the HTTP
status code for easier diagnosis.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
  - TestLogin_V5_NoContent: 204 No Content is treated as success
  - TestLogin_SendsCSRFHeaders: Origin and Referer are sent on login
vavallee added a commit that referenced this pull request May 13, 2026
…Content) (#623)

qBittorrent 5.0 introduced two breaking changes to /api/v2/auth/login
that bindery's client didn't handle. v1.9.4 #618 improved the error
wording for the resulting failures but didn't fix the underlying auth.

  1. CSRF protection. v5.x rejects login requests that lack matching
     Origin and Referer headers. The rejection is silent — qBit returns
     a non-200 with an empty body, which #618 (correctly given what it
     could see) interpreted as a likely IP ban.

  2. Success response. v5.x returns 204 No Content instead of v4.x's
     200 OK + body "Ok.". Bindery's code treated 204 as a failure.

This was reported by @statte in PR #616, opened ~6 hours before #618
landed. The Discord notification workflow (#613) did not fire for #616
for reasons I'm still investigating; we acted on a Discord report from
another user without knowing #616 existed. statte's fix is the actual
root-cause fix and is preserved verbatim here; #618's AuthError type
remains for the legitimate non-200/non-204 failure paths.

Original fix and tests authored by Statte <statte@uplinc.net>.

Co-authored-by: Statte <statte@uplinc.net>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
vavallee added a commit that referenced this pull request May 13, 2026
Lands @statte's qBit v5.x login fix (#616/#623): adds Origin/Referer
CSRF headers and accepts 204 No Content as a successful login response.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vavallee
Copy link
Copy Markdown
Owner

Closing this — but I owe you a straight account of what happened, because this looks worse than it is and I want to make sure you don't read the wrong story into it.

Your PR opened at 20:06 UTC. About 6 hours later, an unrelated user (Zoso) hit roughly the same symptom on the bindery Discord. I worked from that thread, didn't know #616 existed, and shipped a band-aid fix in v1.9.4 #618 that only improved the error wording — it didn't actually fix the underlying v5.x auth break. Your PR did. Genuinely.

That should have been impossible. Earlier the same day I shipped a GitHub Actions workflow (#613) precisely to notify on every external PR via Discord, after closing another contributor's PR in the same kind of mess. The workflow merged at 18:12 UTC, before you opened #616 at 20:06 UTC. It should have fired. It didn't — there's literally no run record for #616 in the actions log, not even a "skipped" status. So the system that was supposed to surface your work failed silently.

That's a real bug, and I'm going to figure out why (separate issue incoming).

What I've done now:

  • Your fix is shipped in v1.9.5 (just tagged, deploying). The implementation and tests are yours verbatim, hybridised with v1.9.4's AuthError type for the cases your fix doesn't cover (legitimate non-2xx/non-204 rejections like wrong creds).
  • The commit message and PR (fix(qbittorrent): support v5.x login (CSRF + 204) — extracted from #616 #623) credit you as primary co-author and call out the v5.x CSRF + 204 root cause as the reason this PR even existed.
  • Closing this PR rather than merging it directly because of the conflict with v1.9.4 — your branch was 6 hours older than my parallel work and rebasing 3 commits over an obsolete error path felt worse than re-landing the change with full attribution.

If you'd like a closer feedback loop, the bindery Discord (link in the README) is where this kind of thing surfaces fastest — happy to give you the actual context on anything else you're working on before you spend the time writing the patch.

Sorry for the duplicate work. Both fixes — yours for the protocol, mine for the error wording — are in main now. Thanks for the very clean PR and the live-instance verification.

@vavallee
Copy link
Copy Markdown
Owner

Forgot to actually drop the link earlier — Discord invite: https://discord.gg/RpuYYRM9cZ. #support for the live-debug stuff, #changelog for release pings. Would be great to have you around.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants