Block HTTP Basic Auth proxy for Piped sources

Piped's session token reuses the Authorization header, so a fronting basic
auth proxy can't coexist with logged-in Piped use — the two would clobber
each other's credentials on every authenticated request.

Add a supportsHTTPBasicAuthProxy capability on Instance/InstanceType (false
for Piped, true for everything else) and route it through:

- AddRemoteServerView refuses Piped if detection only succeeded behind basic
  auth, surfacing a localized "not supported" error instead of a silently
  broken instance, and hides the optional credentials section for Piped.
- EditSourceView hides the basic auth fields for Piped instances and clears
  any legacy stored credentials on save, in case a Piped source was added
  with credentials before this change.
This commit is contained in:
Arkadiusz Fal
2026-05-06 20:17:18 +02:00
parent 11841d7b41
commit 6f8aa9a1b3
4 changed files with 80 additions and 37 deletions

View File

@@ -439,11 +439,13 @@ struct AddRemoteServerView: View {
}
// HTTP Basic Auth credentials.
// Required for Yattee Server (always shown). Optional for other types show only
// when credentials were already provided (e.g., via the basic-auth-required retry
// path), so we don't clutter the form for the normal "no proxy" case.
let showBasicAuthSection = detectedType == .yatteeServer
|| (!basicAuthUsername.isEmpty || !basicAuthPassword.isEmpty)
// Required for Yattee Server (always shown). Optional for types that can sit
// behind a basic-auth proxy show only when credentials were already provided
// (e.g., via the basic-auth-required retry path), so we don't clutter the form
// for the normal "no proxy" case.
let showBasicAuthSection = (detectedType?.supportsHTTPBasicAuthProxy ?? false) &&
(detectedType == .yatteeServer
|| (!basicAuthUsername.isEmpty || !basicAuthPassword.isEmpty))
if showBasicAuthSection {
Section {
@@ -574,6 +576,14 @@ struct AddRemoteServerView: View {
switch result {
case .success(let detectionResult):
LoggingService.shared.debug("[AddRemoteServerView] Detection succeeded: \(detectionResult.type)", category: .api)
if basicAuthHeader != nil, !detectionResult.type.supportsHTTPBasicAuthProxy {
withAnimation {
self.uiState = .error(String(localized: "sources.error.pipedBasicAuthUnsupported"))
}
return
}
withAnimation {
self.detectedType = detectionResult.type
self.detectionResult = detectionResult
@@ -764,7 +774,7 @@ struct AddRemoteServerView: View {
allowInvalidCertificates: allowInvalidCertificates
)
if !basicAuthUsername.isEmpty && !basicAuthPassword.isEmpty {
if !basicAuthUsername.isEmpty, !basicAuthPassword.isEmpty {
appEnvironment.basicAuthCredentialsManager.setCredentials(
username: basicAuthUsername,
password: basicAuthPassword,