diff --git a/AltSign/Sources/ALTAppleAPI+Authentication.swift b/AltSign/Sources/ALTAppleAPI+Authentication.swift index 2d3e50c2..34149216 100644 --- a/AltSign/Sources/ALTAppleAPI+Authentication.swift +++ b/AltSign/Sources/ALTAppleAPI+Authentication.swift @@ -446,11 +446,28 @@ private extension ALTAppleAPI request.httpBody = bodyData httpHeaders.forEach { request.addValue($0.value, forHTTPHeaderField: $0.key) } - let dataTask = self.session.dataTask(with: request) { (data, response, error) in + // Apple's edge serves at most two requests per connection and answers every request + // after that with a 503 HTML error page. Authenticating takes three requests (init, + // complete, apptokens), so the third one fails whenever they share a pooled connection. + // Give each request its own session, and therefore its own connection. + let configuration = URLSessionConfiguration.ephemeral + configuration.httpMaximumConnectionsPerHost = 1 + let session = URLSession(configuration: configuration) + defer { session.finishTasksAndInvalidate() } + + let dataTask = session.dataTask(with: request) { (data, response, error) in do { guard let data = data else { throw error ?? ALTAppleAPIError.unknown() } + // Surface server errors directly; their HTML bodies are not property lists, and + // parsing them yields a misleading "data couldn't be read" error instead. + if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode >= 500 + { + let message = String(format: NSLocalizedString("Apple's authentication servers returned an error (HTTP %d). This is a problem on Apple's end, not with your Apple ID or password.", comment: ""), httpResponse.statusCode) + throw NSError(domain: ALTUnderlyingAppleAPIErrorDomain, code: httpResponse.statusCode, userInfo: [NSLocalizedDescriptionKey: message]) + } + guard let responseDictionary = try PropertyListSerialization.propertyList(from: data, format: nil) as? [String: Any], let dictionary = responseDictionary["Response"] as? [String: Any], let status = dictionary["Status"] as? [String: Any]