Send Piped session token in Authorization header again

Commit aed78c13f moved the session token from the Authorization header to a
?authToken= query parameter on /subscriptions, /subscribe, /unsubscribe,
/user/playlists, and /playlists/{id}. Piped's backend only accepts the
?authToken= form on /feed; every other authenticated route reads it from
Authorization (the Java handler names the variable "session", which is why
the rejected requests returned "session is a required parameter"). Restore
the header form for those five routes and leave feed alone.
This commit is contained in:
Arkadiusz Fal
2026-05-06 20:17:09 +02:00
parent fac297e4d6
commit 11841d7b41

View File

@@ -297,12 +297,10 @@ actor PipedAPI: InstanceAPI {
/// - authToken: The auth token from login
/// - Returns: Array of subscribed channels
func subscriptions(instance: Instance, authToken: String) async throws -> [PipedSubscription] {
// Piped accepts the auth token via the `authToken` query parameter, which keeps the
// `Authorization` header free for HTTP Basic Auth from a fronting reverse proxy.
let endpoint = GenericEndpoint(
path: "/subscriptions",
method: .get,
queryItems: [URLQueryItem(name: "authToken", value: authToken)]
headers: ["Authorization": authToken]
)
let response: [PipedSubscription] = try await httpClient.fetch(endpoint, baseURL: instance.url)
return response
@@ -322,8 +320,7 @@ actor PipedAPI: InstanceAPI {
let endpoint = GenericEndpoint(
path: "/subscribe",
method: .post,
queryItems: [URLQueryItem(name: "authToken", value: authToken)],
headers: ["Content-Type": "application/json"],
headers: ["Authorization": authToken, "Content-Type": "application/json"],
body: bodyData
)
@@ -345,8 +342,7 @@ actor PipedAPI: InstanceAPI {
let endpoint = GenericEndpoint(
path: "/unsubscribe",
method: .post,
queryItems: [URLQueryItem(name: "authToken", value: authToken)],
headers: ["Content-Type": "application/json"],
headers: ["Authorization": authToken, "Content-Type": "application/json"],
body: bodyData
)
@@ -362,7 +358,7 @@ actor PipedAPI: InstanceAPI {
let endpoint = GenericEndpoint(
path: "/user/playlists",
method: .get,
queryItems: [URLQueryItem(name: "authToken", value: authToken)]
headers: ["Authorization": authToken]
)
let response: [PipedUserPlaylist] = try await httpClient.fetch(endpoint, baseURL: instance.url)
return response.map { $0.toPlaylist() }
@@ -375,11 +371,11 @@ actor PipedAPI: InstanceAPI {
/// - authToken: The auth token from login
/// - Returns: Playlist with videos
func userPlaylist(id: String, instance: Instance, authToken: String) async throws -> Playlist {
let authQueryItem = URLQueryItem(name: "authToken", value: authToken)
let headers = ["Authorization": authToken]
let firstEndpoint = GenericEndpoint(
path: "/playlists/\(id)",
method: .get,
queryItems: [authQueryItem]
headers: headers
)
let firstResponse: PipedPlaylistResponse = try await httpClient.fetch(firstEndpoint, baseURL: instance.url)
var allStreams = firstResponse.relatedStreams ?? []
@@ -390,7 +386,8 @@ actor PipedAPI: InstanceAPI {
while let token = nextpage, page < maxPages {
let nextEndpoint = GenericEndpoint(
path: "/nextpage/playlists/\(id)",
queryItems: [URLQueryItem(name: "nextpage", value: token), authQueryItem]
queryItems: [URLQueryItem(name: "nextpage", value: token)],
headers: headers
)
let nextResponse: PipedPlaylistNextPageResponse = try await httpClient.fetch(nextEndpoint, baseURL: instance.url)
let pageStreams = nextResponse.relatedStreams ?? []