Skip to content

feat(QBittorrent): port API-key auth from Radarr/Sonarr - #163

Merged
pennydreadful merged 2 commits into
pennydreadful:developfrom
csmarshall:feature/qbittorrent-apikey-auth
Sep 10, 2026
Merged

pennydreadful merged 2 commits into
pennydreadful:developfrom
csmarshall:feature/qbittorrent-apikey-auth

Conversation

@csmarshall

@csmarshall csmarshall commented May 14, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Port qBittorrent's API-key authentication support (introduced in qBittorrent 5.x) from Radarr and Sonarr to bookshelf. Adds an ApiKey field to the qBit download-client settings; when populated, requests carry an Authorization: Bearer <key> header and the cookie-auth flow is bypassed entirely.

Existing username/password configurations see no behavior change.

Why

qBittorrent 5.x added API tokens as a more secure / scriptable alternative to user passwords. Radarr (source) and Sonarr both support it; bookshelf is the odd one out among the *arrs. Users running modern qBit who'd prefer API-key auth currently can't.

Changes

QBittorrentSettings.cs

  • New ApiKey field at FieldDefinition(4), with PrivacyLevel.ApiKey so it's masked in the UI and exported configs.
  • Validator rejects configurations where ApiKey is set alongside Username or Password, mirroring Radarr's rule.
  • Renumber existing FieldDefinition order numbers (5..14) to slot the API Key field right above Username/Password where users naturally look for it. Property names are unchanged — stored configs are unaffected.

QBittorrentProxyV2.cs

  • BuildRequest emits Authorization: Bearer <key> when ApiKey is set and only attaches BasicNetworkCredential when falling back to username/password.
  • ProcessRequest gains a fast path for the ApiKey case that skips AuthenticateClient (no cookie session needed) and routes 401/403 directly to DownloadClientAuthenticationException, matching the Radarr/Sonarr pattern.

Independent of #162

This PR is intentionally orthogonal to #162 (the auth-response-handling fix). It builds and works whether or not #162 has landed:

Test plan

  • Cross-checked the patch against Radarr's and Sonarr's QBittorrentSettings.cs + QBittorrentProxyV2.cs for behavioral parity.
  • Stored configs preserved (FieldDefinition numbers are display-order only; property names are unchanged).
  • Built locally: dotnet build NzbDrone.Core/Readarr.Core.csproj -c Release clean — 0 warnings, 0 errors.
  • CI to verify build + existing tests.

Out of scope

Other divergences between bookshelf's and Radarr/Sonarr's qBit clients (the AddTags() method, base-class refactor to DownloadClientSettingsBase, translation-key labels, etc.) are deliberately not part of this PR — kept tight to the API-key feature so it's easy to review and accept.

csmarshall and others added 2 commits May 13, 2026 20:43
qBittorrent 5.x added API-key authentication as an alternative to the
classic username/password cookie flow. Radarr and Sonarr support it;
bookshelf doesn't yet. Port the additions verbatim (adapted to
bookshelf's existing settings layout — no other refactors).

Changes:

  src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentSettings.cs
    * New `ApiKey` field at FieldDefinition(4), with PrivacyLevel.ApiKey
      so it's masked in the UI and logs.
    * Validator rejects configurations where ApiKey is set AND
      Username/Password are also set, mirroring Radarr's rule.
    * Renumber existing fields (5..14) to make room for the ApiKey
      field where users naturally look for it (right above Username).
      Property names are unchanged so existing stored configs are
      preserved.

  src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentProxyV2.cs
    * BuildRequest now emits `Authorization: Bearer <key>` when ApiKey
      is set, and only attaches BasicNetworkCredential when falling back
      to username/password. Mixing the two would be redundant and could
      confuse some qBit middlewares.
    * ProcessRequest gains a fast path for the ApiKey case that skips
      AuthenticateClient (no cookie session needed) and routes 401/403
      to DownloadClientAuthenticationException directly, matching the
      Radarr/Sonarr pattern.

Independent of pennydreadful#162: this change builds and works whether or not the
auth-response-handling fix has landed yet. Users on classic
username/password auth see no behavior change.

References:
  https://github.com/Radarr/Radarr/blob/develop/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentSettings.cs
  https://github.com/Radarr/Radarr/blob/develop/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentProxyV2.cs
@pennydreadful
pennydreadful enabled auto-merge (squash) September 10, 2026 18:25
@pennydreadful
pennydreadful merged commit 8bcbde5 into pennydreadful:develop Sep 10, 2026
1 check passed
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