···11import Foundation
2233public protocol AuthTokenProvider: Sendable {
44- /// Returns auth headers to attach to the given request URL, or nil if no
55- /// auth is available. DPoP-bound providers will supply both
66- /// `Authorization` and `DPoP` headers.
44+ /// Returns auth headers to attach to the given request, or nil for anonymous.
55+ /// DPoP-bound providers return both `Authorization: DPoP <token>` and
66+ /// `DPoP: <signed-jwt>` bound to the request's method + URL.
77 func authHeaders(for request: URLRequest) async throws -> [String: String]?
8899- /// Called when the server rejected the previous token so the provider can
1010- /// refresh before the caller retries.
99+ /// Called by `XRPCClient` after any response that uses our headers.
1010+ /// DPoP providers consume the response's `DPoP-Nonce` header here to prepare
1111+ /// the nonce for the next request.
1212+ func handleResponse(_ response: HTTPURLResponse, for request: URLRequest) async
1313+1414+ /// Called after a 401 so the provider can refresh tokens before the
1515+ /// one-shot retry fires. Default implementation is a no-op.
1116 func reportTokenRejected() async
1217}
13181919+public extension AuthTokenProvider {
2020+ func handleResponse(_ response: HTTPURLResponse, for request: URLRequest) async {}
2121+ func reportTokenRejected() async {}
2222+}
2323+1424public struct AnonymousAuthTokenProvider: AuthTokenProvider {
1525 public init() {}
1626 public func authHeaders(for request: URLRequest) async throws -> [String: String]? { nil }
1717- public func reportTokenRejected() async {}
1827}